using MVSDK_Net;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Drawing;
using System.Drawing.Imaging;
using System.Linq;
using System.Runtime.InteropServices;
using System.Threading;
using System.Windows.Forms;
namespace LB_VisionProcesses.Cameras
{
///
/// 华睿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);
}
#endregion
}
}