视觉修改
This commit is contained in:
		
							
								
								
									
										502
									
								
								Check.Main/Camera/HikvisionCamera.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										502
									
								
								Check.Main/Camera/HikvisionCamera.cs
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,502 @@ | ||||
| using MvCamCtrl.NET; | ||||
| using Sunny.UI; | ||||
| using System; | ||||
| using System.Collections.Generic; | ||||
| using System.Drawing; | ||||
| using System.Drawing.Imaging; | ||||
| using System.IO; | ||||
| using System.Linq; | ||||
| using System.Runtime.InteropServices; | ||||
| using System.Text; | ||||
| using System.Threading; | ||||
| using System.Threading.Tasks; | ||||
|  | ||||
| namespace Check.Main.Camera | ||||
| { | ||||
|     public class HikvisionCamera : IDisposable | ||||
|     { | ||||
|         [DllImport("kernel32.dll", EntryPoint = "RtlMoveMemory", SetLastError = false)] | ||||
|         private static extern void CopyMemory(IntPtr dest, IntPtr src, uint count); | ||||
|         // 事件委托 | ||||
|         public delegate void ImageAcquiredEventHandler(HikvisionCamera sender, Bitmap bmp); | ||||
|         // public delegate void ImageAcquiredEventHandler(object sender, Bitmap bmp); | ||||
|         public delegate void CameraMessageEventHandler(object sender, string message, int errorCode = 0); | ||||
|  | ||||
|         // 事件 | ||||
|         public event ImageAcquiredEventHandler ImageAcquired; | ||||
|         public event CameraMessageEventHandler CameraMessage; | ||||
|  | ||||
|         // 私有成员变量 | ||||
|         private MyCamera m_MyCamera; | ||||
|         private MyCamera.MV_CC_DEVICE_INFO_LIST m_stDeviceList; | ||||
|         private bool m_bGrabbing = false; | ||||
|         private Thread m_hReceiveThread = null; | ||||
|  | ||||
|         private Bitmap m_bitmap = null; | ||||
|         private IntPtr m_ConvertDstBuf = IntPtr.Zero; | ||||
|         private uint m_nConvertDstBufLen = 0; | ||||
|         public string Name { get; set; } | ||||
|  | ||||
|         /// <summary> | ||||
|         /// 由外部逻辑分配的、唯一的相机软件编号。 | ||||
|         /// 主要用作图像路由和与逻辑处理器匹配的键。 | ||||
|         /// </summary> | ||||
|         public int CameraIndex { get; set; } | ||||
|  | ||||
|         /// <summary> | ||||
|         /// 相机是否已经打开 | ||||
|         /// </summary> | ||||
|         public bool IsOpen { get; private set; } = false; | ||||
|  | ||||
|         public TriggerModeType TriggerMode { get; internal set; } // internal set 保证只有 CameraManager 能设置它 | ||||
|  | ||||
|  | ||||
|         /// <summary> | ||||
|         /// 相机是否正在采集 | ||||
|         /// </summary> | ||||
|         public bool IsGrabbing => m_bGrabbing; | ||||
|  | ||||
|         public HikvisionCamera() | ||||
|         { | ||||
|             // 初始化SDK | ||||
|             MyCamera.MV_CC_Initialize_NET(); | ||||
|         } | ||||
|  | ||||
|         /// <summary> | ||||
|         /// 查找所有可用的相机设备 | ||||
|         /// </summary> | ||||
|         /// <returns>设备名称列表</returns> | ||||
|         public List<string> FindDevices() | ||||
|         { | ||||
|             var deviceList = new List<string>(); | ||||
|             m_stDeviceList = new MyCamera.MV_CC_DEVICE_INFO_LIST(); | ||||
|             int nRet = MyCamera.MV_CC_EnumDevices_NET(MyCamera.MV_GIGE_DEVICE | MyCamera.MV_USB_DEVICE, ref m_stDeviceList); | ||||
|             if (nRet != MyCamera.MV_OK) | ||||
|             { | ||||
|                 OnCameraMessage("设备枚举失败!", nRet); | ||||
|                 return deviceList; | ||||
|             } | ||||
|  | ||||
|             for (int i = 0; i < m_stDeviceList.nDeviceNum; i++) | ||||
|             { | ||||
|                 var device = (MyCamera.MV_CC_DEVICE_INFO)Marshal.PtrToStructure(m_stDeviceList.pDeviceInfo[i], typeof(MyCamera.MV_CC_DEVICE_INFO)); | ||||
|                 if (device.nTLayerType == MyCamera.MV_GIGE_DEVICE) | ||||
|                 { | ||||
|                     var gigeInfo = (MyCamera.MV_GIGE_DEVICE_INFO_EX)MyCamera.ByteToStruct(device.SpecialInfo.stGigEInfo, typeof(MyCamera.MV_GIGE_DEVICE_INFO_EX)); | ||||
|                     if (!string.IsNullOrEmpty(Encoding.Default.GetString(gigeInfo.chUserDefinedName).TrimEnd('\0'))) | ||||
|                         deviceList.Add("GEV: " + gigeInfo.chUserDefinedName + " (" + gigeInfo.chSerialNumber + ")"); | ||||
|                     else | ||||
|                         deviceList.Add("GEV: " + gigeInfo.chManufacturerName + " " + gigeInfo.chModelName + " (" + gigeInfo.chSerialNumber + ")"); | ||||
|                 } | ||||
|                 else if (device.nTLayerType == MyCamera.MV_USB_DEVICE) | ||||
|                 { | ||||
|                     var usbInfo = (MyCamera.MV_USB3_DEVICE_INFO_EX)MyCamera.ByteToStruct(device.SpecialInfo.stUsb3VInfo, typeof(MyCamera.MV_USB3_DEVICE_INFO_EX)); | ||||
|                     if (!string.IsNullOrEmpty(Encoding.Default.GetString(usbInfo.chUserDefinedName).TrimEnd('\0'))) | ||||
|                         deviceList.Add("U3V: " + usbInfo.chUserDefinedName + " (" + usbInfo.chSerialNumber + ")"); | ||||
|                     else | ||||
|                         deviceList.Add("U3V: " + usbInfo.chManufacturerName + " " + usbInfo.chModelName + " (" + usbInfo.chSerialNumber + ")"); | ||||
|                 } | ||||
|             } | ||||
|             return deviceList; | ||||
|         } | ||||
|  | ||||
|         /// <summary> | ||||
|         /// 根据索引打开相机 | ||||
|         /// </summary> | ||||
|         /// <param name="index">设备索引</param> | ||||
|         /// <returns>成功返回true,否则返回false</returns> | ||||
|         public bool Open(CameraSettings camConfig) | ||||
|         { | ||||
|             string ipCam = ""; | ||||
|             string ipDevice = ""; | ||||
|             FindDevices(); | ||||
|             if (camConfig.IsEnabled == true) | ||||
|             { | ||||
|                 ipCam = camConfig.IPAddress; | ||||
|                 ipDevice = camConfig.IPDeviceAddress; | ||||
|             } | ||||
|             try | ||||
|             { | ||||
|                 if (m_stDeviceList.nDeviceNum == 0 || string.IsNullOrEmpty(camConfig.IPAddress)) | ||||
|                 { | ||||
|                     OnCameraMessage("没有找到设备或索引无效。", -1); | ||||
|                     return false; | ||||
|                 } | ||||
|  | ||||
|                 if (IsOpen) | ||||
|                 { | ||||
|                     OnCameraMessage("相机已经打开。", 0); | ||||
|                     return true; | ||||
|                 } | ||||
|                 MyCamera.MV_CC_DEVICE_INFO device = new MyCamera.MV_CC_DEVICE_INFO(); | ||||
|                 device.nTLayerType = MyCamera.MV_GIGE_DEVICE; | ||||
|                 MyCamera.MV_GIGE_DEVICE_INFO stGigEDev = new MyCamera.MV_GIGE_DEVICE_INFO(); | ||||
|                 var parts = ipCam.Split('.'); | ||||
|                 int nIp1 = Convert.ToInt32(parts[0]); | ||||
|                 int nIp2 = Convert.ToInt32(parts[1]); | ||||
|                 int nIp3 = Convert.ToInt32(parts[2]); | ||||
|                 int nIp4 = Convert.ToInt32(parts[3]); | ||||
|                 stGigEDev.nCurrentIp = (uint)((nIp1 << 24) | (nIp2 << 16) | (nIp3 << 8) | nIp4); | ||||
|  | ||||
|                 parts = ipDevice.Split('.'); | ||||
|                 nIp1 = Convert.ToInt32(parts[0]); | ||||
|                 nIp2 = Convert.ToInt32(parts[1]); | ||||
|                 nIp3 = Convert.ToInt32(parts[2]); | ||||
|                 nIp4 = Convert.ToInt32(parts[3]); | ||||
|                 stGigEDev.nNetExport = (uint)((nIp1 << 24) | (nIp2 << 16) | (nIp3 << 8) | nIp4); | ||||
|                 IntPtr stGigeInfoPtr = Marshal.AllocHGlobal(216); | ||||
|                 Marshal.StructureToPtr(stGigEDev, stGigeInfoPtr, false); | ||||
|                 device.SpecialInfo.stGigEInfo = new Byte[540]; | ||||
|                 Marshal.Copy(stGigeInfoPtr, device.SpecialInfo.stGigEInfo, 0, 540); | ||||
|                 //释放内存空间 | ||||
|                 Marshal.FreeHGlobal(stGigeInfoPtr); | ||||
|  | ||||
|                 //var device = (MyCamera.MV_CC_DEVICE_INFO)Marshal.PtrToStructure(m_stDeviceList.pDeviceInfo[index], typeof(MyCamera.MV_CC_DEVICE_INFO)); | ||||
|                 m_MyCamera = new MyCamera(); | ||||
|                 int nRet = m_MyCamera.MV_CC_CreateDevice_NET(ref device); | ||||
|                 if (nRet != MyCamera.MV_OK) | ||||
|                 { | ||||
|                     OnCameraMessage("创建设备句柄失败!", nRet); | ||||
|                     return false; | ||||
|                 } | ||||
|  | ||||
|                 nRet = m_MyCamera.MV_CC_OpenDevice_NET(); | ||||
|                 if (nRet != MyCamera.MV_OK) | ||||
|                 { | ||||
|                     OnCameraMessage("打开设备失败!", nRet); | ||||
|                     m_MyCamera.MV_CC_DestroyDevice_NET(); | ||||
|                     return false; | ||||
|                 } | ||||
|  | ||||
|                 // 探测网络最佳包大小(只对GigE相机有效) | ||||
|                 if (device.nTLayerType == MyCamera.MV_GIGE_DEVICE) | ||||
|                 { | ||||
|                     int nPacketSize = m_MyCamera.MV_CC_GetOptimalPacketSize_NET(); | ||||
|                     if (nPacketSize > 0) | ||||
|                     { | ||||
|                         m_MyCamera.MV_CC_SetIntValueEx_NET("GevSCPSPacketSize", nPacketSize); | ||||
|                     } | ||||
|                 } | ||||
|  | ||||
|                 // 默认设置为连续模式 | ||||
|                 SetContinuousMode(); | ||||
|  | ||||
|                 IsOpen = true; | ||||
|                 OnCameraMessage("相机打开成功。", 0); | ||||
|                 return true; | ||||
|             } | ||||
|             catch (Exception ex) | ||||
|             { | ||||
|                 OnCameraMessage("相机打开失败。"+ ex.ToString(), 0); | ||||
|                 return false; | ||||
|             } | ||||
|              | ||||
|         } | ||||
|  | ||||
|         /// <summary> | ||||
|         /// 关闭相机 | ||||
|         /// </summary> | ||||
|         public void Close() | ||||
|         { | ||||
|             if (!IsOpen) return; | ||||
|  | ||||
|             if (m_bGrabbing) | ||||
|             { | ||||
|                 StopGrabbing(); | ||||
|             } | ||||
|  | ||||
|             m_MyCamera.MV_CC_CloseDevice_NET(); | ||||
|             m_MyCamera.MV_CC_DestroyDevice_NET(); | ||||
|  | ||||
|             IsOpen = false; | ||||
|             m_MyCamera = null; | ||||
|             OnCameraMessage("相机已关闭。", 0); | ||||
|         } | ||||
|  | ||||
|         /// <summary> | ||||
|         /// 开始采集图像 | ||||
|         /// </summary> | ||||
|         /// <returns>成功返回true</returns> | ||||
|         public bool StartGrabbing() | ||||
|         { | ||||
|             if (!IsOpen || m_bGrabbing) | ||||
|             { | ||||
|                 OnCameraMessage(m_bGrabbing ? "已经在采集中。" : "相机未打开。", -1); | ||||
|                 return false; | ||||
|             } | ||||
|  | ||||
|             // 取图前的必要操作 | ||||
|             if (NecessaryOperBeforeGrab() != MyCamera.MV_OK) | ||||
|             { | ||||
|                 return false; | ||||
|             } | ||||
|  | ||||
|             int nRet = m_MyCamera.MV_CC_StartGrabbing_NET(); | ||||
|             if (nRet != MyCamera.MV_OK) | ||||
|             { | ||||
|                 OnCameraMessage("开始采集失败!", nRet); | ||||
|                 return false; | ||||
|             } | ||||
|  | ||||
|             m_bGrabbing = true; | ||||
|             m_hReceiveThread = new Thread(ReceiveThreadProcess); | ||||
|             m_hReceiveThread.IsBackground = true; | ||||
|             m_hReceiveThread.Start(); | ||||
|  | ||||
|             OnCameraMessage("开始采集。", 0); | ||||
|             return true; | ||||
|         } | ||||
|  | ||||
|         /// <summary> | ||||
|         /// 停止采集图像 | ||||
|         /// </summary> | ||||
|         public void StopGrabbing() | ||||
|         { | ||||
|             if (!m_bGrabbing) return; | ||||
|  | ||||
|             m_bGrabbing = false; | ||||
|             if (m_hReceiveThread != null && m_hReceiveThread.IsAlive) | ||||
|             { | ||||
|                 m_hReceiveThread.Join(1000); // 等待线程退出 | ||||
|             } | ||||
|  | ||||
|             int nRet = m_MyCamera.MV_CC_StopGrabbing_NET(); | ||||
|             if (nRet != MyCamera.MV_OK) | ||||
|             { | ||||
|                 OnCameraMessage("停止采集失败!", nRet); | ||||
|             } | ||||
|  | ||||
|             OnCameraMessage("停止采集。", 0); | ||||
|         } | ||||
|  | ||||
|         /// <summary> | ||||
|         /// 设置为连续采集模式 | ||||
|         /// </summary> | ||||
|         public void SetContinuousMode() | ||||
|         { | ||||
|             if (!IsOpen) return; | ||||
|             m_MyCamera.MV_CC_SetEnumValue_NET("AcquisitionMode", (uint)MyCamera.MV_CAM_ACQUISITION_MODE.MV_ACQ_MODE_CONTINUOUS); | ||||
|             m_MyCamera.MV_CC_SetEnumValue_NET("TriggerMode", (uint)MyCamera.MV_CAM_TRIGGER_MODE.MV_TRIGGER_MODE_OFF); | ||||
|             OnCameraMessage("已设置为连续模式。", 0); | ||||
|         } | ||||
|  | ||||
|         /// <summary> | ||||
|         /// 设置为触发模式 | ||||
|         /// </summary> | ||||
|         /// <param name="isSoftwareTrigger">true为软触发, false为硬触发(Line0)</param> | ||||
|         public void SetTriggerMode(bool isSoftwareTrigger) | ||||
|         { | ||||
|             if (!IsOpen) return; | ||||
|  | ||||
|             m_MyCamera.MV_CC_SetEnumValue_NET("AcquisitionMode", (uint)MyCamera.MV_CAM_ACQUISITION_MODE.MV_ACQ_MODE_CONTINUOUS); // 触发模式也需要在Continuous模式下 | ||||
|             m_MyCamera.MV_CC_SetEnumValue_NET("TriggerMode", (uint)MyCamera.MV_CAM_TRIGGER_MODE.MV_TRIGGER_MODE_ON); | ||||
|  | ||||
|             if (isSoftwareTrigger) | ||||
|             { | ||||
|                 m_MyCamera.MV_CC_SetEnumValue_NET("TriggerSource", (uint)MyCamera.MV_CAM_TRIGGER_SOURCE.MV_TRIGGER_SOURCE_SOFTWARE); | ||||
|                 OnCameraMessage("已设置为软触发模式。", 0); | ||||
|             } | ||||
|             else | ||||
|             { | ||||
|                 m_MyCamera.MV_CC_SetEnumValue_NET("TriggerSource", (uint)MyCamera.MV_CAM_TRIGGER_SOURCE.MV_TRIGGER_SOURCE_LINE0); | ||||
|                 OnCameraMessage("已设置为硬触发(Line0)模式。", 0); | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         /// <summary> | ||||
|         /// 执行一次软触发 | ||||
|         /// </summary> | ||||
|         /// <returns>成功返回true</returns> | ||||
|         public bool SoftwareTrigger() | ||||
|         { | ||||
|             if (!IsOpen || !m_bGrabbing) | ||||
|             { | ||||
|                 OnCameraMessage("请先打开相机并开始采集。", -1); | ||||
|                 return false; | ||||
|             } | ||||
|  | ||||
|             int nRet = m_MyCamera.MV_CC_SetCommandValue_NET("TriggerSoftware"); | ||||
|             if (nRet != MyCamera.MV_OK) | ||||
|             { | ||||
|                 OnCameraMessage("软触发失败!", nRet); | ||||
|                 return false; | ||||
|             } | ||||
|             return true; | ||||
|         } | ||||
|  | ||||
|         /// <summary> | ||||
|         /// 图像接收线程 | ||||
|         /// </summary> | ||||
|         private void ReceiveThreadProcess() | ||||
|         { | ||||
|             MyCamera.MV_FRAME_OUT stFrameInfo = new MyCamera.MV_FRAME_OUT(); | ||||
|             var stConvertParam = new MyCamera.MV_PIXEL_CONVERT_PARAM(); | ||||
|  | ||||
|             while (m_bGrabbing) | ||||
|             { | ||||
|                 int nRet = m_MyCamera.MV_CC_GetImageBuffer_NET(ref stFrameInfo, 1000); | ||||
|                 if (nRet == MyCamera.MV_OK) | ||||
|                 { | ||||
|                     Bitmap bmpForEvent = null; // 在 try 外部声明 | ||||
|                     try | ||||
|                     { | ||||
|                         // 初始化转换参数 | ||||
|                         stConvertParam.nWidth = stFrameInfo.stFrameInfo.nWidth; | ||||
|                         stConvertParam.nHeight = stFrameInfo.stFrameInfo.nHeight; | ||||
|                         stConvertParam.pSrcData = stFrameInfo.pBufAddr; | ||||
|                         stConvertParam.nSrcDataLen = stFrameInfo.stFrameInfo.nFrameLen; | ||||
|                         stConvertParam.enSrcPixelType = stFrameInfo.stFrameInfo.enPixelType; | ||||
|                         stConvertParam.pDstBuffer = m_ConvertDstBuf; | ||||
|                         stConvertParam.nDstBufferSize = m_nConvertDstBufLen; | ||||
|  | ||||
|                         // 创建用于事件的Bitmap,它的格式与类成员m_bitmap一致 | ||||
|                         bmpForEvent = new Bitmap((int)stConvertParam.nWidth, (int)stConvertParam.nHeight, m_bitmap.PixelFormat); | ||||
|  | ||||
|                         // 判断并设置目标像素格式 | ||||
|                         if (bmpForEvent.PixelFormat == PixelFormat.Format8bppIndexed) | ||||
|                         { | ||||
|                             stConvertParam.enDstPixelType = MyCamera.MvGvspPixelType.PixelType_Gvsp_Mono8; | ||||
|                         } | ||||
|                         else | ||||
|                         { | ||||
|                             stConvertParam.enDstPixelType = MyCamera.MvGvspPixelType.PixelType_Gvsp_BGR8_Packed; | ||||
|                         } | ||||
|  | ||||
|                         // 执行像素格式转换 | ||||
|                         nRet = m_MyCamera.MV_CC_ConvertPixelType_NET(ref stConvertParam); | ||||
|                         if (nRet == MyCamera.MV_OK) | ||||
|                         { | ||||
|                             // 转换成功,锁定位图内存并拷贝数据 | ||||
|                             BitmapData bmpData = bmpForEvent.LockBits(new Rectangle(0, 0, stConvertParam.nWidth, stConvertParam.nHeight), ImageLockMode.WriteOnly, bmpForEvent.PixelFormat); | ||||
|  | ||||
|                             // 使用更健壮的逐行拷贝 | ||||
|                             int pixelSize = (bmpForEvent.PixelFormat == PixelFormat.Format8bppIndexed) ? 1 : 3; | ||||
|                             for (int i = 0; i < bmpData.Height; ++i) | ||||
|                             { | ||||
|                                 IntPtr pDst = new IntPtr(bmpData.Scan0.ToInt64() + i * bmpData.Stride); | ||||
|                                 IntPtr pSrc = new IntPtr(m_ConvertDstBuf.ToInt64() + i * stConvertParam.nWidth * pixelSize); | ||||
|                                 CopyMemory(pDst, pSrc, (uint)(stConvertParam.nWidth * pixelSize)); | ||||
|                             } | ||||
|                             bmpForEvent.UnlockBits(bmpData); | ||||
|  | ||||
|                             // 触发图像采集事件,转移 bmpForEvent 的所有权 | ||||
|                             ImageAcquired?.Invoke(this, bmpForEvent); | ||||
|  | ||||
|                             // 【关键】所有权已转移,将本地引用设为null,防止它在finally块中被错误地释放 | ||||
|                             bmpForEvent = null; | ||||
|                         } | ||||
|                         // 如果转换失败,不执行任何操作,让 finally 块来处理 bmpForEvent 的释放 | ||||
|                     } | ||||
|                     finally | ||||
|                     { | ||||
|                         // 【关键】如果 bmpForEvent 不为 null,意味着它被成功创建, | ||||
|                         // 但没有被成功传递给事件处理器(可能因为转换失败或发生其他异常), | ||||
|                         // 在这里必须将其释放。 | ||||
|                         bmpForEvent?.Dispose(); | ||||
|  | ||||
|                         // 无论成功与否,都必须释放相机SDK的内部图像缓存 | ||||
|                         m_MyCamera.MV_CC_FreeImageBuffer_NET(ref stFrameInfo); | ||||
|                     } | ||||
|                 } | ||||
|                 else | ||||
|                 { | ||||
|                     // 超时,继续等待 | ||||
|                     Thread.Sleep(5); | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         /// <summary> | ||||
|         /// 取图前的内存和参数准备 | ||||
|         /// </summary> | ||||
|         private int NecessaryOperBeforeGrab() | ||||
|         { | ||||
|             var stWidth = new MyCamera.MVCC_INTVALUE_EX(); | ||||
|             int nRet = m_MyCamera.MV_CC_GetIntValueEx_NET("Width", ref stWidth); | ||||
|             if (nRet != MyCamera.MV_OK) { OnCameraMessage("获取宽度失败!", nRet); return nRet; } | ||||
|  | ||||
|             var stHeight = new MyCamera.MVCC_INTVALUE_EX(); | ||||
|             nRet = m_MyCamera.MV_CC_GetIntValueEx_NET("Height", ref stHeight); | ||||
|             if (nRet != MyCamera.MV_OK) { OnCameraMessage("获取高度失败!", nRet); return nRet; } | ||||
|  | ||||
|             var stPixelFormat = new MyCamera.MVCC_ENUMVALUE(); | ||||
|             nRet = m_MyCamera.MV_CC_GetEnumValue_NET("PixelFormat", ref stPixelFormat); | ||||
|             if (nRet != MyCamera.MV_OK) { OnCameraMessage("获取像素格式失败!", nRet); return nRet; } | ||||
|  | ||||
|             PixelFormat bitmapPixelFormat; | ||||
|             // 判断当前像素格式是否为Mono | ||||
|             bool isMono = IsMono(stPixelFormat.nCurValue); | ||||
|  | ||||
|             if (isMono) | ||||
|             { | ||||
|                 bitmapPixelFormat = PixelFormat.Format8bppIndexed; | ||||
|                 m_nConvertDstBufLen = (uint)(stWidth.nCurValue * stHeight.nCurValue); | ||||
|             } | ||||
|             else | ||||
|             { | ||||
|                 bitmapPixelFormat = PixelFormat.Format24bppRgb; | ||||
|                 m_nConvertDstBufLen = (uint)(stWidth.nCurValue * stHeight.nCurValue * 3); | ||||
|             } | ||||
|  | ||||
|             // 分配转换后的图像数据缓存 | ||||
|             if (m_ConvertDstBuf != IntPtr.Zero) Marshal.FreeHGlobal(m_ConvertDstBuf); | ||||
|             m_ConvertDstBuf = Marshal.AllocHGlobal((int)m_nConvertDstBufLen); | ||||
|  | ||||
|             // 创建Bitmap对象 | ||||
|             if (m_bitmap != null) m_bitmap.Dispose(); | ||||
|             m_bitmap = new Bitmap((int)stWidth.nCurValue, (int)stHeight.nCurValue, bitmapPixelFormat); | ||||
|  | ||||
|             // 如果是Mono8格式,设置调色板 | ||||
|             if (isMono) | ||||
|             { | ||||
|                 ColorPalette palette = m_bitmap.Palette; | ||||
|                 for (int i = 0; i < 256; i++) palette.Entries[i] = Color.FromArgb(i, i, i); | ||||
|                 m_bitmap.Palette = palette; | ||||
|             } | ||||
|  | ||||
|             return MyCamera.MV_OK; | ||||
|         } | ||||
|  | ||||
|         private bool IsMono(uint enPixelType) | ||||
|         { | ||||
|             switch (enPixelType) | ||||
|             { | ||||
|                 case (uint)MyCamera.MvGvspPixelType.PixelType_Gvsp_Mono8: | ||||
|                 case (uint)MyCamera.MvGvspPixelType.PixelType_Gvsp_Mono10: | ||||
|                 case (uint)MyCamera.MvGvspPixelType.PixelType_Gvsp_Mono10_Packed: | ||||
|                 case (uint)MyCamera.MvGvspPixelType.PixelType_Gvsp_Mono12: | ||||
|                 case (uint)MyCamera.MvGvspPixelType.PixelType_Gvsp_Mono12_Packed: | ||||
|                     return true; | ||||
|                 default: | ||||
|                     return false; | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         /// <summary> | ||||
|         /// 触发相机消息事件 | ||||
|         /// </summary> | ||||
|         private void OnCameraMessage(string message, int errorCode = 0) | ||||
|         { | ||||
|             CameraMessage?.Invoke(this, message, errorCode); | ||||
|         } | ||||
|  | ||||
|         /// <summary> | ||||
|         /// 释放资源 | ||||
|         /// </summary> | ||||
|         public void Dispose() | ||||
|         { | ||||
|             Close(); | ||||
|             if (m_ConvertDstBuf != IntPtr.Zero) | ||||
|             { | ||||
|                 Marshal.FreeHGlobal(m_ConvertDstBuf); | ||||
|                 m_ConvertDstBuf = IntPtr.Zero; | ||||
|             } | ||||
|             if (m_bitmap != null) | ||||
|             { | ||||
|                 m_bitmap.Dispose(); | ||||
|                 m_bitmap = null; | ||||
|             } | ||||
|             MyCamera.MV_CC_Finalize_NET(); | ||||
|         } | ||||
|     } | ||||
| } | ||||
		Reference in New Issue
	
	Block a user