diff --git a/Ink Canvas/Helpers/CameraService.cs b/Ink Canvas/Helpers/CameraService.cs index 9e18fb96..894fe496 100644 --- a/Ink Canvas/Helpers/CameraService.cs +++ b/Ink Canvas/Helpers/CameraService.cs @@ -154,51 +154,91 @@ namespace Ink_Canvas.Helpers } /// - /// 获取当前帧的Bitmap - /// - public Bitmap GetCurrentFrame() - { - lock (_frameLock) - { - return _currentFrame?.Clone() as Bitmap; - } - } - - /// - /// 获取当前帧的BitmapSource(WPF格式) + /// 获取当前帧的BitmapSource(WPF格式),直接返回可用的WPF位图 /// public BitmapSource GetCurrentFrameAsBitmapSource() { lock (_frameLock) { if (_currentFrame == null) + { + LogHelper.WriteLogToFile("GetCurrentFrameAsBitmapSource: _currentFrame为null"); return null; + } try { - using (var memory = new MemoryStream()) + LogHelper.WriteLogToFile($"GetCurrentFrameAsBitmapSource: 开始处理帧,类型={_currentFrame.GetType().FullName}"); + LogHelper.WriteLogToFile($"GetCurrentFrameAsBitmapSource: 帧HashCode={_currentFrame.GetHashCode()}"); + + // 验证当前帧的有效性 + var width = _currentFrame.Width; + var height = _currentFrame.Height; + LogHelper.WriteLogToFile($"GetCurrentFrameAsBitmapSource: 当前帧尺寸={width}x{height}"); + + // 验证位图有效性 + if (width <= 0 || height <= 0) { - _currentFrame.Save(memory, ImageFormat.Png); - memory.Position = 0; + LogHelper.WriteLogToFile("当前帧无效: 尺寸为0", LogHelper.LogType.Warning); + return null; + } - var bitmapImage = new BitmapImage(); - bitmapImage.BeginInit(); - bitmapImage.CacheOption = BitmapCacheOption.OnLoad; - bitmapImage.StreamSource = memory; - bitmapImage.EndInit(); - bitmapImage.Freeze(); + // 使用更安全的方法转换位图 + var bitmapData = _currentFrame.LockBits( + new Rectangle(0, 0, width, height), + ImageLockMode.ReadOnly, + _currentFrame.PixelFormat); - return bitmapImage; + try + { + // 根据像素格式选择合适的WPF像素格式 + System.Windows.Media.PixelFormat wpfPixelFormat; + switch (_currentFrame.PixelFormat) + { + case PixelFormat.Format24bppRgb: + wpfPixelFormat = System.Windows.Media.PixelFormats.Bgr24; + break; + case PixelFormat.Format32bppArgb: + wpfPixelFormat = System.Windows.Media.PixelFormats.Bgra32; + break; + case PixelFormat.Format32bppRgb: + wpfPixelFormat = System.Windows.Media.PixelFormats.Bgr32; + break; + default: + wpfPixelFormat = System.Windows.Media.PixelFormats.Bgr24; + break; + } + + var bitmapSource = System.Windows.Media.Imaging.BitmapSource.Create( + bitmapData.Width, + bitmapData.Height, + _currentFrame.HorizontalResolution, + _currentFrame.VerticalResolution, + wpfPixelFormat, + null, + bitmapData.Scan0, + bitmapData.Stride * bitmapData.Height, + bitmapData.Stride); + + bitmapSource.Freeze(); + LogHelper.WriteLogToFile($"GetCurrentFrameAsBitmapSource: 成功创建BitmapSource"); + return bitmapSource; + } + finally + { + _currentFrame.UnlockBits(bitmapData); } } catch (Exception ex) { LogHelper.WriteLogToFile($"转换帧为BitmapSource失败: {ex.Message}", LogHelper.LogType.Error); + LogHelper.WriteLogToFile($"异常详情: {ex}", LogHelper.LogType.Error); return null; } } } + /// /// 视频源新帧事件处理 /// @@ -206,13 +246,52 @@ namespace Ink_Canvas.Helpers { try { + LogHelper.WriteLogToFile($"VideoSource_NewFrame: 接收到新帧"); + lock (_frameLock) { // 释放之前的帧 _currentFrame?.Dispose(); - // 克隆新帧 - _currentFrame = eventArgs.Frame.Clone() as Bitmap; + // 创建新的位图,避免Clone的问题 + var sourceFrame = eventArgs.Frame; + LogHelper.WriteLogToFile($"VideoSource_NewFrame: 源帧类型={sourceFrame?.GetType().FullName}"); + LogHelper.WriteLogToFile($"VideoSource_NewFrame: 源帧HashCode={sourceFrame?.GetHashCode()}"); + + if (sourceFrame != null) + { + try + { + var width = sourceFrame.Width; + var height = sourceFrame.Height; + LogHelper.WriteLogToFile($"VideoSource_NewFrame: 源帧尺寸={width}x{height}"); + + if (width > 0 && height > 0) + { + _currentFrame = new Bitmap(width, height, PixelFormat.Format24bppRgb); + using (var graphics = Graphics.FromImage(_currentFrame)) + { + graphics.DrawImage(sourceFrame, 0, 0); + } + LogHelper.WriteLogToFile($"VideoSource_NewFrame: 成功创建新帧,HashCode={_currentFrame.GetHashCode()}"); + } + else + { + LogHelper.WriteLogToFile($"VideoSource_NewFrame: 源帧尺寸无效"); + _currentFrame = null; + } + } + catch (Exception frameEx) + { + LogHelper.WriteLogToFile($"VideoSource_NewFrame: 处理源帧失败: {frameEx.Message}", LogHelper.LogType.Error); + _currentFrame = null; + } + } + else + { + LogHelper.WriteLogToFile($"VideoSource_NewFrame: 源帧为null"); + _currentFrame = null; + } } // 在UI线程中触发事件 diff --git a/Ink Canvas/MainWindow_cs/MW_ImageInsert.cs b/Ink Canvas/MainWindow_cs/MW_ImageInsert.cs index 2848ae09..b7352fa1 100644 --- a/Ink Canvas/MainWindow_cs/MW_ImageInsert.cs +++ b/Ink Canvas/MainWindow_cs/MW_ImageInsert.cs @@ -28,12 +28,14 @@ namespace Ink_Canvas public Rectangle Area; public List Path; public Bitmap CameraImage; + public System.Windows.Media.Imaging.BitmapSource CameraBitmapSource; - public ScreenshotResult(Rectangle area, List path = null, Bitmap cameraImage = null) + public ScreenshotResult(Rectangle area, List path = null, Bitmap cameraImage = null, System.Windows.Media.Imaging.BitmapSource cameraBitmapSource = null) { Area = area; Path = path; CameraImage = cameraImage; + CameraBitmapSource = cameraBitmapSource; } } @@ -60,9 +62,14 @@ namespace Ink_Canvas if (screenshotResult.HasValue) { // 检查是否是摄像头截图 - if (screenshotResult.Value.CameraImage != null) + if (screenshotResult.Value.CameraBitmapSource != null) { - // 摄像头截图 + // 摄像头截图(使用BitmapSource) + await InsertBitmapSourceToCanvas(screenshotResult.Value.CameraBitmapSource); + } + else if (screenshotResult.Value.CameraImage != null) + { + // 摄像头截图(使用Bitmap) await InsertScreenshotToCanvas(screenshotResult.Value.CameraImage); } else if (screenshotResult.Value.Area.Width > 0 && screenshotResult.Value.Area.Height > 0) @@ -164,7 +171,16 @@ namespace Ink_Canvas if (selectorWindow.ShowDialog() == true) { // 检查是否是摄像头截图 - if (selectorWindow.CameraImage != null) + if (selectorWindow.CameraBitmapSource != null) + { + result = new ScreenshotResult( + Rectangle.Empty, // 摄像头截图不需要区域 + null, // 摄像头截图不需要路径 + null, // 不再使用Bitmap + selectorWindow.CameraBitmapSource // 摄像头BitmapSource + ); + } + else if (selectorWindow.CameraImage != null) { result = new ScreenshotResult( Rectangle.Empty, // 摄像头截图不需要区域 @@ -236,8 +252,40 @@ namespace Ink_Canvas { try { + // 验证位图有效性 + if (bitmap == null) + { + ShowNotification("截图数据无效"); + return; + } + + // 添加详细的位图调试信息 + LogHelper.WriteLogToFile($"InsertScreenshotToCanvas: 开始处理位图"); + LogHelper.WriteLogToFile($"位图对象类型: {bitmap.GetType().FullName}"); + LogHelper.WriteLogToFile($"位图对象HashCode: {bitmap.GetHashCode()}"); + + // 检查位图是否已被释放 + try + { + var testWidth = bitmap.Width; + var testHeight = bitmap.Height; + LogHelper.WriteLogToFile($"位图尺寸验证成功: {testWidth}x{testHeight}"); + } + catch (Exception ex) + { + LogHelper.WriteLogToFile($"位图验证失败: {ex.Message}", LogHelper.LogType.Error); + ShowNotification("截图数据已损坏"); + return; + } + // 将Bitmap转换为WPF BitmapSource var bitmapSource = ConvertBitmapToBitmapSource(bitmap); + + if (bitmapSource == null) + { + ShowNotification("转换截图失败"); + return; + } // 创建WPF Image控件 var image = new Image @@ -293,6 +341,67 @@ namespace Ink_Canvas } } + // 将BitmapSource插入到画布(用于摄像头截图) + private async Task InsertBitmapSourceToCanvas(System.Windows.Media.Imaging.BitmapSource bitmapSource) + { + try + { + LogHelper.WriteLogToFile($"InsertBitmapSourceToCanvas: 开始处理BitmapSource"); + + // 创建WPF Image控件 + var image = new Image + { + Source = bitmapSource, + Stretch = Stretch.Uniform + }; + RenderOptions.SetBitmapScalingMode(image, BitmapScalingMode.HighQuality); + + // 生成唯一名称 + string timestamp = "camera_" + DateTime.Now.ToString("yyyyMMdd_HH_mm_ss_fff"); + image.Name = timestamp; + + // 初始化TransformGroup + InitializeScreenshotTransform(image); + + // 设置截图属性,避免被InkCanvas选择系统处理 + image.IsHitTestVisible = true; + image.Focusable = false; + + // 初始化InkCanvas选择设置 + InitializeInkCanvasSelectionSettings(); + + // 等待图片加载完成后再进行居中处理 + image.Loaded += (sender, e) => + { + // 确保在UI线程中执行 + Dispatcher.BeginInvoke(new Action(() => + { + CenterAndScaleScreenshot(image); + // 绑定事件处理器 + BindScreenshotEvents(image); + }), DispatcherPriority.Loaded); + }; + + // 添加到画布 + inkCanvas.Children.Add(image); + + // 提交历史记录 + timeMachine.CommitElementInsertHistory(image); + + // 插入图片后切换到选择模式并刷新浮动栏高光显示 + SetCurrentToolMode(InkCanvasEditingMode.Select); + UpdateCurrentToolMode("select"); + HideSubPanels("select"); + + ShowNotification("摄像头截图已插入到画布"); + } + catch (Exception ex) + { + ShowNotification($"插入摄像头截图失败: {ex.Message}"); + LogHelper.WriteLogToFile($"插入摄像头截图失败: {ex.Message}", LogHelper.LogType.Error); + } + } + // 初始化截图的TransformGroup private void InitializeScreenshotTransform(Image image) { @@ -501,24 +610,235 @@ namespace Ink_Canvas { try { - using (var memory = new MemoryStream()) + // 验证位图有效性 + if (bitmap == null) { - bitmap.Save(memory, ImageFormat.Png); - memory.Position = 0; + LogHelper.WriteLogToFile("位图无效: 位图为null", LogHelper.LogType.Warning); + return null; + } - var bitmapImage = new BitmapImage(); - bitmapImage.BeginInit(); - bitmapImage.CacheOption = BitmapCacheOption.OnLoad; - bitmapImage.StreamSource = memory; - bitmapImage.EndInit(); - bitmapImage.Freeze(); + // 尝试访问位图属性,如果失败说明位图已损坏 + int width, height; + try + { + width = bitmap.Width; + height = bitmap.Height; + } + catch (Exception ex) + { + LogHelper.WriteLogToFile($"位图已损坏,无法访问属性: {ex.Message}", LogHelper.LogType.Error); + return null; + } - return bitmapImage; + if (width <= 0 || height <= 0) + { + LogHelper.WriteLogToFile($"位图无效: 尺寸为{width}x{height}", LogHelper.LogType.Warning); + return null; + } + + LogHelper.WriteLogToFile($"开始转换位图: 尺寸={width}x{height}, 格式={bitmap.PixelFormat}, DPI={bitmap.HorizontalResolution}x{bitmap.VerticalResolution}"); + + // 使用更安全的方法转换位图 + var bitmapData = bitmap.LockBits( + new Rectangle(0, 0, bitmap.Width, bitmap.Height), + ImageLockMode.ReadOnly, + bitmap.PixelFormat); + + try + { + LogHelper.WriteLogToFile($"LockBits成功: Stride={bitmapData.Stride}, Scan0={bitmapData.Scan0}"); + + // 根据像素格式选择合适的WPF像素格式 + System.Windows.Media.PixelFormat wpfPixelFormat; + switch (bitmap.PixelFormat) + { + case PixelFormat.Format24bppRgb: + wpfPixelFormat = System.Windows.Media.PixelFormats.Bgr24; + LogHelper.WriteLogToFile("使用Bgr24像素格式"); + break; + case PixelFormat.Format32bppArgb: + wpfPixelFormat = System.Windows.Media.PixelFormats.Bgra32; + LogHelper.WriteLogToFile("使用Bgra32像素格式"); + break; + case PixelFormat.Format32bppRgb: + wpfPixelFormat = System.Windows.Media.PixelFormats.Bgr32; + LogHelper.WriteLogToFile("使用Bgr32像素格式"); + break; + default: + // 默认使用Bgr24,如果格式不匹配则转换 + wpfPixelFormat = System.Windows.Media.PixelFormats.Bgr24; + LogHelper.WriteLogToFile($"未知像素格式{bitmap.PixelFormat},使用默认Bgr24"); + break; + } + + var bitmapSource = System.Windows.Media.Imaging.BitmapSource.Create( + bitmapData.Width, + bitmapData.Height, + bitmap.HorizontalResolution, + bitmap.VerticalResolution, + wpfPixelFormat, + null, + bitmapData.Scan0, + bitmapData.Stride * bitmapData.Height, + bitmapData.Stride); + + bitmapSource.Freeze(); + LogHelper.WriteLogToFile("位图转换成功"); + return bitmapSource; + } + finally + { + bitmap.UnlockBits(bitmapData); } } catch (Exception ex) { - LogHelper.WriteLogToFile($"转换位图失败: {ex.Message}", LogHelper.LogType.Error); + LogHelper.WriteLogToFile($"直接转换位图失败: {ex.Message}", LogHelper.LogType.Error); + LogHelper.WriteLogToFile($"异常详情: {ex}", LogHelper.LogType.Error); + + // 尝试使用备用方法:内存流转换 + try + { + LogHelper.WriteLogToFile("尝试使用内存流方式转换位图", LogHelper.LogType.Info); + return ConvertBitmapToBitmapSourceFallback(bitmap); + } + catch (Exception fallbackEx) + { + LogHelper.WriteLogToFile($"备用转换方法也失败: {fallbackEx.Message}", LogHelper.LogType.Error); + LogHelper.WriteLogToFile($"备用方法异常详情: {fallbackEx}", LogHelper.LogType.Error); + + // 最后尝试:使用最简单的转换方法 + try + { + LogHelper.WriteLogToFile("尝试最简单的转换方法", LogHelper.LogType.Info); + return ConvertBitmapToBitmapSourceSimple(bitmap); + } + catch (Exception simpleEx) + { + LogHelper.WriteLogToFile($"简单转换方法也失败: {simpleEx.Message}", LogHelper.LogType.Error); + throw; + } + } + } + } + + // 备用的位图转换方法(使用内存流) + private BitmapSource ConvertBitmapToBitmapSourceFallback(Bitmap bitmap) + { + try + { + LogHelper.WriteLogToFile("开始备用转换方法"); + + // 验证位图有效性 + if (bitmap == null) + { + LogHelper.WriteLogToFile("备用方法:位图为null", LogHelper.LogType.Warning); + return null; + } + + if (bitmap.Width <= 0 || bitmap.Height <= 0) + { + LogHelper.WriteLogToFile($"备用方法:位图尺寸无效 {bitmap.Width}x{bitmap.Height}", LogHelper.LogType.Warning); + return null; + } + + LogHelper.WriteLogToFile($"备用方法:位图尺寸={bitmap.Width}x{bitmap.Height}, 格式={bitmap.PixelFormat}"); + + // 创建一个新的位图,确保格式正确 + using (var convertedBitmap = new Bitmap(bitmap.Width, bitmap.Height, PixelFormat.Format24bppRgb)) + { + LogHelper.WriteLogToFile("创建转换位图成功"); + + using (var graphics = Graphics.FromImage(convertedBitmap)) + { + LogHelper.WriteLogToFile("开始绘制到转换位图"); + graphics.DrawImage(bitmap, 0, 0); + LogHelper.WriteLogToFile("绘制完成"); + } + + using (var memory = new MemoryStream()) + { + LogHelper.WriteLogToFile("开始保存到内存流"); + convertedBitmap.Save(memory, ImageFormat.Png); + LogHelper.WriteLogToFile($"保存完成,内存流大小={memory.Length}"); + + memory.Position = 0; + + var bitmapImage = new BitmapImage(); + bitmapImage.BeginInit(); + bitmapImage.CacheOption = BitmapCacheOption.OnLoad; + bitmapImage.StreamSource = memory; + bitmapImage.EndInit(); + bitmapImage.Freeze(); + + LogHelper.WriteLogToFile("备用转换方法成功"); + return bitmapImage; + } + } + } + catch (Exception ex) + { + LogHelper.WriteLogToFile($"备用转换方法失败: {ex.Message}", LogHelper.LogType.Error); + LogHelper.WriteLogToFile($"备用方法异常详情: {ex}", LogHelper.LogType.Error); + throw; + } + } + + // 最简单的位图转换方法 + private BitmapSource ConvertBitmapToBitmapSourceSimple(Bitmap bitmap) + { + try + { + LogHelper.WriteLogToFile("开始简单转换方法"); + + if (bitmap == null) + { + LogHelper.WriteLogToFile("简单方法:位图为null", LogHelper.LogType.Warning); + return null; + } + + LogHelper.WriteLogToFile($"简单方法:位图尺寸={bitmap.Width}x{bitmap.Height}"); + + // 使用最基础的方法:直接保存为PNG然后加载 + var tempFile = System.IO.Path.GetTempFileName() + ".png"; + + try + { + LogHelper.WriteLogToFile($"保存临时文件到: {tempFile}"); + bitmap.Save(tempFile, ImageFormat.Png); + + LogHelper.WriteLogToFile("开始加载临时文件"); + var bitmapImage = new BitmapImage(); + bitmapImage.BeginInit(); + bitmapImage.UriSource = new Uri(tempFile); + bitmapImage.CacheOption = BitmapCacheOption.OnLoad; + bitmapImage.EndInit(); + bitmapImage.Freeze(); + + LogHelper.WriteLogToFile("简单转换方法成功"); + return bitmapImage; + } + finally + { + // 清理临时文件 + try + { + if (System.IO.File.Exists(tempFile)) + { + System.IO.File.Delete(tempFile); + LogHelper.WriteLogToFile("临时文件已删除"); + } + } + catch (Exception deleteEx) + { + LogHelper.WriteLogToFile($"删除临时文件失败: {deleteEx.Message}", LogHelper.LogType.Warning); + } + } + } + catch (Exception ex) + { + LogHelper.WriteLogToFile($"简单转换方法失败: {ex.Message}", LogHelper.LogType.Error); + LogHelper.WriteLogToFile($"简单方法异常详情: {ex}", LogHelper.LogType.Error); throw; } } diff --git a/Ink Canvas/Windows/ScreenshotSelectorWindow.xaml.cs b/Ink Canvas/Windows/ScreenshotSelectorWindow.xaml.cs index 57bd9f8b..7f2f6c72 100644 --- a/Ink Canvas/Windows/ScreenshotSelectorWindow.xaml.cs +++ b/Ink Canvas/Windows/ScreenshotSelectorWindow.xaml.cs @@ -49,6 +49,7 @@ namespace Ink_Canvas public DrawingRectangle? SelectedArea { get; private set; } public List SelectedPath { get; private set; } public Bitmap CameraImage { get; private set; } + public System.Windows.Media.Imaging.BitmapSource CameraBitmapSource { get; private set; } public ScreenshotSelectorWindow() { @@ -156,18 +157,35 @@ namespace Ink_Canvas { if (_isCameraMode && CameraPreviewImage != null && frame != null) { - // 克隆帧以避免在转换过程中被释放 - using (var clonedFrame = frame.Clone() as Bitmap) + try { - if (clonedFrame != null) + // 验证帧的有效性 + if (frame.Width <= 0 || frame.Height <= 0) { - var bitmapSource = ConvertBitmapToBitmapSource(clonedFrame); - if (bitmapSource != null) - { - CameraPreviewImage.Source = bitmapSource; - CameraStatusText.Text = "摄像头已连接"; - } + LogHelper.WriteLogToFile($"无效的摄像头帧: {frame.Width}x{frame.Height}", LogHelper.LogType.Warning); + return; } + + // 创建新的位图,避免Clone的问题 + var clonedFrame = new Bitmap(frame.Width, frame.Height, System.Drawing.Imaging.PixelFormat.Format24bppRgb); + using (var graphics = System.Drawing.Graphics.FromImage(clonedFrame)) + { + graphics.DrawImage(frame, 0, 0); + } + + var bitmapSource = ConvertBitmapToBitmapSource(clonedFrame); + if (bitmapSource != null) + { + CameraPreviewImage.Source = bitmapSource; + CameraStatusText.Text = "摄像头已连接"; + } + + // 释放临时位图 + clonedFrame.Dispose(); + } + catch (Exception frameEx) + { + LogHelper.WriteLogToFile($"处理摄像头帧时出错: {frameEx.Message}", LogHelper.LogType.Error); } } })); @@ -197,19 +215,57 @@ namespace Ink_Canvas { try { - using (var memory = new System.IO.MemoryStream()) + // 验证位图有效性 + if (bitmap == null || bitmap.Width <= 0 || bitmap.Height <= 0) { - bitmap.Save(memory, System.Drawing.Imaging.ImageFormat.Png); - memory.Position = 0; + LogHelper.WriteLogToFile("位图无效: 空位图或尺寸为0", LogHelper.LogType.Warning); + return null; + } - var bitmapImage = new System.Windows.Media.Imaging.BitmapImage(); - bitmapImage.BeginInit(); - bitmapImage.CacheOption = System.Windows.Media.Imaging.BitmapCacheOption.OnLoad; - bitmapImage.StreamSource = memory; - bitmapImage.EndInit(); - bitmapImage.Freeze(); + // 使用更安全的方法转换位图 + var bitmapData = bitmap.LockBits( + new System.Drawing.Rectangle(0, 0, bitmap.Width, bitmap.Height), + System.Drawing.Imaging.ImageLockMode.ReadOnly, + bitmap.PixelFormat); - return bitmapImage; + try + { + // 根据像素格式选择合适的WPF像素格式 + System.Windows.Media.PixelFormat wpfPixelFormat; + switch (bitmap.PixelFormat) + { + case System.Drawing.Imaging.PixelFormat.Format24bppRgb: + wpfPixelFormat = System.Windows.Media.PixelFormats.Bgr24; + break; + case System.Drawing.Imaging.PixelFormat.Format32bppArgb: + wpfPixelFormat = System.Windows.Media.PixelFormats.Bgra32; + break; + case System.Drawing.Imaging.PixelFormat.Format32bppRgb: + wpfPixelFormat = System.Windows.Media.PixelFormats.Bgr32; + break; + default: + // 默认使用Bgr24,如果格式不匹配则转换 + wpfPixelFormat = System.Windows.Media.PixelFormats.Bgr24; + break; + } + + var bitmapSource = System.Windows.Media.Imaging.BitmapSource.Create( + bitmapData.Width, + bitmapData.Height, + bitmap.HorizontalResolution, + bitmap.VerticalResolution, + wpfPixelFormat, + null, + bitmapData.Scan0, + bitmapData.Stride * bitmapData.Height, + bitmapData.Stride); + + bitmapSource.Freeze(); + return bitmapSource; + } + finally + { + bitmap.UnlockBits(bitmapData); } } catch (Exception ex) @@ -430,12 +486,12 @@ namespace Ink_Canvas { if (_cameraService != null && _cameraService.IsCapturing) { - // 获取当前帧 - var currentFrame = _cameraService.GetCurrentFrame(); - if (currentFrame != null) + // 直接获取BitmapSource,避免Bitmap传递问题 + var bitmapSource = _cameraService.GetCurrentFrameAsBitmapSource(); + if (bitmapSource != null) { - // 保存摄像头图像 - CameraImage = currentFrame.Clone() as Bitmap; + // 保存BitmapSource而不是Bitmap + CameraBitmapSource = bitmapSource; // 停止摄像头预览 _cameraService.StopPreview();