using MVSDK_Net; using System; using System.Collections.Generic; using System.Diagnostics; using System.Drawing.Imaging; using System.Linq; using System.Runtime.InteropServices; using System.Text; using System.Threading.Tasks; namespace LB_VisionProcesses.Cameras.HRCameras { /// /// 华睿2D工业相机实现类 /// 基于MVSDK_Net SDK封装 /// public class HRCamera : BaseCamera { #region 私有字段 private MyCamera _camera; // 华睿相机设备对象 private Thread _grabThread; // 图像采集线程 private bool _isGrabbing; // 采集状态标志 private bool _threadRunning; // 线程运行标志 private bool _handleCreated = false; // 句柄是否已创建 private Thread _callbackThread; // 回调处理线程 private List _frameList; // 图像缓存列表 private readonly object _frameLock = new object(); // 帧缓存锁 // CopyMemory API声明 [System.Runtime.InteropServices.DllImport("kernel32.dll", EntryPoint = "RtlMoveMemory")] private static extern void CopyMemory(IntPtr dest, IntPtr src, uint count); #endregion #region 构造函数和析构函数 /// /// 构造函数 /// public HRCamera() { _camera = new MyCamera(); _frameList = new List(); Brand = CameraBrand.HRCamera; _isGrabbing = false; _threadRunning = false; } /// /// 析构函数 /// ~HRCamera() { Dispose(false); } #endregion #region 设备管理操作 /// /// 获取相机SN枚举列表 /// /// 相机SN列表 public override List GetListEnum() { List cameraList = new List(); try { // 枚举所有设备 IMVDefine.IMV_DeviceList deviceList = new IMVDefine.IMV_DeviceList(); IMVDefine.IMV_EInterfaceType interfaceType = IMVDefine.IMV_EInterfaceType.interfaceTypeAll; int result = MyCamera.IMV_EnumDevices(ref deviceList, (uint)interfaceType); if (result == IMVDefine.IMV_OK && deviceList.nDevNum > 0) { for (int i = 0; i < deviceList.nDevNum; i++) { IMVDefine.IMV_DeviceInfo deviceInfo = (IMVDefine.IMV_DeviceInfo) Marshal.PtrToStructure( deviceList.pDevInfo + Marshal.SizeOf(typeof(IMVDefine.IMV_DeviceInfo)) * i, typeof(IMVDefine.IMV_DeviceInfo)); string cameraInfo = $"{deviceInfo.cameraName}[{deviceInfo.serialNumber}]"; cameraList.Add(cameraInfo); } } else { // 记录日志或抛出异常 //throw new Exception($"枚举设备失败,错误码:{result}"); Debug.WriteLine("枚举设备失败!"); } } catch (Exception ex) { // 记录错误日志 System.Diagnostics.Debug.WriteLine($"获取相机列表失败:{ex.Message}"); throw; } return cameraList; } /// /// 初始化相机设备 /// /// 相机序列号 /// 窗口句柄(可选) /// 初始化是否成功 public override bool InitDevice(string SN, object Handle = null) { try { // 确保彻底关闭和清理 if (_camera != null) { if (_camera.IMV_IsOpen()) { _camera.IMV_Close(); } if (_handleCreated) { _camera.IMV_DestroyHandle(); _handleCreated = false; } } // 枚举设备并匹配SN List cameraList = GetListEnum(); int cameraIndex = -1; for (int i = 0; i < cameraList.Count; i++) { if (cameraList[i].Contains(SN)) { cameraIndex = i; break; } } if (cameraIndex == -1) { throw new Exception($"未找到序列号为 {SN} 的相机"); } // 创建设备句柄 int result = _camera.IMV_CreateHandle(IMVDefine.IMV_ECreateHandleMode.modeByIndex, cameraIndex); if (result != IMVDefine.IMV_OK) { throw new Exception($"创建设备句柄失败,错误码:{result}"); } _handleCreated = true; // 打开设备 result = _camera.IMV_Open(); if (result != IMVDefine.IMV_OK) { throw new Exception($"打开相机失败,错误码:{result}"); } // 设置设备属性 this.SN = SN; isGrabbing = false; // 设置缓存个数为8 _camera.IMV_SetBufferCount(8); return true; } catch (Exception ex) { System.Diagnostics.Debug.WriteLine($"初始化相机失败:{ex.Message}"); return false; } } /// /// 关闭相机设备 /// /// 关闭是否成功 public override bool CloseDevice() { try { if (_camera == null) return true; // 停止采集 if (_camera.IMV_IsGrabbing()) { StopGrabbing(); } // 关闭设备 if (_camera.IMV_IsOpen()) { int result = _camera.IMV_Close(); if (result != IMVDefine.IMV_OK) { System.Diagnostics.Debug.WriteLine($"关闭相机失败,错误码:{result}"); } } // 销毁句柄 if (_handleCreated) { _camera.IMV_DestroyHandle(); _handleCreated = false; } // 释放资源 _isGrabbing = false; isGrabbing = false; // 清理帧缓存 lock (_frameLock) { foreach (var frame in _frameList) { var tempFrame = frame; // 创建临时变量 _camera.IMV_ReleaseFrame(ref tempFrame); } _frameList.Clear(); } return true; } catch (Exception ex) { System.Diagnostics.Debug.WriteLine($"关闭相机失败:{ex.Message}"); return false; } } #endregion #region 图像采集操作 /// /// 开始图像采集 /// /// 采集启动是否成功 public override bool StartGrabbing() { try { if (_camera == null || !_camera.IMV_IsOpen()) { throw new Exception("相机未打开"); } // 停止现有采集 if (_isGrabbing) { StopGrabbing(); } // 启动采集 int result = _camera.IMV_StartGrabbing(); if (result != IMVDefine.IMV_OK) { throw new Exception($"启动采集失败,错误码:{result}"); } _isGrabbing = true; isGrabbing = true; // 启动采集线程 _threadRunning = true; _grabThread = new Thread(GrabThreadProc); _grabThread.IsBackground = true; _grabThread.Start(); return true; } catch (Exception ex) { System.Diagnostics.Debug.WriteLine($"启动采集失败:{ex.Message}"); _isGrabbing = false; isGrabbing = false; return false; } } /// /// 停止图像采集 /// /// 停止是否成功 public override bool StopGrabbing() { try { if (_camera == null || !_isGrabbing) return true; // 停止线程 _threadRunning = false; if (_grabThread != null && _grabThread.IsAlive) { _grabThread.Join(1000); _grabThread = null; } // 停止采集 int result = _camera.IMV_StopGrabbing(); if (result != IMVDefine.IMV_OK) { System.Diagnostics.Debug.WriteLine($"停止采集失败,错误码:{result}"); } _isGrabbing = false; isGrabbing = false; // 清理缓存 lock (_frameLock) { foreach (var frame in _frameList) { var tempFrame = frame; // 创建临时变量 _camera.IMV_ReleaseFrame(ref tempFrame); } _frameList.Clear(); } return true; } catch (Exception ex) { System.Diagnostics.Debug.WriteLine($"停止采集失败:{ex.Message}"); return false; } } /// /// 执行软触发 /// /// 触发是否成功 public override bool SoftTrigger() { try { if (_camera == null || !_camera.IMV_IsOpen()) { throw new Exception("相机未打开"); } int result = _camera.IMV_ExecuteCommandFeature("TriggerSoftware"); return result == IMVDefine.IMV_OK; } catch (Exception ex) { System.Diagnostics.Debug.WriteLine($"软触发失败:{ex.Message}"); return false; } } #endregion #region 参数设置和获取 /// /// 设置触发模式 /// /// 触发模式 /// 触发源 /// 设置是否成功 public override bool SetTriggerMode(TriggerMode mode, TriggerSource source = TriggerSource.Line0) { try { if (_camera == null || !_camera.IMV_IsOpen()) { throw new Exception("相机未打开"); } // 设置触发模式 string triggerMode = mode == TriggerMode.On ? "On" : "Off"; int result = _camera.IMV_SetEnumFeatureSymbol("TriggerMode", triggerMode); if (result != IMVDefine.IMV_OK) { throw new Exception($"设置触发模式失败,错误码:{result}"); } // 设置触发源 if (mode == TriggerMode.On) { string triggerSource = GetTriggerSourceString(source); result = _camera.IMV_SetEnumFeatureSymbol("TriggerSource", triggerSource); if (result != IMVDefine.IMV_OK) { throw new Exception($"设置触发源失败,错误码:{result}"); } } return true; } catch (Exception ex) { System.Diagnostics.Debug.WriteLine($"设置触发模式失败:{ex.Message}"); return false; } } /// /// 获取触发模式 /// /// 触发模式 /// 触发源 /// 获取是否成功 public override bool GetTriggerMode(out TriggerMode mode, out TriggerSource source) { mode = TriggerMode.Off; source = TriggerSource.Software; try { if (_camera == null || !_camera.IMV_IsOpen()) { throw new Exception("相机未打开"); } // 获取触发模式 IMVDefine.IMV_String triggerMode = new IMVDefine.IMV_String(); int result = _camera.IMV_GetEnumFeatureSymbol("TriggerMode", ref triggerMode); if (result == IMVDefine.IMV_OK) { mode = triggerMode.str == "On" ? TriggerMode.On : TriggerMode.Off; } // 获取触发源 IMVDefine.IMV_String triggerSource = new IMVDefine.IMV_String(); result = _camera.IMV_GetEnumFeatureSymbol("TriggerSource", ref triggerSource); if (result == IMVDefine.IMV_OK) { source = GetTriggerSourceFromString(triggerSource.str); } return true; } catch (Exception ex) { System.Diagnostics.Debug.WriteLine($"获取触发模式失败:{ex.Message}"); return false; } } /// /// 设置曝光时间 /// /// 曝光时间(微秒) /// 设置是否成功 public override bool SetExpouseTime(double value) { try { if (_camera == null || !_camera.IMV_IsOpen()) { throw new Exception("相机未打开"); } // 验证曝光时间范围 double minExp = 0, maxExp = 0; int result = _camera.IMV_GetDoubleFeatureMin("ExposureTime", ref minExp); if (result != IMVDefine.IMV_OK) { throw new Exception($"获取曝光时间最小值失败,错误码:{result}"); } result = _camera.IMV_GetDoubleFeatureMax("ExposureTime", ref maxExp); if (result != IMVDefine.IMV_OK) { throw new Exception($"获取曝光时间最大值失败,错误码:{result}"); } if (value < minExp || value > maxExp) { throw new Exception($"曝光时间超出范围,有效范围:{minExp} - {maxExp}"); } // 设置曝光时间 result = _camera.IMV_SetDoubleFeatureValue("ExposureTime", value); if (result != IMVDefine.IMV_OK) { throw new Exception($"设置曝光时间失败,错误码:{result}"); } return true; } catch (Exception ex) { System.Diagnostics.Debug.WriteLine($"设置曝光时间失败:{ex.Message}"); return false; } } /// /// 获取曝光时间 /// /// 曝光时间 /// 获取是否成功 public override bool GetExpouseTime(out double value) { value = 0; try { if (_camera == null || !_camera.IMV_IsOpen()) { throw new Exception("相机未打开"); } int result = _camera.IMV_GetDoubleFeatureValue("ExposureTime", ref value); return result == IMVDefine.IMV_OK; } catch (Exception ex) { System.Diagnostics.Debug.WriteLine($"获取曝光时间失败:{ex.Message}"); return false; } } /// /// 设置增益 /// /// 增益值 /// 设置是否成功 public override bool SetGain(double gain) { try { if (_camera == null || !_camera.IMV_IsOpen()) { throw new Exception("相机未打开"); } string gainFeature = _camera.IMV_FeatureIsValid("Gain") ? "Gain" : "GainRaw"; // 验证增益范围 double minGain = 0, maxGain = 0; int result = _camera.IMV_GetDoubleFeatureMin(gainFeature, ref minGain); if (result != IMVDefine.IMV_OK) { throw new Exception($"获取增益最小值失败,错误码:{result}"); } result = _camera.IMV_GetDoubleFeatureMax(gainFeature, ref maxGain); if (result != IMVDefine.IMV_OK) { throw new Exception($"获取增益最大值失败,错误码:{result}"); } if (gain < minGain) gain = minGain; if (gain > maxGain) gain = maxGain; // 设置增益 result = _camera.IMV_SetDoubleFeatureValue(gainFeature, gain); if (result != IMVDefine.IMV_OK) { throw new Exception($"设置增益失败,错误码:{result}"); } return true; } catch (Exception ex) { System.Diagnostics.Debug.WriteLine($"设置增益失败:{ex.Message}"); return false; } } /// /// 获取增益值 /// /// 增益值 /// 获取是否成功 public override bool GetGain(out double gain) { gain = 0; try { if (_camera == null || !_camera.IMV_IsOpen()) { throw new Exception("相机未打开"); } string gainFeature = _camera.IMV_FeatureIsValid("Gain") ? "Gain" : "GainRaw"; int result = _camera.IMV_GetDoubleFeatureValue(gainFeature, ref gain); return result == IMVDefine.IMV_OK; } catch (Exception ex) { System.Diagnostics.Debug.WriteLine($"获取增益失败:{ex.Message}"); return false; } } /// /// 设置触发极性 /// /// 触发极性 /// 是否成功 public override bool SetTriggerPolarity(TriggerPolarity polarity) { try { if (_camera == null || !_camera.IMV_IsOpen()) return false; string activation = (polarity == TriggerPolarity.RisingEdge || polarity == TriggerPolarity.HighLevel) ? "RisingEdge" : "FallingEdge"; int result = _camera.IMV_SetEnumFeatureSymbol("TriggerActivation", activation); return result == IMVDefine.IMV_OK; } catch (Exception ex) { System.Diagnostics.Debug.WriteLine($"设置触发极性失败:{ex.Message}"); return false; } } /// /// 获取触发极性 /// /// 触发极性 /// 是否成功 public override bool GetTriggerPolarity(out TriggerPolarity polarity) { polarity = TriggerPolarity.RisingEdge; try { if (_camera == null || !_camera.IMV_IsOpen()) return false; IMVDefine.IMV_String activation = new IMVDefine.IMV_String(); int result = _camera.IMV_GetEnumFeatureSymbol("TriggerActivation", ref activation); if (result == IMVDefine.IMV_OK) { polarity = activation.str == "RisingEdge" ? TriggerPolarity.RisingEdge : TriggerPolarity.FallingEdge; return true; } return false; } catch (Exception ex) { System.Diagnostics.Debug.WriteLine($"获取触发极性失败:{ex.Message}"); return false; } } /// /// 设置触发滤波时间 (us) /// public override bool SetTriggerFliter(double flitertime) { try { if (_camera == null || !_camera.IMV_IsOpen()) return false; // 华睿相机通常使用 LineDebouncerTime 控制滤波 if (_camera.IMV_FeatureIsValid("LineDebouncerTime")) { int result = _camera.IMV_SetDoubleFeatureValue("LineDebouncerTime", flitertime); return result == IMVDefine.IMV_OK; } return false; } catch (Exception ex) { System.Diagnostics.Debug.WriteLine($"设置触发滤波失败:{ex.Message}"); return false; } } /// /// 获取触发滤波时间 (us) /// public override bool GetTriggerFliter(out double flitertime) { flitertime = 0; try { if (_camera == null || !_camera.IMV_IsOpen()) return false; if (_camera.IMV_FeatureIsValid("LineDebouncerTime")) { int result = _camera.IMV_GetDoubleFeatureValue("LineDebouncerTime", ref flitertime); return result == IMVDefine.IMV_OK; } return false; } catch (Exception ex) { System.Diagnostics.Debug.WriteLine($"获取触发滤波失败:{ex.Message}"); return false; } } /// /// 设置触发延时 (us) /// public override bool SetTriggerDelay(double delay) { try { if (_camera == null || !_camera.IMV_IsOpen()) return false; if (_camera.IMV_FeatureIsValid("TriggerDelay")) { int result = _camera.IMV_SetDoubleFeatureValue("TriggerDelay", delay); return result == IMVDefine.IMV_OK; } return false; } catch (Exception ex) { System.Diagnostics.Debug.WriteLine($"设置触发延时失败:{ex.Message}"); return false; } } /// /// 获取触发延时 (us) /// public override bool GetTriggerDelay(out double delay) { delay = 0; try { if (_camera == null || !_camera.IMV_IsOpen()) return false; if (_camera.IMV_FeatureIsValid("TriggerDelay")) { int result = _camera.IMV_GetDoubleFeatureValue("TriggerDelay", ref delay); return result == IMVDefine.IMV_OK; } return false; } catch (Exception ex) { System.Diagnostics.Debug.WriteLine($"获取触发延时失败:{ex.Message}"); return false; } } /// /// 设置信号线模式 /// public override bool SetLineMode(IOLines line, LineMode mode) { try { if (_camera == null || !_camera.IMV_IsOpen()) return false; // 选择线路 int result = _camera.IMV_SetEnumFeatureSymbol("LineSelector", line.ToString()); if (result != IMVDefine.IMV_OK) return false; // 设置模式 string lineMode = mode == LineMode.Input ? "Input" : "Output"; result = _camera.IMV_SetEnumFeatureSymbol("LineMode", lineMode); return result == IMVDefine.IMV_OK; } catch (Exception ex) { System.Diagnostics.Debug.WriteLine($"设置信号线模式失败:{ex.Message}"); return false; } } /// /// 设置信号线电平状态 /// public override bool SetLineStatus(IOLines line, LineStatus linestatus) { try { if (_camera == null || !_camera.IMV_IsOpen()) return false; // 仅对输出线路有效 int result = _camera.IMV_SetEnumFeatureSymbol("LineSelector", line.ToString()); if (result != IMVDefine.IMV_OK) return false; bool status = linestatus == LineStatus.Hight; result = _camera.IMV_SetBoolFeatureValue("UserOutputValue", status); return result == IMVDefine.IMV_OK; } catch (Exception ex) { System.Diagnostics.Debug.WriteLine($"设置信号线状态失败:{ex.Message}"); return false; } } /// /// 获取信号线电平状态 /// public override bool GetLineStatus(IOLines line, out LineStatus lineStatus) { lineStatus = LineStatus.Low; try { if (_camera == null || !_camera.IMV_IsOpen()) return false; int result = _camera.IMV_SetEnumFeatureSymbol("LineSelector", line.ToString()); if (result != IMVDefine.IMV_OK) return false; bool status = false; result = _camera.IMV_GetBoolFeatureValue("LineStatus", ref status); if (result == IMVDefine.IMV_OK) { lineStatus = status ? LineStatus.Hight : LineStatus.Low; return true; } return false; } catch (Exception ex) { System.Diagnostics.Debug.WriteLine($"获取信号线状态失败:{ex.Message}"); return false; } } /// /// 自动白平衡 /// public override bool AutoBalanceWhite() { try { if (_camera == null || !_camera.IMV_IsOpen()) return false; if (_camera.IMV_FeatureIsValid("BalanceWhiteAuto")) { int result = _camera.IMV_SetEnumFeatureSymbol("BalanceWhiteAuto", "Once"); return result == IMVDefine.IMV_OK; } return false; } catch (Exception ex) { System.Diagnostics.Debug.WriteLine($"自动白平衡失败:{ex.Message}"); return false; } } #endregion #region 采集和转换辅助方法 /// /// 图像采集线程处理函数 /// private void GrabThreadProc() { while (_threadRunning) { IMVDefine.IMV_Frame frame = new IMVDefine.IMV_Frame(); try { // 获取图像帧 int result = _camera.IMV_GetFrame(ref frame, 1000); if (result == IMVDefine.IMV_OK) { // 处理图像帧 ProcessFrame(frame); } else { // 即使获取失败,也尝试释放帧,防止SDK内部缓存泄露 // 注意:frame是每次新建的,如果GetFrame没填充,这里释放应该是安全的(视SDK实现而定) var tempFrame = frame; _camera.IMV_ReleaseFrame(ref tempFrame); if ((uint)result != 0x80000001 && result != -119 && result != -102) // 超时错误代码 { // 非超时错误 System.Diagnostics.Debug.WriteLine($"获取图像帧失败,错误码:{result}"); Thread.Sleep(10); // 出错时稍作等待 } } } catch (Exception ex) { System.Diagnostics.Debug.WriteLine($"采集线程异常:{ex.Message}"); Thread.Sleep(10); } Thread.Sleep(1); } } /// /// 处理图像帧 /// /// 图像帧 private void ProcessFrame(IMVDefine.IMV_Frame frame) { try { // 将图像数据转换为Bitmap Bitmap bitmap = ConvertFrameToBitmap(frame); if (bitmap != null) { // 触发图像采集事件 CameraEventArgs args = new CameraEventArgs(SN, bitmap); ImageGrabbed?.Invoke(this, args); // 更新回调图像 CallBackImg = bitmap; } } catch (Exception ex) { System.Diagnostics.Debug.WriteLine($"处理图像帧失败:{ex.Message}"); } finally { // 确保无论如何都释放帧,防止缓存占满 var tempFrame = frame; _camera.IMV_ReleaseFrame(ref tempFrame); } } /// /// 将图像帧转换为Bitmap /// /// 图像帧 /// Bitmap对象 private Bitmap ConvertFrameToBitmap(IMVDefine.IMV_Frame frame) { try { Bitmap bitmap = null; switch (frame.frameInfo.pixelFormat) { case IMVDefine.IMV_EPixelType.gvspPixelMono8: bitmap = CreateMono8Bitmap(frame); break; case IMVDefine.IMV_EPixelType.gvspPixelBGR8: bitmap = CreateBgr8Bitmap(frame); break; default: // 其他格式需要转换 bitmap = ConvertToBGR8(frame); break; } return bitmap; } catch (Exception ex) { System.Diagnostics.Debug.WriteLine($"图像格式转换失败:{ex.Message}"); return null; } } /// /// 创建Mono8格式Bitmap /// private Bitmap CreateMono8Bitmap(IMVDefine.IMV_Frame frame) { Bitmap bitmap = new Bitmap((int)frame.frameInfo.width, (int)frame.frameInfo.height, PixelFormat.Format8bppIndexed); // 设置灰度调色板 ColorPalette palette = bitmap.Palette; for (int i = 0; i < 256; i++) { palette.Entries[i] = Color.FromArgb(i, i, i); } bitmap.Palette = palette; // 复制图像数据 BitmapData bmpData = bitmap.LockBits( new Rectangle(0, 0, bitmap.Width, bitmap.Height), ImageLockMode.WriteOnly, bitmap.PixelFormat); // 使用CopyMemory API进行内存复制 CopyMemory(bmpData.Scan0, frame.pData, (uint)Math.Min(frame.frameInfo.size, (uint)(bmpData.Stride * bitmap.Height))); bitmap.UnlockBits(bmpData); return bitmap; } /// /// 创建BGR8格式Bitmap /// private Bitmap CreateBgr8Bitmap(IMVDefine.IMV_Frame frame) { Bitmap bitmap = new Bitmap((int)frame.frameInfo.width, (int)frame.frameInfo.height, PixelFormat.Format24bppRgb); BitmapData bmpData = bitmap.LockBits( new Rectangle(0, 0, bitmap.Width, bitmap.Height), ImageLockMode.WriteOnly, bitmap.PixelFormat); // 使用CopyMemory API进行内存复制 CopyMemory(bmpData.Scan0, frame.pData, (uint)Math.Min(frame.frameInfo.size, (uint)(bmpData.Stride * bitmap.Height))); bitmap.UnlockBits(bmpData); return bitmap; } /// /// 转换为BGR8格式 /// private Bitmap ConvertToBGR8(IMVDefine.IMV_Frame frame) { IMVDefine.IMV_PixelConvertParam convertParam = new IMVDefine.IMV_PixelConvertParam { nWidth = frame.frameInfo.width, nHeight = frame.frameInfo.height, ePixelFormat = frame.frameInfo.pixelFormat, pSrcData = frame.pData, nSrcDataLen = frame.frameInfo.size, nPaddingX = frame.frameInfo.paddingX, nPaddingY = frame.frameInfo.paddingY, eBayerDemosaic = IMVDefine.IMV_EBayerDemosaic.demosaicBilinear, eDstPixelFormat = IMVDefine.IMV_EPixelType.gvspPixelBGR8, nDstBufSize = frame.frameInfo.width * frame.frameInfo.height * 3 }; IntPtr dstBuffer = Marshal.AllocHGlobal((int)convertParam.nDstBufSize); convertParam.pDstBuf = dstBuffer; try { int result = _camera.IMV_PixelConvert(ref convertParam); if (result == IMVDefine.IMV_OK) { return CreateBgr8BitmapFromBuffer(dstBuffer, frame.frameInfo.width, frame.frameInfo.height); } return null; } finally { Marshal.FreeHGlobal(dstBuffer); } } /// /// 从缓冲区创建BGR8 Bitmap /// private Bitmap CreateBgr8BitmapFromBuffer(IntPtr buffer, uint width, uint height) { Bitmap bitmap = new Bitmap((int)width, (int)height, PixelFormat.Format24bppRgb); BitmapData bmpData = bitmap.LockBits( new Rectangle(0, 0, bitmap.Width, bitmap.Height), ImageLockMode.WriteOnly, bitmap.PixelFormat); // 使用CopyMemory API进行安全的内存复制 CopyMemory(bmpData.Scan0, buffer, (uint)(width * height * 3)); bitmap.UnlockBits(bmpData); return bitmap; } /// /// 将触发源枚举转换为字符串 /// private string GetTriggerSourceString(TriggerSource source) { return source switch { TriggerSource.Software => "Software", TriggerSource.Line0 => "Line0", TriggerSource.Line1 => "Line1", TriggerSource.Line2 => "Line2", TriggerSource.Line3 => "Line3", TriggerSource.Line4 => "Line4", TriggerSource.Line5 => "Line5", _ => "Software" }; } /// /// 将字符串转换为触发源枚举 /// private TriggerSource GetTriggerSourceFromString(string source) { return source switch { "Software" => TriggerSource.Software, "Line0" => TriggerSource.Line0, "Line1" => TriggerSource.Line1, "Line2" => TriggerSource.Line2, "Line3" => TriggerSource.Line3, "Line4" => TriggerSource.Line4, "Line5" => TriggerSource.Line5, _ => TriggerSource.Software }; } #endregion #region IDisposable实现 private bool _disposed = false; protected virtual void Dispose(bool disposing) { if (!_disposed) { if (disposing) { // 释放托管资源 } // 释放非托管资源 CloseDevice(); _disposed = true; } } public override void Dispose() { Dispose(true); GC.SuppressFinalize(this); } public override bool StartWith_SoftTriggerModel() { SetTriggerMode(TriggerMode.Off, TriggerSource.Software); return StartGrabbing(); } public override bool StartWith_HardTriggerModel(TriggerSource hardtriggeritem = TriggerSource.Line0) { if (hardtriggeritem == TriggerSource.Software) hardtriggeritem = TriggerSource.Line0; SetTriggerMode(TriggerMode.On, hardtriggeritem); return StartGrabbing(); } public override bool GetImage(out Bitmap bitmap, int outtime = 3000) { bitmap = null; try { // 设置超时时间 DateTime lastTime = DateTime.Now.AddMilliseconds(outtime); // 判断是否超时 while (lastTime > DateTime.Now)// 设置超时时间为 3 秒 { if (CallBackImg != null) { lock (CallBackImg) { // 保存旧 Bitmap 并释放 bitmap = CallBackImg.Clone() as Bitmap; // 创建副本 } // 释放旧资源 CallBackImg.Dispose(); CallBackImg = null; return true; } } return false; } catch { return bitmap == null ? false : true; } } public override bool GetImageWithSoftTrigger(out Bitmap bitmap, int outtime = 3000) { if (!isGrabbing) StartGrabbing(); GetTriggerMode(out TriggerMode triggerMode, out TriggerSource triggerSource); if (triggerMode != TriggerMode.On && triggerSource != TriggerSource.Software) SetTriggerMode(TriggerMode.On, TriggerSource.Software); bitmap = null; CallBackImg = null; if (!SoftTrigger()) return false; // 开始时间 DateTime startTime = DateTime.Now; // 当前时间 // 判断是否超时 while (DateTime.Now < startTime.AddMilliseconds(outtime))// 设置超时时间为 3 秒 { GetImage(out bitmap, 50); if (bitmap != null) break; Thread.Sleep(10); } if (triggerMode != TriggerMode.On) SetTriggerMode(TriggerMode.On, triggerSource); return (bitmap != null); } public override void SetCamConfig(CameraConfig config) { if (Enum.TryParse(config.Params.Inputs["触发模式"].ToString(), out TriggerMode TriggerMode) && Enum.TryParse(config.Params.Inputs["触发方式"].ToString(), out TriggerSource TriggerSource) && Enum.TryParse(config.Params.Inputs["触发极性"].ToString(), out TriggerPolarity TriggerPolarity) ) { SetTriggerMode(TriggerMode, TriggerSource); SetTriggerPolarity(TriggerPolarity); SetTriggerFliter(Convert.ToDouble(config.Params.Inputs["触发消抖"].ToString())); SetTriggerDelay(Convert.ToDouble(config.Params.Inputs["触发延时"].ToString())); SetExpouseTime(Convert.ToDouble(config.Params.Inputs["曝光时间"].ToString())); SetGain(Convert.ToDouble(config.Params.Inputs["增益"].ToString())); } } public override void GetCamConfig(out CameraConfig config) { GetTriggerMode(out TriggerMode triggerMode, out TriggerSource triggerSource); GetTriggerPolarity(out TriggerPolarity triggerPolarity); GetTriggerFliter(out double triggerfilter); GetTriggerDelay(out double triggerdelay); GetExpouseTime(out double expouseTime); GetGain(out double gain); config = new CameraConfig(null); config.Params.Inputs.Add("触发模式", triggerMode); config.Params.Inputs.Add("触发方式", triggerSource); config.Params.Inputs.Add("触发极性", triggerPolarity); config.Params.Inputs.Add("触发消抖", triggerfilter); config.Params.Inputs.Add("触发延时", triggerdelay); config.Params.Inputs.Add("曝光时间", expouseTime); config.Params.Inputs.Add("增益", gain); } #endregion } }