Utils.cs 67 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293
  1. using UnityEngine;
  2. using System;
  3. using System.Collections;
  4. using System.Collections.Generic;
  5. using System.Runtime.InteropServices;
  6. using System.IO;
  7. using AOT;
  8. using OpenCVForUnity.CoreModule;
  9. namespace OpenCVForUnity.UnityUtils
  10. {
  11. public static class Utils
  12. {
  13. /**
  14. * Returns this "OpenCV for Unity" version number.
  15. *
  16. * @return this "OpenCV for Unity" version number
  17. */
  18. public static string getVersion ()
  19. {
  20. return "2.3.3";
  21. }
  22. /**
  23. * Copies OpenCV Mat data to Pixel Data IntPtr.
  24. * <p>
  25. * <br>This function copies the OpenCV Mat data to the pixel data IntPtr.
  26. * <br>The pixel data has to be of the same byte size as the Mat data ([total() * elemSize()] byte).
  27. * <br>Because this function doesn't check bounds, is faster than Mat.get().
  28. *
  29. * @param mat a Mat object.
  30. * @param intPtr the pixel data has to be of the same byte size as the Mat data ([total() * elemSize()] byte).
  31. */
  32. public static void copyFromMat (Mat mat, IntPtr intPtr)
  33. {
  34. if (mat != null)
  35. mat.ThrowIfDisposed ();
  36. if (mat == null)
  37. throw new ArgumentNullException ("mat == null");
  38. if (intPtr == IntPtr.Zero)
  39. throw new ArgumentNullException ("intPtr == IntPtr.Zero");
  40. #if UNITY_PRO_LICENSE || ((UNITY_ANDROID || UNITY_IOS || UNITY_WEBGL) && !UNITY_EDITOR) || UNITY_5 || UNITY_5_3_OR_NEWER
  41. OpenCVForUnity_MatDataToByteArray (mat.nativeObj, intPtr);
  42. #else
  43. return;
  44. #endif
  45. }
  46. /**
  47. * Copies Pixel Data IntPtr to OpenCV Mat data.
  48. * <p>
  49. * <br>This function copy the pixel data IntPtr to the OpenCV Mat data.
  50. * <br>The Mat object has to be of the same byte size as the pixel data ([total() * elemSize()] byte).
  51. * <br>Because this function doesn't check bounds, is faster than Mat.put().
  52. *
  53. * @param intPtr a pixel data IntPtr.
  54. * @param mat the Mat object has to be of the same byte size as the pixel data ([total() * elemSize()] byte).
  55. */
  56. public static void copyToMat (IntPtr intPtr, Mat mat)
  57. {
  58. if (mat != null)
  59. mat.ThrowIfDisposed ();
  60. if (intPtr == IntPtr.Zero)
  61. throw new ArgumentNullException ("intPtr == IntPtr.Zero");
  62. if (mat == null)
  63. throw new ArgumentNullException ("mat == null");
  64. #if UNITY_PRO_LICENSE || ((UNITY_ANDROID || UNITY_IOS || UNITY_WEBGL) && !UNITY_EDITOR) || UNITY_5 || UNITY_5_3_OR_NEWER
  65. OpenCVForUnity_ByteArrayToMatData (intPtr, mat.nativeObj);
  66. #else
  67. return;
  68. #endif
  69. }
  70. /**
  71. * Copies OpenCV Mat data to Pixel Data Array.
  72. * <p>
  73. * <br>This function copies the OpenCV Mat data to the pixel data Array.
  74. * <br>The pixel data Array has to be of the same byte size as the Mat data ([total() * elemSize()] byte).
  75. * <br>Because this function doesn't check bounds, is faster than Mat.get().
  76. *
  77. * @param mat a Mat object.
  78. * @param array the pixel data Array has to be of the same byte size as the Mat data ([total() * elemSize()] byte).
  79. */
  80. public static void copyFromMat<T> (Mat mat, IList<T> array)
  81. {
  82. if (mat != null)
  83. mat.ThrowIfDisposed ();
  84. if (mat == null)
  85. throw new ArgumentNullException ("mat == null");
  86. if (array == null)
  87. throw new ArgumentNullException ("array == null");
  88. #if UNITY_PRO_LICENSE || ((UNITY_ANDROID || UNITY_IOS || UNITY_WEBGL) && !UNITY_EDITOR) || UNITY_5 || UNITY_5_3_OR_NEWER
  89. GCHandle arrayHandle = GCHandle.Alloc (array, GCHandleType.Pinned);
  90. OpenCVForUnity_MatDataToByteArray (mat.nativeObj, arrayHandle.AddrOfPinnedObject ());
  91. arrayHandle.Free ();
  92. #else
  93. return;
  94. #endif
  95. }
  96. /**
  97. * Copies Pixel Data Array to OpenCV Mat data.
  98. * <p>
  99. * <br>This function copies the pixel data Array to the OpenCV Mat data.
  100. * <br>The Mat object has to be of the same byte size as the pixel data Array ([total() * elemSize()] byte).
  101. * <br>Because this function doesn't check bounds, is faster than Mat.put().
  102. *
  103. * @param array a pixel data Array.
  104. * @param mat the Mat object has to be of the same byte size as the pixel data Array ([total() * elemSize()] byte).
  105. */
  106. public static void copyToMat<T> (IList<T> array, Mat mat)
  107. {
  108. if (mat != null)
  109. mat.ThrowIfDisposed ();
  110. if (array == null)
  111. throw new ArgumentNullException ("array == null");
  112. if (mat == null)
  113. throw new ArgumentNullException ("mat == null");
  114. #if UNITY_PRO_LICENSE || ((UNITY_ANDROID || UNITY_IOS || UNITY_WEBGL) && !UNITY_EDITOR) || UNITY_5 || UNITY_5_3_OR_NEWER
  115. GCHandle arrayHandle = GCHandle.Alloc (array, GCHandleType.Pinned);
  116. OpenCVForUnity_ByteArrayToMatData (arrayHandle.AddrOfPinnedObject (), mat.nativeObj);
  117. arrayHandle.Free ();
  118. #else
  119. return;
  120. #endif
  121. }
  122. /**
  123. * Converts OpenCV Mat to Unity Texture2D.
  124. * <p>
  125. * <br>This function converts the OpenCV Mat to the Unity Texture2D image.
  126. * <br>The Mat object has to be of the types 'CV_8UC4' (RGBA) , 'CV_8UC3' (RGB) or 'CV_8UC1' (GRAY).
  127. * <br>The Texture2D object has to be of the TextureFormat 'RGBA32' or 'ARGB32'. (SetPixels32() must function.)
  128. * <br>The Texture2D object has to be of the same size as the Mat (width * height).
  129. *
  130. * @param mat the Mat object has to be of the types 'CV_8UC4' (RGBA) , 'CV_8UC3' (RGB) or 'CV_8UC1' (GRAY)
  131. * @param texture2D the Texture2D object has to be of the TextureFormat 'RGBA32' or 'ARGB32'. (SetPixels32() must function.) The Texture2D object has to be of the same size as the Mat (width * height).
  132. * @param flip if true, the mat is fliped before converting.
  133. * @param flipCode a flag to specify how to flip the array; 0 means flipping around the x-axis and positive value (for example, 1) means flipping around y-axis. Negative value (for example, -1) means flipping around both axes.
  134. * @param flipAfter if true, the mat is fliped after converting. If you want to use mat even after calling this function, set true.
  135. * @param updateMipmaps When set to true, mipmap levels are recalculated.
  136. * @param makeNoLongerReadable When set to true, system memory copy of a texture is released.
  137. */
  138. public static void matToTexture2D (Mat mat, Texture2D texture2D, bool flip = true, int flipCode = 0, bool flipAfter = false, bool updateMipmaps = false, bool makeNoLongerReadable = false)
  139. {
  140. matToTexture2D (mat, texture2D, null, flip, flipCode, flipAfter, updateMipmaps, makeNoLongerReadable);
  141. }
  142. /**
  143. * Converts OpenCV Mat to Unity Texture2D.
  144. * <p>
  145. * <br>This function converts the OpenCV Mat to the Unity Texture2D image.
  146. * <br>The Mat object has to be of the types 'CV_8UC4' (RGBA) , 'CV_8UC3' (RGB) or 'CV_8UC1' (GRAY).
  147. * <br>The Texture2D object has to be of the TextureFormat 'RGBA32' or 'ARGB32'. (SetPixels32() must function.)
  148. * <br>The Texture2D object has to be of the same size as the Mat (width * height).
  149. *
  150. * @param mat the Mat object has to be of the types 'CV_8UC4' (RGBA) , 'CV_8UC3' (RGB) or 'CV_8UC1' (GRAY)
  151. * @param texture2D the Texture2D object has to be of the TextureFormat 'RGBA32' or 'ARGB32'. (SetPixels32() must function) The Texture2D object has to be of the same size as the Mat (width * height).
  152. * @param bufferColors the optional array to receive pixel data.
  153. * You can optionally pass in an array of Color32s to use in colors to avoid allocating new memory each frame.
  154. * The array needs to be initialized to a length matching width * height of the texture. (<a href="http://docs.unity3d.com/ScriptReference/WebCamTexture.GetPixels32.html">http://docs.unity3d.com/ScriptReference/WebCamTexture.GetPixels32.html</a>)
  155. * @param flip if true, the mat is fliped before converting.
  156. * @param flipCode a flag to specify how to flip the array; 0 means flipping around the x-axis and positive value (for example, 1) means flipping around y-axis. Negative value (for example, -1) means flipping around both axes.
  157. * @param flipAfter if true, the mat is fliped after converting. If you want to use mat even after calling this function, set true.
  158. * @param updateMipmaps When set to true, mipmap levels are recalculated.
  159. * @param makeNoLongerReadable When set to true, system memory copy of a texture is released.
  160. */
  161. public static void matToTexture2D (Mat mat, Texture2D texture2D, Color32[] bufferColors, bool flip = true, int flipCode = 0, bool flipAfter = false, bool updateMipmaps = false, bool makeNoLongerReadable = false)
  162. {
  163. if (mat != null)
  164. mat.ThrowIfDisposed ();
  165. if (mat == null)
  166. throw new ArgumentNullException ("mat == null");
  167. if (texture2D == null)
  168. throw new ArgumentNullException ("texture2D == null");
  169. if (mat.cols () != texture2D.width || mat.rows () != texture2D.height)
  170. throw new ArgumentException ("The Texture2D object has to be of the same size");
  171. // Core.flip (mat, mat, 0);
  172. //
  173. // byte[] data = new byte[mat.cols () * mat.rows () * mat.channels ()];
  174. // mat.get (0, 0, data);
  175. //
  176. // Core.flip (mat, mat, 0);
  177. //
  178. // if (texture2D.format == TextureFormat.ARGB32 || texture2D.format == TextureFormat.BGRA32 || texture2D.format == TextureFormat.RGBA32) {
  179. //
  180. // Color32[] colors = new Color32[mat.cols () * mat.rows ()];
  181. //
  182. //
  183. //
  184. // if (mat.type () == CvType.CV_8UC1) {
  185. // for (int i = 0; i < colors.Length; i++) {
  186. // colors [i] = new Color32 (data [i], data [i], data [i], 255);
  187. // }
  188. // } else if (mat.type () == CvType.CV_8UC3) {
  189. // for (int i = 0; i < colors.Length; i++) {
  190. // colors [i] = new Color32 (data [(i * 3) + 0], data [(i * 3) + 1], data [(i * 3) + 2], 255);
  191. // }
  192. // } else if (mat.type () == CvType.CV_8UC4) {
  193. // for (int i = 0; i < colors.Length; i++) {
  194. // colors [i] = new Color32 (data [(i * 4) + 0], data [(i * 4) + 1], data [(i * 4) + 2], data [(i * 4) + 3]);
  195. // }
  196. // }
  197. //
  198. //
  199. // texture2D.SetPixels32 (colors);
  200. //
  201. // } else {
  202. // Color[] colors = new Color[mat.cols () * mat.rows ()];
  203. //
  204. // if (mat.type () == CvType.CV_8UC1) {
  205. // for (int i = 0; i < colors.Length; i++) {
  206. // colors [i] = new Color ((float)data [i] / 255.0f, data [i] / 255.0f, data [i] / 255.0f);
  207. // }
  208. // } else if (mat.type () == CvType.CV_8UC3) {
  209. // for (int i = 0; i < colors.Length; i++) {
  210. // colors [i] = new Color ((float)data [(i * 3) + 0] / 255.0f, (float)data [(i * 3) + 1] / 255.0f, (float)data [(i * 3) + 2] / 255.0f);
  211. // }
  212. // } else if (mat.type () == CvType.CV_8UC4) {
  213. // for (int i = 0; i < colors.Length; i++) {
  214. // colors [i] = new Color ((float)data [(i * 4) + 0] / 255.0f, (float)data [(i * 4) + 1] / 255.0f, (float)data [(i * 4) + 2] / 255.0f);
  215. // }
  216. // }
  217. //
  218. //
  219. // texture2D.SetPixels (colors);
  220. //
  221. // }
  222. //
  223. // texture2D.Apply ();
  224. // #if UNITY_PRO_LICENSE || ((UNITY_ANDROID || UNITY_IOS || UNITY_WEBGL) && !UNITY_EDITOR) || UNITY_5 || UNITY_5_3_OR_NEWER
  225. // if(mat.type () == CvType.CV_8UC4){
  226. // OpenCVForUnity_LowLevelMatToTexture (mat.nativeObj, texture2D.GetNativeTexturePtr(), texture2D.width, texture2D.height);
  227. //
  228. // return;
  229. // }
  230. //
  231. // #endif
  232. #if UNITY_PRO_LICENSE || ((UNITY_ANDROID || UNITY_IOS || UNITY_WEBGL) && !UNITY_EDITOR) || UNITY_5 || UNITY_5_3_OR_NEWER
  233. #if UNITY_5_3_OR_NEWER
  234. int type = mat.type ();
  235. if (mat.isContinuous () && (texture2D.format == TextureFormat.RGBA32 && type == CvType.CV_8UC4) || (texture2D.format == TextureFormat.RGB24 && type == CvType.CV_8UC3) || (texture2D.format == TextureFormat.Alpha8 && type == CvType.CV_8UC1)) {
  236. if (flip) {
  237. Core.flip (mat, mat, flipCode);
  238. }
  239. texture2D.LoadRawTextureData ((IntPtr)mat.dataAddr (), (int)mat.total () * (int)mat.elemSize ());
  240. texture2D.Apply (updateMipmaps, makeNoLongerReadable);
  241. if (flipAfter) {
  242. Core.flip (mat, mat, flipCode);
  243. }
  244. return;
  245. }
  246. #endif
  247. GCHandle colorsHandle;
  248. if (bufferColors == null) {
  249. Color32[] colors = texture2D.GetPixels32 ();
  250. colorsHandle = GCHandle.Alloc (colors, GCHandleType.Pinned);
  251. OpenCVForUnity_MatToTexture (mat.nativeObj, colorsHandle.AddrOfPinnedObject (), flip, flipCode, flipAfter);
  252. texture2D.SetPixels32 (colors);
  253. } else {
  254. colorsHandle = GCHandle.Alloc (bufferColors, GCHandleType.Pinned);
  255. OpenCVForUnity_MatToTexture (mat.nativeObj, colorsHandle.AddrOfPinnedObject (), flip, flipCode, flipAfter);
  256. texture2D.SetPixels32 (bufferColors);
  257. }
  258. texture2D.Apply (updateMipmaps, makeNoLongerReadable);
  259. colorsHandle.Free ();
  260. #else
  261. return;
  262. #endif
  263. }
  264. /**
  265. * Fast converts OpenCV Mat to Unity Texture2D. (Unity5.3+)
  266. * <p>
  267. * <br>This function converts the OpenCV Mat to the Unity Texture2D image.
  268. * <br>Passed Mat data should be of required size to fill the whole texture according to its width, height, data format and mipmapCount.
  269. * <br>This function doesn't check bounds.
  270. *
  271. * @param mat
  272. * @param texture2D The Texture2D object has to be of the same size as the Mat (width * height).
  273. * @param flip if true, the mat is fliped before converting.
  274. * @param flipCode a flag to specify how to flip the array; 0 means flipping around the x-axis and positive value (for example, 1) means flipping around y-axis. Negative value (for example, -1) means flipping around both axes.
  275. * @param flipAfter if true, the mat is fliped after converting. If you want to use mat even after calling this function, set true.
  276. * @param updateMipmaps When set to true, mipmap levels are recalculated.
  277. * @param makeNoLongerReadable When set to true, system memory copy of a texture is released.
  278. */
  279. public static void fastMatToTexture2D (Mat mat, Texture2D texture2D, bool flip = true, int flipCode = 0, bool flipAfter = false, bool updateMipmaps = false, bool makeNoLongerReadable = false)
  280. {
  281. if (mat != null)
  282. mat.ThrowIfDisposed ();
  283. if (mat == null)
  284. throw new ArgumentNullException ("mat == null");
  285. if (texture2D == null)
  286. throw new ArgumentNullException ("texture2D == null");
  287. #if UNITY_PRO_LICENSE || ((UNITY_ANDROID || UNITY_IOS || UNITY_WEBGL) && !UNITY_EDITOR) || UNITY_5 || UNITY_5_3_OR_NEWER
  288. #if UNITY_5_3_OR_NEWER
  289. if (!mat.isContinuous ()) {
  290. throw new ArgumentException ("mat.isContinuous() must be true.");
  291. }
  292. if (flip) {
  293. Core.flip (mat, mat, flipCode);
  294. }
  295. try
  296. {
  297. if((int)mat.total() * (int)mat.elemSize()>0)
  298. {
  299. texture2D.LoadRawTextureData((IntPtr)mat.dataAddr(), (int)mat.total() * (int)mat.elemSize());
  300. }
  301. texture2D.Apply(updateMipmaps, makeNoLongerReadable);
  302. if (flipAfter)
  303. {
  304. Core.flip(mat, mat, flipCode);
  305. }
  306. }
  307. catch
  308. {
  309. }
  310. return;
  311. #else
  312. return;
  313. #endif
  314. #else
  315. return;
  316. #endif
  317. }
  318. /**
  319. * Converts Unity Texture2D to OpenCV Mat.
  320. * <p>
  321. * <br>This function converts the Unity Texture2D image to the OpenCV Mat.
  322. * <br>The Mat object has to be of the same size as the Texture2D (width * height).
  323. * <br>The Mat object has to be of the types 'CV_8UC4' (RGBA) , 'CV_8UC3' (RGB) or 'CV_8UC1' (GRAY).
  324. *
  325. * @param texture2D the Texture2D object has to be of the TextureFormat 'RGBA32' or 'ARGB32'. (SetPixels32() must function)
  326. * @param mat the Mat object has to be of the same size as the Texture2D (width * height).
  327. * The Mat object has to be of the types 'CV_8UC4' (RGBA) , 'CV_8UC3' (RGB) or 'CV_8UC1' (GRAY).
  328. * @param flip if true, the mat is fliped after converting.
  329. * @param flipCode a flag to specify how to flip the array; 0 means flipping around the x-axis and positive value (for example, 1) means flipping around y-axis. Negative value (for example, -1) means flipping around both axes.
  330. */
  331. public static void texture2DToMat (Texture2D texture2D, Mat mat, bool flip = true, int flipCode = 0)
  332. {
  333. if (mat != null)
  334. mat.ThrowIfDisposed ();
  335. if (texture2D == null)
  336. throw new ArgumentNullException ("texture2D == null");
  337. if (mat == null)
  338. throw new ArgumentNullException ("mat == null");
  339. if (mat.cols () != texture2D.width || mat.rows () != texture2D.height)
  340. throw new ArgumentException ("The Mat object has to be of the same size");
  341. // byte[] data = new byte[mat.cols () * mat.rows () * mat.channels ()];
  342. //
  343. // Color32[] colors = texture2D.GetPixels32 ();
  344. //
  345. // if (mat.type () == CvType.CV_8UC1) {
  346. // for (int i = 0; i < colors.Length; i++) {
  347. // data [i] = colors [i].b;
  348. // }
  349. // mat.put (0, 0, data);
  350. // Core.flip (mat, mat, 0);
  351. // } else if (mat.type () == CvType.CV_8UC3) {
  352. // for (int i = 0; i < colors.Length; i++) {
  353. // data [(i * 3) + 0] = colors [i].b;
  354. // data [(i * 3) + 1] = colors [i].g;
  355. // data [(i * 3) + 2] = colors [i].r;
  356. // }
  357. // mat.put (0, 0, data);
  358. // Core.flip (mat, mat, 0);
  359. // } else if (mat.type () == CvType.CV_8UC4) {
  360. // for (int i = 0; i < colors.Length; i++) {
  361. // data [(i * 4) + 0] = colors [i].b;
  362. // data [(i * 4) + 1] = colors [i].g;
  363. // data [(i * 4) + 2] = colors [i].r;
  364. // data [(i * 4) + 3] = colors [i].a;
  365. // }
  366. // mat.put (0, 0, data);
  367. // Core.flip (mat, mat, 0);
  368. // }
  369. // #if UNITY_PRO_LICENSE || ((UNITY_ANDROID || UNITY_IOS || UNITY_WEBGL) && !UNITY_EDITOR) || UNITY_5 || UNITY_5_3_OR_NEWER
  370. // if(mat.type () == CvType.CV_8UC4){
  371. // OpenCVForUnity_LowLevelTextureToMat (texture2D.GetNativeTexturePtr(), texture2D.width, texture2D.height, mat.nativeObj);
  372. //
  373. // return;
  374. // }
  375. //
  376. // #endif
  377. #if UNITY_PRO_LICENSE || ((UNITY_ANDROID || UNITY_IOS || UNITY_WEBGL) && !UNITY_EDITOR) || UNITY_5 || UNITY_5_3_OR_NEWER
  378. #if (UNITY_5 && !UNITY_5_0) || UNITY_5_3_OR_NEWER
  379. int type = mat.type ();
  380. if ((texture2D.format == TextureFormat.RGBA32 && type == CvType.CV_8UC4) || (texture2D.format == TextureFormat.RGB24 && type == CvType.CV_8UC3) || (texture2D.format == TextureFormat.Alpha8 && type == CvType.CV_8UC1)) {
  381. mat.put (0, 0, texture2D.GetRawTextureData ());
  382. if (flip) {
  383. Core.flip (mat, mat, flipCode);
  384. }
  385. return;
  386. }
  387. #endif
  388. Color32[] colors = texture2D.GetPixels32 ();
  389. GCHandle colorsHandle = GCHandle.Alloc (colors, GCHandleType.Pinned);
  390. OpenCVForUnity_TextureToMat (colorsHandle.AddrOfPinnedObject (), mat.nativeObj, flip, flipCode);
  391. colorsHandle.Free ();
  392. #else
  393. return;
  394. #endif
  395. }
  396. /**
  397. * Fast converts Unity Texture2D to OpenCV Mat. (Unity5.1+)
  398. * <p>
  399. * <br>This function converts the Unity Texture2D image to the OpenCV Mat.
  400. * <br>Mat data size must be the same as the texture data size.
  401. * <br>This function doesn't check bounds.
  402. *
  403. * @param texture2D
  404. * @param mat the Mat object has to be of the same size as the Texture2D (width * height).
  405. * @param flip if true, the mat is fliped after converting.
  406. * @param flipCode a flag to specify how to flip the array; 0 means flipping around the x-axis and positive value (for example, 1) means flipping around y-axis. Negative value (for example, -1) means flipping around both axes.
  407. */
  408. public static void fastTexture2DToMat (Texture2D texture2D, Mat mat, bool flip = true, int flipCode = 0)
  409. {
  410. if (mat != null)
  411. mat.ThrowIfDisposed ();
  412. if (texture2D == null)
  413. throw new ArgumentNullException ("texture2D == null");
  414. if (mat == null)
  415. throw new ArgumentNullException ("mat == null");
  416. #if UNITY_PRO_LICENSE || ((UNITY_ANDROID || UNITY_IOS || UNITY_WEBGL) && !UNITY_EDITOR) || UNITY_5 || UNITY_5_3_OR_NEWER
  417. #if (UNITY_5 && !UNITY_5_0) || UNITY_5_3_OR_NEWER
  418. Utils.copyToMat (texture2D.GetRawTextureData (), mat);
  419. if (flip) {
  420. Core.flip (mat, mat, flipCode);
  421. }
  422. return;
  423. #else
  424. return;
  425. #endif
  426. #else
  427. return;
  428. #endif
  429. }
  430. /**
  431. * Converts Unity WebCamTexture to OpenCV Mat.
  432. * <p>
  433. * <br>This function converts the Unity WebCamTexture image to the OpenCV Mat.
  434. * <br>The Mat object has to be of the same size as the WebCamTexture (width * height).
  435. * <br>The Mat object has to be of the types 'CV_8UC4' (RGBA) , 'CV_8UC3' (RGB) or 'CV_8UC1' (GRAY).
  436. *
  437. * @param webcamTexture a WebCamTexture object.
  438. * @param mat the Mat object has to be of the same size as the WebCamTexture (width * height).
  439. * The Mat object has to be of the types 'CV_8UC4' (RGBA) , 'CV_8UC3' (RGB) or 'CV_8UC1' (GRAY).
  440. * @param flip if true, the mat is fliped after converting.
  441. * @param flipCode a flag to specify how to flip the array; 0 means flipping around the x-axis and positive value (for example, 1) means flipping around y-axis. Negative value (for example, -1) means flipping around both axes.
  442. */
  443. public static void webCamTextureToMat (WebCamTexture webCamTexture, Mat mat, bool flip = true, int flipCode = 0)
  444. {
  445. webCamTextureToMat (webCamTexture, mat, null, flip, flipCode);
  446. }
  447. /**
  448. * Converts Unity WebCamTexture to OpenCV Mat.
  449. * <p>
  450. * <br>This function converts the Unity WebCamTexture image to the OpenCV Mat.
  451. * <br>The Mat object has to be of the same size as the WebCamTexture (width * height).
  452. * <br>The Mat object has to be of the types 'CV_8UC4' (RGBA) , 'CV_8UC3' (RGB) or 'CV_8UC1' (GRAY).
  453. *
  454. * @param webcamTexture a WebCamTexture object.
  455. * @param mat the Mat object has to be of the same size as the WebCamTexture' (width * height).
  456. * The Mat object has to be of the types 'CV_8UC4' (RGBA) , 'CV_8UC3' (RGB) or 'CV_8UC1' (GRAY).
  457. * @param bufferColors the optional array to receive pixel data.
  458. * You can optionally pass in an array of Color32s to use in colors to avoid allocating new memory each frame.
  459. * The array needs to be initialized to a length matching width * height of the texture. (http://docs.unity3d.com/ScriptReference/WebCamTexture.GetPixels32.html)
  460. * @param flip if true, the mat is fliped after converting.
  461. * @param flipCode a flag to specify how to flip the array; 0 means flipping around the x-axis and positive value (for example, 1) means flipping around y-axis. Negative value (for example, -1) means flipping around both axes.
  462. */
  463. public static void webCamTextureToMat (WebCamTexture webCamTexture, Mat mat, Color32[] bufferColors, bool flip = true, int flipCode = 0)
  464. {
  465. if (mat != null)
  466. mat.ThrowIfDisposed ();
  467. if (webCamTexture == null)
  468. throw new ArgumentNullException ("webCamTexture == null");
  469. if (mat == null)
  470. throw new ArgumentNullException ("mat == null");
  471. if (mat.cols () != webCamTexture.width || mat.rows () != webCamTexture.height)
  472. throw new ArgumentException ("The Mat object has to be of the same size");
  473. // byte[] data = new byte[mat.cols () * mat.rows () * mat.channels ()];
  474. //
  475. // Color32[] colors = webCamTexture.GetPixels32 ();
  476. //
  477. // if (mat.type () == CvType.CV_8UC1) {
  478. // for (int i = 0; i < colors.Length; i++) {
  479. // data [i] = colors [i].b;
  480. // }
  481. // mat.put (0, 0, data);
  482. // Core.flip (mat, mat, 0);
  483. // } else if (mat.type () == CvType.CV_8UC3) {
  484. // for (int i = 0; i < colors.Length; i++) {
  485. // data [(i * 3) + 0] = colors [i].r;
  486. // data [(i * 3) + 1] = colors [i].g;
  487. // data [(i * 3) + 2] = colors [i].b;
  488. // }
  489. // mat.put (0, 0, data);
  490. // Core.flip (mat, mat, 0);
  491. // } else if (mat.type () == CvType.CV_8UC4) {
  492. // for (int i = 0; i < colors.Length; i++) {
  493. // data [(i * 4) + 0] = colors [i].r;
  494. // data [(i * 4) + 1] = colors [i].g;
  495. // data [(i * 4) + 2] = colors [i].b;
  496. // data [(i * 4) + 3] = colors [i].a;
  497. // }
  498. // mat.put (0, 0, data);
  499. // Core.flip (mat, mat, 0);
  500. // }
  501. // #if UNITY_PRO_LICENSE || ((UNITY_ANDROID || UNITY_IOS || UNITY_WEBGL) && !UNITY_EDITOR) || UNITY_5 || UNITY_5_3_OR_NEWER
  502. // if(mat.type () == CvType.CV_8UC4){
  503. // OpenCVForUnity_LowLevelTextureToMat (webCamTexture.GetNativeTexturePtr(), webCamTexture.width, webCamTexture.height, mat.nativeObj);
  504. //
  505. // return;
  506. // }
  507. //
  508. // #endif
  509. #if (UNITY_IOS && !UNITY_EDITOR && (UNITY_4_6_3 || UNITY_5_0_0 || UNITY_5_0_1))
  510. if (mat.type () == CvType.CV_8UC4) {
  511. OpenCVForUnity_LowLevelTextureToMat (webCamTexture.GetNativeTexturePtr (), webCamTexture.width, webCamTexture.height, mat.nativeObj);
  512. if (Utils.getLowLevelGraphicsDeviceType() == 16 && Utils.getLowLevelTextureFormat (webCamTexture) == 80) {
  513. Imgproc.cvtColor (mat, mat, Imgproc.COLOR_BGRA2RGBA);
  514. }
  515. Core.flip (mat, mat, 0);
  516. return;
  517. }
  518. #endif
  519. #if UNITY_PRO_LICENSE || ((UNITY_ANDROID || UNITY_IOS || UNITY_WEBGL) && !UNITY_EDITOR) || UNITY_5 || UNITY_5_3_OR_NEWER
  520. GCHandle colorsHandle;
  521. if (bufferColors == null) {
  522. Color32[] colors = webCamTexture.GetPixels32 ();
  523. colorsHandle = GCHandle.Alloc (colors, GCHandleType.Pinned);
  524. } else {
  525. webCamTexture.GetPixels32 (bufferColors);
  526. colorsHandle = GCHandle.Alloc (bufferColors, GCHandleType.Pinned);
  527. }
  528. OpenCVForUnity_TextureToMat (colorsHandle.AddrOfPinnedObject (), mat.nativeObj, flip, flipCode);
  529. colorsHandle.Free ();
  530. #else
  531. return;
  532. #endif
  533. }
  534. /**
  535. * Converts Texture to Texture2D.
  536. * <p>
  537. * <br>This function converts the Texture image to the Texture2D image.
  538. * <br>The texture and texture2D need to be the same size.
  539. * <br>The texture2D's TextureFormat needs to be RGBA32 (Unity5.5+), ARGB32, RGB24, RGBAFloat or RGBAHalf.
  540. *
  541. * @param texture a texture object.
  542. * @param texture2D a texture2D object.
  543. */
  544. public static void textureToTexture2D (Texture texture, Texture2D texture2D)
  545. {
  546. if (texture == null)
  547. throw new ArgumentNullException ("texture == null");
  548. if (texture2D == null)
  549. throw new ArgumentNullException ("texture2D == null");
  550. if (texture.width != texture2D.width || texture.height != texture2D.height)
  551. throw new ArgumentException ("texture and texture2D need to be the same size.");
  552. RenderTexture prevRT = RenderTexture.active;
  553. if (texture is RenderTexture) {
  554. RenderTexture.active = (RenderTexture)texture;
  555. texture2D.ReadPixels (new UnityEngine.Rect (0f, 0f, texture2D.width, texture2D.height), 0, 0, false);
  556. texture2D.Apply (false, false);
  557. } else {
  558. RenderTexture tempRT = RenderTexture.GetTemporary (texture2D.width, texture2D.height, 0, RenderTextureFormat.ARGB32);
  559. Graphics.Blit (texture, tempRT);
  560. RenderTexture.active = tempRT;
  561. texture2D.ReadPixels (new UnityEngine.Rect (0f, 0f, texture2D.width, texture2D.height), 0, 0, false);
  562. texture2D.Apply (false, false);
  563. RenderTexture.ReleaseTemporary (tempRT);
  564. }
  565. RenderTexture.active = prevRT;
  566. }
  567. /**
  568. * Register Plugin on WebGL.
  569. * <p>
  570. * <br>For the WebGL platform, please call this method before calling IntPtrToTextureInRenderThread(), ArrayToTextureInRenderThread() and MatToTextureInRenderThread() methods.
  571. */
  572. public static void registerWebGLPlugin ()
  573. {
  574. #if UNITY_WEBGL && !UNITY_EDITOR
  575. if(isWebGLPluginRegistered)return;
  576. OpenCVForUnity_RegisterPlugin();
  577. isWebGLPluginRegistered = true;
  578. #endif
  579. }
  580. /**
  581. * Copies Pixel Data IntPtr to Texture at render thread.
  582. * <p>
  583. * <br>This function copies the pixel data IntPtr to Texture at render thread.
  584. * <br>The pixel data has to be of the same byte size as the Texture data ([width * height * 4] byte)
  585. * <br>The texture's TextureFormat needs to be 4byte per pixel (RGBA32(Unity5.5+), ARGB32).
  586. *
  587. * @param intPtr the pixel data has to be of the same byte size as the Texture data ([width * height * 4] byte).
  588. * @param texture the texture's TextureFormat needs to be 4byte per pixel (RGBA32(Unity5.5+), ARGB32).
  589. */
  590. public static void intPtrToTextureInRenderThread (IntPtr intPtr, Texture texture)
  591. {
  592. if (intPtr == IntPtr.Zero)
  593. throw new ArgumentNullException ("intPtr == IntPtr.Zero");
  594. if (texture == null)
  595. throw new ArgumentNullException ("texture == null");
  596. #if UNITY_PRO_LICENSE || ((UNITY_ANDROID || UNITY_IOS || UNITY_WEBGL) && !UNITY_EDITOR) || UNITY_5 || UNITY_5_3_OR_NEWER
  597. OpenCVForUnity_SetByteArrayFromUnity (intPtr, 0, 0, 0);
  598. OpenCVForUnity_SetTextureFromUnity (texture.GetNativeTexturePtr (), texture.width, texture.height, 4);
  599. GL.IssuePluginEvent (OpenCVForUnity_GetRenderEventFunc (), 1);
  600. #else
  601. return;
  602. #endif
  603. }
  604. /**
  605. * Copies Pixel Data Array to Texture at render thread.
  606. * <p>
  607. * <br>This function copies the pixel data Array to Texture at render thread.
  608. * <br>The pixel data Array has to be of the same byte size as the Texture data ([width * height * 4] byte)
  609. * <br>The texture's TextureFormat needs to be 4byte per pixel (RGBA32(Unity5.5+), ARGB32).
  610. *
  611. * @param array the pixel data Array has to be of the same byte size as the Texture data ([width * height * 4] byte).
  612. * @param texture the texture's TextureFormat needs to be 4byte per pixel (RGBA32(Unity5.5+), ARGB32).
  613. */
  614. public static void arrayToTextureInRenderThread<T> (IList<T> array, Texture texture)
  615. {
  616. if (array == null)
  617. throw new ArgumentNullException ("array == null");
  618. if (texture == null)
  619. throw new ArgumentNullException ("texture == null");
  620. #if UNITY_PRO_LICENSE || ((UNITY_ANDROID || UNITY_IOS || UNITY_WEBGL) && !UNITY_EDITOR) || UNITY_5 || UNITY_5_3_OR_NEWER
  621. GCHandle arrayHandle = GCHandle.Alloc (array, GCHandleType.Pinned);
  622. OpenCVForUnity_SetByteArrayFromUnity (arrayHandle.AddrOfPinnedObject (), 0, 0, 0);
  623. OpenCVForUnity_SetTextureFromUnity (texture.GetNativeTexturePtr (), texture.width, texture.height, 4);
  624. GL.IssuePluginEvent (OpenCVForUnity_GetRenderEventFunc (), 1);
  625. arrayHandle.Free ();
  626. #else
  627. return;
  628. #endif
  629. }
  630. /**
  631. * Copies OpenCV Mat data to Texture at render thread.
  632. * <p>
  633. * <br>This function copies the OpenCV Mat data to Texture at render thread.
  634. * <br>This method does not flip mat before copying mat to the texture.
  635. * <br>The OpenCV Mat data has to be of the same byte size as the Texture data ([width * height * 4] byte)
  636. * <br>The texture's TextureFormat needs to be 4byte per pixel (RGBA32(Unity5.5+), ARGB32).
  637. *
  638. * @param mat the OpenCV Mat data has to be of the same byte size as the Texture data ([width * height * 4] byte).
  639. * @param texture the texture's TextureFormat needs to be 4byte per pixel (RGBA32(Unity5.5+), ARGB32).
  640. */
  641. public static void matToTextureInRenderThread (Mat mat, Texture texture)
  642. {
  643. if (mat != null)
  644. mat.ThrowIfDisposed ();
  645. if (mat == null)
  646. throw new ArgumentNullException ("mat == null");
  647. if (texture == null)
  648. throw new ArgumentNullException ("texture == null");
  649. if (mat.cols () != texture.width || mat.rows () != texture.height)
  650. throw new ArgumentException ("The Texture object has to be of the same size");
  651. #if UNITY_PRO_LICENSE || ((UNITY_ANDROID || UNITY_IOS || UNITY_WEBGL) && !UNITY_EDITOR) || UNITY_5 || UNITY_5_3_OR_NEWER
  652. if (!mat.isContinuous ()) {
  653. throw new ArgumentException ("mat.isContinuous() must be true.");
  654. }
  655. OpenCVForUnity_SetByteArrayFromUnity ((IntPtr)mat.dataAddr (), mat.width (), mat.height (), (int)mat.elemSize ());
  656. OpenCVForUnity_SetTextureFromUnity (texture.GetNativeTexturePtr (), texture.width, texture.height, 4);
  657. GL.IssuePluginEvent (OpenCVForUnity_GetRenderEventFunc (), 1);
  658. #else
  659. return;
  660. #endif
  661. }
  662. /**
  663. * Gets the readable path of a file in the "StreamingAssets" folder.
  664. * <p>
  665. * <br>Set a relative file path from the starting point of the "StreamingAssets" folder. e.g. "foobar.txt" or "hogehoge/foobar.txt".
  666. * <br>[Android] The target file that exists in the "StreamingAssets" folder is copied into the folder of the Application.persistentDataPath. If refresh flag is false, when the file has already been copied, the file is not copied. If refresh flag is true, the file is always copied.
  667. * <br>[WebGL] If the target file has not yet been copied to WebGL's virtual filesystem, you need to use getFilePathAsync() at first.
  668. *
  669. * @param filepath a relative file path starting from "StreamingAssets" folder.
  670. * @param refresh [Android] If refresh flag is false, when the file has already been copied, the file is not copied. If refresh flag is true, the file is always copied.
  671. * @param timeout [Android 2017.1+] Sets UnityWebRequest to attempt to abort after the number of seconds in timeout has passed. No timeout is applied when timeout is set to 0 and this property defaults to 0.
  672. * @return returns a readable file path in case of success and returns empty in case of error.
  673. */
  674. public static string getFilePath (string filepath, bool refresh = false, int timeout = 0)
  675. {
  676. #if UNITY_ANDROID && !UNITY_EDITOR
  677. filepath = filepath.TrimStart (chTrims);
  678. string srcPath = Path.Combine (Application.streamingAssetsPath, filepath);
  679. string destPath = Path.Combine (Application.persistentDataPath, "opencvforunity");
  680. destPath = Path.Combine (destPath, filepath);
  681. if (!refresh && File.Exists (destPath))
  682. return destPath;
  683. #if UNITY_2017_1_OR_NEWER
  684. using (UnityEngine.Networking.UnityWebRequest request = UnityEngine.Networking.UnityWebRequest.Get (srcPath)) {
  685. request.timeout = timeout;
  686. #if UNITY_2018_2_OR_NEWER
  687. request.SendWebRequest ();
  688. #else
  689. request.Send ();
  690. #endif
  691. while (!request.isDone) {;}
  692. #if UNITY_2017_1_OR_NEWER
  693. if (request.isHttpError || request.isNetworkError) {
  694. #else
  695. if (request.isError) {
  696. #endif
  697. Debug.LogWarning (request.error);
  698. Debug.LogWarning (request.responseCode);
  699. return String.Empty;
  700. }
  701. //create Directory
  702. String dirPath = Path.GetDirectoryName (destPath);
  703. if (!Directory.Exists (dirPath))
  704. Directory.CreateDirectory (dirPath);
  705. File.WriteAllBytes (destPath, request.downloadHandler.data);
  706. }
  707. #else
  708. using (WWW request = new WWW (srcPath)) {
  709. while (!request.isDone) {;}
  710. if (!string.IsNullOrEmpty(request.error)) {
  711. Debug.LogWarning (request.error);
  712. return String.Empty;
  713. }
  714. //create Directory
  715. String dirPath = Path.GetDirectoryName (destPath);
  716. if (!Directory.Exists (dirPath))
  717. Directory.CreateDirectory (dirPath);
  718. File.WriteAllBytes (destPath, request.bytes);
  719. }
  720. #endif
  721. return destPath;
  722. #elif UNITY_WEBGL && !UNITY_EDITOR
  723. filepath = filepath.TrimStart (chTrims);
  724. string destPath = Path.Combine(Path.AltDirectorySeparatorChar.ToString(), "opencvforunity");
  725. destPath = Path.Combine(destPath, filepath);
  726. if (File.Exists(destPath)){
  727. return destPath;
  728. }else{
  729. return String.Empty;
  730. }
  731. #else
  732. filepath = filepath.TrimStart (chTrims);
  733. string destPath = Path.Combine (Application.streamingAssetsPath, filepath);
  734. if (File.Exists (destPath)) {
  735. return destPath;
  736. } else {
  737. return String.Empty;
  738. }
  739. #endif
  740. }
  741. /**
  742. * Gets the multiple readable paths of files in the "StreamingAssets" folder.
  743. * <p>
  744. * <br>Set a relative file path from the starting point of the "StreamingAssets" folder. e.g. "foobar.txt" or "hogehoge/foobar.txt".
  745. * <br>[Android] The target file that exists in the "StreamingAssets" folder is copied into the folder of the Application.persistentDataPath. If refresh flag is false, when the file has already been copied, the file is not copied. If refresh flag is true, the file is always copied.
  746. * <br>[WebGL] If the target file has not yet been copied to WebGL's virtual filesystem, you need to use getFilePathAsync() at first.
  747. *
  748. * @param filepaths an array of relative file paths starting from the "StreamingAssets" folder.
  749. * @param refresh [Android] If refresh flag is false, when the file has already been copied, the file is not copied. If refresh flag is true, the file is always copied.
  750. * @param timeout [Android 2017.1+] Sets UnityWebRequest to attempt to abort after the number of seconds in timeout has passed. No timeout is applied when timeout is set to 0 and this property defaults to 0.
  751. * @return returns an array of readable file paths.
  752. */
  753. public static string[] getMultipleFilePaths (string[] filepaths, bool refresh = false, int timeout = 0)
  754. {
  755. string[] result = new string[filepaths.Length];
  756. for (int i = 0; i < filepaths.Length; i++) {
  757. result [i] = getFilePath (filepaths [i], refresh, timeout);
  758. }
  759. return result;
  760. }
  761. /**
  762. * Gets the readable path of a file in the "StreamingAssets" folder by using coroutines.
  763. * <p>
  764. * <br>Set a relative file path from the starting point of the "StreamingAssets" folder. e.g. "foobar.txt" or "hogehoge/foobar.txt".
  765. * <br>[Android] The target file that exists in the "StreamingAssets" folder is copied into the folder of the Application.persistentDataPath. If refresh flag is false, when the file has already been copied, the file is not copied. If refresh flag is true, the file is always copied.
  766. * <br>[WebGL] The target file in the "StreamingAssets" folder is copied to the WebGL's virtual filesystem. If refresh flag is false, when the file has already been copied, the file is not copied. If refresh flag is true, the file is always copied.
  767. *
  768. * @param filepath a relative file path starting from the "StreamingAssets" folder.
  769. * @param completed a callback function that is called when the process is completed. Returns a readable file path in case of success and returns empty in case of error.
  770. * @param refresh [Android][WebGL] If refresh flag is false, when the file has already been copied, the file is not copied. If refresh flag is true, the file is always copied.
  771. * @param timeout [Android 2017.1+][WebGL] Sets UnityWebRequest to attempt to abort after the number of seconds in timeout has passed. No timeout is applied when timeout is set to 0 and this property defaults to 0.
  772. * @return returns an IEnumerator object. Yielding the IEnumerator inside a coroutine will cause the coroutine to pause until the UnityWebRequest encounters a system error or finishes communicating.
  773. */
  774. public static IEnumerator getFilePathAsync (string filepath, Action<string> completed, bool refresh = false, int timeout = 0)
  775. {
  776. return getFilePathAsync (filepath, completed, null, null, refresh, timeout);
  777. }
  778. /**
  779. * Gets the readable path of a file in the "StreamingAssets" folder by using coroutines.
  780. * <p>
  781. * <br>Set a relative file path from the starting point of the "StreamingAssets" folder. e.g. "foobar.txt" or "hogehoge/foobar.txt".
  782. * <br>[Android] The target file that exists in the "StreamingAssets" folder is copied into the folder of the Application.persistentDataPath. If refresh flag is false, when the file has already been copied, the file is not copied. If refresh flag is true, the file is always copied.
  783. * <br>[WebGL] The target file in the "StreamingAssets" folder is copied to the WebGL's virtual filesystem. If refresh flag is false, when the file has already been copied, the file is not copied. If refresh flag is true, the file is always copied.
  784. *
  785. * @param filepath a relative file path starting from the "StreamingAssets" folder.
  786. * @param completed a callback function that is called when the process is completed. Returns a readable file path in case of success and returns empty in case of error.
  787. * @param progressChanged a callback function that is called when the process is the progress. Returns the file path and a progress value (0.0 to 1.0).
  788. * @param refresh [Android][WebGL] If refresh flag is false, when the file has already been copied, the file is not copied. If refresh flag is true, the file is always copied.
  789. * @param timeout [Android 2017.1+][WebGL] Sets UnityWebRequest to attempt to abort after the number of seconds in timeout has passed. No timeout is applied when timeout is set to 0 and this property defaults to 0.
  790. * @return returns an IEnumerator object. Yielding the IEnumerator inside a coroutine will cause the coroutine to pause until the UnityWebRequest encounters a system error or finishes communicating.
  791. */
  792. public static IEnumerator getFilePathAsync (string filepath, Action<string> completed, Action<string, float> progressChanged, bool refresh = false, int timeout = 0)
  793. {
  794. return getFilePathAsync (filepath, completed, progressChanged, null, refresh, timeout);
  795. }
  796. /**
  797. * Gets the readable path of a file in the "StreamingAssets" folder by using coroutines.
  798. * <p>
  799. * <br>Set a relative file path from the starting point of the "StreamingAssets" folder. e.g. "foobar.txt" or "hogehoge/foobar.txt".
  800. * <br>[Android] The target file that exists in the "StreamingAssets" folder is copied into the folder of the Application.persistentDataPath. If refresh flag is false, when the file has already been copied, the file is not copied. If refresh flag is true, the file is always copied.
  801. * <br>[WebGL] The target file in the "StreamingAssets" folder is copied to the WebGL's virtual filesystem. If refresh flag is false, when the file has already been copied, the file is not copied. If refresh flag is true, the file is always copied.
  802. *
  803. * @param filepath a relative file path starting from the "StreamingAssets" folder.
  804. * @param completed a callback function that is called when the process is completed. Returns a readable file path in case of success and returns empty in case of error.
  805. * @param progressChanged a callback function that is called when the process is the progress. Returns the file path and a progress value (0.0 to 1.0).
  806. * @param errorOccurred a callback function that is called when the process is error occurred. Returns the file path and an error string and an error response code.
  807. * @param refresh [Android][WebGL] If refresh flag is false, when the file has already been copied, the file is not copied. If refresh flag is true, the file is always copied.
  808. * @param timeout [Android 2017.1+][WebGL] Sets UnityWebRequest to attempt to abort after the number of seconds in timeout has passed. No timeout is applied when timeout is set to 0 and this property defaults to 0.
  809. * @return returns an IEnumerator object. Yielding the IEnumerator inside a coroutine will cause the coroutine to pause until the UnityWebRequest encounters a system error or finishes communicating.
  810. */
  811. public static IEnumerator getFilePathAsync (string filepath, Action<string> completed, Action<string, float> progressChanged, Action<string, string, long> errorOccurred, bool refresh = false, int timeout = 0)
  812. {
  813. #if (UNITY_ANDROID || UNITY_WEBGL) && !UNITY_EDITOR
  814. filepath = filepath.TrimStart (chTrims);
  815. string srcPath = Path.Combine(Application.streamingAssetsPath, filepath);
  816. #if UNITY_ANDROID
  817. string destPath = Path.Combine(Application.persistentDataPath, "opencvforunity");
  818. #else
  819. string destPath = Path.Combine(Path.AltDirectorySeparatorChar.ToString(), "opencvforunity");
  820. #endif
  821. destPath = Path.Combine(destPath, filepath);
  822. if (!refresh && File.Exists(destPath)){
  823. if (progressChanged != null)
  824. progressChanged (filepath, 0);
  825. yield return null;
  826. if (progressChanged != null)
  827. progressChanged (filepath, 1);
  828. if (completed != null)
  829. completed (destPath);
  830. } else {
  831. #if UNITY_WEBGL || (UNITY_ANDROID && UNITY_2017_1_OR_NEWER)
  832. using (UnityEngine.Networking.UnityWebRequest request = UnityEngine.Networking.UnityWebRequest.Get (srcPath)) {
  833. request.timeout = timeout;
  834. #if UNITY_2018_2_OR_NEWER
  835. request.SendWebRequest ();
  836. #else
  837. request.Send ();
  838. #endif
  839. while (!request.isDone) {
  840. if (progressChanged != null)
  841. progressChanged (filepath, request.downloadProgress);
  842. yield return null;
  843. }
  844. if (progressChanged != null)
  845. progressChanged (filepath, request.downloadProgress);
  846. #if UNITY_2017_1_OR_NEWER
  847. if (request.isHttpError || request.isNetworkError) {
  848. #else
  849. if (request.isError) {
  850. #endif
  851. Debug.LogWarning (request.error);
  852. Debug.LogWarning (request.responseCode);
  853. if (errorOccurred != null) {
  854. errorOccurred (filepath, request.error, request.responseCode);
  855. } else {
  856. if (completed != null)
  857. completed (String.Empty);
  858. }
  859. yield break;
  860. }
  861. //create Directory
  862. String dirPath = Path.GetDirectoryName (destPath);
  863. if (!Directory.Exists (dirPath))
  864. Directory.CreateDirectory (dirPath);
  865. File.WriteAllBytes (destPath, request.downloadHandler.data);
  866. }
  867. #else
  868. using (WWW request = new WWW (srcPath)) {
  869. while (!request.isDone) {
  870. if (progressChanged != null)
  871. progressChanged(filepath, request.progress);
  872. yield return null;
  873. }
  874. if (progressChanged != null)
  875. progressChanged (filepath, request.progress);
  876. if (!string.IsNullOrEmpty(request.error)) {
  877. Debug.LogWarning (request.error);
  878. if (errorOccurred != null) {
  879. errorOccurred (filepath, request.error, 0);
  880. } else {
  881. if (completed != null)
  882. completed (String.Empty);
  883. }
  884. yield break;
  885. }
  886. //create Directory
  887. String dirPath = Path.GetDirectoryName (destPath);
  888. if (!Directory.Exists (dirPath))
  889. Directory.CreateDirectory (dirPath);
  890. File.WriteAllBytes(destPath, request.bytes);
  891. }
  892. #endif
  893. if (completed != null)
  894. completed (destPath);
  895. }
  896. #else
  897. filepath = filepath.TrimStart (chTrims);
  898. string destPath = Path.Combine (Application.streamingAssetsPath, filepath);
  899. if (progressChanged != null)
  900. progressChanged (filepath, 0);
  901. yield return null;
  902. if (progressChanged != null)
  903. progressChanged (filepath, 1);
  904. if (File.Exists (destPath)) {
  905. if (completed != null)
  906. completed (destPath);
  907. } else {
  908. if (errorOccurred != null) {
  909. errorOccurred (filepath, "Unknown Error", 0);
  910. } else {
  911. if (completed != null)
  912. completed (String.Empty);
  913. }
  914. }
  915. #endif
  916. yield break;
  917. }
  918. /**
  919. * Gets the multiple readable paths of files in the "StreamingAssets" folder by using coroutines.
  920. * <p>
  921. * <br>Set a relative file path from the starting point of the "StreamingAssets" folder. e.g. "foobar.txt" or "hogehoge/foobar.txt".
  922. * <br>[Android] The target file that exists in the "StreamingAssets" folder is copied into the folder of the Application.persistentDataPath. If refresh flag is false, when the file has already been copied, the file is not copied. If refresh flag is true, the file is always copied.
  923. * <br>[WebGL] The target file in the "StreamingAssets" folder is copied to the WebGL's virtual filesystem. If refresh flag is false, when the file has already been copied, the file is not copied. If refresh flag is true, the file is always copied.
  924. *
  925. * @param filepaths an array of relative file paths starting from the "StreamingAssets" folder.
  926. * @param allCompleted a callback function that is called when the process is completed. Returns an array of readable file paths.
  927. * @param refresh [Android][WebGL] If refresh flag is false, when the file has already been copied, the file is not copied. If refresh flag is true, the file is always copied.
  928. * @param timeout [Android 2017.1+][WebGL] Sets UnityWebRequest to attempt to abort after the number of seconds in timeout has passed. No timeout is applied when timeout is set to 0 and this property defaults to 0.
  929. * @return returns an IEnumerator object. Yielding the IEnumerator inside a coroutine will cause the coroutine to pause until the UnityWebRequest encounters a system error or finishes communicating.
  930. */
  931. public static IEnumerator getMultipleFilePathsAsync (string[] filepaths, Action<string[]> allCompleted, bool refresh = false, int timeout = 0)
  932. {
  933. return getMultipleFilePathsAsync (filepaths, allCompleted, null, null, refresh, timeout);
  934. }
  935. /**
  936. * Gets the multiple readable paths of files in the "StreamingAssets" folder by using coroutines.
  937. * <p>
  938. * <br>Set a relative file path from the starting point of the "StreamingAssets" folder. e.g. "foobar.txt" or "hogehoge/foobar.txt".
  939. * <br>[Android] The target file that exists in the "StreamingAssets" folder is copied into the folder of the Application.persistentDataPath. If refresh flag is false, when the file has already been copied, the file is not copied. If refresh flag is true, the file is always copied.
  940. * <br>[WebGL] The target file in the "StreamingAssets" folder is copied to the WebGL's virtual filesystem. If refresh flag is false, when the file has already been copied, the file is not copied. If refresh flag is true, the file is always copied.
  941. *
  942. * @param filepaths an array of relative file paths starting from the "StreamingAssets" folder.
  943. * @param allCompleted a callback function that is called when the process is completed. Returns an array of readable file paths.
  944. * @param progressChanged a callback function that is called when the process is the progress. Returns the file path and a progress value (0.0 to 1.0).
  945. * @param refresh [Android][WebGL] If refresh flag is false, when the file has already been copied, the file is not copied. If refresh flag is true, the file is always copied.
  946. * @param timeout [Android 2017.1+][WebGL] Sets UnityWebRequest to attempt to abort after the number of seconds in timeout has passed. No timeout is applied when timeout is set to 0 and this property defaults to 0.
  947. * @return returns an IEnumerator object. Yielding the IEnumerator inside a coroutine will cause the coroutine to pause until the UnityWebRequest encounters a system error or finishes communicating.
  948. */
  949. public static IEnumerator getMultipleFilePathsAsync (string[] filepaths, Action<string[]> allCompleted, Action<string, float> progressChanged, bool refresh = false, int timeout = 0)
  950. {
  951. return getMultipleFilePathsAsync (filepaths, allCompleted, progressChanged, null, refresh, timeout);
  952. }
  953. /**
  954. * Gets the multiple readable paths of files in the "StreamingAssets" folder by using coroutines.
  955. * <p>
  956. * <br>Set a relative file path from the starting point of the "StreamingAssets" folder. e.g. "foobar.txt" or "hogehoge/foobar.txt".
  957. * <br>[Android] The target file that exists in the "StreamingAssets" folder is copied into the folder of the Application.persistentDataPath. If refresh flag is false, when the file has already been copied, the file is not copied. If refresh flag is true, the file is always copied.
  958. * <br>[WebGL] The target file in the "StreamingAssets" folder is copied to the WebGL's virtual filesystem. If refresh flag is false, when the file has already been copied, the file is not copied. If refresh flag is true, the file is always copied.
  959. *
  960. * @param filepaths an array of relative file paths starting from the "StreamingAssets" folder.
  961. * @param allCompleted a callback function that is called when the process is completed. Returns an array of readable file paths.
  962. * @param progressChanged a callback function that is called when the process is the progress. Returns the file path and a progress value (0.0 to 1.0).
  963. * @param errorOccurred a callback function that is called when the process is error occurred. Returns the file path and an error string and an error response code.
  964. * @param refresh [Android][WebGL] If refresh flag is false, when the file has already been copied, the file is not copied. If refresh flag is true, the file is always copied.
  965. * @param timeout [Android 2017.1+][WebGL] Sets UnityWebRequest to attempt to abort after the number of seconds in timeout has passed. No timeout is applied when timeout is set to 0 and this property defaults to 0.
  966. * @return returns an IEnumerator object. Yielding the IEnumerator inside a coroutine will cause the coroutine to pause until the UnityWebRequest encounters a system error or finishes communicating.
  967. */
  968. public static IEnumerator getMultipleFilePathsAsync (string[] filepaths, Action<string[]> allCompleted, Action<string, float> progressChanged, Action<string, string, long> errorOccurred, bool refresh = false, int timeout = 0)
  969. {
  970. string[] readableFilePaths = new string[filepaths.Length];
  971. for (int i = 0; i < filepaths.Length; i++) {
  972. yield return getFilePathAsync (filepaths [i], (result) => {
  973. readableFilePaths [i] = result;
  974. }, progressChanged, errorOccurred, refresh, timeout);
  975. }
  976. if (allCompleted != null)
  977. allCompleted (readableFilePaths);
  978. }
  979. private static char[] chTrims = {
  980. '.',
  981. #if UNITY_WINRT_8_1 && !UNITY_EDITOR
  982. '/',
  983. '\\'
  984. #else
  985. System.IO.Path.DirectorySeparatorChar,
  986. System.IO.Path.AltDirectorySeparatorChar
  987. #endif
  988. };
  989. /// <summary>
  990. /// if true, CvException is thrown instead of calling Debug.LogError (msg).
  991. /// </summary>
  992. #pragma warning disable 0414
  993. private static bool throwOpenCVException = false;
  994. #pragma warning restore 0414
  995. /**
  996. * Sets the debug mode.
  997. * <p>
  998. * <br>if debugMode is true, The error log of the Native side OpenCV will be displayed on the Unity Editor Console.However, if throwException is true, CvException is thrown instead of calling Debug.LogError (msg).
  999. * <br>Please use as follows.
  1000. * <br>Utils.setDebugMode(true);
  1001. * <br>aaa
  1002. * <br>bbb
  1003. * <br>ccc
  1004. * <br>Utils.setDebugMode(false);
  1005. *
  1006. * @param debugMode if true, The error log of the Native side OpenCV will be displayed on the Unity Editor Console.
  1007. * @param throwException if true, CvException is thrown instead of calling Debug.LogError (msg).
  1008. */
  1009. public static void setDebugMode (bool debugMode, bool throwException = false)
  1010. {
  1011. #if (UNITY_PRO_LICENSE || UNITY_5 || UNITY_5_3_OR_NEWER)
  1012. OpenCVForUnity_SetDebugMode (debugMode);
  1013. if (debugMode) {
  1014. OpenCVForUnity_SetDebugLogFunc (debugLogFunc);
  1015. // OpenCVForUnity_DebugLogTest ();
  1016. } else {
  1017. OpenCVForUnity_SetDebugLogFunc (null);
  1018. }
  1019. throwOpenCVException = throwException;
  1020. #endif
  1021. }
  1022. #if (UNITY_PRO_LICENSE || UNITY_5 || UNITY_5_3_OR_NEWER)
  1023. private delegate void DebugLogDelegate (string str);
  1024. [MonoPInvokeCallback (typeof(DebugLogDelegate))]
  1025. private static void debugLogFunc (string str)
  1026. {
  1027. if (throwOpenCVException) {
  1028. throw new CvException (str);
  1029. } else {
  1030. Debug.LogError (str);
  1031. }
  1032. }
  1033. #endif
  1034. internal static int URShift (int number, int bits)
  1035. {
  1036. if (number >= 0)
  1037. return number >> bits;
  1038. else
  1039. return (number >> bits) + (2 << ~bits);
  1040. }
  1041. internal static long URShift (long number, int bits)//TODO:@check
  1042. {
  1043. if (number >= 0)
  1044. return number >> bits;
  1045. else
  1046. return (number >> bits) + (2 << ~bits);
  1047. }
  1048. internal static int HashContents<T> (this IEnumerable<T> enumerable)//TODO:@check
  1049. {
  1050. int hash = 0x218A9B2C;
  1051. foreach (var item in enumerable) {
  1052. int thisHash = item.GetHashCode ();
  1053. //mix up the bits.
  1054. hash = thisHash ^ ((hash << 5) + hash);
  1055. }
  1056. return hash;
  1057. }
  1058. #if (UNITY_IOS || UNITY_WEBGL) && !UNITY_EDITOR
  1059. const string LIBNAME = "__Internal";
  1060. #else
  1061. const string LIBNAME = "opencvforunity";
  1062. #endif
  1063. [DllImport (LIBNAME)]
  1064. private static extern void OpenCVForUnity_SetDebugMode (bool flag);
  1065. [DllImport (LIBNAME)]
  1066. private static extern void OpenCVForUnity_SetDebugLogFunc (DebugLogDelegate func);
  1067. [DllImport (LIBNAME)]
  1068. private static extern void OpenCVForUnity_DebugLogTest ();
  1069. [DllImport (LIBNAME)]
  1070. private static extern void OpenCVForUnity_MatToTexture (IntPtr mat, IntPtr textureColors, bool flip, int flipCode, bool flipAfter);
  1071. [DllImport (LIBNAME)]
  1072. private static extern void OpenCVForUnity_TextureToMat (IntPtr textureColors, IntPtr Mat, bool flip, int flipCode);
  1073. [DllImport (LIBNAME)]
  1074. private static extern void OpenCVForUnity_MatDataToByteArray (IntPtr mat, IntPtr byteArray);
  1075. [DllImport (LIBNAME)]
  1076. private static extern void OpenCVForUnity_ByteArrayToMatData (IntPtr byteArray, IntPtr Mat);
  1077. [DllImport (LIBNAME)]
  1078. private static extern void OpenCVForUnity_SetTextureFromUnity (System.IntPtr texture, int width, int height, int bytesPerPixel);
  1079. [DllImport (LIBNAME)]
  1080. private static extern void OpenCVForUnity_SetByteArrayFromUnity (System.IntPtr byteArray, int width, int height, int bytesPerPixel);
  1081. [DllImport (LIBNAME)]
  1082. private static extern IntPtr OpenCVForUnity_GetRenderEventFunc ();
  1083. #if UNITY_WEBGL && !UNITY_EDITOR
  1084. private static bool isWebGLPluginRegistered = false;
  1085. [DllImport(LIBNAME)]
  1086. private static extern void OpenCVForUnity_RegisterPlugin();
  1087. #endif
  1088. }
  1089. }