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 { /// /// CameraControl.xaml 的交互逻辑 /// 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"} } } /// /// 更新预先创建的 WriteableBitmap 的像素数据 /// 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"); } } }