|
|
@@ -0,0 +1,203 @@
|
|
|
+using System;
|
|
|
+using System.Collections.Generic;
|
|
|
+using System.Drawing;
|
|
|
+using System.Drawing.Imaging;
|
|
|
+using System.Linq;
|
|
|
+using System.Runtime.InteropServices;
|
|
|
+using System.Text;
|
|
|
+using System.Threading.Tasks;
|
|
|
+using VisionDesigner;
|
|
|
+
|
|
|
+namespace MvvmScaffoldFrame48.DLL.ImageAlgorithm
|
|
|
+{
|
|
|
+ public static class HikVisionAlgorithmRelated
|
|
|
+ {
|
|
|
+ public static void ConvertBitmap2MVDImage(Bitmap cBitmapImg, CMvdImage cMvdImg)
|
|
|
+ {
|
|
|
+ // 参数合法性判断
|
|
|
+ if (null == cBitmapImg || null == cMvdImg)
|
|
|
+ {
|
|
|
+ throw new MvdException(MVD_MODULE_TYPE.MVD_MODUL_APP, MVD_ERROR_CODE.MVD_E_PARAMETER_ILLEGAL);
|
|
|
+ }
|
|
|
+
|
|
|
+ // 判断像素格式
|
|
|
+ if (PixelFormat.Format8bppIndexed != cBitmapImg.PixelFormat && PixelFormat.Format24bppRgb != cBitmapImg.PixelFormat)
|
|
|
+ {
|
|
|
+ throw new MvdException(MVD_MODULE_TYPE.MVD_MODUL_APP, MVD_ERROR_CODE.MVD_E_SUPPORT);
|
|
|
+ }
|
|
|
+
|
|
|
+ Int32 nImageWidth = cBitmapImg.Width;
|
|
|
+ Int32 nImageHeight = cBitmapImg.Height;
|
|
|
+ Int32 nChannelNum = 0;
|
|
|
+ BitmapData bitmapData = null;
|
|
|
+
|
|
|
+ try
|
|
|
+ {
|
|
|
+ // 获取图像信息
|
|
|
+ if (PixelFormat.Format8bppIndexed == cBitmapImg.PixelFormat) // 灰度图
|
|
|
+ {
|
|
|
+ bitmapData = cBitmapImg.LockBits(new Rectangle(0, 0, nImageWidth, nImageHeight)
|
|
|
+ , ImageLockMode.ReadOnly
|
|
|
+ , PixelFormat.Format8bppIndexed);
|
|
|
+ cMvdImg.InitImage(Convert.ToUInt32(nImageWidth), Convert.ToUInt32(nImageHeight), MVD_PIXEL_FORMAT.MVD_PIXEL_MONO_08);
|
|
|
+ nChannelNum = 1;
|
|
|
+ }
|
|
|
+ else if (PixelFormat.Format24bppRgb == cBitmapImg.PixelFormat) // 彩色图
|
|
|
+ {
|
|
|
+ bitmapData = cBitmapImg.LockBits(new Rectangle(0, 0, nImageWidth, nImageHeight)
|
|
|
+ , ImageLockMode.ReadOnly
|
|
|
+ , PixelFormat.Format24bppRgb);
|
|
|
+ cMvdImg.InitImage(Convert.ToUInt32(nImageWidth), Convert.ToUInt32(nImageHeight), MVD_PIXEL_FORMAT.MVD_PIXEL_RGB_RGB24_C3);
|
|
|
+ nChannelNum = 3;
|
|
|
+ }
|
|
|
+
|
|
|
+ // 考虑图像是否4字节对齐,bitmap要求4字节对齐,而mvdimage不要求对齐
|
|
|
+ if (0 == nImageWidth % 4) // 4字节对齐时,直接拷贝
|
|
|
+ {
|
|
|
+ Marshal.Copy(bitmapData.Scan0, cMvdImg.GetImageData().stDataChannel[0].arrDataBytes, 0, nImageWidth * nImageHeight * nChannelNum);
|
|
|
+ }
|
|
|
+ else // 按步长逐行拷贝
|
|
|
+ {
|
|
|
+ // 每行实际占用字节数
|
|
|
+ Int32 nRowPixelByteNum = nImageWidth * nChannelNum + 4 - (nImageWidth * nChannelNum % 4);
|
|
|
+ // 每行首字节首地址
|
|
|
+ IntPtr bitmapDataRowPos = IntPtr.Zero;
|
|
|
+ for (int i = 0; i < nImageHeight; i++)
|
|
|
+ {
|
|
|
+ // 获取每行第一个像素值的首地址
|
|
|
+ bitmapDataRowPos = new IntPtr(bitmapData.Scan0.ToInt64() + nRowPixelByteNum * i);
|
|
|
+ Marshal.Copy(bitmapDataRowPos, cMvdImg.GetImageData().stDataChannel[0].arrDataBytes, i * nImageWidth * nChannelNum, nImageWidth * nChannelNum);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // bitmap彩色图按BGR存储,而MVDimg按RGB存储,改变存储顺序
|
|
|
+ // 交换R和B
|
|
|
+ if (PixelFormat.Format24bppRgb == cBitmapImg.PixelFormat)
|
|
|
+ {
|
|
|
+ byte bTemp;
|
|
|
+ byte[] bMvdImgData = cMvdImg.GetImageData().stDataChannel[0].arrDataBytes;
|
|
|
+ for (int i = 0; i < nImageWidth * nImageHeight; i++)
|
|
|
+ {
|
|
|
+ bTemp = bMvdImgData[3 * i];
|
|
|
+ bMvdImgData[3 * i] = bMvdImgData[3 * i + 2];
|
|
|
+ bMvdImgData[3 * i + 2] = bTemp;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ finally
|
|
|
+ {
|
|
|
+ cBitmapImg.UnlockBits(bitmapData);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ public static void ConvertMVDImage2Bitmap(CMvdImage cMvdImg, ref Bitmap cBitmapImg)
|
|
|
+ {
|
|
|
+ // 参数合法性判断
|
|
|
+ if (null == cMvdImg)
|
|
|
+ {
|
|
|
+ throw new MvdException(MVD_MODULE_TYPE.MVD_MODUL_APP, MVD_ERROR_CODE.MVD_E_PARAMETER_ILLEGAL);
|
|
|
+ }
|
|
|
+
|
|
|
+ // 判断像素格式
|
|
|
+ if (MVD_PIXEL_FORMAT.MVD_PIXEL_MONO_08 != cMvdImg.PixelFormat && MVD_PIXEL_FORMAT.MVD_PIXEL_RGB_RGB24_C3 != cMvdImg.PixelFormat)
|
|
|
+ {
|
|
|
+ throw new MvdException(MVD_MODULE_TYPE.MVD_MODUL_APP, MVD_ERROR_CODE.MVD_E_SUPPORT);
|
|
|
+ }
|
|
|
+
|
|
|
+ Int32 nImageWidth = Convert.ToInt32(cMvdImg.Width);
|
|
|
+ Int32 nImageHeight = Convert.ToInt32(cMvdImg.Height);
|
|
|
+ Int32 nChannelNum = 0;
|
|
|
+ BitmapData bitmapData = null;
|
|
|
+ byte[] bBitmapDataTemp = null;
|
|
|
+ try
|
|
|
+ {
|
|
|
+ // 获取图像信息
|
|
|
+ if (MVD_PIXEL_FORMAT.MVD_PIXEL_MONO_08 == cMvdImg.PixelFormat) // 灰度图
|
|
|
+ {
|
|
|
+ cBitmapImg = new Bitmap(nImageWidth, nImageHeight, PixelFormat.Format8bppIndexed);
|
|
|
+
|
|
|
+ // 灰度图需指定调色板
|
|
|
+ ColorPalette colorPalette = cBitmapImg.Palette;
|
|
|
+ for (int j = 0; j < 256; j++)
|
|
|
+ {
|
|
|
+ colorPalette.Entries[j] = Color.FromArgb(j, j, j);
|
|
|
+ }
|
|
|
+ cBitmapImg.Palette = colorPalette;
|
|
|
+
|
|
|
+ bitmapData = cBitmapImg.LockBits(new Rectangle(0, 0, nImageWidth, nImageHeight)
|
|
|
+ , ImageLockMode.WriteOnly
|
|
|
+ , PixelFormat.Format8bppIndexed);
|
|
|
+
|
|
|
+ // 灰度图不做深拷贝
|
|
|
+ bBitmapDataTemp = cMvdImg.GetImageData().stDataChannel[0].arrDataBytes;
|
|
|
+ nChannelNum = 1;
|
|
|
+ }
|
|
|
+ else if (MVD_PIXEL_FORMAT.MVD_PIXEL_RGB_RGB24_C3 == cMvdImg.PixelFormat) // 彩色图
|
|
|
+ {
|
|
|
+ cBitmapImg = new Bitmap(nImageWidth, nImageHeight, PixelFormat.Format24bppRgb);
|
|
|
+ bitmapData = cBitmapImg.LockBits(new Rectangle(0, 0, nImageWidth, nImageHeight)
|
|
|
+ , ImageLockMode.WriteOnly
|
|
|
+ , PixelFormat.Format24bppRgb);
|
|
|
+ // 彩色图做深拷贝
|
|
|
+ bBitmapDataTemp = new byte[cMvdImg.GetImageData().stDataChannel[0].nLen];
|
|
|
+ Array.Copy(cMvdImg.GetImageData().stDataChannel[0].arrDataBytes, bBitmapDataTemp, bBitmapDataTemp.Length);
|
|
|
+ nChannelNum = 3;
|
|
|
+ }
|
|
|
+
|
|
|
+ // bitmap彩色图按BGR存储,而MVDimg按RGB存储,改变存储顺序
|
|
|
+ // 交换R和B
|
|
|
+ if (MVD_PIXEL_FORMAT.MVD_PIXEL_RGB_RGB24_C3 == cMvdImg.PixelFormat)
|
|
|
+ {
|
|
|
+ byte bTemp;
|
|
|
+ for (int i = 0; i < nImageWidth * nImageHeight; i++)
|
|
|
+ {
|
|
|
+ bTemp = bBitmapDataTemp[3 * i];
|
|
|
+ bBitmapDataTemp[3 * i] = bBitmapDataTemp[3 * i + 2];
|
|
|
+ bBitmapDataTemp[3 * i + 2] = bTemp;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // 考虑图像是否4字节对齐,bitmap要求4字节对齐,而mvdimage不要求对齐
|
|
|
+ if (0 == nImageWidth % 4) // 4字节对齐时,直接拷贝
|
|
|
+ {
|
|
|
+ Marshal.Copy(bBitmapDataTemp, 0, bitmapData.Scan0, nImageWidth * nImageHeight * nChannelNum);
|
|
|
+ }
|
|
|
+ else // 按步长逐行拷贝
|
|
|
+ {
|
|
|
+ // 每行实际占用字节数
|
|
|
+ Int32 nRowPixelByteNum = nImageWidth * nChannelNum + 4 - (nImageWidth * nChannelNum % 4);
|
|
|
+ // 每行首字节首地址
|
|
|
+ IntPtr bitmapDataRowPos = IntPtr.Zero;
|
|
|
+ for (int i = 0; i < nImageHeight; i++)
|
|
|
+ {
|
|
|
+ // 获取每行第一个像素值的首地址
|
|
|
+ bitmapDataRowPos = new IntPtr(bitmapData.Scan0.ToInt64() + nRowPixelByteNum * i);
|
|
|
+ Marshal.Copy(bBitmapDataTemp, i * nImageWidth * nChannelNum, bitmapDataRowPos, nImageWidth * nChannelNum);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ cBitmapImg.UnlockBits(bitmapData);
|
|
|
+ }
|
|
|
+ catch (MvdException ex)
|
|
|
+ {
|
|
|
+ if (null != cBitmapImg)
|
|
|
+ {
|
|
|
+ cBitmapImg.UnlockBits(bitmapData);
|
|
|
+ cBitmapImg.Dispose();
|
|
|
+ cBitmapImg = null;
|
|
|
+ }
|
|
|
+ throw ex;
|
|
|
+ }
|
|
|
+ catch (System.Exception ex)
|
|
|
+ {
|
|
|
+ if (null != cBitmapImg)
|
|
|
+ {
|
|
|
+ cBitmapImg.UnlockBits(bitmapData);
|
|
|
+ cBitmapImg.Dispose();
|
|
|
+ cBitmapImg = null;
|
|
|
+ }
|
|
|
+ throw ex;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|