67 lines
2.0 KiB
C#
Raw Normal View History

2025-09-15 14:45:54 +08:00
using System;
using System.IO;
using System.Linq;
using System.Windows.Controls;
using System.Windows.Media;
using System.Windows.Media.Imaging;
public class RTSPPreviewRenderer : IDisposable
{
private Canvas _canvas;
private Image _imageControl;
private WriteableBitmap _bitmap;
public bool Adaptive { get; set; } = true;
public RTSPPreviewRenderer(Canvas canvas)
{
_canvas = canvas ?? throw new ArgumentNullException(nameof(canvas));
_imageControl = new Image();
_canvas.Children.Add(_imageControl);
Canvas.SetLeft(_imageControl, 0);
Canvas.SetTop(_imageControl, 0);
}
/// <summary>更新帧到 Canvas</summary>
public void UpdateFrame(byte[] pixelData, int width, int height)
{
if (_bitmap == null || _bitmap.PixelWidth != width || _bitmap.PixelHeight != height)
{
_bitmap = new WriteableBitmap(width, height, 96, 96, PixelFormats.Bgra32, null);
_imageControl.Source = _bitmap;
}
_bitmap.Lock();
_bitmap.WritePixels(new System.Windows.Int32Rect(0, 0, width, height), pixelData, width * 4, 0);
_bitmap.AddDirtyRect(new System.Windows.Int32Rect(0, 0, width, height));
_bitmap.Unlock();
// 自动适应 Canvas
if (Adaptive)
{
double scaleX = _canvas.ActualWidth / width;
double scaleY = _canvas.ActualHeight / height;
double scale = Math.Min(scaleX, scaleY);
_imageControl.Width = width * scale;
_imageControl.Height = height * scale;
Canvas.SetLeft(_imageControl, (_canvas.ActualWidth - _imageControl.Width) / 2);
Canvas.SetTop(_imageControl, (_canvas.ActualHeight - _imageControl.Height) / 2);
}
else
{
_imageControl.Width = _canvas.ActualWidth;
_imageControl.Height = _canvas.ActualHeight;
Canvas.SetLeft(_imageControl, 0);
Canvas.SetTop(_imageControl, 0);
}
}
public void Dispose()
{
_bitmap = null;
}
}