You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何使用SharpDX将Direct2D BitmapRenderTarget的Bitmap绘制到WicRenderTarget?

解决SharpDX中BitmapRenderTarget内容转WicRenderTarget并保存为PNG的问题

你的代码出现静默崩溃主要有几个核心问题:

  • 错误将渲染目标尺寸赋值给DotsPerInch属性,DPI是每英寸点数(比如标准96),并非画布尺寸
  • 直接绘制BitmapRenderTarget的Bitmap到WicRenderTarget存在资源兼容性问题,且未正确托管非托管资源
  • 缺少完整的PNG编码保存逻辑

修复方案一:直接使用WicRenderTarget绘制并保存(更高效)

跳过BitmapRenderTarget的中间步骤,直接在WicRenderTarget上完成绘制并导出为PNG:

using SharpDX;
using SharpDX.Direct2D1;
using SharpDX.WIC;
using System.IO;

// 计算缩放后尺寸
int scaledWidth = (int)(_deviceContext.Size.Width * Zoom);
int scaledHeight = (int)(_deviceContext.Size.Height * Zoom);
Size2F standardDpi = new(96, 96); // 标准屏幕DPI

// 初始化WIC组件
_imagingFactory = new ImagingFactory();
_wicBitmap = new Bitmap(_imagingFactory, scaledWidth, scaledHeight, PixelFormat.Format32bppPBGRA, BitmapCreateCacheOption.CacheOnLoad);

// 创建WicRenderTarget
using var wicRenderTarget = new WicRenderTarget(_deviceContext.Factory, _wicBitmap, new RenderTargetProperties(new PixelFormat(Format.Unknown, AlphaMode.Premultiplied))
{
    DotsPerInch = standardDpi,
    AntialiasMode = AntialiasMode.PerPrimitive
});

// 执行绘制
wicRenderTarget.BeginDraw();
wicRenderTarget.Clear(new RawColor4(1, 1, 1, 1));
using var blackBrush = new SolidColorBrush(wicRenderTarget, new RawColor4(0, 0, 0, 1));
wicRenderTarget.DrawLine(new RawVector2(0, 0), new RawVector2(100, 100), blackBrush, 1);
wicRenderTarget.EndDraw();

// 编码并保存为PNG
using var outputStream = new FileStream("output.png", FileMode.Create);
using var pngEncoder = new PngBitmapEncoder(_imagingFactory);
pngEncoder.Initialize(outputStream);

using var frameEncoder = new BitmapFrameEncode(pngEncoder);
frameEncoder.Initialize();
frameEncoder.SetSize(scaledWidth, scaledHeight);
PixelFormat targetFormat = PixelFormat.Format32bppPBGRA;
frameEncoder.SetPixelFormat(ref targetFormat);
frameEncoder.WriteSource(_wicBitmap);
frameEncoder.Commit();

pngEncoder.Commit();

// 转换为Direct2D Bitmap供后续使用
Bitmap = Bitmap.FromWicBitmap(_deviceContext, _wicBitmap);

修复方案二:保留BitmapRenderTarget,直接导出内容到WIC

如果必须先使用BitmapRenderTarget绘制,可直接将其内容转换为WIC Bitmap,跳过中间绘制步骤:

using SharpDX;
using SharpDX.Direct2D1;
using SharpDX.WIC;
using System.IO;

Size2F scaledSize = new((float)(_deviceContext.Size.Width * Zoom), (float)(_deviceContext.Size.Height * Zoom));
Size2F standardDpi = new(96, 96);

// 创建BitmapRenderTarget并绘制
using var bitmapRenderTarget = new BitmapRenderTarget(_deviceContext, CompatibleRenderTargetOptions.None, scaledSize)
{
    DotsPerInch = standardDpi,
    AntialiasMode = AntialiasMode.PerPrimitive
};

bitmapRenderTarget.BeginDraw();
bitmapRenderTarget.Clear(new RawColor4(1, 1, 1, 1));
using var blackBrush = new SolidColorBrush(bitmapRenderTarget, new RawColor4(0, 0, 0, 1));
bitmapRenderTarget.DrawLine(new RawVector2(0, 0), new RawVector2(100, 100), blackBrush, 1);
bitmapRenderTarget.EndDraw();

// 直接从BitmapRenderTarget的Bitmap创建WIC Bitmap
_imagingFactory = new ImagingFactory();
_wicBitmap = new Bitmap(_imagingFactory, bitmapRenderTarget.Bitmap, BitmapCreateCacheOption.CacheOnLoad);

// 保存为PNG(同方案一的编码逻辑)
using var outputStream = new FileStream("output.png", FileMode.Create);
using var pngEncoder = new PngBitmapEncoder(_imagingFactory);
pngEncoder.Initialize(outputStream);

using var frameEncoder = new BitmapFrameEncode(pngEncoder);
frameEncoder.Initialize();
frameEncoder.SetSize((int)scaledSize.Width, (int)scaledSize.Height);
PixelFormat targetFormat = PixelFormat.Format32bppPBGRA;
frameEncoder.SetPixelFormat(ref targetFormat);
frameEncoder.WriteSource(_wicBitmap);
frameEncoder.Commit();

pngEncoder.Commit();

Bitmap = Bitmap.FromWicBitmap(_deviceContext, _wicBitmap);

关键修复说明

  • 修正DPI设置:DotsPerInch必须设置为每英寸点数(如96),而非画布尺寸,否则会导致渲染上下文参数异常
  • 托管非托管资源:使用using语句自动释放SharpDX的非托管对象(如Brush、RenderTarget),避免内存泄漏和静默崩溃
  • 简化转换流程:方案二直接通过BitmapRenderTarget的Bitmap创建WIC Bitmap,规避跨RenderTarget绘制的兼容性问题
  • 补充PNG编码:原代码缺少完整的PNG保存逻辑,上述代码补充了从WIC Bitmap到PNG文件的完整编码流程

内容的提问来源于stack exchange,提问作者user25472896

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.19 09:58:11