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 { /// /// Bitmap转MVDImage /// /// /// /// 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); } } /// /// MVDImage转Bitmap /// /// /// /// 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; } } /// /// 加载图片(从文件) /// /// public static CMvdImage LoadImage(string LoadImagePath) { CMvdImage m_stInputImage = null; try { if (!string.IsNullOrEmpty(LoadImagePath)) { if (null == m_stInputImage) { m_stInputImage = new CMvdImage(); } m_stInputImage.InitImage(LoadImagePath); Console.WriteLine("Finish loading image from [" + LoadImagePath + "]."); } } catch (MvdException ex) { Console.WriteLine("Fail to load image from [" + LoadImagePath + "]. ErrorCode: 0x" + ex.ErrorCode.ToString("X")); } catch (Exception ex) { Console.WriteLine("Fail to load image from [" + LoadImagePath + "]. Error: " + ex.Message); } return m_stInputImage; } /// /// 加载图片(从Bitmap) /// /// public static CMvdImage LoadImage(Bitmap bitmap) { CMvdImage m_stInputImage = null; try { if (bitmap != null) { if (null == m_stInputImage) { m_stInputImage = new CMvdImage(); } //m_stInputImage.InitImage(bitmap); ConvertBitmap2MVDImage(bitmap, m_stInputImage); Console.WriteLine("Finish loading image from [BitMap]."); } } catch (MvdException ex) { Console.WriteLine("Fail to load image from [BitMap]. ErrorCode: 0x" + ex.ErrorCode.ToString("X")); } catch (Exception ex) { Console.WriteLine("Fail to load image from [BitMap]. Error: " + ex.Message); } return m_stInputImage; } } }