Files
BaslerCapture/MainWindow.xaml.cs
2025-11-28 14:57:00 +08:00

281 lines
9.3 KiB
C#

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();
}
}
}