using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Runtime.InteropServices; using System.IO; using System.Drawing; using System.Drawing.Imaging; namespace LeatherApp.Device.CamerUtil { class BufferToImage { [DllImport("kernel32.dll")] public static extern void CopyMemory(IntPtr Destination, IntPtr Source, int Length); // 缓冲区句柄 public IntPtr m_pBuffer = new IntPtr(-1); // 缓冲区锁 public object m_mutexBuffer = new object(); // Bitmap锁 public object m_mutexBitmap = new object(); // 缓冲区大小 public int m_nBufferSize = -1; // 像素位数 public int m_nDepth = -1; // 图像通道数 public int m_nChannels = -1; // 图像宽度 public int m_nWidth = -1; // 图像高度 public int m_nHeight = -1; // Bitmap public Bitmap m_bmp = null; /* * @brief: 构造函数 * @param [in] nSize: 缓冲区大小 * @param [in] nDepth: 像素位数 * @param [in] nChannels: 图像通道数 * @param [in] nWidth: 图像宽度 * @param [in] nHeight: 图像高度 * */ public BufferToImage(int nSize, int nDepth, int nChannels, int nWidth, int nHeight) { m_pBuffer = Marshal.AllocHGlobal(nSize); m_nBufferSize = nSize; m_nDepth = nDepth; m_nChannels = nChannels; m_nWidth = nWidth; m_nHeight = nHeight; PixelFormat nPixelFormat = PixelFormat.Undefined; switch (nChannels) { case 1: nPixelFormat = PixelFormat.Format8bppIndexed; break; case 3: case 4: nPixelFormat = PixelFormat.Format24bppRgb; break; } m_bmp = new Bitmap(m_nWidth, m_nHeight, nPixelFormat); // 如果是灰度图像需要设置调色盘 if (nPixelFormat == System.Drawing.Imaging.PixelFormat.Format8bppIndexed) { ColorPalette cp = m_bmp.Palette; for (int i = 0; i < 256; i++) cp.Entries[i] = System.Drawing.Color.FromArgb(i, i, i); m_bmp.Palette = cp; } } /* * @brief: 释放缓冲区 * @return: */ public void freeBuffer() { if (m_pBuffer != new IntPtr(-1)) Marshal.FreeHGlobal(m_pBuffer); if (m_bmp != null) m_bmp.Dispose(); m_bmp = null; } /* * @brief:将源缓冲区的图像数据转为Image * @param [in] pSrc: 源缓冲区指针 * @return: Image */ public Bitmap toBmp(IntPtr pSrc) { lock (m_mutexBitmap) { lock (m_mutexBuffer) { CopyMemory(m_pBuffer, pSrc, m_nBufferSize); if (m_nChannels == 4) { readRGBC(); return (Bitmap)m_bmp.Clone(); } Rectangle rect = new Rectangle(0, 0, m_bmp.Width, m_bmp.Height); BitmapData bitmapData = m_bmp.LockBits(rect, ImageLockMode.ReadWrite, m_bmp.PixelFormat); int nShift = m_nDepth - 8; int nStride = m_nBufferSize / m_bmp.Height; // 8bit 像素直接拷贝,高于8位的去除低位 if (m_nDepth == 8) { for (int i = 0; i < m_bmp.Height; i++) { IntPtr iptrDst = bitmapData.Scan0 + bitmapData.Stride * i; IntPtr iptrSrc = m_pBuffer + nStride * i; CopyMemory(iptrDst, iptrSrc, nStride); } m_bmp.UnlockBits(bitmapData); } else { short[] pData = new short[m_nBufferSize / 2]; byte[] pDstData = new byte[m_nBufferSize]; nStride = bitmapData.Stride; Marshal.Copy(m_pBuffer, pData, 0, m_nBufferSize / 2); for (int i = 0; i < bitmapData.Height; i++) { for (int j = 0; j < nStride; j++) { pDstData[i * nStride + j] = (byte)(pData[i * nStride + j] >> nShift); } } Marshal.Copy(pDstData, 0, bitmapData.Scan0, (m_nBufferSize / 2)); m_bmp.UnlockBits(bitmapData); } return (Bitmap)m_bmp.Clone(); } } } public Image toImage(IntPtr pSrc) { return (Image)toBmp(pSrc); } /* * @brief: 转换四通道图像数据,仅保留RGB通道数据 * @return: */ public void readRGBC() { Rectangle rect = new Rectangle(0, 0, m_bmp.Width, m_bmp.Height); BitmapData bitmapData = m_bmp.LockBits(rect, ImageLockMode.ReadWrite, m_bmp.PixelFormat); int nShift = m_nDepth - 8; int nStride = bitmapData.Stride; int nCount = 0; byte[] pByteData = new byte[m_nBufferSize]; byte[] pDstData = new byte[(m_nBufferSize * 3) / 4]; Marshal.Copy(m_pBuffer, pByteData, 0, m_nBufferSize); if (m_nDepth == 8) { for (int i = 0; i < m_bmp.Height; i++) { for (int j = 0; j < nStride; j = j + 3) { pDstData[i * nStride + j] = (byte)(pByteData[nCount]); pDstData[i * nStride + j + 1] = (byte)(pByteData[nCount + 1]); pDstData[i * nStride + j + 2] = (byte)(pByteData[nCount + 2]); nCount += 4; } } Marshal.Copy(pDstData, 0, bitmapData.Scan0, (m_nBufferSize * 3 / 4)); m_bmp.UnlockBits(bitmapData); return; } short[] pShortData = new short[m_nBufferSize / 2]; Marshal.Copy(m_pBuffer, pShortData, 0, m_nBufferSize / 2); for (int i = 0; i < bitmapData.Height; i++) { for (int j = 0; j < nStride; j = j + 3) { pDstData[i * nStride + j] = (byte)(pShortData[nCount] >> nShift); pDstData[i * nStride + j + 1] = (byte)(pShortData[nCount + 1] >> nShift); pDstData[i * nStride + j + 2] = (byte)(pShortData[nCount + 2] >> nShift); nCount += 4; } } Marshal.Copy(pDstData, 0, bitmapData.Scan0, (m_nBufferSize * 3 / 8)); m_bmp.UnlockBits(bitmapData); } } }