版博士V2.0程序
25개 이상의 토픽을 선택하실 수 없습니다. Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

ScannerDev.cs 41 KiB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952
  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 MvCamCtrl.NET;
  16. using Newtonsoft.Json.Linq;
  17. using OpenCvSharp.Dnn;
  18. using static ControllerDllCSharp.ClassLibControllerDll;
  19. namespace ProductionControl.Device
  20. {
  21. public class ScannerDev : IDisposable
  22. {
  23. private uint m_nRowStep = 0;
  24. [DllImport("user32.dll")]
  25. [return: MarshalAs(UnmanagedType.Bool)]
  26. private static extern bool IsWindow(IntPtr hWnd);
  27. public enum ScannerType
  28. {
  29. [Description("板卡相机")]
  30. GENTL = 0,
  31. [Description("网口相机")]
  32. CC = 1,
  33. }
  34. private ScannerType scannerType;
  35. public string bmpSavePath { get; private set; }
  36. public Action<WarningEnum, string> WarningEvent;
  37. /// <summary>
  38. /// 拍照回传 (1-num,文件名.bmp)
  39. /// </summary>
  40. public Action<int, string> ScanEventPath;
  41. //public Action<int, byte[]> ScanEvent;
  42. public Action<int, Bitmap> ScanEvent;
  43. /// <summary>
  44. /// 曝光
  45. /// </summary>
  46. public float ExposureTime { get; private set; }
  47. /// <summary>
  48. /// 增益
  49. /// </summary>
  50. public float Gain { get; private set; }
  51. /// <summary>
  52. /// 帧率
  53. /// </summary>
  54. public float ResultingFrameRate { get; private set; }
  55. /// <summary>
  56. /// 图片大小
  57. /// </summary>
  58. public Size size { get; private set; }
  59. /// <summary>
  60. /// 是否连续模式
  61. /// </summary>
  62. public bool isContinuousMode { get; private set; }
  63. /// <summary>
  64. /// 是否打开设备成功
  65. /// </summary>
  66. public bool IsInit { get; private set; } = false;
  67. //public string ErrInfo { get; private set; }
  68. //private System.Timers.Timer timer = new System.Timers.Timer();
  69. #region
  70. private static MyCamera.cbOutputExdelegate ImageCallback;
  71. private static MyCamera.MV_CHUNK_DATA_CONTENT stChunkInfo;// Chunk结构体信息
  72. private MyCamera.MV_GENTL_DEV_INFO_LIST m_stGentDeviceList = new MyCamera.MV_GENTL_DEV_INFO_LIST();
  73. private MyCamera.MV_GENTL_IF_INFO_LIST m_stIFInfoList = new MyCamera.MV_GENTL_IF_INFO_LIST();
  74. private MyCamera.MV_CC_DEVICE_INFO_LIST m_stCCDeviceList = new MyCamera.MV_CC_DEVICE_INFO_LIST();
  75. private MyCamera device = new MyCamera();
  76. private bool m_bGrabbing = false;//开始采集TAG
  77. private Thread m_hReceiveThread = null;
  78. //显示图像控件句柄
  79. private IntPtr previewHwnd = IntPtr.Zero;
  80. //拍照数量
  81. private int scanNum = 0;
  82. #endregion
  83. public ScannerDev(ScannerType type)
  84. {
  85. this.scannerType = type;
  86. }
  87. public bool open()
  88. {
  89. if (IsInit) return true;
  90. System.GC.Collect();
  91. int nRet;
  92. try
  93. {
  94. if (this.scannerType == ScannerType.GENTL)
  95. {
  96. nRet = MyCamera.MV_CC_EnumInterfacesByGenTL_NET(ref m_stIFInfoList, Config.Scanner_GENTL_CTI);
  97. if (File.Exists(Config.Scanner_GENTL_CTI))
  98. {
  99. if (0 != nRet || m_stIFInfoList.nInterfaceNum < 1)
  100. {
  101. WarningEvent?.Invoke(WarningEnum.High, $"Enumerate interfaces fail! ({nRet})");
  102. return false;
  103. }
  104. }
  105. //
  106. MyCamera.MV_GENTL_IF_INFO stIFInfo = (MyCamera.MV_GENTL_IF_INFO)Marshal.PtrToStructure(m_stIFInfoList.pIFInfo[0], typeof(MyCamera.MV_GENTL_IF_INFO));
  107. nRet = MyCamera.MV_CC_EnumDevicesByGenTL_NET(ref stIFInfo, ref m_stGentDeviceList);
  108. if (0 != nRet || m_stGentDeviceList.nDeviceNum < 1)
  109. {
  110. WarningEvent?.Invoke(WarningEnum.High, $"Enumerate devices fail! ({nRet})");
  111. return false;
  112. }
  113. // ch:获取选择的设备信息 | en:Get selected device information
  114. MyCamera.MV_GENTL_DEV_INFO device = (MyCamera.MV_GENTL_DEV_INFO)Marshal.PtrToStructure(m_stGentDeviceList.pDeviceInfo[0], typeof(MyCamera.MV_GENTL_DEV_INFO));
  115. // ch:打开设备 | en:Open device
  116. if (null == this.device)
  117. {
  118. this.device = new MyCamera();
  119. if (null == this.device)
  120. {
  121. WarningEvent?.Invoke(WarningEnum.High, $"Open device fail!");
  122. return false;
  123. }
  124. }
  125. nRet = this.device.MV_CC_CreateDeviceByGenTL_NET(ref device);
  126. if (MyCamera.MV_OK != nRet)
  127. {
  128. WarningEvent?.Invoke(WarningEnum.High, $"Open device fail! ({nRet})");
  129. return false;
  130. }
  131. nRet = this.device.MV_CC_OpenDevice_NET();
  132. if (MyCamera.MV_OK != nRet)
  133. {
  134. this.device.MV_CC_DestroyDevice_NET();
  135. WarningEvent?.Invoke(WarningEnum.High, $"Device open fail! ({nRet})");
  136. return false;
  137. }
  138. }
  139. else //CC
  140. {
  141. nRet = MyCamera.MV_CC_EnumDevices_NET(MyCamera.MV_GIGE_DEVICE | MyCamera.MV_USB_DEVICE, ref m_stCCDeviceList);
  142. if (0 != nRet || m_stCCDeviceList.nDeviceNum < 1)
  143. {
  144. WarningEvent?.Invoke(WarningEnum.High, $"Enumerate devices fail! ({nRet})");
  145. return false;
  146. }
  147. // ch:获取选择的设备信息
  148. MyCamera.MV_CC_DEVICE_INFO device = (MyCamera.MV_CC_DEVICE_INFO)Marshal.PtrToStructure(m_stCCDeviceList.pDeviceInfo[0], typeof(MyCamera.MV_CC_DEVICE_INFO));
  149. // ch:打开设备 | en:Open device
  150. if (null == this.device)
  151. {
  152. this.device = new MyCamera();
  153. if (null == this.device)
  154. {
  155. WarningEvent?.Invoke(WarningEnum.High, $"Open device fail!");
  156. return false;
  157. }
  158. }
  159. nRet = this.device.MV_CC_CreateDevice_NET(ref device);
  160. if (MyCamera.MV_OK != nRet)
  161. {
  162. WarningEvent?.Invoke(WarningEnum.High, $"Open device fail! ({nRet})");
  163. return false;
  164. }
  165. nRet = this.device.MV_CC_OpenDevice_NET();
  166. if (MyCamera.MV_OK != nRet)
  167. {
  168. this.device.MV_CC_DestroyDevice_NET();
  169. WarningEvent?.Invoke(WarningEnum.High, $"Open device fail! ({nRet})");
  170. return false;
  171. }
  172. // ch:探测网络最佳包大小(只对GigE相机有效) | en:Detection network optimal package size(It only works for the GigE camera)
  173. if (device.nTLayerType == MyCamera.MV_GIGE_DEVICE)
  174. {
  175. int nPacketSize = this.device.MV_CC_GetOptimalPacketSize_NET();
  176. if (nPacketSize > 0)
  177. {
  178. nRet = this.device.MV_CC_SetIntValue_NET("GevSCPSPacketSize", (uint)nPacketSize);
  179. //if (nRet != MyCamera.MV_OK)
  180. //{
  181. // ShowErrorMsg("Set Packet Size failed!", nRet);
  182. //}
  183. }
  184. else
  185. {
  186. //ShowErrorMsg("Get Packet Size failed!", nPacketSize);
  187. }
  188. }
  189. }
  190. // ch:注册回调函数 | en:Register image callback //本类不使用回调,使用线程主动循环读取
  191. //ImageCallback = new MyCamera.cbOutputExdelegate(ImageCallbackFunc);
  192. //nRet = device.MV_CC_RegisterImageCallBackEx_NET(ImageCallback, IntPtr.Zero);
  193. //if (MyCamera.MV_OK != nRet)
  194. //{
  195. // WarningEvent?.Invoke(WarningEnum.High, $"Register image callback failed! ({nRet})");
  196. // return false;
  197. //}
  198. init2();
  199. // ch:设置采集[软触发/连续]模式 | en:Set Continues Aquisition Mode
  200. device.MV_CC_SetEnumValue_NET("AcquisitionMode", (uint)MyCamera.MV_CAM_ACQUISITION_MODE.MV_ACQ_MODE_CONTINUOUS);
  201. setMode(false); //软触发
  202. //
  203. getParam();
  204. IsInit = true;
  205. //timer.Elapsed += Timer_Elapsed;
  206. //timer.Interval = 100;
  207. //timer.Enabled = true;
  208. return true;
  209. }
  210. catch (Exception ex)
  211. {
  212. WarningEvent?.Invoke(WarningEnum.High, ex.Message);
  213. return false;
  214. }
  215. }
  216. public void close()
  217. {
  218. if (!IsInit) return;
  219. try
  220. {
  221. IsInit = false;
  222. // ch:取流标志位清零 | en:Reset flow flag bit
  223. if (m_bGrabbing == true)
  224. {
  225. m_bGrabbing = false;
  226. m_hReceiveThread.Join();
  227. }
  228. // ch:关闭设备 | en:Close Device
  229. device.MV_CC_CloseDevice_NET();
  230. device.MV_CC_DestroyDevice_NET();
  231. }
  232. catch { }
  233. }
  234. /// <summary>
  235. ///
  236. /// </summary>
  237. /// <param name="hwnd">显示图像控件句柄</param>
  238. /// <returns></returns>
  239. public bool start(IntPtr preview_Hwnd,string bmp_save_path)
  240. {
  241. if (!IsInit) return false;
  242. if (m_bGrabbing) return true;
  243. this.previewHwnd= preview_Hwnd;
  244. this.bmpSavePath = bmp_save_path;
  245. // ch:标志位置位true | en:Set position bit true
  246. m_bGrabbing = true;
  247. m_hReceiveThread = new Thread(ReceiveThreadProcess);
  248. m_hReceiveThread.Start();
  249. // ch:开始采集 | en:Start Grabbing
  250. int nRet = device.MV_CC_StartGrabbing_NET();
  251. if (MyCamera.MV_OK != nRet)
  252. {
  253. m_bGrabbing = false;
  254. m_hReceiveThread.Join();
  255. WarningEvent?.Invoke(WarningEnum.High, $"Start Grabbing Fail! ({nRet})");
  256. return false;
  257. }
  258. return true;
  259. }
  260. public bool stop()
  261. {
  262. if (!IsInit) return false;
  263. if (!m_bGrabbing) return true;
  264. try
  265. {
  266. // ch:标志位设为false | en:Set flag bit false
  267. m_bGrabbing = false;
  268. m_hReceiveThread.Join();
  269. // ch:停止采集 | en:Stop Grabbing
  270. int nRet = device.MV_CC_StopGrabbing_NET();
  271. if (nRet != MyCamera.MV_OK)
  272. {
  273. WarningEvent?.Invoke(WarningEnum.High, $"Stop Grabbing Fail! ({nRet})");
  274. return false;
  275. }
  276. }
  277. catch
  278. {
  279. return false;
  280. }
  281. return true;
  282. }
  283. #region private
  284. private bool init2()
  285. {
  286. // ch:获取包大小 || en: Get Payload Size
  287. MyCamera.MVCC_INTVALUE stParam = new MyCamera.MVCC_INTVALUE();
  288. //int nRet = device.MV_CC_GetIntValue_NET("PayloadSize", ref stParam);//strKey [IN] 属性键值,如获取宽度信息则为"Width" pstValue[IN][OUT] 返回给调用者有关相机属性结构体指针
  289. //if (MyCamera.MV_OK != nRet)
  290. //{
  291. // System.Windows.Forms.MessageBox.Show("Get PayloadSize Fail");
  292. // return false;
  293. //}
  294. //g_nPayloadSize = stParam.nCurValue;
  295. // ch:获取高 || en: Get Height
  296. int nRet = device.MV_CC_GetIntValue_NET("Height", ref stParam);
  297. if (MyCamera.MV_OK != nRet)
  298. {
  299. System.Windows.Forms.MessageBox.Show("Get Height Fail");
  300. return false;
  301. }
  302. uint nHeight = stParam.nCurValue;
  303. // ch:获取宽 || en: Get Width
  304. nRet = device.MV_CC_GetIntValue_NET("Width", ref stParam);
  305. if (MyCamera.MV_OK != nRet)
  306. {
  307. System.Windows.Forms.MessageBox.Show("Get Width Fail");
  308. return false;
  309. }
  310. uint nWidth = stParam.nCurValue;
  311. this.size = new Size((int)nWidth, (int)nHeight);
  312. // ch:获取步长 || en: Get nRowStep
  313. m_nRowStep = nWidth * nHeight;
  314. return true;
  315. }
  316. /// <summary>
  317. /// false-软/硬 触发 true-连续
  318. /// </summary>
  319. /// <param name="type"></param>
  320. public void setMode(bool isContinuous, MyCamera.MV_CAM_TRIGGER_SOURCE triggerSource= MyCamera.MV_CAM_TRIGGER_SOURCE.MV_TRIGGER_SOURCE_SOFTWARE)
  321. {
  322. if (isContinuous)
  323. {
  324. device.MV_CC_SetEnumValue_NET("TriggerMode", (uint)MyCamera.MV_CAM_TRIGGER_MODE.MV_TRIGGER_MODE_OFF);
  325. }
  326. else
  327. {
  328. device.MV_CC_SetEnumValue_NET("TriggerMode", (uint)MyCamera.MV_CAM_TRIGGER_MODE.MV_TRIGGER_MODE_ON);
  329. // ch:触发源选择:0 - Line0;
  330. // 1 - Line1;
  331. // 2 - Line2;
  332. // 3 - Line3;
  333. // 4 - Counter;
  334. // 7 - Software;
  335. //if (cbSoftTrigger.Checked)
  336. device.MV_CC_SetEnumValue_NET("TriggerSource", (uint)triggerSource);
  337. //else
  338. // m_MyCamera.MV_CC_SetEnumValue_NET("TriggerSource", (uint)MyCamera.MV_CAM_TRIGGER_SOURCE.MV_TRIGGER_SOURCE_LINE0);
  339. }
  340. isContinuousMode = isContinuous;
  341. }
  342. public void setPreviewWin(IntPtr preview_Hwnd)
  343. {
  344. this.previewHwnd = preview_Hwnd;
  345. }
  346. public void ReceiveThreadProcess()
  347. {
  348. MyCamera.MV_FRAME_OUT stFrameInfo = new MyCamera.MV_FRAME_OUT();
  349. MyCamera.MV_DISPLAY_FRAME_INFO stDisplayInfo = new MyCamera.MV_DISPLAY_FRAME_INFO();
  350. int nRet = MyCamera.MV_OK;
  351. while (m_bGrabbing)
  352. {
  353. bool isOpenWin = IsWindow(this.previewHwnd);
  354. if ((!isContinuousMode && this.scanNum < 1) ||
  355. (isContinuousMode && (this.previewHwnd == IntPtr.Zero || !isOpenWin)))
  356. {
  357. Thread.Sleep(50);
  358. continue;
  359. }
  360. //
  361. nRet = device.MV_CC_GetImageBuffer_NET(ref stFrameInfo, 1000);
  362. if (nRet == MyCamera.MV_OK)
  363. {
  364. if (RemoveCustomPixelFormats(stFrameInfo.stFrameInfo.enPixelType)
  365. || stFrameInfo.stFrameInfo.nFrameLen == 0)
  366. {
  367. device.MV_CC_FreeImageBuffer_NET(ref stFrameInfo);
  368. continue;
  369. }
  370. //pictureBox1显示
  371. if (this.previewHwnd != IntPtr.Zero && isOpenWin)
  372. {
  373. stDisplayInfo.hWnd = this.previewHwnd;// pictureBox1.Handle;
  374. stDisplayInfo.pData = stFrameInfo.pBufAddr;
  375. stDisplayInfo.nDataLen = stFrameInfo.stFrameInfo.nFrameLen;
  376. stDisplayInfo.nWidth = stFrameInfo.stFrameInfo.nWidth;
  377. stDisplayInfo.nHeight = stFrameInfo.stFrameInfo.nHeight;
  378. stDisplayInfo.enPixelType = stFrameInfo.stFrameInfo.enPixelType;
  379. device.MV_CC_DisplayOneFrame_NET(ref stDisplayInfo);
  380. }
  381. //保存
  382. if (this.scanNum>0)//save tag
  383. {
  384. MyCamera.MV_SAVE_IMG_TO_FILE_PARAM stSaveFileParam = new MyCamera.MV_SAVE_IMG_TO_FILE_PARAM();
  385. //lock (BufForDriverLock)
  386. {
  387. if (scannerType == ScannerType.CC)
  388. {
  389. stSaveFileParam.enImageType = MyCamera.MV_SAVE_IAMGE_TYPE.MV_Image_Bmp;
  390. stSaveFileParam.enPixelType = stFrameInfo.stFrameInfo.enPixelType;
  391. stSaveFileParam.pData = stFrameInfo.pBufAddr;//m_BufForDriver;
  392. stSaveFileParam.nDataLen = stFrameInfo.stFrameInfo.nFrameLen;
  393. stSaveFileParam.nHeight = stFrameInfo.stFrameInfo.nHeight;
  394. stSaveFileParam.nWidth = stFrameInfo.stFrameInfo.nWidth;
  395. stSaveFileParam.iMethodValue = 2;
  396. //Save path
  397. //stSaveFileParam.pImagePath = this.bmpSavePath + "\\" + scannerType.ToString() + "_w" + stSaveFileParam.nWidth.ToString() + "_h" + stSaveFileParam.nHeight.ToString() + "_fn" + stFrameInfo.stFrameInfo.nFrameNum.ToString() + ".bmp";
  398. stSaveFileParam.pImagePath = this.bmpSavePath + "\\" + DateTime.Now.Ticks + ".bmp";
  399. //m_MyCamera.MV_CC_RegisterImageCallBackEx_NET(new MyCamera.cbOutputExdelegate(ImageCallBack), IntPtr.Zero);
  400. nRet = device.MV_CC_SaveImageToFile_NET(ref stSaveFileParam);
  401. if (MyCamera.MV_OK == nRet)
  402. {
  403. if (ScanEventPath != null)
  404. ScanEventPath?.Invoke(this.scanNum--, stSaveFileParam.pImagePath);
  405. else
  406. ScanEvent?.Invoke(this.scanNum--, read2Bmp(stSaveFileParam.pImagePath));
  407. }
  408. }
  409. else
  410. {
  411. //=== raw byte[]
  412. //byte[] rawFileBuff = toRawImage(stFrameInfo);
  413. //if (rawFileBuff != null)
  414. // ScanEvent?.Invoke(this.scanNum--, rawFileBuff);
  415. //=== bmp
  416. Bitmap bmp = toBitmap(stFrameInfo.pBufAddr, stFrameInfo.stFrameInfo);
  417. //bmp = bytes2bmp(bmp2bytes(bmp));
  418. //string bmpPath = "d:\\" + DateTime.Now.Ticks + ".bmp";
  419. //bmp.Save(bmpPath, ImageFormat.Bmp);
  420. ////bmp = (Bitmap)Bitmap.FromFile(bmpPath);
  421. //bmp = read2Bmp(bmpPath);
  422. if (bmp != null)
  423. ScanEvent?.Invoke(this.scanNum--, bmp);
  424. }
  425. }
  426. }
  427. //free
  428. device.MV_CC_FreeImageBuffer_NET(ref stFrameInfo);
  429. }
  430. else
  431. {
  432. Thread.Sleep(5);
  433. }
  434. }
  435. }
  436. public void AfterGigeUsbImageAcquired_Station1(MyCamera.MV_FRAME_OUT_INFO_EX pFrameInfo, IntPtr pTemp )
  437. {
  438. Bitmap Station1Image1 = new System.Drawing.Bitmap(pFrameInfo.nWidth, pFrameInfo.nHeight, pFrameInfo.nWidth * 1, System.Drawing.Imaging.PixelFormat.Format8bppIndexed, pTemp);
  439. ColorPalette cp = Station1Image1.Palette;
  440. for (int i = 0; i < 256; i++)
  441. {
  442. cp.Entries[i] = Color.FromArgb(i, i, i);
  443. }
  444. Station1Image1.Palette = cp;
  445. }
  446. private byte[] toRawImage(MyCamera.MV_FRAME_OUT stFrameOut)
  447. {
  448. MyCamera.MvGvspPixelType enType = MyCamera.MvGvspPixelType.PixelType_Gvsp_Undefined;
  449. uint nChannelNum = 0;
  450. if (IsColorPixelFormat(stFrameOut.stFrameInfo.enPixelType))
  451. {
  452. enType = MyCamera.MvGvspPixelType.PixelType_Gvsp_RGB8_Packed;
  453. nChannelNum = 3;
  454. }
  455. else if (IsMonoPixelFormat(stFrameOut.stFrameInfo.enPixelType))
  456. {
  457. enType = MyCamera.MvGvspPixelType.PixelType_Gvsp_Mono8;
  458. nChannelNum = 1;
  459. }
  460. else
  461. return null;
  462. //
  463. if (enType != MyCamera.MvGvspPixelType.PixelType_Gvsp_Undefined)
  464. {
  465. IntPtr pBufForConvert = Marshal.AllocHGlobal((int)(stFrameOut.stFrameInfo.nWidth * stFrameOut.stFrameInfo.nHeight * nChannelNum));
  466. MyCamera.MV_PIXEL_CONVERT_PARAM stConvertPixelParam = new MyCamera.MV_PIXEL_CONVERT_PARAM();
  467. stConvertPixelParam.nWidth = stFrameOut.stFrameInfo.nWidth;
  468. stConvertPixelParam.nHeight = stFrameOut.stFrameInfo.nHeight;
  469. stConvertPixelParam.pSrcData = stFrameOut.pBufAddr;
  470. stConvertPixelParam.nSrcDataLen = stFrameOut.stFrameInfo.nFrameLen;
  471. stConvertPixelParam.enSrcPixelType = stFrameOut.stFrameInfo.enPixelType;
  472. stConvertPixelParam.enDstPixelType = enType;
  473. stConvertPixelParam.pDstBuffer = pBufForConvert;
  474. stConvertPixelParam.nDstBufferSize = (uint)(stFrameOut.stFrameInfo.nWidth * stFrameOut.stFrameInfo.nHeight * nChannelNum);
  475. int nRet = device.MV_CC_ConvertPixelType_NET(ref stConvertPixelParam);
  476. if (MyCamera.MV_OK != nRet)
  477. return null;
  478. // ch:将图像数据保存到本地文件 | en:Save image data to local file
  479. byte[] rawImage = new byte[stConvertPixelParam.nDstLen];
  480. Marshal.Copy(stConvertPixelParam.pDstBuffer, rawImage, 0, (int)stConvertPixelParam.nDstLen);
  481. if (pBufForConvert != IntPtr.Zero)
  482. Marshal.FreeHGlobal(pBufForConvert);
  483. //
  484. return rawImage;
  485. }
  486. return null;
  487. }
  488. private Bitmap toBitmap(IntPtr pData, MyCamera.MV_FRAME_OUT_INFO_EX pFrameInfo)
  489. {
  490. int nRet = MyCamera.MV_OK;
  491. //MyCamera device = m_pMyCamera;
  492. //MyCamera.MV_FRAME_OUT_INFO_EX pFrameInfo = new MyCamera.MV_FRAME_OUT_INFO_EX();
  493. //IntPtr pData = System.Runtime.InteropServices.Marshal.AllocHGlobal((int)g_nPayloadSize);
  494. if (pData == IntPtr.Zero)
  495. return null;
  496. IntPtr pTemp = IntPtr.Zero;
  497. IntPtr pImageBuffer = IntPtr.Zero;
  498. if (IsColorPixelFormat(pFrameInfo.enPixelType)) // 彩色图像处理
  499. {
  500. if (pFrameInfo.enPixelType == MyCamera.MvGvspPixelType.PixelType_Gvsp_RGB8_Packed)
  501. {
  502. pTemp = pData;
  503. }
  504. else
  505. {
  506. // 其他格式彩色图像转为RGB
  507. nRet = getBmpPtr(device, pData, pFrameInfo.nHeight, pFrameInfo.nWidth, pFrameInfo.enPixelType, pImageBuffer, MyCamera.MvGvspPixelType.PixelType_Gvsp_RGB8_Packed);
  508. if (MyCamera.MV_OK != nRet)
  509. return null;
  510. pTemp = pImageBuffer;
  511. }
  512. // Packed转Plane
  513. Byte[] byteArrImageData = new Byte[m_nRowStep * 3];
  514. unsafe
  515. {
  516. byte* pBufForSaveImage = (byte*)pTemp;
  517. UInt32 nSupWidth = (pFrameInfo.nWidth + (UInt32)3) & 0xfffffffc;
  518. for (int nRow = 0; nRow < pFrameInfo.nHeight; nRow++)
  519. {
  520. for (int col = 0; col < pFrameInfo.nWidth; col++)
  521. {
  522. byteArrImageData[nRow * nSupWidth + col] = pBufForSaveImage[nRow * pFrameInfo.nWidth * 3 + (3 * col)];
  523. byteArrImageData[pFrameInfo.nWidth * pFrameInfo.nHeight + nRow * nSupWidth + col] = pBufForSaveImage[nRow * pFrameInfo.nWidth * 3 + (3 * col + 1)];
  524. byteArrImageData[pFrameInfo.nWidth * pFrameInfo.nHeight * 2 + nRow * nSupWidth + col] = pBufForSaveImage[nRow * pFrameInfo.nWidth * 3 + (3 * col + 2)];
  525. }
  526. }
  527. pTemp = System.Runtime.InteropServices.Marshal.UnsafeAddrOfPinnedArrayElement(byteArrImageData, 0);
  528. }
  529. //
  530. Bitmap Station1Image1 = new System.Drawing.Bitmap(pFrameInfo.nWidth, pFrameInfo.nHeight, pFrameInfo.nWidth * 3, System.Drawing.Imaging.PixelFormat.Format24bppRgb, pTemp);
  531. //ColorPalette cp = Station1Image1.Palette;
  532. //for (int i = 0; i < 256; i++)
  533. //{
  534. // cp.Entries[i] = Color.FromArgb(i, i, i);
  535. //}
  536. //Station1Image1.Palette = cp;
  537. return Station1Image1;
  538. }
  539. else if (IsMonoPixelFormat(pFrameInfo.enPixelType)) // Mono图像处理
  540. {
  541. if (pFrameInfo.enPixelType == MyCamera.MvGvspPixelType.PixelType_Gvsp_Mono8)
  542. {
  543. pTemp = pData;
  544. }
  545. else
  546. {
  547. // 其他格式Mono转为Mono8
  548. //nRet = ConvertToMono8(device, pData, pImageBuffer, pFrameInfo.nHeight, pFrameInfo.nWidth, pFrameInfo.enPixelType);
  549. nRet = getBmpPtr(device, pData, pFrameInfo.nHeight, pFrameInfo.nWidth, pFrameInfo.enPixelType, pImageBuffer, MyCamera.MvGvspPixelType.PixelType_Gvsp_RGB8_Packed);
  550. if (MyCamera.MV_OK != nRet)
  551. return null;
  552. pTemp = pImageBuffer;
  553. }
  554. //
  555. Bitmap Station1Image1 = new System.Drawing.Bitmap(pFrameInfo.nWidth, pFrameInfo.nHeight, pFrameInfo.nWidth * 1, System.Drawing.Imaging.PixelFormat.Format8bppIndexed, pTemp);
  556. ColorPalette cp = Station1Image1.Palette;
  557. for (int i = 0; i < 256; i++)
  558. {
  559. cp.Entries[i] = Color.FromArgb(i, i, i);
  560. }
  561. Station1Image1.Palette = cp;
  562. return Station1Image1;
  563. }
  564. else
  565. return null;
  566. }
  567. public Int32 getBmpPtr(MyCamera device, IntPtr pSrc, ushort nHeight, ushort nWidth, MyCamera.MvGvspPixelType nPixelType, IntPtr pDst, MyCamera.MvGvspPixelType type)
  568. {
  569. if (IntPtr.Zero == pSrc || IntPtr.Zero == pDst)
  570. {
  571. return MyCamera.MV_E_PARAMETER;
  572. }
  573. int nRet = MyCamera.MV_OK;
  574. //MyCamera device = obj as MyCamera;
  575. MyCamera.MV_PIXEL_CONVERT_PARAM stPixelConvertParam = new MyCamera.MV_PIXEL_CONVERT_PARAM();
  576. stPixelConvertParam.pSrcData = pSrc;//源数据
  577. if (IntPtr.Zero == stPixelConvertParam.pSrcData)
  578. {
  579. return -1;
  580. }
  581. stPixelConvertParam.nWidth = nWidth;//图像宽度
  582. stPixelConvertParam.nHeight = nHeight;//图像厚度
  583. stPixelConvertParam.enSrcPixelType = nPixelType;//源数据的格式
  584. stPixelConvertParam.nSrcDataLen = (uint)(nWidth * nHeight * ((((uint)nPixelType) >> 16) & 0x00ff) >> 3);
  585. stPixelConvertParam.nDstBufferSize = (uint)(nWidth * nHeight * ((((uint)type) >> 16) & 0x00ff) >> 3);
  586. stPixelConvertParam.pDstBuffer = pDst;//转换后的数据
  587. stPixelConvertParam.enDstPixelType = type;
  588. stPixelConvertParam.nDstBufferSize = (uint)nWidth * nHeight * 3;
  589. nRet = device.MV_CC_ConvertPixelType_NET(ref stPixelConvertParam);//格式转换
  590. if (MyCamera.MV_OK != nRet)
  591. {
  592. return -1;
  593. }
  594. return MyCamera.MV_OK;
  595. }
  596. /// <summary>
  597. /// 其他黑白格式转为Mono8
  598. /// </summary>
  599. /// <param name="obj"></param>
  600. /// <param name="pInData">输出图片数据</param>
  601. /// <param name="pOutData">输出图片数据</param>
  602. /// <param name="nHeight">高</param>
  603. /// <param name="nWidth">宽</param>
  604. /// <param name="nPixelType">像素格式</param>
  605. /// <returns></returns>
  606. public Int32 ConvertToMono8(MyCamera device, IntPtr pInData, IntPtr pOutData, ushort nHeight, ushort nWidth, MyCamera.MvGvspPixelType nPixelType)
  607. {
  608. if (IntPtr.Zero == pInData || IntPtr.Zero == pOutData)
  609. {
  610. return MyCamera.MV_E_PARAMETER;
  611. }
  612. int nRet = MyCamera.MV_OK;
  613. //MyCamera device = obj as MyCamera;
  614. MyCamera.MV_PIXEL_CONVERT_PARAM stPixelConvertParam = new MyCamera.MV_PIXEL_CONVERT_PARAM();
  615. stPixelConvertParam.pSrcData = pInData;//源数据
  616. if (IntPtr.Zero == stPixelConvertParam.pSrcData)
  617. {
  618. return -1;
  619. }
  620. stPixelConvertParam.nWidth = nWidth;//图像宽度
  621. stPixelConvertParam.nHeight = nHeight;//图像厚度
  622. stPixelConvertParam.enSrcPixelType = nPixelType;//源数据的格式
  623. stPixelConvertParam.nSrcDataLen = (uint)(nWidth * nHeight * ((((uint)nPixelType) >> 16) & 0x00ff) >> 3);
  624. stPixelConvertParam.nDstBufferSize = (uint)(nWidth * nHeight * ((((uint)MyCamera.MvGvspPixelType.PixelType_Gvsp_RGB8_Packed) >> 16) & 0x00ff) >> 3);
  625. stPixelConvertParam.pDstBuffer = pOutData;//转换后的数据
  626. stPixelConvertParam.enDstPixelType = MyCamera.MvGvspPixelType.PixelType_Gvsp_Mono8;
  627. stPixelConvertParam.nDstBufferSize = (uint)(nWidth * nHeight * 3);
  628. nRet = device.MV_CC_ConvertPixelType_NET(ref stPixelConvertParam);//格式转换
  629. if (MyCamera.MV_OK != nRet)
  630. {
  631. return -1;
  632. }
  633. return nRet;
  634. }
  635. /// <summary>
  636. /// 其他彩色格式转为RGB8
  637. /// </summary>
  638. /// <param name="obj"></param>
  639. /// <param name="pSrc"></param>
  640. /// <param name="nHeight"></param>
  641. /// <param name="nWidth"></param>
  642. /// <param name="nPixelType"></param>
  643. /// <param name="pDst"></param>
  644. /// <returns></returns>
  645. public Int32 ConvertToRGB(MyCamera device, IntPtr pSrc, ushort nHeight, ushort nWidth, MyCamera.MvGvspPixelType nPixelType, IntPtr pDst)
  646. {
  647. if (IntPtr.Zero == pSrc || IntPtr.Zero == pDst)
  648. {
  649. return MyCamera.MV_E_PARAMETER;
  650. }
  651. int nRet = MyCamera.MV_OK;
  652. //MyCamera device = obj as MyCamera;
  653. MyCamera.MV_PIXEL_CONVERT_PARAM stPixelConvertParam = new MyCamera.MV_PIXEL_CONVERT_PARAM();
  654. stPixelConvertParam.pSrcData = pSrc;//源数据
  655. if (IntPtr.Zero == stPixelConvertParam.pSrcData)
  656. {
  657. return -1;
  658. }
  659. stPixelConvertParam.nWidth = nWidth;//图像宽度
  660. stPixelConvertParam.nHeight = nHeight;//图像厚度
  661. stPixelConvertParam.enSrcPixelType = nPixelType;//源数据的格式
  662. stPixelConvertParam.nSrcDataLen = (uint)(nWidth * nHeight * ((((uint)nPixelType) >> 16) & 0x00ff) >> 3);
  663. stPixelConvertParam.nDstBufferSize = (uint)(nWidth * nHeight * ((((uint)MyCamera.MvGvspPixelType.PixelType_Gvsp_RGB8_Packed) >> 16) & 0x00ff) >> 3);
  664. stPixelConvertParam.pDstBuffer = pDst;//转换后的数据
  665. stPixelConvertParam.enDstPixelType = MyCamera.MvGvspPixelType.PixelType_Gvsp_RGB8_Packed;
  666. stPixelConvertParam.nDstBufferSize = (uint)nWidth * nHeight * 3;
  667. nRet = device.MV_CC_ConvertPixelType_NET(ref stPixelConvertParam);//格式转换
  668. if (MyCamera.MV_OK != nRet)
  669. {
  670. return -1;
  671. }
  672. return MyCamera.MV_OK;
  673. }
  674. private static void ImageCallbackFunc(IntPtr pData, ref MyCamera.MV_FRAME_OUT_INFO_EX pFrameInfo, IntPtr pUser)
  675. {
  676. //Print parse the timestamp information in the frame
  677. Console.WriteLine("ImageCallBack: ExposureTime[" + Convert.ToString(pFrameInfo.fExposureTime)
  678. + "], SecondCount[" + Convert.ToString(pFrameInfo.nSecondCount)
  679. + "], CycleCount[" + Convert.ToString(pFrameInfo.nCycleCount)
  680. + "], CycleOffset[" + Convert.ToString(pFrameInfo.nCycleOffset)
  681. + "], FrameNum[" + Convert.ToString(pFrameInfo.nFrameNum) + "]");
  682. int nStrSize = Marshal.SizeOf(stChunkInfo);
  683. int nUnparsedChunkContent = (int)pFrameInfo.UnparsedChunkList.pUnparsedChunkContent;
  684. for (int i = 0; i < pFrameInfo.nUnparsedChunkNum; i++)
  685. {
  686. stChunkInfo = (MyCamera.MV_CHUNK_DATA_CONTENT)Marshal.PtrToStructure((IntPtr)(nUnparsedChunkContent + i * nStrSize), typeof(MyCamera.MV_CHUNK_DATA_CONTENT));
  687. Console.WriteLine("ChunkInfo:" + "ChunkID[0x{0:x8}],ChunkLen[" + Convert.ToString(stChunkInfo.nChunkLen) + "]", stChunkInfo.nChunkID);
  688. }
  689. Console.WriteLine("************************************");
  690. }
  691. static bool IsMonoPixelFormat(MyCamera.MvGvspPixelType enType)
  692. {
  693. switch (enType)
  694. {
  695. case MyCamera.MvGvspPixelType.PixelType_Gvsp_Mono8:
  696. case MyCamera.MvGvspPixelType.PixelType_Gvsp_Mono10:
  697. case MyCamera.MvGvspPixelType.PixelType_Gvsp_Mono10_Packed:
  698. case MyCamera.MvGvspPixelType.PixelType_Gvsp_Mono12:
  699. case MyCamera.MvGvspPixelType.PixelType_Gvsp_Mono12_Packed:
  700. return true;
  701. default:
  702. return false;
  703. }
  704. }
  705. static bool IsColorPixelFormat(MyCamera.MvGvspPixelType enType)
  706. {
  707. switch (enType)
  708. {
  709. case MyCamera.MvGvspPixelType.PixelType_Gvsp_RGB8_Packed:
  710. case MyCamera.MvGvspPixelType.PixelType_Gvsp_BGR8_Packed:
  711. case MyCamera.MvGvspPixelType.PixelType_Gvsp_YUV422_Packed:
  712. case MyCamera.MvGvspPixelType.PixelType_Gvsp_YUV422_YUYV_Packed:
  713. case MyCamera.MvGvspPixelType.PixelType_Gvsp_BayerGR8:
  714. case MyCamera.MvGvspPixelType.PixelType_Gvsp_BayerRG8:
  715. case MyCamera.MvGvspPixelType.PixelType_Gvsp_BayerGB8:
  716. case MyCamera.MvGvspPixelType.PixelType_Gvsp_BayerBG8:
  717. case MyCamera.MvGvspPixelType.PixelType_Gvsp_BayerGB10:
  718. case MyCamera.MvGvspPixelType.PixelType_Gvsp_BayerGB10_Packed:
  719. case MyCamera.MvGvspPixelType.PixelType_Gvsp_BayerBG10:
  720. case MyCamera.MvGvspPixelType.PixelType_Gvsp_BayerBG10_Packed:
  721. case MyCamera.MvGvspPixelType.PixelType_Gvsp_BayerRG10:
  722. case MyCamera.MvGvspPixelType.PixelType_Gvsp_BayerRG10_Packed:
  723. case MyCamera.MvGvspPixelType.PixelType_Gvsp_BayerGR10:
  724. case MyCamera.MvGvspPixelType.PixelType_Gvsp_BayerGR10_Packed:
  725. case MyCamera.MvGvspPixelType.PixelType_Gvsp_BayerGB12:
  726. case MyCamera.MvGvspPixelType.PixelType_Gvsp_BayerGB12_Packed:
  727. case MyCamera.MvGvspPixelType.PixelType_Gvsp_BayerBG12:
  728. case MyCamera.MvGvspPixelType.PixelType_Gvsp_BayerBG12_Packed:
  729. case MyCamera.MvGvspPixelType.PixelType_Gvsp_BayerRG12:
  730. case MyCamera.MvGvspPixelType.PixelType_Gvsp_BayerRG12_Packed:
  731. case MyCamera.MvGvspPixelType.PixelType_Gvsp_BayerGR12:
  732. case MyCamera.MvGvspPixelType.PixelType_Gvsp_BayerGR12_Packed:
  733. return true;
  734. default:
  735. return false;
  736. }
  737. }
  738. // ch:去除自定义的像素格式 | en:Remove custom pixel formats
  739. private bool RemoveCustomPixelFormats(MyCamera.MvGvspPixelType enPixelFormat)
  740. {
  741. long nResult = ((long)enPixelFormat) & (unchecked((long)0x80000000));
  742. if (0x80000000 == nResult)
  743. {
  744. return true;
  745. }
  746. else
  747. {
  748. return false;
  749. }
  750. }
  751. #endregion
  752. public void getParam()
  753. {
  754. if (!IsInit) return;
  755. MyCamera.MVCC_FLOATVALUE stParam = new MyCamera.MVCC_FLOATVALUE();
  756. int nRet = device.MV_CC_GetFloatValue_NET("ExposureTime", ref stParam);
  757. if (MyCamera.MV_OK == nRet)
  758. {
  759. ExposureTime = stParam.fCurValue;//.ToString("F1");
  760. }
  761. nRet = device.MV_CC_GetFloatValue_NET("Gain", ref stParam);
  762. if (MyCamera.MV_OK == nRet)
  763. {
  764. Gain = stParam.fCurValue;//.ToString("F1");
  765. }
  766. nRet = device.MV_CC_GetFloatValue_NET("ResultingFrameRate", ref stParam);
  767. if (MyCamera.MV_OK == nRet)
  768. {
  769. ResultingFrameRate = stParam.fCurValue;//.ToString("F1");
  770. }
  771. }
  772. /// <summary>
  773. ///
  774. /// </summary>
  775. /// <param name="exposureTime">曝光</param>
  776. /// <param name="gain">增益</param>
  777. /// <param name="resultingFrameRate">帧率</param>
  778. public void setParam(float exposureTime, float gain=0, float resultingFrameRate=0)
  779. {
  780. if (!IsInit) return;
  781. bool change = false;
  782. int nRet;
  783. if (exposureTime != ExposureTime)
  784. {
  785. device.MV_CC_SetEnumValue_NET("ExposureAuto", 0);
  786. nRet = device.MV_CC_SetFloatValue_NET("ExposureTime", exposureTime);
  787. if (nRet != MyCamera.MV_OK)
  788. {
  789. WarningEvent?.Invoke(WarningEnum.Normal, $"Scanner Set Exposure Time Fail! ({nRet})");
  790. }
  791. change = true;
  792. }
  793. if (gain != Gain)
  794. {
  795. device.MV_CC_SetEnumValue_NET("GainAuto", 0);
  796. nRet = device.MV_CC_SetFloatValue_NET("Gain", gain);
  797. if (nRet != MyCamera.MV_OK)
  798. {
  799. WarningEvent?.Invoke(WarningEnum.Normal, $"Scanner Set Gain Time Fail! ({nRet})");
  800. }
  801. change = true;
  802. }
  803. if (resultingFrameRate != ResultingFrameRate)
  804. {
  805. nRet = device.MV_CC_SetFloatValue_NET("AcquisitionFrameRate", resultingFrameRate);
  806. if (nRet != MyCamera.MV_OK)
  807. {
  808. WarningEvent?.Invoke(WarningEnum.Normal, $"Scanner Set AcquisitionFrameRate Time Fail! ({nRet})");
  809. }
  810. change = true;
  811. }
  812. //
  813. if(change)
  814. getParam();
  815. }
  816. /// <summary>
  817. /// 软触发拍照
  818. /// </summary>
  819. /// <param name="num">拍照数量</param>
  820. /// <returns></returns>
  821. public bool scan(int num=1)
  822. {
  823. if (!IsInit) return false;
  824. if (!isContinuousMode)
  825. {
  826. // ch:触发命令 | en:Trigger command
  827. int nRet = device.MV_CC_SetCommandValue_NET("TriggerSoftware");
  828. if (MyCamera.MV_OK != nRet)
  829. {
  830. WarningEvent?.Invoke(WarningEnum.Normal, $"Trigger Software Fail! ({nRet})");
  831. return false;
  832. }
  833. }
  834. this.scanNum= num;
  835. return true;
  836. }
  837. public void Dispose()
  838. {
  839. stop();
  840. }
  841. private byte[] bmp2bytes(Bitmap bmp)
  842. {
  843. MemoryStream ms = new MemoryStream();
  844. bmp.Save(ms, System.Drawing.Imaging.ImageFormat.Bmp);
  845. byte[] bytes = ms.GetBuffer(); //byte[] bytes= ms.ToArray(); 这两句都可以,至于区别么,下面有解释
  846. ms.Close();
  847. bmp.Dispose();
  848. return bytes;
  849. }
  850. private Bitmap bytes2bmp(byte[] bytes)
  851. {
  852. MemoryStream ms1 = new MemoryStream(bytes);
  853. Bitmap bm = (Bitmap)Image.FromStream(ms1);
  854. ms1.Close();
  855. return bm;
  856. }
  857. public Bitmap read2Bmp(string path)
  858. {
  859. MemoryStream ms = new System.IO.MemoryStream(File.ReadAllBytes(path));
  860. Bitmap bmp = new Bitmap(ms);
  861. ms.Close();
  862. ms.Dispose();
  863. //FileStream fs = new FileStream(path, FileMode.Open);
  864. //byte[] bmpdata = new byte[fs.Length];
  865. //fs.Read(bmpdata, 0, bmpdata.Length);
  866. //Bitmap bmp = new Bitmap(fs);
  867. //fs.Close();
  868. return bmp;
  869. }
  870. }
  871. }