using Basler.Pylon; using Microsoft.Win32; using Microsoft.WindowsAPICodePack.Dialogs; using System; using System.IO; using System.Threading.Tasks; using System.Windows; using System.Windows.Media.Imaging; namespace WpfApp1 { public partial class MainWindow : Window { private Camera _camera; private string _saveFolder = @"C:\CapturedImages"; private ICameraInfo? _selectedCameraInfo; private bool _isCameraStarted = false; public MainWindow() { InitializeComponent(); WindowStyle = WindowStyle.None; ResizeMode = ResizeMode.NoResize; WindowState = WindowState.Maximized; ButtonPanel1.IsEnabled = false; StatusText.Text = "正在初始化相机...请稍后"; Task.Run(() => InitializeCameraAsync()); } private async Task InitializeCameraAsync() { try { var cameras = CameraFinder.Enumerate(); if (cameras.Count == 0) { Dispatcher.Invoke(() => { ButtonPanel1.IsEnabled = true; StatusText.Text = "未检测到相机"; }); return; } _selectedCameraInfo = cameras[0]; await Task.CompletedTask; Dispatcher.Invoke(() => { ButtonPanel1.IsEnabled = true; StatusText.Text = "相机初始化完成,请选择相机并随后‘开启推流’开始取流"; StartCameraButton.Content = "开启推流"; }); } catch (Exception ex) { Dispatcher.Invoke(() => MessageBox.Show("初始化失败: " + ex.Message)); } } private void StartCameraButton_Click(object sender, RoutedEventArgs e) { try { // 确保相机已打开 if ((_camera == null || !_camera.IsOpen) && _selectedCameraInfo != null) { if (_camera != null) { try { _camera.StreamGrabber.Stop(); _camera.StreamGrabber.ImageGrabbed -= OnImageGrabbed; _camera.Close(); } catch { } finally { _camera = null; } } _camera = new Camera(_selectedCameraInfo); _camera.Open(); _camera.Parameters[PLCamera.AcquisitionMode].SetValue(PLCamera.AcquisitionMode.Continuous); } if (_camera == null || !_camera.IsOpen) { StatusText.Text = "请先选择一个相机"; return; } if (!_isCameraStarted) { _camera.StreamGrabber.ImageGrabbed += OnImageGrabbed; _camera.StreamGrabber.Start(GrabStrategy.LatestImages, GrabLoop.ProvidedByStreamGrabber); _isCameraStarted = true; StatusText.Text = "推流已开启"; StartCameraButton.Content = "关闭推流"; } else { try { _camera.StreamGrabber.Stop(); _camera.StreamGrabber.ImageGrabbed -= OnImageGrabbed; _isCameraStarted = false; StatusText.Text = "推流已关闭"; StartCameraButton.Content = "开启推流"; } catch (Exception ex) { StatusText.Text = "关闭推流失败:" + ex.Message; } } } catch (Exception ex) { StatusText.Text = "推流切换失败:" + ex.Message; } } private void OnImageGrabbed(object sender, ImageGrabbedEventArgs e) { try { using (IGrabResult result = e.GrabResult) { if (!result.GrabSucceeded) return; var converter = new PixelDataConverter(); converter.OutputPixelFormat = PixelType.BGRA8packed; byte[] buffer = new byte[result.Width * result.Height * 4]; converter.Convert(buffer, result); Dispatcher.Invoke(() => { CameraImage.Source = BitmapSource.Create( result.Width, result.Height, 96, 96, System.Windows.Media.PixelFormats.Bgra32, null, buffer, result.Width * 4); }); } } catch { // 忽略异常 } } private void CaptureButton_Click(object sender, RoutedEventArgs e) { if (CameraImage.Source == null) { StatusText.Text = "没有图像可保存"; return; } try { string filePath = Path.Combine(_saveFolder, $"Capture_{DateTime.Now:yyyyMMdd_HHmmss}.png"); SaveImage(CameraImage.Source as BitmapSource, filePath); StatusText.Text = $"图像已保存到:{filePath}"; } catch (Exception ex) { StatusText.Text = "保存失败:" + ex.Message; } } private void SaveImage(BitmapSource bitmap, string filePath) { var encoder = new PngBitmapEncoder(); encoder.Frames.Add(BitmapFrame.Create(bitmap)); using (FileStream stream = new FileStream(filePath, FileMode.Create)) { encoder.Save(stream); } } private void ChangeFolderButton_Click(object sender, RoutedEventArgs e) { var selected = FolderHelper.SelectFolder(); if (selected != null) { _saveFolder = selected; StatusText.Text = $"保存目录已切换为:{_saveFolder}"; } } protected override void OnClosing(System.ComponentModel.CancelEventArgs e) { base.OnClosing(e); if (_camera != null) { try { _camera.StreamGrabber.Stop(); _camera.StreamGrabber.ImageGrabbed -= OnImageGrabbed; _camera.Close(); } catch (Exception ex) { StatusText.Text = "关闭相机时出错:" + ex.Message; } finally { _camera = null; _isCameraStarted = false; } } } private void SelectCameraButton_Click(object sender, RoutedEventArgs e) { var dlg = new SelectCamera(); dlg.Owner = this; if (dlg.ShowDialog() == true) { var selectedInfo = dlg.SelectedCameraInfo; _selectedCameraInfo = selectedInfo; // 关闭旧相机,打开新相机,但不取流 try { if (_camera != null) { try { _camera.StreamGrabber.Stop(); _camera.StreamGrabber.ImageGrabbed -= OnImageGrabbed; _camera.Close(); } catch { } finally { _camera = null; _isCameraStarted = false; } } _camera = new Camera(_selectedCameraInfo); _camera.Open(); _camera.Parameters[PLCamera.AcquisitionMode].SetValue(PLCamera.AcquisitionMode.Continuous); _isCameraStarted = false; StatusText.Text = $"已选择并打开相机:{selectedInfo[CameraInfoKey.SerialNumber]}(未取流)。点击‘开启推流’开始/停止推流"; StartCameraButton.Content = "开启推流"; } catch (Exception ex) { StatusText.Text = "打开相机失败:" + ex.Message; } } } private void ExitButton_Click(object sender, RoutedEventArgs e) { Close(); } private void TimedCaptureButton_Click(object sender, RoutedEventArgs e) { // 定时拍摄只要求相机已打开,无需取流 if (_camera == null || !_camera.IsOpen) { MessageBox.Show("请先选择相机(会自动打开但不取流)"); return; } var dlg = new TimedCapture(_camera); dlg.Owner = this; dlg.ShowDialog(); } } }