194 lines
7.3 KiB
C#
194 lines
7.3 KiB
C#
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);
|
||
}
|
||
}
|
||
} |