87 lines
2.4 KiB
C#
87 lines
2.4 KiB
C#
using SHH.Contracts;
|
|
using System.IO;
|
|
using System.Windows;
|
|
using System.Windows.Media;
|
|
using System.Windows.Media.Imaging;
|
|
|
|
namespace SHH.CameraDashboard
|
|
{
|
|
public class VideoTileViewModel : ViewModelBase, IDisposable
|
|
{
|
|
// --- 绑定属性 ---
|
|
|
|
private ImageSource _displayImage;
|
|
public ImageSource DisplayImage
|
|
{
|
|
get => _displayImage;
|
|
set => SetProperty(ref _displayImage, value);
|
|
}
|
|
|
|
private string _cameraName;
|
|
public string CameraName
|
|
{
|
|
get => _cameraName;
|
|
set => SetProperty(ref _cameraName, value);
|
|
}
|
|
|
|
private string _statusInfo;
|
|
public string StatusInfo
|
|
{
|
|
get => _statusInfo;
|
|
set => SetProperty(ref _statusInfo, value);
|
|
}
|
|
|
|
private bool _isConnected;
|
|
public bool IsConnected
|
|
{
|
|
get => _isConnected;
|
|
set => SetProperty(ref _isConnected, value);
|
|
}
|
|
|
|
// --- 构造函数 ---
|
|
public VideoTileViewModel(string ip, int port, string name)
|
|
{
|
|
CameraName = name;
|
|
StatusInfo = "连接中...";
|
|
|
|
IsConnected = true;
|
|
}
|
|
|
|
private void HandleNewFrame(VideoPayload payload)
|
|
{
|
|
// 必须回到 UI 线程更新 ImageSource
|
|
Application.Current.Dispatcher.Invoke(() =>
|
|
{
|
|
// 1. 更新图片
|
|
byte[] data = payload.TargetImageBytes ?? payload.OriginalImageBytes;
|
|
if (data != null && data.Length > 0)
|
|
{
|
|
DisplayImage = ByteToBitmap(data);
|
|
}
|
|
|
|
// 2. 更新状态文字
|
|
StatusInfo = $"{payload.CaptureTime:HH:mm:ss} | {data?.Length / 1024} KB";
|
|
});
|
|
}
|
|
|
|
// 简单的 Bytes 转 BitmapImage (生产环境建议优化为 WriteableBitmap)
|
|
private BitmapImage ByteToBitmap(byte[] bytes)
|
|
{
|
|
var bitmap = new BitmapImage();
|
|
using (var stream = new MemoryStream(bytes))
|
|
{
|
|
bitmap.BeginInit();
|
|
bitmap.CacheOption = BitmapCacheOption.OnLoad;
|
|
bitmap.StreamSource = stream;
|
|
bitmap.EndInit();
|
|
}
|
|
bitmap.Freeze(); // 必须冻结才能跨线程
|
|
return bitmap;
|
|
}
|
|
|
|
public void Dispose()
|
|
{
|
|
IsConnected = false;
|
|
}
|
|
}
|
|
} |