革博士程序V1仓库
Nie możesz wybrać więcej, niż 25 tematów Tematy muszą się zaczynać od litery lub cyfry, mogą zawierać myślniki ('-') i mogą mieć do 35 znaków.

825 wiersze
35 KiB

  1. using System;
  2. using System.Collections.Generic;
  3. using System.ComponentModel;
  4. using System.Drawing;
  5. using System.Drawing.Imaging;
  6. using System.IO;
  7. using System.Linq;
  8. using System.Reflection;
  9. using System.Runtime.InteropServices;
  10. using System.Text;
  11. using System.Threading;
  12. using System.Threading.Tasks;
  13. using System.Timers;
  14. using System.Windows.Forms;
  15. using LeatherApp.Interface;
  16. //using MvCamCtrl.NET;
  17. using MvFGCtrlC.NET;
  18. using Newtonsoft.Json.Linq;
  19. using OpenCvSharp;
  20. using OpenCvSharp.Dnn;
  21. //using static ControllerDllCSharp.ClassLibControllerDll;
  22. namespace LeatherApp.Device
  23. {
  24. public class CamerCardDev : ABSCamerCardDev,IDisposable
  25. {
  26. [DllImport("user32.dll")]
  27. [return: MarshalAs(UnmanagedType.Bool)]
  28. private static extern bool IsWindow(IntPtr hWnd);
  29. [DllImport("kernel32.dll", EntryPoint = "RtlCopyMemory", SetLastError = false)]
  30. public static extern void CopyMemory(IntPtr dest, IntPtr src, uint count);
  31. //
  32. private int scanIndex = 0; //实际拍照从1开始命名,因先加的1
  33. private string bmpSavePath;
  34. /// <summary>
  35. /// 曝光 3.00-10000.00
  36. /// </summary>
  37. public float ExposureTime { get; private set; }
  38. /// <summary>
  39. /// 增益 0-23.981199
  40. /// </summary>
  41. public float Gain { get; private set; }
  42. /// <summary>
  43. /// 帧率 0-429496.718750
  44. /// </summary>
  45. public float ResultingFrameRate { get; private set; }
  46. /// <summary>
  47. /// 图片大小
  48. /// </summary>
  49. public System.Drawing.Size size { get; private set; }
  50. /// <summary>
  51. /// 是否连续模式
  52. /// </summary>
  53. public bool isContinuousMode { get; private set; }
  54. /// <summary>
  55. /// 是否打开设备成功
  56. /// </summary>
  57. public bool IsInit { get; private set; } = false;
  58. //public string ErrInfo { get; private set; }
  59. //private System.Timers.Timer timer = new System.Timers.Timer();
  60. private int _scannerCardIndex = 0;//采集卡索引
  61. private int _scannerIndex=0;//相机索引(一个采集卡上可插多个相机)
  62. #region
  63. public enum SAVE_IAMGE_TYPE
  64. {
  65. Image_Undefined = 0, // ch:未定义的图像格式 | en:Undefined Image Type
  66. Image_Bmp = 1, // ch:BMP图像格式 | en:BMP Image Type
  67. Image_Jpeg = 2, // ch:JPEG图像格式 | en:Jpeg Image Type
  68. }
  69. // ch:判断用户自定义像素格式 | en:Determine custom pixel format
  70. public const Int32 CUSTOMER_PIXEL_FORMAT = unchecked((Int32)0x80000000);
  71. public const UInt32 TRIGGER_MODE_ON = 1; // ch:触发模式开 | en:Trigger mode on
  72. public const UInt32 TRIGGER_MODE_OFF = 0; // ch:触发模式关 | en:Trigger mode off
  73. CSystem m_cSystem = new CSystem(); // ch:操作采集卡 | en:Interface operations
  74. CInterface m_cInterface = null; // ch:操作采集卡和设备 | en:Interface and device operation
  75. CDevice m_cDevice = null; // ch:操作设备和流 | en:Device and stream operation
  76. CStream m_cStream = null; // ch:操作流和缓存 | en:Stream and buffer operation
  77. uint m_nInterfaceNum = 0; // ch:采集卡数量 | en:Interface number
  78. bool m_bIsIFOpen = false; // ch:采集卡是否打开 | en:Whether to open interface
  79. bool m_bIsDeviceOpen = false; // ch:设备是否打开 | en:Whether to open device
  80. bool m_bIsGrabbing = false; // ch:是否在抓图 | en:Whether to start grabbing
  81. uint m_nTriggerMode = TRIGGER_MODE_OFF; // ch:触发模式 | en:Trigger Mode
  82. bool m_bThreadState = false; // ch:线程状态 | en:Thread state
  83. Thread m_hGrabThread = null; // ch:取流线程 | en:Grabbing thread
  84. private static Object m_LockForSaveImage = new Object(); // ch:存图锁 | en:Lock for saving image
  85. IntPtr m_pDataBuf = IntPtr.Zero; // ch:数据缓存 | en:Data buffer
  86. uint m_nDataBufSize = 0; // ch:数据缓存大小 | en:Length of data buffer
  87. IntPtr m_pSaveImageBuf = IntPtr.Zero; // ch:图像缓存 | en:Image buffer
  88. uint m_nSaveImageBufSize = 0; // ch:图像缓存大小 | en:Length of image buffer
  89. MV_FG_INPUT_IMAGE_INFO m_stImageInfo = new MV_FG_INPUT_IMAGE_INFO(); // ch:图像信息 | en:Image info
  90. delegate void ShowDisplayError(int nRet);
  91. //显示图像控件句柄
  92. private PictureBox previewHwnd=null;
  93. #endregion
  94. public CamerCardDev( )
  95. {
  96. }
  97. public override bool open(int cardIndex = 0,int scannerIndex = 0)
  98. {
  99. if (IsInit) return true;
  100. //m_stIFInfoList = _m_stIFInfoList;
  101. _scannerCardIndex = cardIndex;
  102. _scannerIndex = scannerIndex;
  103. System.GC.Collect();
  104. try
  105. {
  106. int nRet = 0;
  107. bool bChanged = false;
  108. // ch:枚举采集卡 | en:Enum interface
  109. nRet = m_cSystem.UpdateInterfaceList(
  110. CParamDefine.MV_FG_CAMERALINK_INTERFACE | CParamDefine.MV_FG_GEV_INTERFACE | CParamDefine.MV_FG_CXP_INTERFACE | CParamDefine.MV_FG_XoF_INTERFACE,
  111. ref bChanged);
  112. if (CErrorCode.MV_FG_SUCCESS != nRet)
  113. {
  114. WarningEvent?.Invoke(DateTime.Now,WarningEnum.High, "Enum Interface failed, ErrorCode:" + nRet.ToString("X"));
  115. return false;
  116. }
  117. m_nInterfaceNum = 0;
  118. // ch:获取采集卡数量 | en:Get interface num
  119. nRet = m_cSystem.GetNumInterfaces(ref m_nInterfaceNum);
  120. if (CErrorCode.MV_FG_SUCCESS != nRet)
  121. {
  122. WarningEvent?.Invoke(DateTime.Now,WarningEnum.High, "Get interface number failed, ErrorCode:" + nRet.ToString("X"));
  123. return false;
  124. }
  125. if (0 == m_nInterfaceNum)
  126. {
  127. WarningEvent?.Invoke(DateTime.Now,WarningEnum.High, "No interface found");
  128. return false;
  129. }
  130. if (cardIndex + 1 > m_nInterfaceNum)
  131. {
  132. WarningEvent?.Invoke(DateTime.Now,WarningEnum.High, "cardIndex > interface.count!");
  133. return false;
  134. }
  135. //打开采集卡
  136. // 如果已经打开,则先关闭采集卡
  137. if (null != m_cInterface)
  138. {
  139. m_cInterface.CloseInterface();
  140. m_cInterface = null;
  141. }
  142. // ch:打开采集卡,获得采集卡句柄 | en:Open interface, get handle
  143. nRet = m_cSystem.OpenInterface((uint)cardIndex, out m_cInterface);
  144. if (CErrorCode.MV_FG_SUCCESS != nRet)
  145. {
  146. WarningEvent?.Invoke(DateTime.Now,WarningEnum.High, "Open Interface failed, ErrorCode:" + nRet.ToString("X"));
  147. return false;
  148. }
  149. m_bIsIFOpen = true;
  150. //====枚举设备
  151. uint nDeviceNum = 0;
  152. // ch:枚举采集卡上的相机 | en:Enum camera of interface
  153. nRet = m_cInterface.UpdateDeviceList(ref bChanged);
  154. if (CErrorCode.MV_FG_SUCCESS != nRet)
  155. {
  156. WarningEvent?.Invoke(DateTime.Now,WarningEnum.High, "Update device list failed, ErrorCode:" + nRet.ToString("X"));
  157. return false;
  158. }
  159. // ch:获取设备数量 | en:Get device number
  160. nRet = m_cInterface.GetNumDevices(ref nDeviceNum);
  161. if (CErrorCode.MV_FG_SUCCESS != nRet)
  162. {
  163. WarningEvent?.Invoke(DateTime.Now,WarningEnum.High, "Get devices number failed, ErrorCode:" + nRet.ToString("X"));
  164. return false;
  165. }
  166. if (0 == nDeviceNum)
  167. {
  168. WarningEvent?.Invoke(DateTime.Now,WarningEnum.High, "No Device found");
  169. return false;
  170. }
  171. if (scannerIndex + 1 > nDeviceNum)
  172. {
  173. WarningEvent?.Invoke(DateTime.Now,WarningEnum.High, "scannerIndex > Device.count!");
  174. return false;
  175. }
  176. //====打开设备
  177. // 如果已经打开,则先关闭通道
  178. if (null != m_cStream)
  179. {
  180. m_cStream.CloseStream();
  181. m_cStream = null;
  182. }
  183. // 如果已经打开,则先关闭设备
  184. if (null != m_cDevice)
  185. {
  186. m_cDevice.CloseDevice();
  187. m_cDevice = null;
  188. }
  189. // ch:打开设备,获得设备句柄 | en:Open device, get handle
  190. nRet = m_cInterface.OpenDevice((uint)scannerIndex, out m_cDevice);
  191. if (CErrorCode.MV_FG_SUCCESS != nRet)
  192. {
  193. WarningEvent?.Invoke(DateTime.Now,WarningEnum.High, "Open device failed, ErrorCode:" + nRet.ToString("X"));
  194. return false;
  195. }
  196. m_bIsDeviceOpen = true;
  197. //=====打开触发模式
  198. CParam cDeviceParam = new CParam(m_cInterface);
  199. // ch:打开触发模式 | en:Open Trigger Mode
  200. //nRet = cDeviceParam.SetEnumValue("TriggerMode", TRIGGER_MODE_ON);
  201. //if (CErrorCode.MV_FG_SUCCESS != nRet)
  202. //{
  203. // WarningEvent?.Invoke(DateTime.Now,WarningEnum.High, "Turn on trigger mode failed, ErrorCode:" + nRet.ToString("X"));
  204. // //关闭设备和采集卡
  205. // m_cDevice.CloseDevice();
  206. // m_bIsDeviceOpen = false;
  207. // m_cInterface.CloseInterface();
  208. // m_cInterface = null;
  209. // return false;
  210. //}
  211. m_nTriggerMode = TRIGGER_MODE_ON;
  212. cDeviceParam.SetEnumValue("TriggerSource", (uint)0);//CC1=0
  213. // ch:注册回调函数 | en:Register image callback //本类不使用回调,使用线程主动循环读取
  214. //ImageCallback = new MyCamera.cbOutputExdelegate(ImageCallbackFunc);
  215. //nRet = device.MV_CC_RegisterImageCallBackEx_NET(ImageCallback, IntPtr.Zero);
  216. //if (MyCamera.MV_OK != nRet)
  217. //{
  218. // WarningEvent?.Invoke(DateTime.Now,WarningEnum.High, $"Register image callback failed! ({nRet})");
  219. // return false;
  220. //}
  221. //开始采集
  222. //startGrab();
  223. //
  224. getParam();
  225. IsInit = true;
  226. //timer.Elapsed += Timer_Elapsed;
  227. //timer.Interval = 100;
  228. //timer.Enabled = true;
  229. return true;
  230. }
  231. catch (Exception ex)
  232. {
  233. WarningEvent?.Invoke(DateTime.Now,WarningEnum.High, ex.Message);
  234. return false;
  235. }
  236. }
  237. public override void close()
  238. {
  239. if (!IsInit) return;
  240. try
  241. {
  242. IsInit = false;
  243. //=====关闭设备
  244. if (m_bThreadState)
  245. {
  246. m_bThreadState = false;
  247. m_hGrabThread.Join();
  248. }
  249. int nRet = 0;
  250. if (m_bIsGrabbing)
  251. {
  252. // ch:停止取流 | en:Stop Acquisition
  253. nRet = m_cStream.StopAcquisition();
  254. if (CErrorCode.MV_FG_SUCCESS != nRet)
  255. {
  256. WarningEvent?.Invoke(DateTime.Now,WarningEnum.Low,"Stop acquistion failed, ErrorCode:" + nRet.ToString("X"));
  257. }
  258. m_bIsGrabbing = false;
  259. }
  260. if (null != m_cStream)
  261. {
  262. // ch:关闭流通道 | en:Close stream channel
  263. nRet = m_cStream.CloseStream();
  264. if (CErrorCode.MV_FG_SUCCESS != nRet)
  265. {
  266. WarningEvent?.Invoke(DateTime.Now,WarningEnum.Low,"Close stream channel failed, ErrorCode:" + nRet.ToString("X"));
  267. }
  268. m_cStream = null;
  269. }
  270. if (null != m_cDevice)
  271. {
  272. // ch:关闭设备 | en:Close device
  273. nRet = m_cDevice.CloseDevice();
  274. if (CErrorCode.MV_FG_SUCCESS != nRet)
  275. {
  276. WarningEvent?.Invoke(DateTime.Now,WarningEnum.Low,"Close device failed, ErrorCode:" + nRet.ToString("X"));
  277. }
  278. m_cDevice = null;
  279. }
  280. m_bIsDeviceOpen = false;
  281. if (IntPtr.Zero != m_pDataBuf)
  282. {
  283. Marshal.FreeHGlobal(m_pDataBuf);
  284. m_pDataBuf = IntPtr.Zero;
  285. }
  286. m_nDataBufSize = 0;
  287. if (IntPtr.Zero != m_pSaveImageBuf)
  288. {
  289. Marshal.FreeHGlobal(m_pSaveImageBuf);
  290. m_pSaveImageBuf = IntPtr.Zero;
  291. }
  292. m_nSaveImageBufSize = 0;
  293. //======关闭采集卡
  294. if (null == m_cInterface)
  295. return;
  296. // ch:关闭采集卡 | en:Close interface
  297. nRet = m_cInterface.CloseInterface();
  298. //if (CErrorCode.MV_FG_SUCCESS != nRet)
  299. //{
  300. // WarningEvent?.Invoke(DateTime.Now,WarningEnum.Low,"Close interface failed, ErrorCode:" + nRet.ToString("X"));
  301. // return;
  302. //}
  303. m_cInterface = null;
  304. m_bIsIFOpen = false;
  305. }
  306. catch { }
  307. }
  308. /// <summary>
  309. ///
  310. /// </summary>
  311. /// <param name="hwnd">显示图像控件句柄</param>
  312. /// <returns></returns>
  313. public override bool start(PictureBox preview_Hwnd,string bmp_save_path)
  314. {
  315. if (!IsInit) return false;
  316. this.previewHwnd= preview_Hwnd;
  317. this.bmpSavePath = bmp_save_path;
  318. //开始采集
  319. startGrab();
  320. return true;
  321. }
  322. /// <summary>
  323. /// 停止采集
  324. /// </summary>
  325. public override void stop()
  326. {
  327. if (!IsInit) return;
  328. try
  329. {
  330. if (false == m_bIsDeviceOpen || false == m_bIsGrabbing)
  331. {
  332. return;
  333. }
  334. // ch:标志位设为false | en:Set flag bit false
  335. m_bThreadState = false;
  336. m_hGrabThread.Join();
  337. // ch:停止取流 | en:Stop Acquisition
  338. int nRet = m_cStream.StopAcquisition();
  339. if (CErrorCode.MV_FG_SUCCESS != nRet)
  340. {
  341. //WarningEvent?.Invoke(DateTime.Now,WarningEnum.Low,"Stop acquistion failed, ErrorCode:" + nRet.ToString("X"));
  342. return;
  343. }
  344. m_bIsGrabbing = false;
  345. // ch:关闭流通道 | en:Close stream channel
  346. nRet = m_cStream.CloseStream();
  347. if (CErrorCode.MV_FG_SUCCESS != nRet)
  348. {
  349. //WarningEvent?.Invoke(DateTime.Now,WarningEnum.Low,"Close stream channel failed, ErrorCode:" + nRet.ToString("X"));
  350. }
  351. m_cStream = null;
  352. }
  353. catch
  354. {
  355. return;
  356. }
  357. }
  358. /// <summary>
  359. /// num 因拍了一张后回传的,当前已经是1了
  360. /// </summary>
  361. /// <param name="num"></param>
  362. public override void resetScanIndex()
  363. {
  364. scanIndex = 0;//
  365. }
  366. #region private
  367. //开始采集
  368. private void startGrab()
  369. {
  370. if (!m_bIsDeviceOpen)
  371. {
  372. WarningEvent?.Invoke(DateTime.Now,WarningEnum.High, "Please open device first");
  373. return;
  374. }
  375. if (m_bIsGrabbing)
  376. {
  377. return;
  378. }
  379. // ch:获取流通道个数 | en:Get number of stream
  380. uint nStreamNum = 0;
  381. int nRet = m_cDevice.GetNumStreams(ref nStreamNum);
  382. if (CErrorCode.MV_FG_SUCCESS != nRet)
  383. {
  384. WarningEvent?.Invoke(DateTime.Now,WarningEnum.High, "Get streams number failed, ErrorCode:" + nRet.ToString("X"));
  385. return;
  386. }
  387. if (0 == nStreamNum)
  388. {
  389. WarningEvent?.Invoke(DateTime.Now,WarningEnum.High, "No valid stream channel");
  390. return;
  391. }
  392. // ch:打开流通道(目前只支持单个通道) | en:Open stream(Only a single stream is supported now)
  393. nRet = m_cDevice.OpenStream(0, out m_cStream);
  394. if (CErrorCode.MV_FG_SUCCESS != nRet)
  395. {
  396. WarningEvent?.Invoke(DateTime.Now,WarningEnum.High, "Open stream failed, ErrorCode:" + nRet.ToString("X"));
  397. return;
  398. }
  399. // ch:设置SDK内部缓存数量 | en:Set internal buffer number
  400. const uint nBufNum = 5;
  401. nRet = m_cStream.SetBufferNum(nBufNum);
  402. if (CErrorCode.MV_FG_SUCCESS != nRet)
  403. {
  404. WarningEvent?.Invoke(DateTime.Now,WarningEnum.High, "Set buffer number failed, ErrorCode:" + nRet.ToString("X"));
  405. return;
  406. }
  407. // ch:创建取流线程 | en:Create acquistion thread
  408. m_bThreadState = true;
  409. m_hGrabThread = new Thread(ReceiveThreadProcess);
  410. if (null == m_hGrabThread)
  411. {
  412. m_bThreadState = false;
  413. WarningEvent?.Invoke(DateTime.Now,WarningEnum.High, "Create thread failed");
  414. return;
  415. }
  416. m_hGrabThread.Start();
  417. // ch:开始取流 | en:Start Acquisition
  418. nRet = m_cStream.StartAcquisition();
  419. if (CErrorCode.MV_FG_SUCCESS != nRet)
  420. {
  421. m_bThreadState = false;
  422. WarningEvent?.Invoke(DateTime.Now,WarningEnum.High, "Start acquistion failed, ErrorCode:" + nRet.ToString("X"));
  423. return;
  424. }
  425. m_bIsGrabbing = true;
  426. }
  427. public void setPreviewWin(PictureBox preview_Hwnd)
  428. {
  429. this.previewHwnd = preview_Hwnd;
  430. }
  431. public void ReceiveThreadProcess()
  432. {
  433. CImageProcess cImgProc = new CImageProcess(m_cStream);
  434. MV_FG_BUFFER_INFO stFrameInfo = new MV_FG_BUFFER_INFO(); // ch:图像信息 | en:Frame info
  435. MV_FG_INPUT_IMAGE_INFO stDisplayInfo = new MV_FG_INPUT_IMAGE_INFO(); // ch:显示的图像信息 | en:Display frame info
  436. const uint nTimeout = 1000;
  437. int nRet = 0;
  438. while (m_bThreadState)
  439. {
  440. if (m_bIsGrabbing)
  441. {
  442. // ch:获取一帧图像缓存信息 | en:Get one frame buffer's info
  443. nRet = m_cStream.GetFrameBuffer(ref stFrameInfo, nTimeout);
  444. if (CErrorCode.MV_FG_SUCCESS == nRet)
  445. {
  446. // 用于保存图片
  447. lock (m_LockForSaveImage)
  448. {
  449. if (IntPtr.Zero == m_pDataBuf || m_nDataBufSize < stFrameInfo.nFilledSize)
  450. {
  451. if (IntPtr.Zero != m_pDataBuf)
  452. {
  453. Marshal.FreeHGlobal(m_pDataBuf);
  454. m_pDataBuf = IntPtr.Zero;
  455. }
  456. m_pDataBuf = Marshal.AllocHGlobal((Int32)stFrameInfo.nFilledSize);
  457. if (IntPtr.Zero == m_pDataBuf)
  458. {
  459. m_cStream.ReleaseFrameBuffer(stFrameInfo);
  460. break;
  461. }
  462. m_nDataBufSize = stFrameInfo.nFilledSize;
  463. }
  464. CopyMemory(m_pDataBuf, stFrameInfo.pBuffer, stFrameInfo.nFilledSize);
  465. m_stImageInfo.nWidth = stFrameInfo.nWidth;
  466. m_stImageInfo.nHeight = stFrameInfo.nHeight;
  467. m_stImageInfo.enPixelType = stFrameInfo.enPixelType;
  468. m_stImageInfo.pImageBuf = m_pDataBuf;
  469. m_stImageInfo.nImageBufLen = stFrameInfo.nFilledSize;
  470. //
  471. var imgbuff=SaveImage();
  472. if(imgbuff != null)
  473. {
  474. scanIndex++;
  475. //if (ScanEventPath != null)//Ge用的这个
  476. //{
  477. // string imagpath = $"{this.bmpSavePath}{scanIndex}_dev{_scannerCardIndex}.bmp";
  478. // File.WriteAllBytes(imagpath, imgbuff);
  479. // ScanEventPath?.Invoke(scanIndex, imagpath, _scannerCardIndex);
  480. //}
  481. //else
  482. {
  483. Mat mat = Mat.ImDecode(imgbuff);
  484. //string imagpath = $"{this.bmpSavePath}{scanIndex}_dev{_scannerCardIndex}.bmp";
  485. //File.WriteAllBytes(imagpath, imgbuff);
  486. ScanEvent?.Invoke(scanIndex, mat, _scannerCardIndex);
  487. }
  488. }
  489. }
  490. // 自定义格式不支持显示
  491. if (RemoveCustomPixelFormats(stFrameInfo.enPixelType))
  492. {
  493. m_cStream.ReleaseFrameBuffer(stFrameInfo);
  494. continue;
  495. }
  496. // 配置显示图像的参数
  497. //pictureBox1显示
  498. if (this.previewHwnd != null && IsWindow(this.previewHwnd.Handle))
  499. {
  500. stDisplayInfo.nWidth = stFrameInfo.nWidth;
  501. stDisplayInfo.nHeight = stFrameInfo.nHeight;
  502. stDisplayInfo.enPixelType = stFrameInfo.enPixelType;
  503. stDisplayInfo.pImageBuf = stFrameInfo.pBuffer;
  504. stDisplayInfo.nImageBufLen = stFrameInfo.nFilledSize;
  505. nRet = cImgProc.DisplayOneFrame(previewHwnd.Handle, ref stDisplayInfo);
  506. if (CErrorCode.MV_FG_SUCCESS != nRet)
  507. {
  508. m_cStream.ReleaseFrameBuffer(stFrameInfo);
  509. //this.Invoke(new ShowDisplayError(DisplayError), new object[] { nRet });
  510. break;
  511. }
  512. }
  513. m_cStream.ReleaseFrameBuffer(stFrameInfo);
  514. }
  515. else
  516. {
  517. if (TRIGGER_MODE_ON == m_nTriggerMode)
  518. {
  519. Thread.Sleep(5);
  520. }
  521. }
  522. }
  523. else
  524. {
  525. Thread.Sleep(5);
  526. }
  527. }
  528. }
  529. private byte[] SaveImage(SAVE_IAMGE_TYPE enSaveImageType= SAVE_IAMGE_TYPE.Image_Bmp)
  530. {
  531. int nRet = 0;
  532. lock (m_LockForSaveImage)
  533. {
  534. if (IntPtr.Zero == m_pDataBuf)
  535. return null;// CErrorCode.MV_FG_ERR_NO_DATA;
  536. if (RemoveCustomPixelFormats(m_stImageInfo.enPixelType))
  537. return null;//CErrorCode.MV_FG_ERR_INVALID_VALUE;
  538. uint nMaxImageLen = m_stImageInfo.nWidth * m_stImageInfo.nHeight * 4 + 2048; // 确保存图空间足够,包括图像头
  539. if (IntPtr.Zero == m_pSaveImageBuf || m_nSaveImageBufSize < nMaxImageLen)
  540. {
  541. if (IntPtr.Zero != m_pSaveImageBuf)
  542. {
  543. Marshal.FreeHGlobal(m_pSaveImageBuf);
  544. m_pSaveImageBuf = IntPtr.Zero;
  545. }
  546. m_pSaveImageBuf = Marshal.AllocHGlobal((Int32)nMaxImageLen);
  547. if (IntPtr.Zero == m_pSaveImageBuf)
  548. return null;//CErrorCode.MV_FG_ERR_OUT_OF_MEMORY;
  549. m_nSaveImageBufSize = nMaxImageLen;
  550. }
  551. CImageProcess cImgSave = new CImageProcess(m_cStream);
  552. System.DateTime currentTime = new System.DateTime();
  553. currentTime = System.DateTime.Now;
  554. do
  555. {
  556. if (SAVE_IAMGE_TYPE.Image_Bmp == enSaveImageType)
  557. {
  558. MV_FG_SAVE_BITMAP_INFO stBmpInfo = new MV_FG_SAVE_BITMAP_INFO();
  559. stBmpInfo.stInputImageInfo = m_stImageInfo;
  560. stBmpInfo.pBmpBuf = m_pSaveImageBuf;
  561. stBmpInfo.nBmpBufSize = m_nSaveImageBufSize;
  562. stBmpInfo.enCfaMethod = MV_FG_CFA_METHOD.MV_FG_CFA_METHOD_OPTIMAL;
  563. // ch:保存BMP图像 | en:Save to BMP
  564. nRet = cImgSave.SaveBitmap(ref stBmpInfo);
  565. if (CErrorCode.MV_FG_SUCCESS != nRet)
  566. break;
  567. // ch:将图像数据保存到本地文件 | en:Save image data to local file
  568. byte[] byteData = new byte[stBmpInfo.nBmpBufLen];
  569. Marshal.Copy(stBmpInfo.pBmpBuf, byteData, 0, (int)stBmpInfo.nBmpBufLen);
  570. //保存文件
  571. //string strName = "Image_w" + stBmpInfo.stInputImageInfo.nWidth.ToString() +
  572. // "_h" + stBmpInfo.stInputImageInfo.nHeight.ToString() + "_" + currentTime.Minute.ToString() +
  573. // currentTime.Second.ToString() + currentTime.Millisecond.ToString() + ".bmp";
  574. //FileStream pFile = new FileStream(strName, FileMode.Create);
  575. //if (null == pFile)
  576. //{
  577. // nRet = CErrorCode.MV_FG_ERR_ERROR;
  578. // break;
  579. //}
  580. //pFile.Write(byteData, 0, byteData.Length);
  581. //pFile.Close();
  582. return byteData;
  583. }
  584. else if (SAVE_IAMGE_TYPE.Image_Jpeg == enSaveImageType)
  585. {
  586. MV_FG_SAVE_JPEG_INFO stJpgInfo = new MV_FG_SAVE_JPEG_INFO();
  587. stJpgInfo.stInputImageInfo = m_stImageInfo;
  588. stJpgInfo.pJpgBuf = m_pSaveImageBuf;
  589. stJpgInfo.nJpgBufSize = m_nSaveImageBufSize;
  590. stJpgInfo.nJpgQuality = 80; // JPG编码质量(0-100]
  591. stJpgInfo.enCfaMethod = MV_FG_CFA_METHOD.MV_FG_CFA_METHOD_OPTIMAL;
  592. // ch:保存JPG图像 | en:Save to JPG
  593. nRet = cImgSave.SaveJpeg(ref stJpgInfo);
  594. if (CErrorCode.MV_FG_SUCCESS != nRet)
  595. break;
  596. // ch:将图像数据保存到本地文件 | en:Save image data to local file
  597. byte[] byteData = new byte[stJpgInfo.nJpgBufLen];
  598. Marshal.Copy(stJpgInfo.pJpgBuf, byteData, 0, (int)stJpgInfo.nJpgBufLen);
  599. //保存文件
  600. //string strName = "Image_w" + stJpgInfo.stInputImageInfo.nWidth.ToString() +
  601. // "_h" + stJpgInfo.stInputImageInfo.nHeight.ToString() + "_" + currentTime.Minute.ToString() +
  602. // currentTime.Second.ToString() + currentTime.Millisecond.ToString() + ".jpg";
  603. //FileStream pFile = new FileStream(strName, FileMode.Create);
  604. //if (null == pFile)
  605. //{
  606. // nRet = CErrorCode.MV_FG_ERR_ERROR;
  607. // break;
  608. //}
  609. //pFile.Write(byteData, 0, byteData.Length);
  610. //pFile.Close();
  611. return byteData;
  612. }
  613. else
  614. {
  615. nRet = CErrorCode.MV_FG_ERR_INVALID_PARAMETER;
  616. break;
  617. }
  618. } while (false);
  619. }
  620. return null;//
  621. }
  622. // ch:去除自定义的像素格式 | en:Remove custom pixel formats
  623. private bool RemoveCustomPixelFormats(MV_FG_PIXEL_TYPE enPixelFormat)
  624. {
  625. Int32 nResult = ((int)enPixelFormat) & CUSTOMER_PIXEL_FORMAT;
  626. if (CUSTOMER_PIXEL_FORMAT == nResult)
  627. {
  628. return true;
  629. }
  630. else
  631. {
  632. return false;
  633. }
  634. }
  635. #endregion
  636. public override double[] getFeatureRangeValue(string featureName)
  637. {
  638. switch (featureName)
  639. {
  640. case "ExposureTime":
  641. return new double[2] { 0, 10000 };
  642. case "Gain":
  643. return new double[2] { 0.01, 255 };
  644. default: return new double[0] { };
  645. }
  646. }
  647. public override void getParam()
  648. {
  649. if (!IsInit) return;
  650. CParam cDeviceParam = new CParam(m_cInterface);
  651. MV_FG_FLOATVALUE stParam=new MV_FG_FLOATVALUE();
  652. int nRet = cDeviceParam.GetFloatValue("ExposureTime", ref stParam);
  653. if (nRet == CErrorCode.MV_FG_SUCCESS) ExposureTime = stParam.fCurValue;
  654. nRet = cDeviceParam.GetFloatValue("Gain", ref stParam);
  655. if (nRet == CErrorCode.MV_FG_SUCCESS) Gain = stParam.fCurValue;
  656. nRet = cDeviceParam.GetFloatValue("ResultingFrameRate", ref stParam);
  657. if (nRet == CErrorCode.MV_FG_SUCCESS) ResultingFrameRate = stParam.fCurValue;
  658. }
  659. /// <summary>
  660. ///
  661. /// </summary>
  662. /// <param name="exposureTime">曝光</param>
  663. /// <param name="gain">增益</param>
  664. /// <param name="resultingFrameRate">帧率</param>
  665. public override bool setParam(float exposureTime, float gain =-1, float resultingFrameRate =-1)
  666. {
  667. if (!IsInit) return false;
  668. CParam cDeviceParam = new CParam(m_cInterface);
  669. //cDeviceParam.GetXmlFile()
  670. //cDeviceParam.GetNodeAccessMode
  671. //cDeviceParam.GetNodeInterfaceType
  672. bool change = false;
  673. int nRet;
  674. if (exposureTime != ExposureTime && exposureTime != -1)
  675. {
  676. //device.MV_CC_SetEnumValue_NET("ExposureAuto", 0);
  677. //nRet = device.MV_CC_SetFloatValue_NET("ExposureTime", exposureTime);
  678. nRet = cDeviceParam.SetEnumValue("ExposureAuto", (uint)0);
  679. if (CErrorCode.MV_FG_SUCCESS != nRet)
  680. WarningEvent?.Invoke(DateTime.Now,WarningEnum.Low, "ExposureTime SetEnumValue(\"ExposureAuto\") res=" + nRet);
  681. nRet = cDeviceParam.SetFloatValue("ExposureTime", exposureTime);
  682. if (CErrorCode.MV_FG_SUCCESS != nRet)
  683. WarningEvent?.Invoke(DateTime.Now,WarningEnum.Low, "ExposureTime SetFloatValue(\"ExposureTime\") res=" + nRet);
  684. change = true;
  685. }
  686. if (gain != Gain && gain != -1)
  687. {
  688. //device.MV_CC_SetEnumValue_NET("GainAuto", 0);
  689. //nRet = device.MV_CC_SetFloatValue_NET("Gain", gain);
  690. cDeviceParam.SetEnumValue("GainAuto", (uint)0);
  691. cDeviceParam.SetFloatValue("Gain", gain);
  692. change = true;
  693. }
  694. if (resultingFrameRate != ResultingFrameRate && resultingFrameRate != -1)
  695. {
  696. cDeviceParam.SetFloatValue("AcquisitionFrameRate", resultingFrameRate);
  697. change = true;
  698. }
  699. //
  700. if (change)
  701. getParam();
  702. return change;
  703. }
  704. public void Dispose()
  705. {
  706. stop();
  707. close();
  708. }
  709. private byte[] bmp2bytes(Bitmap bmp)
  710. {
  711. MemoryStream ms = new MemoryStream();
  712. bmp.Save(ms, System.Drawing.Imaging.ImageFormat.Bmp);
  713. byte[] bytes = ms.GetBuffer(); //byte[] bytes= ms.ToArray(); 这两句都可以,至于区别么,下面有解释
  714. ms.Close();
  715. bmp.Dispose();
  716. return bytes;
  717. }
  718. private Bitmap bytes2bmp(byte[] bytes)
  719. {
  720. MemoryStream ms1 = new MemoryStream(bytes);
  721. Bitmap bm = (Bitmap)Image.FromStream(ms1);
  722. ms1.Close();
  723. return bm;
  724. }
  725. public Bitmap read2Bmp(string path)
  726. {
  727. MemoryStream ms = new System.IO.MemoryStream(File.ReadAllBytes(path));
  728. Bitmap bmp = new Bitmap(ms);
  729. ms.Close();
  730. ms.Dispose();
  731. //FileStream fs = new FileStream(path, FileMode.Open);
  732. //byte[] bmpdata = new byte[fs.Length];
  733. //fs.Read(bmpdata, 0, bmpdata.Length);
  734. //Bitmap bmp = new Bitmap(fs);
  735. //fs.Close();
  736. return bmp;
  737. }
  738. }
  739. }