#define MVCAMERA
|
|
using MvCameraControl;
|
using LB_VisionProcesses;
|
using System.Diagnostics;
|
using System.Runtime.InteropServices;
|
using LB_VisionProcesses.Cameras;
|
|
namespace LB_VisionProcesses.Cameras.HikCameras
|
{
|
public class HikCamera : BaseCamera
|
{
|
readonly DeviceTLayerType enumTLayerType = DeviceTLayerType.MvGigEDevice | DeviceTLayerType.MvUsbDevice
|
| DeviceTLayerType.MvGenTLGigEDevice | DeviceTLayerType.MvGenTLCXPDevice | DeviceTLayerType.MvGenTLCameraLinkDevice | DeviceTLayerType.MvGenTLXoFDevice;
|
public HikCamera() : base()
|
{
|
Brand = CameraBrand.HikCamera;
|
}
|
|
#region param
|
[DllImport("kernel32.dll", EntryPoint = "RtlMoveMemory", SetLastError = false)]
|
public static extern void CopyMemory(IntPtr dest, IntPtr src, uint count);
|
|
List<IDeviceInfo> deviceInfoList = new List<IDeviceInfo>();
|
List<string> deviceSNList = new List<string>();
|
|
IDevice device = null;
|
IInterface _ifInstance;
|
|
IntPtr m_BufForDriver = IntPtr.Zero;
|
UInt32 _bufferSize = 3072 * 2048 * 3;
|
private byte[] _buffer;
|
private uint _buffSizeForSaveImage = 3072 * 2048 * (16 * 3 + 4) + 2048;
|
private byte[] _bufForSaveImage;
|
private Object m_BufForSaveImageLock = new Object();
|
public IntPtr m_pSaveImageBuf = IntPtr.Zero;
|
#endregion
|
|
#region operate
|
public override List<string> GetListEnum()
|
{
|
List<string> deviceList = new List<string>();
|
foreach (var item in GetListInfoEnum())
|
{
|
IDeviceInfo deviceInfo = item;
|
if (deviceInfo.UserDefinedName != "")
|
{
|
//deviceList.Add(deviceInfo.TLayerType.ToString() + ": " + deviceInfo.UserDefinedName + " (" + deviceInfo.SerialNumber + ")");
|
deviceList.Add(deviceInfo.SerialNumber);
|
}
|
else
|
{
|
//deviceList.Add(deviceInfo.TLayerType.ToString() + ": " + deviceInfo.ManufacturerName + " " + deviceInfo.ModelName + " (" + deviceInfo.SerialNumber + ")");
|
deviceList.Add(deviceInfo.SerialNumber);
|
}
|
}
|
return deviceList;
|
}
|
|
public override bool InitDevice(string CamSN, object handle = null)
|
{
|
try
|
{
|
int nRet;
|
if (string.IsNullOrEmpty(CamSN)) return false;
|
var infolist = GetListInfoEnum();
|
if (infolist.Count < 1) return false;
|
|
IDeviceInfo deviceInfo = infolist[0];
|
bool selectSNflag = false;
|
foreach (var item in infolist)
|
{
|
if (item.SerialNumber.Equals(CamSN))
|
{
|
deviceInfo = item;
|
selectSNflag = true;
|
break;
|
}
|
}
|
if (!selectSNflag) return false;
|
|
try
|
{
|
// ch:打开设备 | en:Open device
|
device = DeviceFactory.CreateDevice(deviceInfo);
|
}
|
catch (Exception ex)
|
{
|
MessageBox.Show("Create Device fail!" + ex.Message, "异常");
|
return false;
|
}
|
|
|
nRet = device.Open();
|
if (nRet != MvError.MV_OK)
|
{
|
ShowErrorMsg("Open Device fail!", nRet);
|
return false;
|
}
|
|
// ch:探测网络最佳包大小(只对GigE相机有效) | en:Detection network optimal package size(It only works for the GigE camera)
|
if (device is IGigEDevice)
|
{
|
int packetSize;
|
nRet = (device as IGigEDevice).GetOptimalPacketSize(out packetSize);
|
if (packetSize > 0)
|
{
|
nRet = device.Parameters.SetIntValue("GevSCPSPacketSize", packetSize);
|
if (nRet != MvError.MV_OK)
|
{
|
Debug.WriteLine("Warning: Set Packet Size failed {0:x8}", nRet);
|
}
|
else
|
{
|
Debug.WriteLine("Set PacketSize to {0}", packetSize);
|
}
|
}
|
else
|
{
|
Debug.WriteLine("Warning: Get Packet Size failed {0:x8}", nRet);
|
}
|
}
|
|
// ch:设置触发模式为On || en:set trigger mode as On
|
// 设置为Off会一直触发回调
|
SetTriggerMode(TriggerMode.On, TriggerSource.Software);
|
device.Parameters.SetEnumValueByString("AcquisitionMode", "Continuous");
|
|
// ch:注册回调函数 | en:Register image callback
|
// 注册回调函数操作应放在打开采集流操作之前
|
device.StreamGrabber.FrameGrabedEvent += CallBackEventHandler;
|
|
if (nRet != MvError.MV_OK)
|
{
|
Debug.WriteLine("Set TriggerMode failed:{0:x8}", nRet);
|
return false;
|
}
|
|
if (!StartGrabbing())
|
{
|
Debug.WriteLine("开始采集失败");
|
return false;
|
}
|
|
//ch: 设置合适的缓存节点数量 | en: Setting the appropriate number of image nodes
|
device.StreamGrabber.SetImageNodeNum(5);
|
|
SN = CamSN;
|
Brand = CameraBrand.HikCamera;
|
return true;
|
}
|
catch { return false; }
|
}
|
|
public override bool CloseDevice()
|
{
|
if (device == null)
|
{
|
return false;
|
}
|
try
|
{
|
isGrabbing = false;
|
if (m_BufForDriver != IntPtr.Zero)
|
{
|
Marshal.Release(m_BufForDriver);
|
}
|
|
// ch:关闭设备 | en:Close device
|
var nRet = device.Close();
|
if (MvError.MV_OK == nRet)
|
{
|
// ch:销毁设备 | en:Destroy device
|
device.Dispose();
|
return true;
|
}
|
nRet = device.Close();
|
if (MvError.MV_OK != nRet)
|
{
|
Debug.WriteLine("Close device failed:{0:x8}", nRet);
|
return false;
|
}
|
|
// ch:销毁设备 | en:Destroy device
|
device.Dispose();
|
|
device = null;
|
return true;
|
}
|
catch
|
{
|
device = null;
|
return false;
|
}
|
}
|
|
/// <summary>
|
/// ch:软触发执行一次 | en:Trigger once by software
|
/// </summary>
|
public override bool SoftTrigger()
|
{
|
int nRet;
|
// ch:触发命令 | en:Trigger command
|
nRet = device.Parameters.SetCommandValue("TriggerSoftware");
|
|
return (MvError.MV_OK == nRet);
|
}
|
#endregion
|
|
#region SettingConfig
|
public override bool SetTriggerMode(TriggerMode mode = TriggerMode.On, TriggerSource triggerEnum = TriggerSource.None)
|
{
|
try
|
{
|
int nRet;
|
switch (mode)
|
{
|
case TriggerMode.Off:
|
nRet = device.Parameters.SetEnumValueByString("TriggerMode", "Off");
|
break;
|
case TriggerMode.On:
|
nRet = device.Parameters.SetEnumValueByString("TriggerMode", "On");
|
break;
|
default:
|
nRet = device.Parameters.SetEnumValueByString("TriggerMode", "On");
|
break;
|
}
|
bool flag1 = (MvError.MV_OK == nRet);
|
switch (triggerEnum)
|
{
|
case TriggerSource.Software:
|
nRet = device.Parameters.SetEnumValueByString("TriggerSource", "Software");
|
break;
|
case TriggerSource.Line0:
|
nRet = device.Parameters.SetEnumValueByString("TriggerSource", "Line0");
|
break;
|
case TriggerSource.Line1:
|
nRet = device.Parameters.SetEnumValueByString("TriggerSource", "Line1");
|
break;
|
case TriggerSource.Line2:
|
nRet = device.Parameters.SetEnumValueByString("TriggerSource", "Line2");
|
break;
|
case TriggerSource.Line3:
|
nRet = device.Parameters.SetEnumValueByString("TriggerSource", "Line3");
|
break;
|
case TriggerSource.Line4:
|
nRet = device.Parameters.SetEnumValueByString("TriggerSource", "Line4");
|
break;
|
default:
|
break;
|
}
|
bool flag2 = (MvError.MV_OK == nRet);
|
return flag1 && flag2;
|
}
|
catch { return false; }
|
}
|
|
public override bool GetTriggerMode(out TriggerMode mode, out TriggerSource source)
|
{
|
int nRet;
|
mode = TriggerMode.On;
|
source = TriggerSource.Software;
|
|
IEnumValue enumValue;
|
nRet = device.Parameters.GetEnumValue("TriggerMode", out enumValue);
|
bool flag1 = (MvError.MV_OK == nRet);
|
if (flag1)
|
{
|
switch (enumValue.CurEnumEntry.Symbolic)
|
{
|
case "On":
|
mode = TriggerMode.On;
|
break;
|
case "Off":
|
mode = TriggerMode.Off;
|
break;
|
default:
|
mode = TriggerMode.On;
|
break;
|
}
|
}
|
|
nRet = device.Parameters.GetEnumValue("TriggerSource", out enumValue);
|
bool flag2 = (MvError.MV_OK == nRet);
|
if (flag2)
|
{
|
switch (enumValue.CurEnumEntry.Symbolic)
|
{
|
case "TriggerSoftware":
|
case "Software":
|
source = TriggerSource.Software;
|
break;
|
case "Line0":
|
source = TriggerSource.Line0;
|
break;
|
case "Line1":
|
source = TriggerSource.Line1;
|
break;
|
case "Line2":
|
source = TriggerSource.Line2;
|
break;
|
default:
|
source = TriggerSource.Line0;
|
break;
|
}
|
}
|
return flag1 && flag2;
|
}
|
|
public override bool SetExpouseTime(double value)
|
{
|
try
|
{
|
int nRet = device.Parameters.SetFloatValue("ExposureTime", Convert.ToSingle(value));
|
return (MvError.MV_OK == nRet);
|
}
|
catch { return false; }
|
|
}
|
|
public override bool GetExpouseTime(out double value)
|
{
|
IFloatValue floatValue;
|
int nRet = device.Parameters.GetFloatValue("ExposureTime", out floatValue);
|
value = Convert.ToDouble(floatValue.CurValue);
|
return (MvError.MV_OK == nRet);
|
}
|
|
public override bool SetTriggerPolarity(TriggerPolarity polarity)
|
{
|
//return true;
|
|
IEnumValue enumValue;
|
int nRet = device.Parameters.GetEnumValue("TimerTriggerActivation", out enumValue);
|
if (nRet != MvError.MV_OK)
|
return false;
|
|
for (int i = 0; i < enumValue.SupportedNum; ++i)
|
{
|
if (polarity.ToString().Equals(enumValue.SupportEnumEntries[i].Symbolic, StringComparison.OrdinalIgnoreCase))
|
{
|
nRet = device.Parameters.SetEnumValue("TimerTriggerActivation", enumValue.SupportEnumEntries[i].Value);
|
if (nRet != MvError.MV_OK)
|
return false;
|
|
break;
|
}
|
}
|
return (MvError.MV_OK == nRet);
|
}
|
|
public override bool GetTriggerPolarity(out TriggerPolarity polarity)
|
{
|
polarity = TriggerPolarity.RisingEdge;
|
//return true;
|
|
IEnumValue enumValue;
|
int nRet = device.Parameters.GetEnumValue("TimerTriggerActivation", out enumValue);
|
if (nRet != MvError.MV_OK)
|
{
|
return false;
|
}
|
string activate = enumValue.CurEnumEntry.Symbolic;
|
//1下降沿 0上升沿
|
|
//上升沿
|
if (activate == "RisingEdge")
|
polarity = TriggerPolarity.RisingEdge;
|
//下降沿
|
else if (activate == "FallingEdge")
|
|
polarity = TriggerPolarity.FallingEdge;
|
return (MvError.MV_OK == nRet);
|
}
|
|
public override bool SetTriggerFliter(double flitertime)
|
{
|
try
|
{
|
int nRet = device.Parameters.SetIntValue("LineDebouncerTimeNs", (uint)flitertime);
|
//nRet = device.Parameters.SetIntValue("LineDebouncerTime", (uint)flitertime);
|
return (MvError.MV_OK == nRet);
|
}
|
catch { return false; }
|
}
|
|
public override bool GetTriggerFliter(out double flitertime)
|
{
|
flitertime = 1000;
|
IFloatValue floatValue;
|
int nRet = device.Parameters.GetFloatValue("ExposureTime", out floatValue);
|
flitertime = Convert.ToDouble(floatValue.CurValue);
|
return (MvError.MV_OK == nRet);
|
}
|
|
public override bool SetTriggerDelay(double delay)
|
{
|
try
|
{
|
int nRet = device.Parameters.SetFloatValue("TriggerDelay", Convert.ToSingle(delay));
|
return (MvError.MV_OK == nRet);
|
}
|
catch { return false; }
|
}
|
|
public override bool GetTriggerDelay(out double delay)
|
{
|
delay = 0;
|
IFloatValue floatValue;
|
int nRet = device.Parameters.GetFloatValue("TriggerDelay", out floatValue);
|
delay = Convert.ToDouble(floatValue.CurValue);
|
return (MvError.MV_OK == nRet);
|
}
|
|
public override bool SetGain(double gain)
|
{
|
try
|
{
|
int nRet = device.Parameters.SetFloatValue("Gain", Convert.ToSingle(gain));
|
return (MvError.MV_OK == nRet);
|
}
|
catch { return false; }
|
}
|
|
public override bool GetGain(out double gain)
|
{
|
gain = 0;
|
IFloatValue floatValue;
|
int nRet = device.Parameters.GetFloatValue("Gain", out floatValue);
|
gain = Convert.ToDouble(floatValue.CurValue);
|
return (MvError.MV_OK == nRet);
|
}
|
|
public override bool SetLineMode(IOLines line, LineMode mode)
|
{
|
int nRet = device.Parameters.SetEnumValueByString(line.ToString(), mode.ToString());
|
return (MvError.MV_OK == nRet);
|
}
|
|
public override bool SetLineStatus(IOLines line, LineStatus linestatus)
|
{
|
int nRet = device.Parameters.SetBoolValue(line.ToString(), linestatus.Equals(LineStatus.Hight));
|
return (MvError.MV_OK == nRet);
|
}
|
|
public override bool GetLineStatus(IOLines line, out LineStatus linestatus)
|
{
|
bool resultsignal = false;
|
int nRet = device.Parameters.GetBoolValue(line.ToString(), out resultsignal);
|
linestatus = resultsignal ? LineStatus.Hight : LineStatus.Low;
|
return (MvError.MV_OK == nRet);
|
}
|
|
public override bool AutoBalanceWhite()
|
{
|
int nRet = device.Parameters.SetEnumValueByString("BalanceWhiteAuto", "Once");
|
return (MvError.MV_OK == nRet);
|
}
|
|
#endregion
|
|
#region helper
|
// ch:显示错误信息 | en:Show error message
|
private void ShowErrorMsg(string message, int errorCode)
|
{
|
string errorMsg;
|
if (errorCode == 0)
|
errorMsg = message;
|
else
|
errorMsg = message + ": Error =" + String.Format("{0:X}", errorCode);
|
|
switch (errorCode)
|
{
|
case MvError.MV_E_HANDLE: errorMsg += " Error or invalid handle "; break;
|
case MvError.MV_E_SUPPORT: errorMsg += " Not supported function "; break;
|
case MvError.MV_E_BUFOVER: errorMsg += " Cache is full "; break;
|
case MvError.MV_E_CALLORDER: errorMsg += " Function calling order error "; break;
|
case MvError.MV_E_PARAMETER: errorMsg += " Incorrect parameter "; break;
|
case MvError.MV_E_RESOURCE: errorMsg += " Applying resource failed "; break;
|
case MvError.MV_E_NODATA: errorMsg += " No data "; break;
|
case MvError.MV_E_PRECONDITION: errorMsg += " Precondition error, or running environment changed "; break;
|
case MvError.MV_E_VERSION: errorMsg += " Version mismatches "; break;
|
case MvError.MV_E_NOENOUGH_BUF: errorMsg += " Insufficient memory "; break;
|
case MvError.MV_E_UNKNOW: errorMsg += " Unknown error "; break;
|
case MvError.MV_E_GC_GENERIC: errorMsg += " General error "; break;
|
case MvError.MV_E_GC_ACCESS: errorMsg += " Node accessing condition error "; break;
|
case MvError.MV_E_ACCESS_DENIED: errorMsg += " No permission "; break;
|
case MvError.MV_E_BUSY: errorMsg += " Device is busy, or network disconnected "; break;
|
case MvError.MV_E_NETER: errorMsg += " Network error "; break;
|
}
|
|
MessageBox.Show(errorMsg, "异常");
|
}
|
public override bool StartGrabbing()
|
{
|
try
|
{
|
// Set default state after grabbing starts
|
// Turn off real-time mode which is default
|
// 0: real-time
|
// 1: trigger
|
|
CallBackImg = null;
|
int nRet = device.StreamGrabber.StartGrabbing();
|
if (MvError.MV_OK != nRet) Debug.WriteLine("Grab start failed");
|
isGrabbing = true;
|
return (MvError.MV_OK == nRet);
|
}
|
catch (Exception ex)
|
{
|
Debug.WriteLine("StartGrabbing failed: " + ex.Message);
|
return false;
|
}
|
}
|
|
public override bool StopGrabbing()
|
{
|
int nRet = device.StreamGrabber.StopGrabbing();
|
if (MvError.MV_OK != nRet) Debug.WriteLine("Grab stop failed");
|
isGrabbing = false;
|
CallBackImg = null;
|
|
return (MvError.MV_OK == nRet);
|
}
|
|
private List<IDeviceInfo> GetListInfoEnum()
|
{
|
System.GC.Collect();
|
deviceInfoList.Clear();
|
// ch:创建设备列表 | en:Create Device List
|
int nRet = DeviceEnumerator.EnumDevices(enumTLayerType, out deviceInfoList);
|
if (nRet != MvError.MV_OK)
|
{
|
ShowErrorMsg("Enumerate devices fail!", nRet);
|
return new List<IDeviceInfo>();
|
}
|
|
// ch:在窗体列表中显示设备名 | en:Display device name in the form list
|
for (int i = 0; i < deviceInfoList.Count; i++)
|
{
|
IDeviceInfo deviceInfo = deviceInfoList[i];
|
if (deviceInfo.UserDefinedName != "")
|
deviceSNList.Add(deviceInfo.TLayerType.ToString() + ": " + deviceInfo.UserDefinedName + " (" + deviceInfo.SerialNumber + ")");
|
else
|
deviceSNList.Add(deviceInfo.TLayerType.ToString() + ": " + deviceInfo.ManufacturerName + " " + deviceInfo.ModelName + " (" + deviceInfo.SerialNumber + ")");
|
}
|
|
// ch:选择第一项 | en:Select the first item
|
if (deviceInfoList.Count != 0)
|
{
|
deviceSNList[0] = deviceSNList[0];
|
}
|
return deviceInfoList;
|
}
|
|
static bool IsMonoPixelFormat(MvGvspPixelType enType)
|
{
|
switch (enType)
|
{
|
case MvGvspPixelType.PixelType_Gvsp_Mono10:
|
case MvGvspPixelType.PixelType_Gvsp_Mono10_Packed:
|
case MvGvspPixelType.PixelType_Gvsp_Mono12:
|
case MvGvspPixelType.PixelType_Gvsp_Mono12_Packed:
|
return true;
|
default:
|
return false;
|
}
|
}
|
|
static bool IsColorPixelFormat(MvGvspPixelType enType)
|
{
|
switch (enType)
|
{
|
case MvGvspPixelType.PixelType_Gvsp_BGR8_Packed:
|
case MvGvspPixelType.PixelType_Gvsp_YUV422_Packed:
|
case MvGvspPixelType.PixelType_Gvsp_YUV422_YUYV_Packed:
|
case MvGvspPixelType.PixelType_Gvsp_BayerGR8:
|
case MvGvspPixelType.PixelType_Gvsp_BayerRG8:
|
case MvGvspPixelType.PixelType_Gvsp_BayerGB8:
|
case MvGvspPixelType.PixelType_Gvsp_BayerBG8:
|
case MvGvspPixelType.PixelType_Gvsp_BayerGB10:
|
case MvGvspPixelType.PixelType_Gvsp_BayerGB10_Packed:
|
case MvGvspPixelType.PixelType_Gvsp_BayerBG10:
|
case MvGvspPixelType.PixelType_Gvsp_BayerBG10_Packed:
|
case MvGvspPixelType.PixelType_Gvsp_BayerRG10:
|
case MvGvspPixelType.PixelType_Gvsp_BayerRG10_Packed:
|
case MvGvspPixelType.PixelType_Gvsp_BayerGR10:
|
case MvGvspPixelType.PixelType_Gvsp_BayerGR10_Packed:
|
case MvGvspPixelType.PixelType_Gvsp_BayerGB12:
|
case MvGvspPixelType.PixelType_Gvsp_BayerGB12_Packed:
|
case MvGvspPixelType.PixelType_Gvsp_BayerBG12:
|
case MvGvspPixelType.PixelType_Gvsp_BayerBG12_Packed:
|
case MvGvspPixelType.PixelType_Gvsp_BayerRG12:
|
case MvGvspPixelType.PixelType_Gvsp_BayerRG12_Packed:
|
case MvGvspPixelType.PixelType_Gvsp_BayerGR12:
|
case MvGvspPixelType.PixelType_Gvsp_BayerGR12_Packed:
|
return true;
|
default:
|
return false;
|
}
|
}
|
|
/// <summary>
|
/// 回调函数(不要在内部增加耗时操作)
|
/// </summary>
|
/// <param name="sender"></param>
|
/// <param name="e"></param>
|
private void CallBackEventHandler(object sender, FrameGrabbedEventArgs e)
|
{
|
try
|
{
|
int nRet;
|
//Debug.WriteLine("Get Image Buffer: Width[{0}] , Height[{1}] , FrameNum[{2}]"
|
//, e.FrameOut.Image.Width, e.FrameOut.Image.Height, e.FrameOut.FrameNum);
|
|
IImage inputImage = e.FrameOut.Image;
|
IImage outImage = inputImage;
|
MvGvspPixelType dstPixelType = MvGvspPixelType.PixelType_Gvsp_Undefined;
|
|
if (IsColorPixelFormat(e.FrameOut.Image.PixelType))
|
dstPixelType = MvGvspPixelType.PixelType_Gvsp_RGB8_Packed;
|
else if (IsMonoPixelFormat(e.FrameOut.Image.PixelType))
|
dstPixelType = MvGvspPixelType.PixelType_Gvsp_Mono8;
|
else
|
Debug.WriteLine($"【{DateTime.Now:HH:mm:ss.fff}】Don't need to convert!");
|
|
if (dstPixelType != MvGvspPixelType.PixelType_Gvsp_Undefined)
|
{
|
// ch:像素格式转换 | en:Pixel type convert
|
nRet = device.PixelTypeConverter.ConvertPixelType(inputImage, out outImage, dstPixelType);
|
if (nRet != MvError.MV_OK)
|
{
|
Debug.WriteLine($"【{DateTime.Now:HH:mm:ss.fff}】Image Convert failed:{0:x8}", nRet);
|
return;
|
}
|
//Debug.WriteLine($"【{DateTime.Now:HH:mm:ss.fff}】Image Convert success!");
|
}
|
//ch: 释放图像缓存 | en: Release image buffer
|
device.StreamGrabber.FreeImageBuffer(e.FrameOut);
|
|
if (this.ImageGrabbed != null)
|
this.ImageGrabbed(this, new CameraEventArgs(SN, outImage.ToBitmap()));
|
|
try
|
{
|
CallBackImg = outImage.ToBitmap();
|
if (CallBackImg == null) return;
|
if (GetTriggerMode(out TriggerMode mode, out TriggerSource source))
|
{
|
if (mode == TriggerMode.On && source != TriggerSource.Software)
|
TriggerRunMessageReceived?.Invoke(SN, source.ToString()); // 触发运行事件
|
}
|
}
|
catch { }
|
|
//ActionGetImage?.Invoke(SN, outImage.ToBitmap());
|
}
|
catch { }
|
}
|
|
public override bool GetImage(out Bitmap bitmap, int outtime = 3000)
|
{
|
bitmap = null;
|
|
try
|
{
|
// 设置超时时间
|
DateTime lastTime = DateTime.Now.AddMilliseconds(outtime);
|
// 判断是否超时
|
while (lastTime > DateTime.Now)// 设置超时时间为 3 秒
|
{
|
try
|
{
|
if (CallBackImg != null)
|
{
|
// 保存旧 Bitmap 并释放
|
bitmap = CallBackImg.Clone() as Bitmap; // 创建副本
|
|
// 释放旧资源
|
CallBackImg.Dispose();
|
CallBackImg = null;
|
return true;
|
}
|
}
|
catch { }
|
Thread.Sleep(10);
|
}
|
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);
|
}
|
|
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 StartContinuousGrab()
|
{
|
throw new NotImplementedException();
|
}
|
|
#endregion
|
}
|
}
|