HikVisionAlgorithmRelated.cs 9.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203
  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. public static void ConvertBitmap2MVDImage(Bitmap cBitmapImg, CMvdImage cMvdImg)
  15. {
  16. // 参数合法性判断
  17. if (null == cBitmapImg || null == cMvdImg)
  18. {
  19. throw new MvdException(MVD_MODULE_TYPE.MVD_MODUL_APP, MVD_ERROR_CODE.MVD_E_PARAMETER_ILLEGAL);
  20. }
  21. // 判断像素格式
  22. if (PixelFormat.Format8bppIndexed != cBitmapImg.PixelFormat && PixelFormat.Format24bppRgb != cBitmapImg.PixelFormat)
  23. {
  24. throw new MvdException(MVD_MODULE_TYPE.MVD_MODUL_APP, MVD_ERROR_CODE.MVD_E_SUPPORT);
  25. }
  26. Int32 nImageWidth = cBitmapImg.Width;
  27. Int32 nImageHeight = cBitmapImg.Height;
  28. Int32 nChannelNum = 0;
  29. BitmapData bitmapData = null;
  30. try
  31. {
  32. // 获取图像信息
  33. if (PixelFormat.Format8bppIndexed == cBitmapImg.PixelFormat) // 灰度图
  34. {
  35. bitmapData = cBitmapImg.LockBits(new Rectangle(0, 0, nImageWidth, nImageHeight)
  36. , ImageLockMode.ReadOnly
  37. , PixelFormat.Format8bppIndexed);
  38. cMvdImg.InitImage(Convert.ToUInt32(nImageWidth), Convert.ToUInt32(nImageHeight), MVD_PIXEL_FORMAT.MVD_PIXEL_MONO_08);
  39. nChannelNum = 1;
  40. }
  41. else if (PixelFormat.Format24bppRgb == cBitmapImg.PixelFormat) // 彩色图
  42. {
  43. bitmapData = cBitmapImg.LockBits(new Rectangle(0, 0, nImageWidth, nImageHeight)
  44. , ImageLockMode.ReadOnly
  45. , PixelFormat.Format24bppRgb);
  46. cMvdImg.InitImage(Convert.ToUInt32(nImageWidth), Convert.ToUInt32(nImageHeight), MVD_PIXEL_FORMAT.MVD_PIXEL_RGB_RGB24_C3);
  47. nChannelNum = 3;
  48. }
  49. // 考虑图像是否4字节对齐,bitmap要求4字节对齐,而mvdimage不要求对齐
  50. if (0 == nImageWidth % 4) // 4字节对齐时,直接拷贝
  51. {
  52. Marshal.Copy(bitmapData.Scan0, cMvdImg.GetImageData().stDataChannel[0].arrDataBytes, 0, nImageWidth * nImageHeight * nChannelNum);
  53. }
  54. else // 按步长逐行拷贝
  55. {
  56. // 每行实际占用字节数
  57. Int32 nRowPixelByteNum = nImageWidth * nChannelNum + 4 - (nImageWidth * nChannelNum % 4);
  58. // 每行首字节首地址
  59. IntPtr bitmapDataRowPos = IntPtr.Zero;
  60. for (int i = 0; i < nImageHeight; i++)
  61. {
  62. // 获取每行第一个像素值的首地址
  63. bitmapDataRowPos = new IntPtr(bitmapData.Scan0.ToInt64() + nRowPixelByteNum * i);
  64. Marshal.Copy(bitmapDataRowPos, cMvdImg.GetImageData().stDataChannel[0].arrDataBytes, i * nImageWidth * nChannelNum, nImageWidth * nChannelNum);
  65. }
  66. }
  67. // bitmap彩色图按BGR存储,而MVDimg按RGB存储,改变存储顺序
  68. // 交换R和B
  69. if (PixelFormat.Format24bppRgb == cBitmapImg.PixelFormat)
  70. {
  71. byte bTemp;
  72. byte[] bMvdImgData = cMvdImg.GetImageData().stDataChannel[0].arrDataBytes;
  73. for (int i = 0; i < nImageWidth * nImageHeight; i++)
  74. {
  75. bTemp = bMvdImgData[3 * i];
  76. bMvdImgData[3 * i] = bMvdImgData[3 * i + 2];
  77. bMvdImgData[3 * i + 2] = bTemp;
  78. }
  79. }
  80. }
  81. finally
  82. {
  83. cBitmapImg.UnlockBits(bitmapData);
  84. }
  85. }
  86. public static void ConvertMVDImage2Bitmap(CMvdImage cMvdImg, ref Bitmap cBitmapImg)
  87. {
  88. // 参数合法性判断
  89. if (null == cMvdImg)
  90. {
  91. throw new MvdException(MVD_MODULE_TYPE.MVD_MODUL_APP, MVD_ERROR_CODE.MVD_E_PARAMETER_ILLEGAL);
  92. }
  93. // 判断像素格式
  94. if (MVD_PIXEL_FORMAT.MVD_PIXEL_MONO_08 != cMvdImg.PixelFormat && MVD_PIXEL_FORMAT.MVD_PIXEL_RGB_RGB24_C3 != cMvdImg.PixelFormat)
  95. {
  96. throw new MvdException(MVD_MODULE_TYPE.MVD_MODUL_APP, MVD_ERROR_CODE.MVD_E_SUPPORT);
  97. }
  98. Int32 nImageWidth = Convert.ToInt32(cMvdImg.Width);
  99. Int32 nImageHeight = Convert.ToInt32(cMvdImg.Height);
  100. Int32 nChannelNum = 0;
  101. BitmapData bitmapData = null;
  102. byte[] bBitmapDataTemp = null;
  103. try
  104. {
  105. // 获取图像信息
  106. if (MVD_PIXEL_FORMAT.MVD_PIXEL_MONO_08 == cMvdImg.PixelFormat) // 灰度图
  107. {
  108. cBitmapImg = new Bitmap(nImageWidth, nImageHeight, PixelFormat.Format8bppIndexed);
  109. // 灰度图需指定调色板
  110. ColorPalette colorPalette = cBitmapImg.Palette;
  111. for (int j = 0; j < 256; j++)
  112. {
  113. colorPalette.Entries[j] = Color.FromArgb(j, j, j);
  114. }
  115. cBitmapImg.Palette = colorPalette;
  116. bitmapData = cBitmapImg.LockBits(new Rectangle(0, 0, nImageWidth, nImageHeight)
  117. , ImageLockMode.WriteOnly
  118. , PixelFormat.Format8bppIndexed);
  119. // 灰度图不做深拷贝
  120. bBitmapDataTemp = cMvdImg.GetImageData().stDataChannel[0].arrDataBytes;
  121. nChannelNum = 1;
  122. }
  123. else if (MVD_PIXEL_FORMAT.MVD_PIXEL_RGB_RGB24_C3 == cMvdImg.PixelFormat) // 彩色图
  124. {
  125. cBitmapImg = new Bitmap(nImageWidth, nImageHeight, PixelFormat.Format24bppRgb);
  126. bitmapData = cBitmapImg.LockBits(new Rectangle(0, 0, nImageWidth, nImageHeight)
  127. , ImageLockMode.WriteOnly
  128. , PixelFormat.Format24bppRgb);
  129. // 彩色图做深拷贝
  130. bBitmapDataTemp = new byte[cMvdImg.GetImageData().stDataChannel[0].nLen];
  131. Array.Copy(cMvdImg.GetImageData().stDataChannel[0].arrDataBytes, bBitmapDataTemp, bBitmapDataTemp.Length);
  132. nChannelNum = 3;
  133. }
  134. // bitmap彩色图按BGR存储,而MVDimg按RGB存储,改变存储顺序
  135. // 交换R和B
  136. if (MVD_PIXEL_FORMAT.MVD_PIXEL_RGB_RGB24_C3 == cMvdImg.PixelFormat)
  137. {
  138. byte bTemp;
  139. for (int i = 0; i < nImageWidth * nImageHeight; i++)
  140. {
  141. bTemp = bBitmapDataTemp[3 * i];
  142. bBitmapDataTemp[3 * i] = bBitmapDataTemp[3 * i + 2];
  143. bBitmapDataTemp[3 * i + 2] = bTemp;
  144. }
  145. }
  146. // 考虑图像是否4字节对齐,bitmap要求4字节对齐,而mvdimage不要求对齐
  147. if (0 == nImageWidth % 4) // 4字节对齐时,直接拷贝
  148. {
  149. Marshal.Copy(bBitmapDataTemp, 0, bitmapData.Scan0, nImageWidth * nImageHeight * nChannelNum);
  150. }
  151. else // 按步长逐行拷贝
  152. {
  153. // 每行实际占用字节数
  154. Int32 nRowPixelByteNum = nImageWidth * nChannelNum + 4 - (nImageWidth * nChannelNum % 4);
  155. // 每行首字节首地址
  156. IntPtr bitmapDataRowPos = IntPtr.Zero;
  157. for (int i = 0; i < nImageHeight; i++)
  158. {
  159. // 获取每行第一个像素值的首地址
  160. bitmapDataRowPos = new IntPtr(bitmapData.Scan0.ToInt64() + nRowPixelByteNum * i);
  161. Marshal.Copy(bBitmapDataTemp, i * nImageWidth * nChannelNum, bitmapDataRowPos, nImageWidth * nChannelNum);
  162. }
  163. }
  164. cBitmapImg.UnlockBits(bitmapData);
  165. }
  166. catch (MvdException ex)
  167. {
  168. if (null != cBitmapImg)
  169. {
  170. cBitmapImg.UnlockBits(bitmapData);
  171. cBitmapImg.Dispose();
  172. cBitmapImg = null;
  173. }
  174. throw ex;
  175. }
  176. catch (System.Exception ex)
  177. {
  178. if (null != cBitmapImg)
  179. {
  180. cBitmapImg.UnlockBits(bitmapData);
  181. cBitmapImg.Dispose();
  182. cBitmapImg = null;
  183. }
  184. throw ex;
  185. }
  186. }
  187. }
  188. }