MoS2/App/SicUI/Controls/CameraControl.xaml.cs
2026-08-13 22:07:07 +08:00

161 lines
5.3 KiB
C#
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

using Aitex.Core.RT.Log;
using CommandLine;
using MECF.Framework.Common.DataCenter;
using SicUI.Controls.M2C4Parts;
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Drawing.Imaging;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Security.Cryptography;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using System.Windows.Threading;
using VM.PlatformSDKCS;
namespace SicUI.Controls
{
/// <summary>
/// CameraControl.xaml 的交互逻辑
/// </summary>
public partial class CameraControl : UserControl
{
private WriteableBitmap _bitmap;
private Int32Rect _rect;
private CancellationTokenSource _cts;
public CameraControl()
{
InitializeComponent();
// 获取摄像头分辨率
var width = (int)QueryDataClient.Instance.Service.GetConfig("HikGigeCamera.Width");
var height = (int)QueryDataClient.Instance.Service.GetConfig("HikGigeCamera.Height");
// 创建 WriteableBitmap注意像素格式需要与摄像头输出匹配例如 Bgr24
_bitmap = new WriteableBitmap(width, height, 96, 96, System.Windows.Media.PixelFormats.Bgr24, null);
_rect = new Int32Rect(0, 0, _bitmap.PixelWidth, _bitmap.PixelHeight);
// 只需设置一次 Source不必每帧重新赋值
imageControl.Source = _bitmap;
}
private async Task CaptureLoop(CancellationToken token)
{
while (!token.IsCancellationRequested)
{
try
{
var obj = QueryDataClient.Instance.Service.GetData($"LoadLock.HikGigeCamera.CamBitmap");
if (obj != null)
{
Bitmap b = BytesToBitmap((byte[])obj);
// 在 UI 线程更新图像数据
#pragma warning disable CS4014
Application.Current.Dispatcher.BeginInvoke(
DispatcherPriority.Background,
new Action(() => UpdateBitmap(b)));
#pragma warning restore CS4014
}
}
catch (Exception ex)
{
LOG.Warning($"Camera Capture failed{ex}");
}
// 根据需要调整延时,防止 CPU 占用过高
// 异步延时,释放后台线程资源,并响应取消请求
try
{
await Task.Delay(20, token);
}
catch (OperationCanceledException)
{
break;
}
}
}
public Bitmap BytesToBitmap(byte[] bytes)
{
using (MemoryStream ms = new MemoryStream(bytes))
{
return new Bitmap(ms); // 或使用Image.FromStream:ml-citation{ref="1,18" data="citationList"}
}
}
/// <summary>
/// 更新预先创建的 WriteableBitmap 的像素数据
/// </summary>
private void UpdateBitmap(Bitmap frame)
{
if (frame == null || _bitmap == null) return;
_bitmap.Lock();
try
{
// 3. 移除类级别的 _bitmapData改为局部变量
var rect = new System.Drawing.Rectangle(0, 0, frame.Width, frame.Height);
var bitmapData = frame.LockBits(rect, ImageLockMode.ReadOnly, System.Drawing.Imaging.PixelFormat.Format24bppRgb);
try
{
int size = bitmapData.Height * bitmapData.Stride;
_bitmap.WritePixels(_rect, bitmapData.Scan0, size, bitmapData.Stride, 0, 0);
}
finally
{
// 4. 无论如何必须解锁 GDI 数据
frame.UnlockBits(bitmapData);
}
}
finally
{
// 5. 无论如何必须释放 Bitmap 和解锁 WriteableBitmap
frame.Dispose();
_bitmap.Unlock();
}
}
private void ButtonGrab_Click(object sender, RoutedEventArgs e)
{
InvokeClient.Instance.Service.DoOperation($"LoadLock.HikGigeCamera.Grab","UIGrab");
}
private void ButtonGrabbing_Click(object sender, RoutedEventArgs e)
{
InvokeClient.Instance.Service.DoOperation($"LoadLock.HikGigeCamera.Grabbing");
}
private void CameraControl_Unloaded(object sender, RoutedEventArgs e)
{
_cts?.Cancel();
InvokeClient.Instance.Service.DoOperation($"LoadLock.HikGigeCamera.Stop");
}
private void CameraControl_loaded(object sender, RoutedEventArgs e)
{
_cts = new CancellationTokenSource();
_ = CaptureLoop(_cts.Token);
}
private void ButtonStop_Click(object sender, RoutedEventArgs e)
{
InvokeClient.Instance.Service.DoOperation($"LoadLock.HikGigeCamera.Stop");
}
}
}