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