161 lines
5.3 KiB
C#
161 lines
5.3 KiB
C#
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");
|
||
}
|
||
}
|
||
}
|