AlphaBlendingExample.cs 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631
  1. using System;
  2. using System.Collections;
  3. using System.Collections.Generic;
  4. using System.Runtime.InteropServices;
  5. using UnityEngine;
  6. using UnityEngine.UI;
  7. using UnityEngine.SceneManagement;
  8. //using Unity.IL2CPP.CompilerServices;
  9. using OpenCVForUnity.CoreModule;
  10. using OpenCVForUnity.ImgprocModule;
  11. using OpenCVForUnity.UnityUtils;
  12. namespace OpenCVForUnityExample
  13. {
  14. /// <summary>
  15. /// Alpha Blending Example
  16. /// An example of alpha blending in multiple ways.
  17. ///
  18. /// ### How to speed up pixel array access. (optional) ###
  19. ///
  20. /// # IL2CPP Compiler options:
  21. /// [Il2CppSetOption(Option.ArrayBoundsChecks, false)]
  22. /// [Il2CppSetOption(Option.NullChecks, false)]
  23. /// The runtime checks can be enabled or disabled in C# code using the Il2CppSetOptions attribute. To use this attribute,
  24. /// find the Il2CppSetOptionsAttribute.cs source file in the IL2CPP directory in the Unity Editor installation on your computer.
  25. /// (Data\il2cpp on Windows, Contents/Frameworks/il2cpp on OS X). Copy this source file into the Assets folder in your project.
  26. /// https://docs.unity3d.com/Manual/IL2CPP-CompilerOptions.html
  27. ///
  28. /// # Pointer acccess. (use -unsafe):
  29. /// Unsafe code requires the `unsafe' command line option to be specified.
  30. /// You need to add a file "smcs.rsp" (or "gmcs.rsp") in your "Assets" directory, which contains the line: -unsafe
  31. /// https://answers.unity.com/questions/804103/how-to-enable-unsafe-and-use-pointers.html
  32. ///
  33. /// To use these options, uncomment the code that enables the feature.
  34. /// ######
  35. /// </summary>
  36. public class AlphaBlendingExample : MonoBehaviour
  37. {
  38. public enum ImageSize
  39. {
  40. Original,
  41. Large,
  42. Small
  43. }
  44. /// <summary>
  45. /// The image size.
  46. /// </summary>
  47. public ImageSize imageSize = ImageSize.Original;
  48. /// <summary>
  49. /// The count dropdown.
  50. /// </summary>
  51. public Dropdown imageSizeDropdown;
  52. /// <summary>
  53. /// The count.
  54. /// </summary>
  55. public int count = 100;
  56. /// <summary>
  57. /// The image size dropdown.
  58. /// </summary>
  59. public Dropdown countDropdown;
  60. public MeshRenderer fgQuad;
  61. public MeshRenderer bgQuad;
  62. public MeshRenderer alphaQuad;
  63. public MeshRenderer dstQuad;
  64. Texture2D fgTex;
  65. Texture2D bgTex;
  66. Texture2D alphaTex;
  67. Texture2D dstTex;
  68. Mat fgMat;
  69. Mat bgMat;
  70. Mat alphaMat;
  71. Mat dstMat;
  72. Mat fgMatLarge;
  73. Mat bgMatLarge;
  74. Mat alphaMatLarge;
  75. Mat dstMatLarge;
  76. Mat fgMatROI;
  77. Mat bgMatROI;
  78. Mat alphaMatROI;
  79. Mat dstMatROI;
  80. Mat _fgMat;
  81. Mat _bgMat;
  82. Mat _alphaMat;
  83. Mat _dstMat;
  84. /// <summary>
  85. /// The FPS monitor.
  86. /// </summary>
  87. FpsMonitor fpsMonitor;
  88. // Use this for initialization
  89. void Start ()
  90. {
  91. fpsMonitor = GetComponent<FpsMonitor> ();
  92. imageSizeDropdown.value = (int)imageSize;
  93. countDropdown.value = 2;
  94. fgTex = Resources.Load ("lena") as Texture2D;
  95. bgTex = new Texture2D (fgTex.width, fgTex.height, TextureFormat.RGBA32, false);
  96. alphaTex = new Texture2D (fgTex.width, fgTex.height, TextureFormat.RGBA32, false);
  97. dstTex = new Texture2D (fgTex.width, fgTex.height, TextureFormat.RGBA32, false);
  98. fgMat = new Mat (fgTex.height, fgTex.width, CvType.CV_8UC3);
  99. bgMat = new Mat (fgTex.height, fgTex.width, CvType.CV_8UC3);
  100. alphaMat = new Mat (fgTex.height, fgTex.width, CvType.CV_8UC1);
  101. dstMat = new Mat (fgTex.height, fgTex.width, CvType.CV_8UC3, new Scalar (0, 0, 0));
  102. // Generate fgMat.
  103. Utils.texture2DToMat (fgTex, fgMat);
  104. // Generate bgMat.
  105. Core.flip (fgMat, bgMat, 1);
  106. Core.bitwise_not (bgMat, bgMat);
  107. // Generate alphaMat.
  108. for (int r = 0; r < alphaMat.rows (); r++) {
  109. alphaMat.row (r).setTo (new Scalar (r / (alphaMat.rows () / 256)));
  110. }
  111. #pragma warning disable 0618
  112. Imgproc.linearPolar (alphaMat, alphaMat, new Point (alphaMat.cols () / 2, alphaMat.rows () / 2), alphaMat.rows (), Imgproc.INTER_CUBIC | Imgproc.WARP_FILL_OUTLIERS | Imgproc.WARP_INVERSE_MAP);
  113. #pragma warning restore 0618
  114. // Generate large size Mat.
  115. fgMatLarge = new Mat ();
  116. bgMatLarge = new Mat ();
  117. alphaMatLarge = new Mat ();
  118. dstMatLarge = new Mat ();
  119. Imgproc.resize (fgMat, fgMatLarge, new Size (), 2, 2, 0);
  120. Imgproc.resize (bgMat, bgMatLarge, new Size (), 2, 2, 0);
  121. Imgproc.resize (alphaMat, alphaMatLarge, new Size (), 2, 2, 0);
  122. Imgproc.resize (dstMat, dstMatLarge, new Size (), 2, 2, 0);
  123. // Generate small size Mat (ROI).
  124. OpenCVForUnity.CoreModule.Rect rect = new OpenCVForUnity.CoreModule.Rect (127, 127, 256, 256);
  125. fgMatROI = new Mat (fgMat, rect);
  126. bgMatROI = new Mat (bgMat, rect);
  127. alphaMatROI = new Mat (alphaMat, rect);
  128. dstMatROI = new Mat (dstMat, rect);
  129. Utils.matToTexture2D (fgMat, fgTex, true, 0, true);
  130. Utils.matToTexture2D (bgMat, bgTex, true, 0, true);
  131. Utils.matToTexture2D (alphaMat, alphaTex, true, 0, true);
  132. Utils.matToTexture2D (dstMat, dstTex, true, 0, true);
  133. fgQuad.GetComponent<Renderer> ().material.mainTexture = fgTex;
  134. bgQuad.GetComponent<Renderer> ().material.mainTexture = bgTex;
  135. alphaQuad.GetComponent<Renderer> ().material.mainTexture = alphaTex;
  136. dstQuad.GetComponent<Renderer> ().material.mainTexture = dstTex;
  137. }
  138. private IEnumerator AlphaBlending (Action action, int count = 100)
  139. {
  140. dstMat.setTo (new Scalar (0, 0, 0));
  141. Utils.matToTexture2D (dstMat, dstTex);
  142. yield return null;
  143. switch (imageSize) {
  144. default:
  145. case ImageSize.Original:
  146. _fgMat = fgMat;
  147. _bgMat = bgMat;
  148. _alphaMat = alphaMat;
  149. _dstMat = dstMat;
  150. break;
  151. case ImageSize.Large:
  152. _fgMat = fgMatLarge;
  153. _bgMat = bgMatLarge;
  154. _alphaMat = alphaMatLarge;
  155. _dstMat = dstMatLarge;
  156. break;
  157. case ImageSize.Small:
  158. _fgMat = fgMatROI;
  159. _bgMat = bgMatROI;
  160. _alphaMat = alphaMatROI;
  161. _dstMat = dstMatROI;
  162. break;
  163. }
  164. long ms = time (action, count);
  165. if (imageSize == ImageSize.Large)
  166. Imgproc.resize (dstMatLarge, dstMat, new Size (), 1.0 / 2.0, 1.0 / 2.0, 0);
  167. Utils.matToTexture2D (dstMat, dstTex);
  168. #if UNITY_WSA && ENABLE_DOTNET
  169. if (fpsMonitor != null)
  170. {
  171. fpsMonitor.consoleText = imageSize + " : " + count + " : " + ms + " ms";
  172. }
  173. Debug.Log(imageSize + " : " + count + " : " + ms + " ms");
  174. #else
  175. if (fpsMonitor != null) {
  176. fpsMonitor.consoleText = imageSize + " : " + count + " : " + action.Method.Name + " : " + ms + " ms";
  177. }
  178. Debug.Log (imageSize + " : " + count + " : " + action.Method.Name + " : " + ms + " ms");
  179. #endif
  180. }
  181. private void getput ()
  182. {
  183. AlphaBlend_getput (_fgMat, _bgMat, _alphaMat, _dstMat);
  184. }
  185. private void matOp ()
  186. {
  187. AlphaBlend_matOp (_fgMat, _bgMat, _alphaMat, _dstMat);
  188. }
  189. private void matOp_alpha3c ()
  190. {
  191. AlphaBlend_matOp_alpha3c (_fgMat, _bgMat, _alphaMat, _dstMat);
  192. }
  193. private void copyFromMat ()
  194. {
  195. AlphaBlend_copyFromMat (_fgMat, _bgMat, _alphaMat, _dstMat);
  196. }
  197. private void marshal ()
  198. {
  199. AlphaBlend_Marshal (_fgMat, _bgMat, _alphaMat, _dstMat);
  200. }
  201. private void pointerAccess ()
  202. {
  203. // AlphaBlend_pointerAccess (_fgMat, _bgMat, _alphaMat, _dstMat);
  204. }
  205. private long time (Action action, int count)
  206. {
  207. System.GC.Collect ();
  208. var tw = new System.Diagnostics.Stopwatch ();
  209. tw.Start ();
  210. for (int i = 0; i < count; i++)
  211. action ();
  212. tw.Stop ();
  213. System.GC.Collect ();
  214. return tw.ElapsedMilliseconds;
  215. }
  216. // mat.get() mat.put()
  217. // [Il2CppSetOption(Option.ArrayBoundsChecks, false)]
  218. // [Il2CppSetOption(Option.NullChecks, false)]
  219. private void AlphaBlend_getput (Mat fg, Mat bg, Mat alpha, Mat dst)
  220. {
  221. byte[] fg_byte = new byte[fg.total () * fg.channels ()];
  222. fg.get (0, 0, fg_byte);
  223. byte[] bg_byte = new byte[bg.total () * bg.channels ()];
  224. bg.get (0, 0, bg_byte);
  225. byte[] alpha_byte = new byte[alpha.total () * alpha.channels ()];
  226. alpha.get (0, 0, alpha_byte);
  227. int pixel_i = 0;
  228. int channels = (int)bg.channels ();
  229. int total = (int)bg.total ();
  230. for (int i = 0; i < total; i++) {
  231. if (alpha_byte [i] == 0) {
  232. } else if (alpha_byte [i] == 255) {
  233. bg_byte [pixel_i] = fg_byte [pixel_i];
  234. bg_byte [pixel_i + 1] = fg_byte [pixel_i + 1];
  235. bg_byte [pixel_i + 2] = fg_byte [pixel_i + 2];
  236. } else {
  237. bg_byte [pixel_i] = (byte)((fg_byte [pixel_i] * alpha_byte [i] + bg_byte [pixel_i] * (255 - alpha_byte [i])) >> 8);
  238. bg_byte [pixel_i + 1] = (byte)((fg_byte [pixel_i + 1] * alpha_byte [i] + bg_byte [pixel_i + 1] * (255 - alpha_byte [i])) >> 8);
  239. bg_byte [pixel_i + 2] = (byte)((fg_byte [pixel_i + 2] * alpha_byte [i] + bg_byte [pixel_i + 2] * (255 - alpha_byte [i])) >> 8);
  240. }
  241. pixel_i += channels;
  242. }
  243. dst.put (0, 0, bg_byte);
  244. }
  245. // Mat operation
  246. private void AlphaBlend_matOp (Mat fg, Mat bg, Mat alpha, Mat dst)
  247. {
  248. List<Mat> channels = new List<Mat> ();
  249. using (Mat _bg = new Mat ())
  250. using (Mat inv_alpha = new Mat (alpha.width (), alpha.height (), alpha.type ())) {
  251. Core.bitwise_not (alpha, inv_alpha);
  252. Core.split (bg, channels);
  253. Core.multiply (inv_alpha, channels [0], channels [0], 1.0 / 255);
  254. Core.multiply (inv_alpha, channels [1], channels [1], 1.0 / 255);
  255. Core.multiply (inv_alpha, channels [2], channels [2], 1.0 / 255);
  256. Core.merge (channels, _bg);
  257. using (Mat _fg = new Mat ()) {
  258. Core.split (fg, channels);
  259. Core.multiply (alpha, channels [0], channels [0], 1.0 / 255);
  260. Core.multiply (alpha, channels [1], channels [1], 1.0 / 255);
  261. Core.multiply (alpha, channels [2], channels [2], 1.0 / 255);
  262. Core.merge (channels, _fg);
  263. Core.add (_fg, _bg, dst);
  264. }
  265. }
  266. }
  267. // Mat operation (3channel alpha)
  268. private void AlphaBlend_matOp_alpha3c (Mat fg, Mat bg, Mat alpha, Mat dst)
  269. {
  270. using (Mat inv_alpha = new Mat (alpha.width (), alpha.height (), alpha.type ()))
  271. using (Mat alpha3c = new Mat ())
  272. using (Mat inv_alpha3c = new Mat ()) {
  273. List<Mat> channels = new List<Mat> ();
  274. channels.Add (alpha);
  275. channels.Add (alpha);
  276. channels.Add (alpha);
  277. Core.merge (channels, alpha3c);
  278. Core.bitwise_not (alpha, inv_alpha);
  279. channels.Clear ();
  280. channels.Add (inv_alpha);
  281. channels.Add (inv_alpha);
  282. channels.Add (inv_alpha);
  283. Core.merge (channels, inv_alpha3c);
  284. using (Mat _bg = new Mat ())
  285. using (Mat _fg = new Mat ()) {
  286. Core.multiply (inv_alpha3c, bg, _bg, 1.0 / 255);
  287. Core.multiply (alpha3c, fg, _fg, 1.0 / 255);
  288. Core.add (_fg, _bg, dst);
  289. }
  290. }
  291. }
  292. // Utils.copyFromMat
  293. // [Il2CppSetOption(Option.ArrayBoundsChecks, false)]
  294. // [Il2CppSetOption(Option.NullChecks, false)]
  295. private void AlphaBlend_copyFromMat (Mat fg, Mat bg, Mat alpha, Mat dst)
  296. {
  297. byte[] fg_byte = new byte[fg.total () * fg.channels ()];
  298. Utils.copyFromMat<byte> (fg, fg_byte);
  299. byte[] bg_byte = new byte[bg.total () * bg.channels ()];
  300. Utils.copyFromMat<byte> (bg, bg_byte);
  301. byte[] alpha_byte = new byte[alpha.total () * alpha.channels ()];
  302. Utils.copyFromMat<byte> (alpha, alpha_byte);
  303. int pixel_i = 0;
  304. int channels = (int)bg.channels ();
  305. int total = (int)bg.total ();
  306. for (int i = 0; i < total; i++) {
  307. if (alpha_byte [i] == 0) {
  308. } else if (alpha_byte [i] == 255) {
  309. bg_byte [pixel_i] = fg_byte [pixel_i];
  310. bg_byte [pixel_i + 1] = fg_byte [pixel_i + 1];
  311. bg_byte [pixel_i + 2] = fg_byte [pixel_i + 2];
  312. } else {
  313. bg_byte [pixel_i] = (byte)((fg_byte [pixel_i] * alpha_byte [i] + bg_byte [pixel_i] * (255 - alpha_byte [i])) >> 8);
  314. bg_byte [pixel_i + 1] = (byte)((fg_byte [pixel_i + 1] * alpha_byte [i] + bg_byte [pixel_i + 1] * (255 - alpha_byte [i])) >> 8);
  315. bg_byte [pixel_i + 2] = (byte)((fg_byte [pixel_i + 2] * alpha_byte [i] + bg_byte [pixel_i + 2] * (255 - alpha_byte [i])) >> 8);
  316. }
  317. pixel_i += channels;
  318. }
  319. Utils.copyToMat (bg_byte, dst);
  320. }
  321. // Marshal
  322. // [Il2CppSetOption(Option.ArrayBoundsChecks, false)]
  323. // [Il2CppSetOption(Option.NullChecks, false)]
  324. private void AlphaBlend_Marshal (Mat fg, Mat bg, Mat alpha, Mat dst)
  325. {
  326. byte[] fg_byte = new byte[fg.total () * fg.channels ()];
  327. IntPtr fg_ptr = new IntPtr (fg.dataAddr ());
  328. byte[] bg_byte = new byte[bg.total () * bg.channels ()];
  329. IntPtr bg_ptr = new IntPtr (bg.dataAddr ());
  330. byte[] alpha_byte = new byte[alpha.total () * alpha.channels ()];
  331. IntPtr alpha_ptr = new IntPtr (alpha.dataAddr ());
  332. byte[] dst_byte = new byte[dst.total () * dst.channels ()];
  333. IntPtr dst_ptr = new IntPtr (dst.dataAddr ());
  334. if (fg.isContinuous ()) {
  335. Marshal.Copy (fg_ptr, fg_byte, 0, fg_byte.Length);
  336. Marshal.Copy (bg_ptr, bg_byte, 0, bg_byte.Length);
  337. Marshal.Copy (alpha_ptr, alpha_byte, 0, alpha_byte.Length);
  338. Marshal.Copy (dst_ptr, dst_byte, 0, dst_byte.Length);
  339. } else {
  340. Size wholeSize = new Size ();
  341. Point ofs = new Point ();
  342. bg.locateROI (wholeSize, ofs);
  343. long stride = (long)wholeSize.width * bg.elemSize ();
  344. int w = bg.cols () * bg.channels ();
  345. int h = bg.rows ();
  346. long alpha_stride = (long)wholeSize.width * alpha.channels ();
  347. int alpha_w = alpha.cols () * alpha.channels ();
  348. for (int y = 0; y < h; y++) {
  349. Marshal.Copy (fg_ptr, fg_byte, y * w, w);
  350. Marshal.Copy (bg_ptr, bg_byte, y * w, w);
  351. Marshal.Copy (alpha_ptr, alpha_byte, y * alpha_w, alpha_w);
  352. Marshal.Copy (dst_ptr, dst_byte, y * w, w);
  353. fg_ptr = new IntPtr (fg_ptr.ToInt64 () + stride);
  354. bg_ptr = new IntPtr (bg_ptr.ToInt64 () + stride);
  355. alpha_ptr = new IntPtr (alpha_ptr.ToInt64 () + alpha_stride);
  356. dst_ptr = new IntPtr (dst_ptr.ToInt64 () + stride);
  357. }
  358. }
  359. int pixel_i = 0;
  360. int channels = (int)bg.channels ();
  361. int total = (int)bg.total ();
  362. for (int i = 0; i < total; i++) {
  363. if (alpha_byte [i] == 0) {
  364. } else if (alpha_byte [i] == 255) {
  365. bg_byte [pixel_i] = fg_byte [pixel_i];
  366. bg_byte [pixel_i + 1] = fg_byte [pixel_i + 1];
  367. bg_byte [pixel_i + 2] = fg_byte [pixel_i + 2];
  368. } else {
  369. bg_byte [pixel_i] = (byte)((fg_byte [pixel_i] * alpha_byte [i] + bg_byte [pixel_i] * (255 - alpha_byte [i])) >> 8);
  370. bg_byte [pixel_i + 1] = (byte)((fg_byte [pixel_i + 1] * alpha_byte [i] + bg_byte [pixel_i + 1] * (255 - alpha_byte [i])) >> 8);
  371. bg_byte [pixel_i + 2] = (byte)((fg_byte [pixel_i + 2] * alpha_byte [i] + bg_byte [pixel_i + 2] * (255 - alpha_byte [i])) >> 8);
  372. }
  373. pixel_i += channels;
  374. }
  375. if (fg.isContinuous ()) {
  376. Marshal.Copy (bg_byte, 0, dst_ptr, bg_byte.Length);
  377. } else {
  378. dst_ptr = new IntPtr (dst.dataAddr ());
  379. Size wholeSize = new Size ();
  380. Point ofs = new Point ();
  381. bg.locateROI (wholeSize, ofs);
  382. long stride = (long)wholeSize.width * bg.elemSize ();
  383. int w = bg.cols () * bg.channels ();
  384. int h = bg.rows ();
  385. for (int y = 0; y < h; y++) {
  386. Marshal.Copy (bg_byte, y * w, dst_ptr, w);
  387. dst_ptr = new IntPtr (dst_ptr.ToInt64 () + stride);
  388. }
  389. }
  390. }
  391. /*
  392. // pointer access
  393. // [Il2CppSetOption(Option.ArrayBoundsChecks, false)]
  394. // [Il2CppSetOption(Option.NullChecks, false)]
  395. private void AlphaBlend_pointerAccess (Mat fg, Mat bg, Mat alpha, Mat dst)
  396. {
  397. IntPtr fg_ptr = new IntPtr (fg.dataAddr());
  398. IntPtr bg_ptr = new IntPtr (bg.dataAddr());
  399. IntPtr alpha_ptr = new IntPtr (alpha.dataAddr());
  400. IntPtr dst_ptr = new IntPtr (dst.dataAddr());
  401. if (fg.isContinuous ()) {
  402. int total = (int)bg.total();
  403. unsafe
  404. {
  405. byte* fg_p = (byte*)fg_ptr;
  406. byte* bg_p = (byte*)bg_ptr;
  407. byte* alpha_p = (byte*)alpha_ptr;
  408. byte* dst_p = (byte*)dst_ptr;
  409. for( int i = 0; i < total; i++)
  410. {
  411. *dst_p = (byte)(((*fg_p)*(*alpha_p) + (*bg_p)*(255 - *alpha_p)) >> 8);
  412. fg_p++; bg_p++; dst_p++;
  413. *dst_p = (byte)(((*fg_p)*(*alpha_p) + (*bg_p)*(255 - *alpha_p)) >> 8);
  414. fg_p++; bg_p++; dst_p++;
  415. *dst_p = (byte)(((*fg_p)*(*alpha_p) + (*bg_p)*(255 - *alpha_p)) >> 8);
  416. fg_p++; bg_p++; dst_p++;
  417. alpha_p++;
  418. }
  419. }
  420. } else {
  421. Size wholeSize = new Size ();
  422. Point ofs = new Point ();
  423. bg.locateROI(wholeSize, ofs);
  424. long stride = (long)wholeSize.width * bg.channels ();
  425. int w = bg.cols () * bg.channels ();
  426. int h = bg.rows ();
  427. long alpha_stride = (long)wholeSize.width * alpha.channels ();
  428. int alpha_w = alpha.cols () ;
  429. unsafe
  430. {
  431. byte* fg_p = (byte*)fg_ptr;
  432. byte* bg_p = (byte*)bg_ptr;
  433. byte* alpha_p = (byte*)alpha_ptr;
  434. byte* dst_p = (byte*)dst_ptr;
  435. for (int y = 0; y < h; y++) {
  436. for (int x = 0; x < alpha_w; x++) {
  437. *dst_p = (byte)(((*fg_p)*(*alpha_p) + (*bg_p)*(255 - *alpha_p)) >> 8);
  438. fg_p++; bg_p++; dst_p++;
  439. *dst_p = (byte)(((*fg_p)*(*alpha_p) + (*bg_p)*(255 - *alpha_p)) >> 8);
  440. fg_p++; bg_p++; dst_p++;
  441. *dst_p = (byte)(((*fg_p)*(*alpha_p) + (*bg_p)*(255 - *alpha_p)) >> 8);
  442. fg_p++; bg_p++; dst_p++;
  443. alpha_p++;
  444. }
  445. fg_p += stride - w;
  446. bg_p += stride - w;
  447. alpha_p += alpha_stride - alpha_w;
  448. dst_p += stride - w;
  449. }
  450. }
  451. }
  452. }
  453. */
  454. /// <summary>
  455. /// Raises the back button click event.
  456. /// </summary>
  457. public void OnBackButtonClick ()
  458. {
  459. SceneManager.LoadScene ("OpenCVForUnityExample");
  460. }
  461. /// <summary>
  462. /// Raises the image size dropdown value changed event.
  463. /// </summary>
  464. public void OnImageSizeDropdownValueChanged (int result)
  465. {
  466. if ((int)imageSize != result) {
  467. imageSize = (ImageSize)result;
  468. }
  469. }
  470. /// <summary>
  471. /// Raises the count dropdown value changed event.
  472. /// </summary>
  473. public void OnCountDropdownValueChanged (int result)
  474. {
  475. switch (result) {
  476. default:
  477. case 0:
  478. count = 1;
  479. break;
  480. case 1:
  481. count = 10;
  482. break;
  483. case 2:
  484. count = 100;
  485. break;
  486. }
  487. }
  488. /// <summary>
  489. /// Raises the getput button click event.
  490. /// </summary>
  491. public void OnGetPutButtonClick ()
  492. {
  493. StartCoroutine (AlphaBlending (getput, count));
  494. }
  495. /// <summary>
  496. /// Raises the MatOp button click event.
  497. /// </summary>
  498. public void OnMatOpButtonClick ()
  499. {
  500. StartCoroutine (AlphaBlending (matOp, count));
  501. }
  502. /// <summary>
  503. /// Raises the MatOpAlpha3c button click event.
  504. /// </summary>
  505. public void OnMatOpAlpha3cButtonClick ()
  506. {
  507. StartCoroutine (AlphaBlending (matOp_alpha3c, count));
  508. }
  509. /// <summary>
  510. /// Raises the copyFromMat button click event.
  511. /// </summary>
  512. public void OnCopyFromMatButtonClick ()
  513. {
  514. StartCoroutine (AlphaBlending (copyFromMat, count));
  515. }
  516. /// <summary>
  517. /// Raises the Marshal button click event.
  518. /// </summary>
  519. public void OnMarshalButtonClick ()
  520. {
  521. StartCoroutine (AlphaBlending (marshal, count));
  522. }
  523. /// <summary>
  524. /// Raises the pointer access button click event.
  525. /// </summary>
  526. public void OnPointerAccessButtonClick ()
  527. {
  528. StartCoroutine (AlphaBlending (pointerAccess, count));
  529. }
  530. }
  531. }