HikVisionAlgorithmRelated.cs 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Drawing;
  4. using System.Drawing.Imaging;
  5. using System.Linq;
  6. using System.Runtime.InteropServices;
  7. using System.Text;
  8. using System.Threading.Tasks;
  9. using VisionDesigner;
  10. namespace MvvmScaffoldFrame48.DLL.ImageAlgorithm
  11. {
  12. public static class HikVisionAlgorithmRelated
  13. {
  14. /// <summary>
  15. /// Bitmap转MVDImage
  16. /// </summary>
  17. /// <param name="cBitmapImg"></param>
  18. /// <param name="cMvdImg"></param>
  19. /// <exception cref="MvdException"></exception>
  20. public static void ConvertBitmap2MVDImage(Bitmap cBitmapImg, CMvdImage cMvdImg)
  21. {
  22. // 参数合法性判断
  23. if (null == cBitmapImg || null == cMvdImg)
  24. {
  25. throw new MvdException(MVD_MODULE_TYPE.MVD_MODUL_APP, MVD_ERROR_CODE.MVD_E_PARAMETER_ILLEGAL);
  26. }
  27. // 判断像素格式
  28. if (PixelFormat.Format8bppIndexed != cBitmapImg.PixelFormat && PixelFormat.Format24bppRgb != cBitmapImg.PixelFormat)
  29. {
  30. throw new MvdException(MVD_MODULE_TYPE.MVD_MODUL_APP, MVD_ERROR_CODE.MVD_E_SUPPORT);
  31. }
  32. Int32 nImageWidth = cBitmapImg.Width;
  33. Int32 nImageHeight = cBitmapImg.Height;
  34. Int32 nChannelNum = 0;
  35. BitmapData bitmapData = null;
  36. try
  37. {
  38. // 获取图像信息
  39. if (PixelFormat.Format8bppIndexed == cBitmapImg.PixelFormat) // 灰度图
  40. {
  41. bitmapData = cBitmapImg.LockBits(new Rectangle(0, 0, nImageWidth, nImageHeight)
  42. , ImageLockMode.ReadOnly
  43. , PixelFormat.Format8bppIndexed);
  44. cMvdImg.InitImage(Convert.ToUInt32(nImageWidth), Convert.ToUInt32(nImageHeight), MVD_PIXEL_FORMAT.MVD_PIXEL_MONO_08);
  45. nChannelNum = 1;
  46. }
  47. else if (PixelFormat.Format24bppRgb == cBitmapImg.PixelFormat) // 彩色图
  48. {
  49. bitmapData = cBitmapImg.LockBits(new Rectangle(0, 0, nImageWidth, nImageHeight)
  50. , ImageLockMode.ReadOnly
  51. , PixelFormat.Format24bppRgb);
  52. cMvdImg.InitImage(Convert.ToUInt32(nImageWidth), Convert.ToUInt32(nImageHeight), MVD_PIXEL_FORMAT.MVD_PIXEL_RGB_RGB24_C3);
  53. nChannelNum = 3;
  54. }
  55. // 考虑图像是否4字节对齐,bitmap要求4字节对齐,而mvdimage不要求对齐
  56. if (0 == nImageWidth % 4) // 4字节对齐时,直接拷贝
  57. {
  58. Marshal.Copy(bitmapData.Scan0, cMvdImg.GetImageData().stDataChannel[0].arrDataBytes, 0, nImageWidth * nImageHeight * nChannelNum);
  59. }
  60. else // 按步长逐行拷贝
  61. {
  62. // 每行实际占用字节数
  63. Int32 nRowPixelByteNum = nImageWidth * nChannelNum + 4 - (nImageWidth * nChannelNum % 4);
  64. // 每行首字节首地址
  65. IntPtr bitmapDataRowPos = IntPtr.Zero;
  66. for (int i = 0; i < nImageHeight; i++)
  67. {
  68. // 获取每行第一个像素值的首地址
  69. bitmapDataRowPos = new IntPtr(bitmapData.Scan0.ToInt64() + nRowPixelByteNum * i);
  70. Marshal.Copy(bitmapDataRowPos, cMvdImg.GetImageData().stDataChannel[0].arrDataBytes, i * nImageWidth * nChannelNum, nImageWidth * nChannelNum);
  71. }
  72. }
  73. // bitmap彩色图按BGR存储,而MVDimg按RGB存储,改变存储顺序
  74. // 交换R和B
  75. if (PixelFormat.Format24bppRgb == cBitmapImg.PixelFormat)
  76. {
  77. byte bTemp;
  78. byte[] bMvdImgData = cMvdImg.GetImageData().stDataChannel[0].arrDataBytes;
  79. for (int i = 0; i < nImageWidth * nImageHeight; i++)
  80. {
  81. bTemp = bMvdImgData[3 * i];
  82. bMvdImgData[3 * i] = bMvdImgData[3 * i + 2];
  83. bMvdImgData[3 * i + 2] = bTemp;
  84. }
  85. }
  86. }
  87. finally
  88. {
  89. cBitmapImg.UnlockBits(bitmapData);
  90. }
  91. }
  92. /// <summary>
  93. /// MVDImage转Bitmap
  94. /// </summary>
  95. /// <param name="cMvdImg"></param>
  96. /// <param name="cBitmapImg"></param>
  97. /// <exception cref="MvdException"></exception>
  98. public static void ConvertMVDImage2Bitmap(CMvdImage cMvdImg, ref Bitmap cBitmapImg)
  99. {
  100. // 参数合法性判断
  101. if (null == cMvdImg)
  102. {
  103. throw new MvdException(MVD_MODULE_TYPE.MVD_MODUL_APP, MVD_ERROR_CODE.MVD_E_PARAMETER_ILLEGAL);
  104. }
  105. // 判断像素格式
  106. if (MVD_PIXEL_FORMAT.MVD_PIXEL_MONO_08 != cMvdImg.PixelFormat && MVD_PIXEL_FORMAT.MVD_PIXEL_RGB_RGB24_C3 != cMvdImg.PixelFormat)
  107. {
  108. throw new MvdException(MVD_MODULE_TYPE.MVD_MODUL_APP, MVD_ERROR_CODE.MVD_E_SUPPORT);
  109. }
  110. Int32 nImageWidth = Convert.ToInt32(cMvdImg.Width);
  111. Int32 nImageHeight = Convert.ToInt32(cMvdImg.Height);
  112. Int32 nChannelNum = 0;
  113. BitmapData bitmapData = null;
  114. byte[] bBitmapDataTemp = null;
  115. try
  116. {
  117. // 获取图像信息
  118. if (MVD_PIXEL_FORMAT.MVD_PIXEL_MONO_08 == cMvdImg.PixelFormat) // 灰度图
  119. {
  120. cBitmapImg = new Bitmap(nImageWidth, nImageHeight, PixelFormat.Format8bppIndexed);
  121. // 灰度图需指定调色板
  122. ColorPalette colorPalette = cBitmapImg.Palette;
  123. for (int j = 0; j < 256; j++)
  124. {
  125. colorPalette.Entries[j] = Color.FromArgb(j, j, j);
  126. }
  127. cBitmapImg.Palette = colorPalette;
  128. bitmapData = cBitmapImg.LockBits(new Rectangle(0, 0, nImageWidth, nImageHeight)
  129. , ImageLockMode.WriteOnly
  130. , PixelFormat.Format8bppIndexed);
  131. // 灰度图不做深拷贝
  132. bBitmapDataTemp = cMvdImg.GetImageData().stDataChannel[0].arrDataBytes;
  133. nChannelNum = 1;
  134. }
  135. else if (MVD_PIXEL_FORMAT.MVD_PIXEL_RGB_RGB24_C3 == cMvdImg.PixelFormat) // 彩色图
  136. {
  137. cBitmapImg = new Bitmap(nImageWidth, nImageHeight, PixelFormat.Format24bppRgb);
  138. bitmapData = cBitmapImg.LockBits(new Rectangle(0, 0, nImageWidth, nImageHeight)
  139. , ImageLockMode.WriteOnly
  140. , PixelFormat.Format24bppRgb);
  141. // 彩色图做深拷贝
  142. bBitmapDataTemp = new byte[cMvdImg.GetImageData().stDataChannel[0].nLen];
  143. Array.Copy(cMvdImg.GetImageData().stDataChannel[0].arrDataBytes, bBitmapDataTemp, bBitmapDataTemp.Length);
  144. nChannelNum = 3;
  145. }
  146. // bitmap彩色图按BGR存储,而MVDimg按RGB存储,改变存储顺序
  147. // 交换R和B
  148. if (MVD_PIXEL_FORMAT.MVD_PIXEL_RGB_RGB24_C3 == cMvdImg.PixelFormat)
  149. {
  150. byte bTemp;
  151. for (int i = 0; i < nImageWidth * nImageHeight; i++)
  152. {
  153. bTemp = bBitmapDataTemp[3 * i];
  154. bBitmapDataTemp[3 * i] = bBitmapDataTemp[3 * i + 2];
  155. bBitmapDataTemp[3 * i + 2] = bTemp;
  156. }
  157. }
  158. // 考虑图像是否4字节对齐,bitmap要求4字节对齐,而mvdimage不要求对齐
  159. if (0 == nImageWidth % 4) // 4字节对齐时,直接拷贝
  160. {
  161. Marshal.Copy(bBitmapDataTemp, 0, bitmapData.Scan0, nImageWidth * nImageHeight * nChannelNum);
  162. }
  163. else // 按步长逐行拷贝
  164. {
  165. // 每行实际占用字节数
  166. Int32 nRowPixelByteNum = nImageWidth * nChannelNum + 4 - (nImageWidth * nChannelNum % 4);
  167. // 每行首字节首地址
  168. IntPtr bitmapDataRowPos = IntPtr.Zero;
  169. for (int i = 0; i < nImageHeight; i++)
  170. {
  171. // 获取每行第一个像素值的首地址
  172. bitmapDataRowPos = new IntPtr(bitmapData.Scan0.ToInt64() + nRowPixelByteNum * i);
  173. Marshal.Copy(bBitmapDataTemp, i * nImageWidth * nChannelNum, bitmapDataRowPos, nImageWidth * nChannelNum);
  174. }
  175. }
  176. cBitmapImg.UnlockBits(bitmapData);
  177. }
  178. catch (MvdException ex)
  179. {
  180. if (null != cBitmapImg)
  181. {
  182. cBitmapImg.UnlockBits(bitmapData);
  183. cBitmapImg.Dispose();
  184. cBitmapImg = null;
  185. }
  186. throw ex;
  187. }
  188. catch (System.Exception ex)
  189. {
  190. if (null != cBitmapImg)
  191. {
  192. cBitmapImg.UnlockBits(bitmapData);
  193. cBitmapImg.Dispose();
  194. cBitmapImg = null;
  195. }
  196. throw ex;
  197. }
  198. }
  199. /// <summary>
  200. /// 加载图片(从文件)
  201. /// </summary>
  202. /// <param name="LoadImagePath"></param>
  203. public static CMvdImage LoadImage(string LoadImagePath)
  204. {
  205. CMvdImage m_stInputImage = null;
  206. try
  207. {
  208. if (!string.IsNullOrEmpty(LoadImagePath))
  209. {
  210. if (null == m_stInputImage)
  211. {
  212. m_stInputImage = new CMvdImage();
  213. }
  214. m_stInputImage.InitImage(LoadImagePath);
  215. Console.WriteLine("Finish loading image from [" + LoadImagePath + "].");
  216. }
  217. }
  218. catch (MvdException ex)
  219. {
  220. Console.WriteLine("Fail to load image from [" + LoadImagePath + "]. ErrorCode: 0x" + ex.ErrorCode.ToString("X"));
  221. }
  222. catch (Exception ex)
  223. {
  224. Console.WriteLine("Fail to load image from [" + LoadImagePath + "]. Error: " + ex.Message);
  225. }
  226. return m_stInputImage;
  227. }
  228. /// <summary>
  229. /// 加载图片(从Bitmap)
  230. /// </summary>
  231. /// <param name="bitmap"></param>
  232. public static CMvdImage LoadImage(Bitmap bitmap)
  233. {
  234. CMvdImage m_stInputImage = null;
  235. try
  236. {
  237. if (bitmap != null)
  238. {
  239. if (null == m_stInputImage)
  240. {
  241. m_stInputImage = new CMvdImage();
  242. }
  243. //m_stInputImage.InitImage(bitmap);
  244. ConvertBitmap2MVDImage(bitmap, m_stInputImage);
  245. Console.WriteLine("Finish loading image from [BitMap].");
  246. }
  247. }
  248. catch (MvdException ex)
  249. {
  250. Console.WriteLine("Fail to load image from [BitMap]. ErrorCode: 0x" + ex.ErrorCode.ToString("X"));
  251. }
  252. catch (Exception ex)
  253. {
  254. Console.WriteLine("Fail to load image from [BitMap]. Error: " + ex.Message);
  255. }
  256. return m_stInputImage;
  257. }
  258. }
  259. }