using System; using System.Collections; using System.Collections.Generic; using System.ComponentModel; using System.Diagnostics; using System.Drawing; using System.Drawing.Imaging; using System.IO; using System.Linq; using System.Reflection; using System.Runtime.InteropServices; using System.Text; using System.Threading; using System.Threading.Tasks; using System.Timers; using System.Windows.Forms; using IKapBoardClassLibrary; using IKapC.NET; using LeatherApp.Device.CamerUtil; using LeatherApp.Interface; using Newtonsoft.Json.Linq; using OpenCvSharp; using OpenCvSharp.Dnn; using ErrorCode = IKapBoardClassLibrary.ErrorCode; namespace LeatherApp.Device { public class CamerCardDevIK : ABSCamerCardDev,IDisposable { [DllImport("user32.dll")] [return: MarshalAs(UnmanagedType.Bool)] private static extern bool IsWindow(IntPtr hWnd); [DllImport("kernel32.dll")] public static extern void CopyMemory(IntPtr Destination, IntPtr Source, int Length); // 相机句柄 //private IKDeviceCL m_pDev = new IKDeviceCL(); public IntPtr m_pDev = new IntPtr(-1); // 采集卡句柄 public IntPtr m_pBoard = new IntPtr(-1); // 用户缓冲区,用于图像数据转换 public IntPtr m_pUserBuffer = new IntPtr(-1); // 是否正在采集 public volatile bool m_bGrabingImage = false; // 是否已更新用户缓冲区 public volatile bool m_bUpdateImage = false; // 相机类型,0为GV相机,1为CL相机,2为CXP相机 public int m_nType = -1; // 图像宽度 public int m_nWidth = -1; // 图像高度 public int m_nHeight = -1; // 像素位数 public int m_nDepth = 8; // 图像通道数 public int m_nChannels = 1; // 相机索引 public int m_nDevIndex = -1; // 采集卡索引 public int m_nBoardIndex = -1; // 相机缓冲区个数 public int m_nFrameCount = 2;//只能1 // 当前帧索引 public int m_nCurFrameIndex = 0; // 相机缓冲区大小 public int m_nBufferSize = 0; // 用户缓冲区锁 public object m_mutexImage = new object(); //显示图像控件句柄 private PictureBox previewHwnd = null; // // 保存图像的文件名。 public string m_strFileName = "C:\\CSharpImage.bmp"; // private int scanIndex = 0; //实际拍照从1开始命名,因先加的1 private string bmpSavePath; private Thread readerThread; private Queue frameQueue =new Queue(); /// /// 曝光 3.00-10000.00 /// public float ExposureTime { get; private set; } /// /// 增益 0-23.981199 /// public float Gain { get; private set; } /// /// 帧率 0-429496.718750 /// public float ResultingFrameRate { get; private set; } /// /// 图片大小 /// public System.Drawing.Size size { get; private set; } /// /// 是否打开设备成功 /// public bool IsInit { get; private set; } = false; //public string ErrInfo { get; private set; } //private System.Timers.Timer timer = new System.Timers.Timer(); private int _scannerCardIndex = 0;//采集卡索引 private int _scannerIndex=0;//相机索引(一个采集卡上可插多个相机) private IKDeviceInfo devInfo; BufferToImage hBuffer; private class MyData { public MyData(int _index,Mat _mat) { index= _index; mat = _mat; } public int index; public Mat mat; } // 设备类型枚举 enum IKDeviceType { DEVICE_NIL = 0, DEVICE_CML, DEVICE_CXP, DEVICE_USB, DEVICE_GIGEVISION } // 设备信息结构体 struct IKDeviceInfo { public IKDeviceType nType; public int nDevIndex; public int nBoardIndex; public string sDevName; } /// /// 读取缓存队列线程 /// private void readDataThread() { MyData mydate; while (IsInit) { if (frameQueue.Count > 0) // 如果队列不为空则从队列中获取元素 { lock (frameQueue) { mydate = frameQueue.Dequeue(); } PhotoNumCacheEvent?.Invoke(frameQueue.Count); WarningEvent?.BeginInvoke(DateTime.Now,WarningEnum.Normal, $"相机({_scannerCardIndex})从缓存队列提取一帧图像({mydate.index}),开始回调(队列剩余帧数:{frameQueue.Count})...", null, null); ScanEvent?.Invoke(mydate.index, mydate.mat, _scannerCardIndex); WarningEvent?.BeginInvoke(DateTime.Now,WarningEnum.Normal, $"相机({_scannerCardIndex})图像({mydate.index})回调完成.", null, null); } else { Thread.Sleep(10); } } } public CamerCardDevIK( ) { m_nType = 1; } public override bool open(int nBoardIndex,int nDevIndex) { if (IsInit) return true; _scannerCardIndex = nBoardIndex; WarningEvent?.BeginInvoke(DateTime.Now,WarningEnum.Normal, "open ....",null,null); try { closeDevice(); scanIndex = 0; devInfo = new IKDeviceInfo(); readerThread = new Thread(readDataThread); // 创建读取线程 // uint nDevCount = 2; uint res = IKapCLib.ItkManGetDeviceCount(ref nDevCount); if (res != (uint)ItkStatusErrorId.ITKSTATUS_OK) { WarningEvent?.Invoke(DateTime.Now,WarningEnum.High, "ItkManGetDeviceCount failed"); return false; } IKapCLib.ITKDEV_INFO pDevInfo = new IKapCLib.ITKDEV_INFO(); IKapCLib.ITK_CL_DEV_INFO pClDevInfo = new IKapCLib.ITK_CL_DEV_INFO(); for (uint i = 0; i < nDevCount; ++i) { IKapCLib.ItkManGetDeviceInfo(i, ref pDevInfo); if (pDevInfo.DeviceClass.CompareTo("CameraLink") == 0) { res = IKapCLib.ItkManGetCLDeviceInfo(i, ref pClDevInfo); //if (res != (uint)ItkStatusErrorId.ITKSTATUS_OK) // return; if ((int)pClDevInfo.BoardIndex == nBoardIndex) { devInfo.nType = IKDeviceType.DEVICE_CML; devInfo.nDevIndex = (int)i; devInfo.nBoardIndex = (int)pClDevInfo.BoardIndex; devInfo.sDevName = pDevInfo.FullName; } } } if(devInfo.nType != IKDeviceType.DEVICE_CML) { WarningEvent?.Invoke(DateTime.Now,WarningEnum.High, "对应索引相机不存在 failed"); return false; } // res = IKapCLib.ItkDevOpen((uint)devInfo.nDevIndex , (int)(ItkDeviceAccessMode.ITKDEV_VAL_ACCESS_MODE_CONTROL) , ref m_pDev); if (!Check(res)) { WarningEvent?.Invoke(DateTime.Now,WarningEnum.High, "Camera error:Open camera failed"); return false; } //打开采集卡 m_pBoard = IKapBoard.IKapOpen((uint)BoardType.IKBoardPCIE, (uint)devInfo.nBoardIndex); if (m_pBoard == new IntPtr(-1)) { WarningEvent?.Invoke(DateTime.Now,WarningEnum.High, "IKapOpen failed"); return false; } IsInit = true; readerThread.Start(); return true; } catch (Exception ex) { WarningEvent?.Invoke(DateTime.Now,WarningEnum.High, ex.Message); return false; } } public override void close() { if (!IsInit) return; try { IsInit = false; // 清除回调函数。 UnRegisterCallback(); // 关闭设备。 CloseDevice(); } catch { } } /// /// /// /// 显示图像控件句柄 /// public override bool start(PictureBox preview_Hwnd,string bmp_save_path) { if (!IsInit) return false; WarningEvent?.Invoke(DateTime.Now,WarningEnum.Normal, "start ...."); // 导入配置文件。 string configFileName = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location) + "\\DevCfg\\" + (_scannerCardIndex==0?Config.Carmer1ConfigFilePath: Config.Carmer2ConfigFilePath); if (!File.Exists(configFileName)) { WarningEvent?.Invoke(DateTime.Now,WarningEnum.High, "Fail to get configuration, using default setting!"); return false; } var b=loadConfiguration(configFileName); WarningEvent?.Invoke(DateTime.Now,WarningEnum.Normal, "开始采集 ..."+b.ToString()); this.previewHwnd= preview_Hwnd; this.bmpSavePath = bmp_save_path; //开始采集 //第二个参数 nFrameCount 表示希望 IKapBoardClassLibrary 采集的帧数。 //如果 nFrameCount = 1,IKapBoardClassLibrary 会从相机中采集一帧图像; //如果 nFrameCount = N 且 N> 1,则 IKapBoardClassLibrary 从相机中采集连续的 N 帧图 像; //如果 nFrameCount = 0,则 IKapBoardClassLibrary 开始连续采集图像。 int ret; // 设置抓取模式,IKP_GRAB_NON_BLOCK为非阻塞模式 //int grab_mode = (int)GrabMode.IKP_GRAB_NON_BLOCK; //ret = IKapBoard.IKapSetInfo(m_pBoard, (uint)INFO_ID.IKP_GRAB_MODE, grab_mode); //if (ret != (int)ErrorCode.IK_RTN_OK) // return false; //// 设置帧传输模式,IKP_FRAME_TRANSFER_SYNCHRONOUS_NEXT_EMPTY_WITH_PROTECT为同步保存模式 //int transfer_mode = (int)FrameTransferMode.IKP_FRAME_TRANSFER_SYNCHRONOUS_NEXT_EMPTY_WITH_PROTECT; //ret = IKapBoard.IKapSetInfo(m_pBoard, (uint)INFO_ID.IKP_FRAME_TRANSFER_MODE, transfer_mode); //if (ret != (int)ErrorCode.IK_RTN_OK) // return false; //设置缓冲区格式 ret = IKapBoard.IKapSetInfo(m_pBoard, (uint)INFO_ID.IKP_FRAME_COUNT, 1);// if (ret != (int)ErrorCode.IK_RTN_OK) return false; // 设置帧超时时间 int timeout = -1; ret = IKapBoard.IKapSetInfo(m_pBoard, (uint)INFO_ID.IKP_TIME_OUT, timeout); if (ret != (int)ErrorCode.IK_RTN_OK) return false; // 设置采集模式。 // // Set grab mode. int grab_mode = (int)GrabMode.IKP_GRAB_NON_BLOCK; ret = IKapBoard.IKapSetInfo(m_pBoard, (uint)INFO_ID.IKP_GRAB_MODE, grab_mode); if (ret != (int)ErrorCode.IK_RTN_OK) return false; // 设置传输模式。 int transfer_mode = (int)FrameTransferMode.IKP_FRAME_TRANSFER_SYNCHRONOUS_NEXT_EMPTY_WITH_PROTECT; ret = IKapBoard.IKapSetInfo(m_pBoard, (uint)INFO_ID.IKP_FRAME_TRANSFER_MODE, transfer_mode); if (ret != (int)ErrorCode.IK_RTN_OK) return false; // 注册回调函数 IntPtr hPtr = new IntPtr(-1); OnGrabStartProc = new IKapCallBackProc(OnGrabStartFunc); ret = IKapBoard.IKapRegisterCallback(m_pBoard, (uint)CallBackEvents.IKEvent_GrabStart, Marshal.GetFunctionPointerForDelegate(OnGrabStartProc), hPtr); if (ret != (int)ErrorCode.IK_RTN_OK) return false; OnFrameReadyProc = new IKapCallBackProc(OnFrameReadyFunc); ret = IKapBoard.IKapRegisterCallback(m_pBoard, (uint)CallBackEvents.IKEvent_FrameReady, Marshal.GetFunctionPointerForDelegate(OnFrameReadyProc), hPtr); if (ret != (int)ErrorCode.IK_RTN_OK) return false; OnFrameLostProc = new IKapCallBackProc(OnFrameLostFunc); ret = IKapBoard.IKapRegisterCallback(m_pBoard, (uint)CallBackEvents.IKEvent_FrameLost, Marshal.GetFunctionPointerForDelegate(OnFrameLostProc), hPtr); if (ret != (int)ErrorCode.IK_RTN_OK) return false; OnTimeoutProc = new IKapCallBackProc(OnTimeoutFunc); ret = IKapBoard.IKapRegisterCallback(m_pBoard, (uint)CallBackEvents.IKEvent_TimeOut, Marshal.GetFunctionPointerForDelegate(OnTimeoutProc), hPtr); if (ret != (int)ErrorCode.IK_RTN_OK) return false; OnGrabStopProc = new IKapCallBackProc(OnGrabStopFunc); ret = IKapBoard.IKapRegisterCallback(m_pBoard, (uint)CallBackEvents.IKEvent_GrabStop, Marshal.GetFunctionPointerForDelegate(OnGrabStopProc), hPtr); if (ret != (int)ErrorCode.IK_RTN_OK) return false; m_bUpdateImage = false; m_nCurFrameIndex = 0; ret = IKapBoard.IKapStartGrab(m_pBoard, 0); if (ret != (int)ErrorCode.IK_RTN_OK) return false; //createBuffer b = createBuffer(); if (!b) return false; getParam(); // m_bGrabingImage = true; return true; } /// /// 停止采集 /// public override void stop() { if (!IsInit) return; try { // 停止图像采集。 var ret = IKapBoard.IKapStopGrab(m_pBoard); clearBuffer(); CheckIKapBoard(ret); } catch { return; } } /// /// num 因拍了一张后回传的,当前已经是1了 /// /// public override void resetScanIndex() { scanIndex = 0;// } public override void getParam() { if (!IsInit) return; string result; result = getFeatureValue("ExposureTime"); if (!string.IsNullOrEmpty(result)) ExposureTime = Convert.ToSingle(result); result = getFeatureValue("Gain"); if (!string.IsNullOrEmpty(result)) Gain = Convert.ToSingle(result); } /// /// /// /// 曝光 /// 增益 /// 帧率 public override bool setParam(float exposureTime, float gain =-1, float resultingFrameRate =-1) { if (!IsInit) return false; bool change = false; //WarningEvent?.Invoke(DateTime.Now,WarningEnum.Normal, $"ExposureTime: {exposureTime},{ExposureTime}"); if (exposureTime != ExposureTime && exposureTime != -1) { if(setFeatureValue("ExposureTime", exposureTime.ToString())) change = true; } //WarningEvent?.Invoke(DateTime.Now,WarningEnum.Normal, $"Gain: {gain},{Gain}"); if (gain != Gain && gain != -1) { if (setFeatureValue("Gain", gain.ToString())) change = true; } //if (resultingFrameRate != ResultingFrameRate && resultingFrameRate != -1) //{ // cDeviceParam.SetFloatValue("AcquisitionFrameRate", resultingFrameRate); // change = true; //} // if (change) getParam(); return change; } public void Dispose() { stop(); close(); } //--------------- /* @brief:设置行触发参数。 * * @brief:Set line trigger parameters. */ void SetLineTrigger() { int ret = (int)ErrorCode.IK_RTN_OK; // 设置CC1信号源。 // // Set CC1 signal source. ret = IKapBoard.IKapSetInfo(m_pBoard, (uint)INFO_ID.IKP_CC1_SOURCE, (int)CCSource.IKP_CC_SOURCE_VAL_INTEGRATION_SIGNAL1); CheckIKapBoard(ret); // 设置积分控制方法触发信号源。 // // Set integration control method trigger source. ret = IKapBoard.IKapSetInfo(m_pBoard, (uint)INFO_ID.IKP_INTEGRATION_TRIGGER_SOURCE, (int)IntegrationTriggerSource.IKP_INTEGRATION_TRIGGER_SOURCE_VAL_SHAFT_ENCODER1); CheckIKapBoard(ret); } /* @brief:清除回调函数。 * * @brief:Unregister callback functions. */ private void UnRegisterCallback() { int ret = (int)ErrorCode.IK_RTN_OK; ret = IKapBoard.IKapUnRegisterCallback(m_pBoard, (uint)CallBackEvents.IKEvent_GrabStart); ret = IKapBoard.IKapUnRegisterCallback(m_pBoard, (uint)CallBackEvents.IKEvent_FrameReady); ret = IKapBoard.IKapUnRegisterCallback(m_pBoard, (uint)CallBackEvents.IKEvent_FrameLost); ret = IKapBoard.IKapUnRegisterCallback(m_pBoard, (uint)CallBackEvents.IKEvent_TimeOut); ret = IKapBoard.IKapUnRegisterCallback(m_pBoard, (uint)CallBackEvents.IKEvent_GrabStop); } /* @brief:关闭设备。 * * @brief:Close device. */ private void CloseDevice() { // 关闭采集卡设备。 // // Close frame grabber device. if (!m_pBoard.Equals(-1)) { IKapBoard.IKapClose(m_pBoard); m_pBoard = (IntPtr)(-1); } } /* @brief:判断 IKapBoard 函数是否成功调用。 * @param[in] ret:函数返回值。 * * @brief:Determine whether the IKapBoard function is called successfully. * @param[in] ret:Function return value. */ static void CheckIKapBoard(int ret) { if (ret != (int)ErrorCode.IK_RTN_OK) { string sErrMsg = ""; IKapBoard.IKAPERRORINFO tIKei = new IKapBoardClassLibrary.IKapBoard.IKAPERRORINFO(); // 获取错误码信息。 IKapBoard.IKapGetLastError(ref tIKei, true); // 打印错误信息。 sErrMsg = string.Concat("Error", sErrMsg, "Board Type\t = 0x", tIKei.uBoardType.ToString("X4"), "\n", "Board Index\t = 0x", tIKei.uBoardIndex.ToString("X4"), "\n", "Error Code\t = 0x", tIKei.uErrorCode.ToString("X4"), "\n" ); throw new Exception(sErrMsg); } } #region Callback delegate void IKapCallBackProc(IntPtr pParam); /* @brief:本函数被注册为一个回调函数。当图像采集开始时,函数被调用。 * * @brief:This function is registered as a callback function. When starting grabbing images, the function will be called. */ private IKapCallBackProc OnGrabStartProc; /* @brief:本函数被注册为一个回调函数。当采集丢帧时,函数被调用。 * * @brief:This function is registered as a callback function. When grabbing frame lost, the function will be called. */ private IKapCallBackProc OnFrameLostProc; /* @brief:本函数被注册为一个回调函数。当图像采集超时时,函数被调用。 * * @brief:This function is registered as a callback function. When grabbing images time out, the function will be called. */ private IKapCallBackProc OnTimeoutProc; /* @brief:本函数被注册为一个回调函数。当一帧图像采集完成时,函数被调用。 * * @brief:This function is registered as a callback function. When a frame of image grabbing ready, the function will be called. */ private IKapCallBackProc OnFrameReadyProc; /* @brief:本函数被注册为一个回调函数。当图像采集停止时,函数被调用。 * * @brief:This function is registered as a callback function. When stopping grabbing images, the function will be called. */ private IKapCallBackProc OnGrabStopProc; #endregion #region Callback /* @brief:本函数被注册为一个回调函数。当图像采集开始时,函数被调用。 * @param[in] pParam:输入参数。 * * @brief:This function is registered as a callback function. When starting grabbing images, the function will be called. * @param[in] pParam:Input parameter. */ public void OnGrabStartFunc(IntPtr pParam) { WarningEvent?.BeginInvoke(DateTime.Now,WarningEnum.Normal, "图像开始采集...", null, null); } /* @brief:本函数被注册为一个回调函数。当采集丢帧时,函数被调用。 * @param[in] pParam:输入参数。 * * @brief:This function is registered as a callback function. When grabbing frame lost, the function will be called. * @param[in] pParam:Input parameter. */ public void OnFrameLostFunc(IntPtr pParam) { WarningEvent?.BeginInvoke(DateTime.Now,WarningEnum.High, $"相机({_scannerCardIndex})采集图像({scanIndex})丢帧(Image frame lost),急停告警,需结束重新开始!!!!", null, null); } /* @brief:本函数被注册为一个回调函数。当图像采集超时时,函数被调用。 * @param[in] pParam:输入参数。 * * @brief:This function is registered as a callback function. When grabbing images time out, the function will be called. * @param[in] pParam:Input parameter. */ public void OnTimeoutFunc(IntPtr pParam) { WarningEvent?.BeginInvoke(DateTime.Now,WarningEnum.High, $"相机({_scannerCardIndex})采集图像({scanIndex})超时(Grab image timeout),请检查采集卡!", null, null); } /* @brief:本函数被注册为一个回调函数。当一帧图像采集完成时,函数被调用。 * @param[in] pParam:输入参数。 * * @brief:This function is registered as a callback function. When a frame of image grabbing ready, the function will be called. * @param[in] pParam:Input parameter. */ public void OnFrameReadyFunc(IntPtr pParam) { try { Stopwatch stopwatch = Stopwatch.StartNew(); stopwatch.Start(); int index = ++scanIndex; WarningEvent?.BeginInvoke(DateTime.Now, WarningEnum.Normal, $"OnFrameReadyFunc 相机({_scannerCardIndex})一帧图像({index})采集完成,正在加入队列({frameQueue.Count})...", null, null); IntPtr hPtr = new IntPtr(-1); // 获取当前帧状态 var ret = IKapBoard.IKapGetInfo(m_pBoard, (uint)INFO_ID.IKP_CURRENT_BUFFER_INDEX, ref m_nCurFrameIndex); if (ret != (int)ErrorCode.IK_RTN_OK) return; //IKapBoard.IKAPBUFFERSTATUS status = new IKapBoard.IKAPBUFFERSTATUS(); //IKapBoard.IKapGetBufferStatus(m_pBoard, m_nCurFrameIndex, ref status); //var uFull = status.uFull; //if (uFull == 1)//指明缓冲区是否为满 { IKapBoard.IKapGetBufferAddress(m_pBoard, m_nCurFrameIndex, ref hPtr); //Monitor.Enter(m_mutexImage); lock (m_mutexImage) { CopyMemory(m_pUserBuffer, hPtr, m_nBufferSize); m_bUpdateImage = true; Mat mat = new Mat(m_nHeight, m_nWidth, MatType.CV_8UC3, m_pUserBuffer); //var bmp = hBuffer.toBmp(m_pUserBuffer); //Mat mat = OpenCvSharp.Extensions.BitmapConverter.ToMat(bmp); //bmp.Dispose(); //bmp = null; //Monitor.Enter(frameQueue); lock (frameQueue) frameQueue.Enqueue(new MyData(index, mat.Clone())); PhotoNumCacheEvent?.BeginInvoke(frameQueue.Count, null, null); } } //m_nCurFrameIndex++; //m_nCurFrameIndex = m_nCurFrameIndex % m_nFrameCount; stopwatch.Stop(); WarningEvent?.BeginInvoke(DateTime.Now, WarningEnum.Normal, $"OnFrameReadyFunc 相机({_scannerCardIndex})一帧图像({index})已加入队列({frameQueue.Count}).缓冲区索引={m_nCurFrameIndex};用时:{stopwatch.ElapsedMilliseconds}ms", null, null); } catch (Exception ex) { WarningEvent?.BeginInvoke(DateTime.Now, WarningEnum.High, $"OnFrameReadyFunc 异常,急停告警,需结束重新开始!!!!{ex.Message}\r\n{ex.StackTrace}", null, null); } } /* @brief:本函数被注册为一个回调函数。当图像采集停止时,函数被调用。 * @param[in] pParam:输入参数。 * * @brief:This function is registered as a callback function. When stopping grabbing images, the function will be called. * @param[in] pParam:Input parameter. */ public void OnGrabStopFunc(IntPtr pParam) { Console.WriteLine("Stop grabbing image"); } #endregion private byte[] bmp2bytes(Bitmap bmp) { MemoryStream ms = new MemoryStream(); bmp.Save(ms, System.Drawing.Imaging.ImageFormat.Bmp); byte[] bytes = ms.GetBuffer(); //byte[] bytes= ms.ToArray(); 这两句都可以,至于区别么,下面有解释 ms.Close(); bmp.Dispose(); return bytes; } private Bitmap bytes2bmp(byte[] bytes) { MemoryStream ms1 = new MemoryStream(bytes); Bitmap bm = (Bitmap)Image.FromStream(ms1); ms1.Close(); return bm; } /* * @brief:设置相机特征值 * @param [in] featureName:特征名[ExposureTime,Gain] * @param [in] featureValue:特征值 * @return: 是否设置成功 */ private bool setFeatureValue(string featureName, string featureValue) { IntPtr itkFeature = new IntPtr(-1); uint nType = 0; uint res = IKapCLib.ItkDevAllocFeature(m_pDev, featureName, ref itkFeature); if (!Check(res)) { WarningEvent?.Invoke(DateTime.Now,WarningEnum.Low, $"setFeatureValue({featureName},{featureValue}) Camera error:Allocate feature failed"); return false; } res = IKapCLib.ItkFeatureGetType(itkFeature, ref nType); if (!Check(res)) { WarningEvent?.Invoke(DateTime.Now,WarningEnum.Low, $"setFeatureValue({featureName},{featureValue}) Camera error:Get feature type failed"); return false; } switch (nType) { case (uint)ItkFeatureType.ITKFEATURE_VAL_TYPE_INT32: res = IKapCLib.ItkFeatureSetInt32(itkFeature, Convert.ToInt32(featureValue)); break; case (uint)ItkFeatureType.ITKFEATURE_VAL_TYPE_INT64: res = IKapCLib.ItkFeatureSetInt64(itkFeature, Convert.ToInt64(featureValue)); break; case (uint)ItkFeatureType.ITKFEATURE_VAL_TYPE_FLOAT: case (uint)ItkFeatureType.ITKFEATURE_VAL_TYPE_DOUBLE: res = IKapCLib.ItkFeatureSetDouble(itkFeature, Convert.ToDouble(featureValue)); break; case (uint)ItkFeatureType.ITKFEATURE_VAL_TYPE_ENUM: case (uint)ItkFeatureType.ITKFEATURE_VAL_TYPE_STRING: res = IKapCLib.ItkFeatureFromString(itkFeature, featureValue); break; case (uint)ItkFeatureType.ITKFEATURE_VAL_TYPE_COMMAND: res = IKapCLib.ItkFeatureExecuteCommand(itkFeature); break; } if (!Check(res)) { WarningEvent?.Invoke(DateTime.Now,WarningEnum.Low, $"setFeatureValue({featureName},{featureValue}) Camera error:Set feature failed:" + res); return false; } return true; } private string getFeatureValue(string featureName) { IntPtr itkFeature = new IntPtr(-1); uint nType = 0; uint res = IKapCLib.ItkDevAllocFeature(m_pDev, featureName, ref itkFeature); if (!Check(res)) { WarningEvent?.Invoke(DateTime.Now,WarningEnum.Low, $"getFeatureValue({featureName}) Camera error:Allocate feature failed"); return ""; } res = IKapCLib.ItkFeatureGetType(itkFeature, ref nType); if (!Check(res)) { WarningEvent?.Invoke(DateTime.Now,WarningEnum.Low, $"getFeatureValue({featureName}) Camera error:Get feature type failed"); return ""; } switch (nType) { case (uint)ItkFeatureType.ITKFEATURE_VAL_TYPE_INT32: int result = 0; res = IKapCLib.ItkFeatureGetInt32(itkFeature,ref result); if (!Check(res)) { WarningEvent?.Invoke(DateTime.Now,WarningEnum.Low, $"getFeatureValue({featureName}) Camera error:Get feature failed:" + res); return ""; } return result.ToString(); case (uint)ItkFeatureType.ITKFEATURE_VAL_TYPE_INT64: long resultL = 0; res = IKapCLib.ItkFeatureGetInt64(itkFeature, ref resultL); if (!Check(res)) { WarningEvent?.Invoke(DateTime.Now,WarningEnum.Low, $"getFeatureValue({featureName}) Camera error:Get feature failed:" + res); return ""; } return resultL.ToString(); case (uint)ItkFeatureType.ITKFEATURE_VAL_TYPE_FLOAT: case (uint)ItkFeatureType.ITKFEATURE_VAL_TYPE_DOUBLE: double resultD = 0; res = IKapCLib.ItkFeatureGetDouble(itkFeature, ref resultD); if (!Check(res)) { WarningEvent?.Invoke(DateTime.Now,WarningEnum.Low, $"getFeatureValue({featureName}) Camera error:Get feature failed:" + res); return ""; } return resultD.ToString(); case (uint)ItkFeatureType.ITKFEATURE_VAL_TYPE_ENUM: case (uint)ItkFeatureType.ITKFEATURE_VAL_TYPE_STRING: string results = ""; res = IKapCLib.ItkFeatureFromString(itkFeature, results); if (!Check(res)) { WarningEvent?.Invoke(DateTime.Now,WarningEnum.Low, $"getFeatureValue({featureName}) Camera error:Get feature failed:" + res); return ""; } return results; } if (!Check(res)) { WarningEvent?.Invoke(DateTime.Now,WarningEnum.Low, $"getFeatureValue({featureName}) Camera error:Get feature failed:" + res); return ""; } return ""; } public override double[] getFeatureRangeValue(string featureName) { switch (featureName) { case "ExposureTime": //return new double[2] {3.2,63997}; return new double[2] { 10, 200 }; case "Gain": return new double[2] { 0.01, 8.00 }; default: return new double[0] { }; } } /* *@brief:检查错误码 *@param [in] err:错误码 *@return:是否错误 */ private static bool Check(uint err) { if (err != (uint)ItkStatusErrorId.ITKSTATUS_OK) { System.Diagnostics.Debug.WriteLine("Error code: {0}.\n", err.ToString("x8")); return false; } return true; } //---- private bool isOpen() { return m_pDev != new IntPtr(-1) && m_pBoard != new IntPtr(-1); } private bool closeDevice() { frameQueue.Clear(); if (isOpen()) { IKapBoard.IKapClose(m_pBoard); IKapCLib.ItkDevClose(m_pDev); } return true; } private bool loadConfiguration(string sFilePath) { int ret = IKapBoard.IKapLoadConfigurationFromFile(m_pBoard, sFilePath); return ret == (int)ErrorCode.IK_RTN_OK; } private bool createBuffer() { int ret = (int)ErrorCode.IK_RTN_OK; int nImageType = 0; ret = IKapBoard.IKapGetInfo(m_pBoard, (uint)INFO_ID.IKP_IMAGE_WIDTH, ref m_nWidth); if (ret != (int)ErrorCode.IK_RTN_OK) return false; ret = IKapBoard.IKapGetInfo(m_pBoard, (uint)INFO_ID.IKP_IMAGE_HEIGHT, ref m_nHeight); if (ret != (int)ErrorCode.IK_RTN_OK) return false; ret = IKapBoard.IKapGetInfo(m_pBoard, (uint)INFO_ID.IKP_IMAGE_TYPE, ref nImageType); if (ret != (int)ErrorCode.IK_RTN_OK) return false; ret = IKapBoard.IKapGetInfo(m_pBoard, (uint)INFO_ID.IKP_DATA_FORMAT, ref m_nDepth); if (ret != (int)ErrorCode.IK_RTN_OK) return false; ret = IKapBoard.IKapGetInfo(m_pBoard, (uint)INFO_ID.IKP_FRAME_SIZE, ref m_nBufferSize); if (ret != (int)ErrorCode.IK_RTN_OK) return false; switch (nImageType) { case 0: m_nChannels = 1; break; case 1: case 3: m_nChannels = 3; break; case 2: case 4: m_nChannels = 4; break; } WarningEvent?.Invoke(DateTime.Now,WarningEnum.Normal, $"图片类型:{nImageType},通道数:{m_nChannels},size:{m_nWidth}*{m_nHeight}"); m_pUserBuffer = Marshal.AllocHGlobal(m_nBufferSize); // hBuffer = new BufferToImage(m_nBufferSize , m_nDepth, m_nChannels , m_nWidth, m_nHeight); return true; } private void clearBuffer() { if (m_pUserBuffer == new IntPtr(-1)) return; Marshal.FreeHGlobal(m_pUserBuffer); m_pUserBuffer = new IntPtr(-1); } } }