You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

511 lines
18 KiB

1 month ago
  1. using System;
  2. using System.Collections.Generic;
  3. using System.ComponentModel;
  4. using System.Data;
  5. using System.Drawing;
  6. using System.Drawing.Imaging;
  7. using System.IO;
  8. using System.Linq;
  9. using System.Text;
  10. using System.Threading.Tasks;
  11. using System.Windows.Forms;
  12. using AForge;
  13. using AForge.Controls;
  14. using AForge.Imaging;
  15. using AForge.Video;
  16. using AForge.Video.DirectShow;
  17. using System.Threading;
  18. using System.Reflection;
  19. using ShenTun.Camera.Common;
  20. namespace ShenTun.Camera.AForgeL
  21. {
  22. public partial class FrmCamera : Form
  23. {
  24. private string path_current = "";
  25. private string ini_file = "";
  26. private Photo SelectedPhoto = null;
  27. private FilterInfoCollection videoDevices;
  28. private VideoCaptureDevice videoSource;
  29. private Bitmap imgMap;
  30. private int MaxPiexl = 0;
  31. private int MaxPiexlVideo = 0;
  32. private int _capturesTotal;
  33. private int _capturesTimes;
  34. private string _imageFormat;
  35. private Boolean _isAutoConnect = false;
  36. public DialogResponse Result { get; set; }
  37. public FrmCamera(int capturesTotal, int capturesTimes, string imageFormat, Boolean isAutoConnect)
  38. {
  39. InitializeComponent();
  40. this._capturesTotal = capturesTotal;
  41. this._capturesTimes = capturesTimes;
  42. this._imageFormat = imageFormat;
  43. this._isAutoConnect = isAutoConnect;
  44. SetConfigPath();
  45. }
  46. private void SetConfigPath()
  47. {
  48. path_current = string.Format("{0}\\ShenTun", System.Environment.GetFolderPath(System.Environment.SpecialFolder.MyDocuments));
  49. if (!Directory.Exists(path_current))
  50. {
  51. Directory.CreateDirectory(path_current);
  52. }
  53. ini_file = string.Format("{0}\\Camera.ini", path_current);
  54. }
  55. private void SetFormat()
  56. {
  57. cmbFormat.ValueMember = "Code";
  58. cmbFormat.DisplayMember = "Name";
  59. cmbFormat.DataSource = Common.GetImageFormatList();
  60. }
  61. private void SetCmbDevice()
  62. {
  63. if (videoDevices.Count == 0) return;
  64. string name = "";
  65. List<DeviceItem> list = new List<DeviceItem>();
  66. for (int i = 0; i < videoDevices.Count; i++)
  67. {
  68. name = videoDevices[0].Name;
  69. DeviceItem d = new DeviceItem()
  70. {
  71. Index = i,
  72. Name = name,
  73. };
  74. list.Add(d);
  75. }
  76. cmbCamera.DisplayMember = "Name";
  77. cmbCamera.ValueMember = "Index";
  78. cmbCamera.DataSource = list;
  79. }
  80. private void SetCmbPixelVideo(VideoCapabilities[] _videoCapabilities)
  81. {
  82. if (_videoCapabilities.Length == 0) return;
  83. string text = "";
  84. List<VideoPixelItem> list = new List<VideoPixelItem>();
  85. for (int i = 0; i < _videoCapabilities.Length; i++)
  86. {
  87. text = string.Format("{0} x {1}", _videoCapabilities[i].FrameSize.Width, _videoCapabilities[i].FrameSize.Height);
  88. VideoPixelItem item = new VideoPixelItem()
  89. {
  90. Index = i,
  91. Text = text,
  92. };
  93. list.Add(item);
  94. }
  95. MaxPiexlVideo = _videoCapabilities.Length - 1;
  96. cmbPixelVideo.DataSource = list;
  97. cmbPixelVideo.DisplayMember = "Text";
  98. cmbPixelVideo.ValueMember = "Index";
  99. }
  100. private void SetCmbPixel(VideoCapabilities[] _videoCapabilities)
  101. {
  102. if (_videoCapabilities.Length == 0) return;
  103. string text = "";
  104. List<VideoPixelItem> list = new List<VideoPixelItem>();
  105. for (int i = 0; i < _videoCapabilities.Length; i++)
  106. {
  107. text = string.Format("{0} x {1}", _videoCapabilities[i].FrameSize.Width, _videoCapabilities[i].FrameSize.Height);
  108. VideoPixelItem item = new VideoPixelItem()
  109. {
  110. Index = i,
  111. Text = text,
  112. };
  113. list.Add(item);
  114. }
  115. MaxPiexl = _videoCapabilities.Length - 1;
  116. cmbPixel.DataSource = list;
  117. cmbPixel.DisplayMember = "Text";
  118. cmbPixel.ValueMember = "Index";
  119. }
  120. private void setEnabled(bool isEnabled)
  121. {
  122. btnConnect.Enabled = !isEnabled;
  123. cmbCamera.Enabled = !isEnabled;
  124. cmbPixelVideo.Enabled = isEnabled;
  125. btnDisConnect.Enabled = isEnabled;
  126. btnPhotoGraph.Enabled = isEnabled;
  127. btnProperty.Enabled = isEnabled;
  128. btnMultiPhoto.Enabled = isEnabled;
  129. btnClear.Enabled = isEnabled;
  130. }
  131. private void setInfo(string info)
  132. {
  133. lbInfoText.Text = info;
  134. }
  135. private void CameraConn()
  136. {
  137. videoSource = new VideoCaptureDevice(videoDevices[cmbCamera.SelectedIndex].MonikerString);
  138. int index = Convert.ToInt32(cmbPixel.SelectedValue);
  139. videoSource.VideoResolution = videoSource.VideoCapabilities[index];
  140. videoSourcePlayer1.VideoSource = videoSource;
  141. }
  142. private void FrmCamera_Load(object sender, EventArgs e)
  143. {
  144. setEnabled(false);
  145. try
  146. {
  147. // 枚举所有视频输入设备
  148. videoDevices = new FilterInfoCollection(FilterCategory.VideoInputDevice);
  149. if (videoDevices.Count == 0)
  150. throw new ApplicationException();
  151. SetCmbDevice();
  152. cmbCamera.SelectedIndex = 0;
  153. var _cameraDevice = new VideoCaptureDevice(videoDevices[0].MonikerString);
  154. SetCmbPixelVideo(_cameraDevice.VideoCapabilities);
  155. SetCmbPixel(_cameraDevice.SnapshotCapabilities);
  156. SetFormat();
  157. Common.GetImageFormatList();
  158. ImgFormatItem item = Common.iList.Where(p => (p.Name.Equals(_imageFormat.ToUpper()))).FirstOrDefault();
  159. cmbFormat.SelectedValue = item.Code;
  160. cmbFormat.Enabled = false;
  161. int cameraIndex = Convert.ToInt32(IniConfigHelper.ReadSetting(ini_file, "Option", "CameraIndex", "0"));
  162. cmbCamera.SelectedValue = cameraIndex;
  163. setInfo("设备初始化完成...");
  164. if (_isAutoConnect)
  165. btnConnect_Click(null, null);
  166. }
  167. catch (ApplicationException)
  168. {
  169. //cmbCamera.Items.Add("没有本地设备");
  170. videoDevices = null;
  171. setInfo("没有本地设备...");
  172. }
  173. catch (Exception ex)
  174. {
  175. //cmbCamera.Items.Add("没有本地设备");
  176. videoDevices = null;
  177. setInfo("没有本地设备...");
  178. MessageBox.Show("初始化失败:" + ex.Message);
  179. }
  180. }
  181. private void cmbCamera_SelectedValueChanged(object sender, EventArgs e)
  182. {
  183. try
  184. {
  185. if (this.cmbCamera.SelectedValue == null) return;
  186. if (videoDevices.Count == 0 || videoDevices.Count == 1) return;
  187. int index = Convert.ToInt32(this.cmbCamera.SelectedValue);
  188. var _cameraDevice = new VideoCaptureDevice(videoDevices[index].MonikerString);
  189. SetCmbPixelVideo(_cameraDevice.VideoCapabilities);
  190. SetCmbPixel(_cameraDevice.SnapshotCapabilities);
  191. }
  192. catch (Exception ex)
  193. {
  194. MessageBox.Show("切换摄像头失败:" + ex.Message);
  195. }
  196. }
  197. private void cmbPixelVideo_SelectedValueChanged(object sender, EventArgs e)
  198. {
  199. try
  200. {
  201. if (videoSourcePlayer1.VideoSource == null) return;
  202. if (cmbCamera.Enabled) return;
  203. VideoCaptureDevice videoSource = (VideoCaptureDevice)videoSourcePlayer1.VideoSource;
  204. int index = Convert.ToInt32(cmbPixelVideo.SelectedValue);
  205. videoSource.VideoResolution = videoSource.VideoCapabilities[index];
  206. videoSourcePlayer1.VideoSource = videoSource;
  207. cmbPixel.SelectedValue = cmbPixelVideo.SelectedValue;
  208. }
  209. catch (Exception ex)
  210. {
  211. MessageBox.Show("切换分辨率异常:" + ex.Message);
  212. }
  213. }
  214. private void cmbPixel_SelectedValueChanged(object sender, EventArgs e)
  215. {
  216. try
  217. {
  218. if (videoSourcePlayer1.VideoSource == null) return;
  219. if (cmbCamera.Enabled) return;
  220. VideoCaptureDevice videoSource = (VideoCaptureDevice)videoSourcePlayer1.VideoSource;
  221. int index = Convert.ToInt32(cmbPixel.SelectedValue);
  222. videoSource.SnapshotResolution = videoSource.SnapshotCapabilities[index];
  223. videoSourcePlayer1.VideoSource = videoSource;
  224. if (videoSourcePlayer1.IsRunning)
  225. {
  226. videoSourcePlayer1.SignalToStop();
  227. videoSourcePlayer1.WaitForStop();
  228. }
  229. videoSourcePlayer1.Start();
  230. }
  231. catch (Exception ex)
  232. {
  233. MessageBox.Show("切换分辨率异常:" + ex.Message);
  234. }
  235. }
  236. private void btnConnect_Click(object sender, EventArgs e)
  237. {
  238. try
  239. {
  240. CameraConn();
  241. int pixelVideoIndex = Convert.ToInt32(IniConfigHelper.ReadSetting(ini_file, "Option", "PixelVideoIndex", "0"));
  242. //激活初始化按钮状态
  243. setEnabled(true);
  244. videoSourcePlayer1.Start();
  245. Thread.Sleep(300);
  246. cmbPixelVideo.SelectedValue = pixelVideoIndex;
  247. setInfo("设备已连接...");
  248. }catch(Exception ex)
  249. {
  250. MessageBox.Show("连接失败:" + ex.Message);
  251. }
  252. }
  253. private void btnDisConnect_Click(object sender, EventArgs e)
  254. {
  255. videoSourcePlayer1.SignalToStop();
  256. videoSourcePlayer1.WaitForStop();
  257. setEnabled(false);
  258. setInfo("设备已断开...");
  259. }
  260. void cs_SelectPhotoInfo(string photoId)
  261. {
  262. SelectedPhoto = null;
  263. foreach (var ctrl in flowLayoutPanel1.Controls)
  264. {
  265. if (!(ctrl is Photo)) continue;
  266. if (((Photo)ctrl).PhotoId != photoId)
  267. {
  268. if (((Photo)ctrl).Selected == true)
  269. {
  270. ((Photo)ctrl).Selected = false;
  271. ((Photo)ctrl).Refresh();
  272. }
  273. }else
  274. {
  275. SelectedPhoto = ((Photo)ctrl);
  276. this.picCurrent.Image = SelectedPhoto.Image;
  277. }
  278. }
  279. }
  280. private void btnPhotoGraph_Click(object sender, EventArgs e)
  281. {
  282. try
  283. {
  284. if (!videoSourcePlayer1.IsRunning) return;
  285. imgMap = this.videoSourcePlayer1.GetCurrentVideoFrame();
  286. Photo photo = new Photo()
  287. {
  288. Image = imgMap,
  289. PhotoId = Guid.NewGuid().ToString(),
  290. Size = new Size(40, 40),
  291. };
  292. photo.SelecPhotoInfo+=new Photo.SelectedPhoto(cs_SelectPhotoInfo);
  293. this.flowLayoutPanel1.Controls.Add(photo);
  294. this.picCurrent.Image = photo.Image;
  295. /*
  296. Button b1 = new Button();
  297. MessageBox.Show(string.Format("H:{0},W:{1}", b1.Size.Height, b1.Size.Width));
  298. this.flowLayoutPanel1.Controls.Add(b1);
  299. * * */
  300. }
  301. catch (Exception ex)
  302. {
  303. MessageBox.Show("摄像头异常:" + ex.Message);
  304. }
  305. }
  306. void progressChanged(CommonRequest requset)
  307. {
  308. string infoTitle = requset.Percentage == 100 ? "任务已完成" : "任务正在处理";
  309. string progress = String.Format("{0},进度【{1}%】", infoTitle, requset.Percentage);
  310. this.flowLayoutPanel1.Controls.Add(requset.Photo);
  311. this.picCurrent.Image = requset.Photo.Image;
  312. setInfo(progress);
  313. }
  314. void WorkCompleted(CommonResult result)
  315. {
  316. if (result.Success)
  317. {
  318. //操作成功的处理
  319. }
  320. this.btnMultiPhoto.Enabled = true;
  321. }
  322. private async Task<CommonResult> WorkStart(IProgress<CommonRequest> progress)
  323. {
  324. var result = new CommonResult();
  325. for (int i = 0; i < _capturesTotal; i++)
  326. {
  327. imgMap = this.videoSourcePlayer1.GetCurrentVideoFrame();
  328. Photo photo = new Photo()
  329. {
  330. Image = imgMap,
  331. PhotoId = Guid.NewGuid().ToString(),
  332. Size = new Size(40, 40),
  333. };
  334. photo.SelecPhotoInfo += new Photo.SelectedPhoto(cs_SelectPhotoInfo);
  335. await Task.Delay(_capturesTimes);
  336. CommonRequest pro = new CommonRequest
  337. {
  338. Percentage = i + 1,
  339. Photo = photo,
  340. };
  341. progressChanged(pro);
  342. //progress.Report(pro); //异步窗口不需要在progress对象中进行UI更新
  343. }
  344. result.Success = true;
  345. return result;
  346. }
  347. private async void btnMultiPhoto_Click(object sender, EventArgs e)
  348. {
  349. try
  350. {
  351. if (videoSourcePlayer1.VideoSource == null) return;
  352. this.btnMultiPhoto.Enabled = false;
  353. var reporter = new Progress<CommonRequest>(progressChanged);
  354. var result = await this.WorkStart(reporter);
  355. this.WorkCompleted(result);
  356. }
  357. catch (Exception ex)
  358. {
  359. MessageBox.Show("连拍异常:" + ex.Message);
  360. }
  361. }
  362. private void btnProperty_Click(object sender, EventArgs e)
  363. {
  364. VideoCaptureDevice videoSource = (VideoCaptureDevice)videoSourcePlayer1.VideoSource;
  365. videoSource.DisplayPropertyPage(IntPtr.Zero);
  366. }
  367. private void btnClear_Click(object sender, EventArgs e)
  368. {
  369. try
  370. {
  371. if (this.flowLayoutPanel1.Controls.Count == 0) return;
  372. this.flowLayoutPanel1.Controls.Clear();
  373. this.picCurrent.Image = null;
  374. }
  375. catch (Exception ex)
  376. {
  377. MessageBox.Show("清空异常:" + ex.Message);
  378. }
  379. }
  380. private void btnSave_Click(object sender, EventArgs e)
  381. {
  382. try
  383. {
  384. if(picCurrent.Image==null)
  385. {
  386. MessageBox.Show("没有获取到图片,请先拍照");
  387. return;
  388. }
  389. System.Drawing.Image img = picCurrent.Image;
  390. Bitmap bmp = (Bitmap)img;
  391. System.Drawing.Imaging.ImageFormat format = (ImageFormat)cmbFormat.SelectedValue;
  392. string extenName = Common.GetImageFormatString(format).ToLower();
  393. string fileName = string.Format("{0}\\{1}.{2}", path_current, "photo", extenName);
  394. ImageCodecInfo Encoder = ImageHelper.GetEncoder(format);
  395. System.Drawing.Imaging.Encoder myEncoder = System.Drawing.Imaging.Encoder.Quality;
  396. EncoderParameters myEncoderParameters = new EncoderParameters(1);
  397. EncoderParameter myEncoderParameter = new EncoderParameter(myEncoder, 50L);
  398. myEncoderParameters.Param[0] = myEncoderParameter;
  399. bmp.Save(fileName, Encoder, myEncoderParameters);
  400. System.Drawing.Image imge = System.Drawing.Image.FromFile(fileName);
  401. PhotoResponse resPhoto = new PhotoResponse()
  402. {
  403. Photo = ImageHelper.ConvertImageToBase64(imge),
  404. PhotoFormat = extenName,
  405. };
  406. DialogResponse response = new DialogResponse()
  407. {
  408. code = 1,
  409. message = "Success",
  410. data = resPhoto,
  411. };
  412. Result = response;
  413. this.DialogResult = System.Windows.Forms.DialogResult.OK;
  414. }
  415. catch (Exception ex)
  416. {
  417. MessageBox.Show("保存异常:" + ex.Message);
  418. }
  419. }
  420. private void FrmCamera_FormClosed(object sender, FormClosedEventArgs e)
  421. {
  422. try
  423. {
  424. if (videoSourcePlayer1.IsRunning)
  425. {
  426. videoSourcePlayer1.SignalToStop();
  427. videoSourcePlayer1.WaitForStop();
  428. }
  429. if (cmbCamera.SelectedValue != null)
  430. {
  431. IniConfigHelper.WriteSetting(ini_file, "Option", "CameraIndex", cmbCamera.SelectedValue.ToString());
  432. IniConfigHelper.WriteSetting(ini_file, "Option", "PixelVideoIndex", cmbPixelVideo.SelectedValue.ToString());
  433. }
  434. if(Result==null)
  435. {
  436. DialogResponse response = new DialogResponse()
  437. {
  438. code = 0,
  439. message = "用户取消操作",
  440. };
  441. Result = response;
  442. }
  443. }
  444. catch (Exception ex)
  445. {
  446. MessageBox.Show("关闭异常:" + ex.Message);
  447. }
  448. }
  449. private void btnCancel_Click(object sender, EventArgs e)
  450. {
  451. try
  452. {
  453. DialogResponse response = new DialogResponse()
  454. {
  455. code = 0,
  456. message = "用户取消操作",
  457. };
  458. Result = response;
  459. this.DialogResult = System.Windows.Forms.DialogResult.Cancel;
  460. }
  461. catch (Exception ex)
  462. {
  463. MessageBox.Show("清空异常:" + ex.Message);
  464. }
  465. }
  466. }
  467. }