革博士V2程序
Вы не можете выбрать более 25 тем Темы должны начинаться с буквы или цифры, могут содержать дефисы(-) и должны содержать не более 35 символов.

1 год назад
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using System.Text;
  5. using System.Threading.Tasks;
  6. using System.Runtime.InteropServices;
  7. using System.IO;
  8. using System.Drawing;
  9. using System.Drawing.Imaging;
  10. namespace LeatherApp.Device.CamerUtil
  11. {
  12. class BufferToImage
  13. {
  14. [DllImport("kernel32.dll")]
  15. public static extern void CopyMemory(IntPtr Destination, IntPtr Source, int Length);
  16. // 缓冲区句柄
  17. public IntPtr m_pBuffer = new IntPtr(-1);
  18. // 缓冲区锁
  19. public object m_mutexBuffer = new object();
  20. // Bitmap锁
  21. public object m_mutexBitmap = new object();
  22. // 缓冲区大小
  23. public int m_nBufferSize = -1;
  24. // 像素位数
  25. public int m_nDepth = -1;
  26. // 图像通道数
  27. public int m_nChannels = -1;
  28. // 图像宽度
  29. public int m_nWidth = -1;
  30. // 图像高度
  31. public int m_nHeight = -1;
  32. // Bitmap
  33. public Bitmap m_bmp = null;
  34. /*
  35. * @brief: 构造函数
  36. * @param [in] nSize: 缓冲区大小
  37. * @param [in] nDepth: 像素位数
  38. * @param [in] nChannels: 图像通道数
  39. * @param [in] nWidth: 图像宽度
  40. * @param [in] nHeight: 图像高度
  41. *
  42. */
  43. public BufferToImage(int nSize, int nDepth, int nChannels, int nWidth, int nHeight)
  44. {
  45. m_pBuffer = Marshal.AllocHGlobal(nSize);
  46. m_nBufferSize = nSize;
  47. m_nDepth = nDepth;
  48. m_nChannels = nChannels;
  49. m_nWidth = nWidth;
  50. m_nHeight = nHeight;
  51. PixelFormat nPixelFormat = PixelFormat.Undefined;
  52. switch (nChannels)
  53. {
  54. case 1:
  55. nPixelFormat = PixelFormat.Format8bppIndexed;
  56. break;
  57. case 3:
  58. case 4:
  59. nPixelFormat = PixelFormat.Format24bppRgb;
  60. break;
  61. }
  62. m_bmp = new Bitmap(m_nWidth, m_nHeight, nPixelFormat);
  63. // 如果是灰度图像需要设置调色盘
  64. if (nPixelFormat == System.Drawing.Imaging.PixelFormat.Format8bppIndexed)
  65. {
  66. ColorPalette cp = m_bmp.Palette;
  67. for (int i = 0; i < 256; i++)
  68. cp.Entries[i] = System.Drawing.Color.FromArgb(i, i, i);
  69. m_bmp.Palette = cp;
  70. }
  71. }
  72. /*
  73. * @brief: 释放缓冲区
  74. * @return:
  75. */
  76. public void freeBuffer()
  77. {
  78. if (m_pBuffer != new IntPtr(-1))
  79. Marshal.FreeHGlobal(m_pBuffer);
  80. if (m_bmp != null)
  81. m_bmp.Dispose();
  82. m_bmp = null;
  83. }
  84. /*
  85. * @brief:将源缓冲区的图像数据转为Image
  86. * @param [in] pSrc: 源缓冲区指针
  87. * @return: Image
  88. */
  89. public Bitmap toBmp(IntPtr pSrc)
  90. {
  91. lock (m_mutexBitmap)
  92. {
  93. lock (m_mutexBuffer)
  94. {
  95. CopyMemory(m_pBuffer, pSrc, m_nBufferSize);
  96. if (m_nChannels == 4)
  97. {
  98. readRGBC();
  99. return (Bitmap)m_bmp.Clone();
  100. }
  101. Rectangle rect = new Rectangle(0, 0, m_bmp.Width, m_bmp.Height);
  102. BitmapData bitmapData = m_bmp.LockBits(rect, ImageLockMode.ReadWrite, m_bmp.PixelFormat);
  103. int nShift = m_nDepth - 8;
  104. int nStride = m_nBufferSize / m_bmp.Height;
  105. // 8bit 像素直接拷贝,高于8位的去除低位
  106. if (m_nDepth == 8)
  107. {
  108. for (int i = 0; i < m_bmp.Height; i++)
  109. {
  110. IntPtr iptrDst = bitmapData.Scan0 + bitmapData.Stride * i;
  111. IntPtr iptrSrc = m_pBuffer + nStride * i;
  112. CopyMemory(iptrDst, iptrSrc, nStride);
  113. }
  114. m_bmp.UnlockBits(bitmapData);
  115. }
  116. else
  117. {
  118. short[] pData = new short[m_nBufferSize / 2];
  119. byte[] pDstData = new byte[m_nBufferSize];
  120. nStride = bitmapData.Stride;
  121. Marshal.Copy(m_pBuffer, pData, 0, m_nBufferSize / 2);
  122. for (int i = 0; i < bitmapData.Height; i++)
  123. {
  124. for (int j = 0; j < nStride; j++)
  125. {
  126. pDstData[i * nStride + j] = (byte)(pData[i * nStride + j] >> nShift);
  127. }
  128. }
  129. Marshal.Copy(pDstData, 0, bitmapData.Scan0, (m_nBufferSize / 2));
  130. m_bmp.UnlockBits(bitmapData);
  131. }
  132. return (Bitmap)m_bmp.Clone();
  133. }
  134. }
  135. }
  136. public Image toImage(IntPtr pSrc)
  137. {
  138. return (Image)toBmp(pSrc);
  139. }
  140. /*
  141. * @brief: 转换四通道图像数据,仅保留RGB通道数据
  142. * @return:
  143. */
  144. public void readRGBC()
  145. {
  146. Rectangle rect = new Rectangle(0, 0, m_bmp.Width, m_bmp.Height);
  147. BitmapData bitmapData = m_bmp.LockBits(rect, ImageLockMode.ReadWrite, m_bmp.PixelFormat);
  148. int nShift = m_nDepth - 8;
  149. int nStride = bitmapData.Stride;
  150. int nCount = 0;
  151. byte[] pByteData = new byte[m_nBufferSize];
  152. byte[] pDstData = new byte[(m_nBufferSize * 3) / 4];
  153. Marshal.Copy(m_pBuffer, pByteData, 0, m_nBufferSize);
  154. if (m_nDepth == 8)
  155. {
  156. for (int i = 0; i < m_bmp.Height; i++)
  157. {
  158. for (int j = 0; j < nStride; j = j + 3)
  159. {
  160. pDstData[i * nStride + j] = (byte)(pByteData[nCount]);
  161. pDstData[i * nStride + j + 1] = (byte)(pByteData[nCount + 1]);
  162. pDstData[i * nStride + j + 2] = (byte)(pByteData[nCount + 2]);
  163. nCount += 4;
  164. }
  165. }
  166. Marshal.Copy(pDstData, 0, bitmapData.Scan0, (m_nBufferSize * 3 / 4));
  167. m_bmp.UnlockBits(bitmapData);
  168. return;
  169. }
  170. short[] pShortData = new short[m_nBufferSize / 2];
  171. Marshal.Copy(m_pBuffer, pShortData, 0, m_nBufferSize / 2);
  172. for (int i = 0; i < bitmapData.Height; i++)
  173. {
  174. for (int j = 0; j < nStride; j = j + 3)
  175. {
  176. pDstData[i * nStride + j] = (byte)(pShortData[nCount] >> nShift);
  177. pDstData[i * nStride + j + 1] = (byte)(pShortData[nCount + 1] >> nShift);
  178. pDstData[i * nStride + j + 2] = (byte)(pShortData[nCount + 2] >> nShift);
  179. nCount += 4;
  180. }
  181. }
  182. Marshal.Copy(pDstData, 0, bitmapData.Scan0, (m_nBufferSize * 3 / 8));
  183. m_bmp.UnlockBits(bitmapData);
  184. }
  185. }
  186. }