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

如何在WinUI 3应用中显示System.Drawing.Bitmap对象

解决方法

WinUI 3 的 Image 控件仅接受派生自 Microsoft.UI.Xaml.Media.ImageSource 的类型作为源,System.Drawing.Bitmap 属于GDI+类型,无法直接赋值,需要先转换为WinUI可识别的位图对象,提供两种可直接落地的实现方案:

方案1:内存流转码(实现简单,兼容性好)

无需落地临时文件,全内存完成转换,适合绝大多数静态二维码显示场景:

  1. 引入所需命名空间
using System.Drawing;
using System.IO;
using Microsoft.UI.Xaml.Media.Imaging;
using Windows.Storage.Streams;
  1. 编写类型转换扩展方法
public static async Task<BitmapImage> ToWinUIBitmapSourceAsync(this Bitmap gdiBitmap)
{
    // 将GDI+位图以PNG格式写入内存流,避免画质损失
    using var ms = new MemoryStream();
    gdiBitmap.Save(ms, System.Drawing.Imaging.ImageFormat.Png);
    ms.Position = 0; // 将流读取指针重置到起始位置

    // 初始化WinUI支持的位图对象
    var winUiBitmap = new BitmapImage();
    using var ras = ms.AsRandomAccessStream();
    await winUiBitmap.SetSourceAsync(ras);
    return winUiBitmap;
}
  1. 替换原有图片赋值逻辑
QRCodeGenerator qrCodeGenerator = new();
QRCodeData qrCodeData = qrCodeGenerator.CreateQrCode(associateSoftwareTokenResponse.SecretCode, QRCodeGenerator.ECCLevel.Q);
QRCode qrCode = new(qrCodeData);
// using语句包裹,自动释放GDI+非托管资源
using Bitmap qrCodeBitmap = qrCode.GetGraphic(20);
// 给Image控件赋值
qrCodeImage.Source = await qrCodeBitmap.ToWinUIBitmapSourceAsync();

方案2:像素直接拷贝(性能更高,适合动态刷新场景)

如果需要高频更新二维码(比如时效动态码场景),可以直接拷贝像素数据,省去PNG编解码的开销,渲染延迟更低:

  1. 补充所需命名空间
using System.Runtime.InteropServices.WindowsRuntime;
  1. 编写高性能转换方法
public static WriteableBitmap ToWinUIBitmapSourceFast(this Bitmap gdiBitmap)
{
    // 锁定GDI+位图的像素内存
    var bmpData = gdiBitmap.LockBits(
        new Rectangle(0, 0, gdiBitmap.Width, gdiBitmap.Height),
        System.Drawing.Imaging.ImageLockMode.ReadOnly,
        System.Drawing.Imaging.PixelFormat.Format32bppPArgb);

    // 创建同尺寸的WinUI可写位图
    var writeableBmp = new WriteableBitmap(gdiBitmap.Width, gdiBitmap.Height);
    // 直接拷贝像素数据到WinUI位图缓冲区
    writeableBmp.PixelBuffer.CopyFrom(bmpData.Scan0, (uint)(bmpData.Stride * gdiBitmap.Height));
    
    // 解锁GDI+位图内存
    gdiBitmap.UnlockBits(bmpData);
    return writeableBmp;
}
  1. 调用方式(无需异步等待)
using Bitmap qrCodeBitmap = qrCode.GetGraphic(20);
qrCodeImage.Source = qrCodeBitmap.ToWinUIBitmapSourceFast();

注意事项

  • System.Drawing.Bitmap 封装了非托管GDI+资源,使用完成后必须手动释放,否则会触发内存泄漏,建议统一使用using语句包裹生命周期。
  • 高性能拷贝方案要求GDI+位图的像素格式为32位PARGB,QRCoder生成的默认位图符合该要求,若使用其他来源的Bitmap需要先做像素格式转换。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.02 01:01:26