geboshi_V1/LeatherProject/LeatherApp/Device/CamerUtil/BufferToImage.cs

194 lines
7.3 KiB
C#
Raw Normal View History

2024-03-07 14:03:22 +08:00
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);
}
}
}