improve:截图
This commit is contained in:
@@ -154,51 +154,91 @@ namespace Ink_Canvas.Helpers
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取当前帧的Bitmap
|
||||
/// </summary>
|
||||
public Bitmap GetCurrentFrame()
|
||||
{
|
||||
lock (_frameLock)
|
||||
{
|
||||
return _currentFrame?.Clone() as Bitmap;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取当前帧的BitmapSource(WPF格式)
|
||||
/// 获取当前帧的BitmapSource(WPF格式),直接返回可用的WPF位图
|
||||
/// </summary>
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 视频源新帧事件处理
|
||||
/// </summary>
|
||||
@@ -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线程中触发事件
|
||||
|
||||
@@ -28,12 +28,14 @@ namespace Ink_Canvas
|
||||
public Rectangle Area;
|
||||
public List<Point> Path;
|
||||
public Bitmap CameraImage;
|
||||
public System.Windows.Media.Imaging.BitmapSource CameraBitmapSource;
|
||||
|
||||
public ScreenshotResult(Rectangle area, List<Point> path = null, Bitmap cameraImage = null)
|
||||
public ScreenshotResult(Rectangle area, List<Point> 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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -49,6 +49,7 @@ namespace Ink_Canvas
|
||||
public DrawingRectangle? SelectedArea { get; private set; }
|
||||
public List<WpfPoint> 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();
|
||||
|
||||
Reference in New Issue
Block a user