本文告诉大家如何通过 Vortice 在 Direct2D 里面绘制图片,图片的来源是 WIC 加载出的图片

在上一篇博客 WPF 对接 Vortice 调用 WIC 加载图片 告诉了大家如何对接 Vortice 调用 WIC 加载图片,上一篇博客是将 WIC 层创建的 IWICBitmap 图片放入到 WPF 层进行渲染。本文将告诉大家如何在 Direct2D 里将 WIC 加载的图片绘制

核心的两个点就是用拿到的 IWICBitmapFrameDecode 进行 IWICFormatConverter 转换图片格式,转换为 Format32bppPBGRA 对 Direct2D 友好的格式,再通过 CreateBitmapFromWicBitmap 方法转换为 ID2D1Bitmap 加入绘制

通过上一篇博客可以了解到如下代码可以加载本地图片文件到 WIC 层进行解码

        using var wicImagingFactory = new IWICImagingFactory();
var imageFilePath = System.IO.Path.GetFullPath("Image.png");
using var wicStream = wicImagingFactory.CreateStream(imageFilePath, FileAccess.Read);
using var decoder = wicImagingFactory.CreateDecoderFromStream(wicStream, DecodeOptions.CacheOnLoad/*参数和 WPF 一样*/);
// 解码器将可以解码出图片,对于动态图片可以解析出多张图片出来,对于静态图片只能解析出一张
// 对于静态图片(区别于 gif 等动态图片)只须取首个
using IWICBitmapFrameDecode imageFrame = decoder.GetFrame(0);

这时拿到的 imageFrame 对象还不能立刻扔到 ID2D1RenderTarget.CreateBitmapFromWicBitmap 里面,因为图片的像素格式不一定是对 D2D 友好的,如果没有经过图片颜色格式转换,也许就炸掉,提示 0x88982F80 错误,即 WINCODEC_ERR_UNSUPPORTEDPIXELFORMAT 格式不受支持

转换图片格式自然是不需要大家手写许多代码的,也不需要去担心在 CPU 或 GPU 转码的性能问题,通过内置的 IWICFormatConverter 进行转换,具体转换细节可以作为黑盒的存在,根据不同的硬件设备和驱动条件决定是否走硬件加速。当然,自己想不开,手动转码也是可以的,本文还是写给想得开的伙伴看的

先创建出来 IWICFormatConverter 格式转换器,代码如下

        // 图片的格式不一定是能符合 D2D 预期的,转换一下格式
// 否则 CreateBitmapFromWicBitmap 失败 0x88982F80 WINCODEC_ERR_UNSUPPORTEDPIXELFORMAT
using IWICFormatConverter converter = wicImagingFactory.CreateFormatConverter();

接着调用 Initialize 方法进行初始化,这个 IWICFormatConverter 类型从设计上是继承 IWICBitmapSource 的,也就是这里其实没有立刻做转换,而是表示一个状态,具体在哪一层做实际的转换,这是封装起来的黑盒

        // 这里不是真实的立刻进行转换哦,实际转换执行是隐藏起来的
converter.Initialize(imageFrame, Vortice.WIC.PixelFormat.Format32bppPBGRA, BitmapDitherType.None, null, 0, BitmapPaletteType.MedianCut);
// 这个 IWICFormatConverter 也继承是 IWICBitmapSource 类型

完成转换器逻辑,即可将转换器扔到 CreateBitmapFromWicBitmap 里创建出 D2D.ID2D1Bitmap 进行绘制

        D2D.ID2D1Bitmap d2DBitmap = renderTarget.CreateBitmapFromWicBitmap(converter);

        renderTarget.DrawBitmap(d2DBitmap);

以下是打开本地文件,进行解码,转换颜色格式,创建 ID2D1Bitmap 绘制的代码

    private static void Render(D2D.ID2D1RenderTarget renderTarget)
{
using var wicImagingFactory = new IWICImagingFactory();
var imageFilePath = System.IO.Path.GetFullPath("Image.png");
using var wicStream = wicImagingFactory.CreateStream(imageFilePath, FileAccess.Read);
using var decoder = wicImagingFactory.CreateDecoderFromStream(wicStream, DecodeOptions.CacheOnLoad/*参数和 WPF 一样*/);
// 解码器将可以解码出图片,对于动态图片可以解析出多张图片出来,对于静态图片只能解析出一张
// 对于静态图片(区别于 gif 等动态图片)只须取首个
using IWICBitmapFrameDecode imageFrame = decoder.GetFrame(0); using IWICBitmap bitmap = wicImagingFactory.CreateBitmapFromSource(imageFrame, BitmapCreateCacheOption.CacheOnLoad); // 图片的格式不一定是能符合 D2D 预期的,转换一下格式
// 否则 CreateBitmapFromWicBitmap 失败 0x88982F80 WINCODEC_ERR_UNSUPPORTEDPIXELFORMAT
using IWICFormatConverter converter = wicImagingFactory.CreateFormatConverter();
// 这里不是真实的立刻进行转换哦,实际转换执行是隐藏起来的
converter.Initialize(imageFrame, Vortice.WIC.PixelFormat.Format32bppPBGRA, BitmapDitherType.None, null, 0, BitmapPaletteType.MedianCut);
// 这个 IWICFormatConverter 也继承是 IWICBitmapSource 类型 D2D.ID2D1Bitmap d2DBitmap = renderTarget.CreateBitmapFromWicBitmap(converter); renderTarget.DrawBitmap(d2DBitmap);
}

如果要将图片绘制在给定的范围呢?可以通过将图片转换为贴图画刷的方式然后通过矩形或其他几何承载,如以下的代码将图片绘制在矩形上,通过矩形控制绘制在哪个范围

        using D2D.ID2D1Bitmap d2DBitmap = renderTarget.CreateBitmapFromWicBitmap(converter);

        using var brush = renderTarget.CreateBitmapBrush(d2DBitmap);

        renderTarget.FillRectangle(new Vortice.RawRectF(10, 10, 900, 600), brush);

本文的代码放在githubgitee 欢迎访问

可以通过如下方式获取本文的源代码,先创建一个空文件夹,接着使用命令行 cd 命令进入此空文件夹,在命令行里面输入以下代码,即可获取到本文的代码

git init
git remote add origin https://gitee.com/lindexi/lindexi_gd.git
git pull origin 1e2b04cdfd620ec666e6dbcf58b561dae575e9c1

以上使用的是 gitee 的源,如果 gitee 不能访问,请替换为 github 的源。请在命令行继续输入以下代码

git remote remove origin
git remote add origin https://github.com/lindexi/lindexi_gd.git
git pull origin 1e2b04cdfd620ec666e6dbcf58b561dae575e9c1

获取代码之后,进入 WpfVorticeWicTest 文件夹

更多 DirectX 和 D2D 以及 Vortice 库的博客,请参阅我的 博客导航

另外,我创建了专门聊 Vortice 的 QQ 群: 622808968 欢迎加入交流技术

WPF 对接 Vortice 绘制 WIC 图片的更多相关文章

  1. WPF GDI+字符串绘制成图片(二)

    原文:WPF GDI+字符串绘制成图片(二) 版权声明:本文为博主原创文章,未经博主允许不得转载. https://blog.csdn.net/BYH371256/article/details/83 ...

  2. WPF GDI+字符串绘制成图片(一)

    原文:WPF GDI+字符串绘制成图片(一) 版权声明:本文为博主原创文章,未经博主允许不得转载. https://blog.csdn.net/BYH371256/article/details/83 ...

  3. WPF中自定义绘制内容

    先说结论:实现了在自定义大小的窗口中,加载图片,并在图片上绘制一个矩形框:且在窗口大小改变的情况,保持绘制的矩形框与图片的先对位置不变. 在WinForm中,我们可以很方便地绘制自己需要的内容,在WP ...

  4. android绘制圆形图片的两种方式

    看下效果先 下面有完整的示例代码 使用BitmapShader(着色器) 我们在绘制view 的时候 就是小学上美术课 用水彩笔在本子上画画 使用着色器绘制圆形图片最简单的理解方式 就是把bitmap ...

  5. 使用MFC CImage类绘制PNG图片时遇到的问题

    为了测试CImage绘制PNG图片的效果,我们用截图软件截得一张360的界面,然后使用PhotoShop等工具在图片的周边加上了透明的区域,然后保存成PNG图片文件.CImage首先从文件中加载,即 ...

  6. Win10系列:VC++绘制位图图片

    在使用Direct2D绘制图片的过程中,通过IWICImagingFactory工厂接口来得到绘制图片所需要的资源.本小节将介绍如何通过IWICImagingFactory工厂接口得到这些资源,并使用 ...

  7. Android Developers:绘制9-patch图片

    绘制9-patch图片工具让你使用可见即可得(WYSIWYG)编辑器轻松创建Nine Patch图像. 关于介绍Nine-path图片和它是如何工作的,请在2D Graphics的文档中查阅关于Nin ...

  8. Android View加载圆形图片且同时绘制圆形图片的外部边缘边线及边框:LayerDrawable实现

     Android View加载圆形图片且同时绘制圆形图片的外部边缘边线及边框:LayerDrawable实现 LayerDrawable实现的结果和附录文章1,2,3中的layer-list一致. ...

  9. 自定义View(12)绘制.9图片

    代码如下: // 绘制.9图片 void draw9Path(Canvas canvas){ //创建一个ninePatch的对象实例,第一个参数是bitmap.第二个参数是byte[],这里其实要求 ...

  10. Android ImageView加载圆形图片且同时绘制圆形图片的外部边缘边线及边框

     Android ImageView加载圆形图片且同时绘制圆形图片的外部边缘边线及边框 在Android早期的开发中,如果涉及到圆形图片的处理,往往需要借助于第三方的实现,见附录文章1,2.And ...

随机推荐

  1. 还在用Calendar操作Date?Java8都弃用了,还不知道它的这款强大的工具吗?

    引言 在过去的Java版本中,日期和时间的处理主要依赖于java.util.Date和java.util.Calendar类,然而随着业务系统的复杂以及技术层面的提升,这些传统的日期时间类暴露出了若干 ...

  2. 记录--通过Promise实现分批处理接口请求

    这里给大家分享我在网上总结出来的一些知识,希望对大家有所帮助 如何通过 Promise 实现百条接口请求? 实际项目中遇到需要批量发起上百条接口请求怎么办? 最新案例代码在此!点击看看 前言 不知你项 ...

  3. 虚拟DOM的理解与总结

    这里给大家分享我在网上总结出来的一些知识,希望对大家有所帮助 1. 对虚拟DOM的理解? 从本质上来说,Virtual Dom是一个JavaScript对象,通过对象的方式来表示DOM结构.将页面的状 ...

  4. C# 按指定宽高缩放图片

    /// <summary> /// 按指定宽高缩放图片 /// </summary> /// <param name="image">原图片&l ...

  5. AXI自定义IP之UART调试

    AXI自定义IP之UART调试 1.实验原理 前面的自定义IP中已经将AXI总线的大部分接口设置都一一验证了.基本掌握了关键接受寄存器slv_reg和发送寄存器data_reg_out,可以基本实现简 ...

  6. java使用Ffmpeg合成音频和视频

    1.Maven依赖 <!-- 需要注意,javacv主要是一组API为主,还需要加入对应的实现 --> <dependency> <groupId>org.byte ...

  7. KingbaseES 的角色和权限管理

    KingbaseES使用角色的概念管理数据库访问权限.为了方便权限管理,用户可以建立多个角色,对角色进行授权和权限回收,并把角色授予其他用户. 数据库初始化时,会创建一个超级用户的角色:system( ...

  8. 基于energy score的out-of-distribution数据检测,LeCun都说好 | NerulPS 2020

     论文提出用于out-of-distributions输入检测的energy-based方案,通过非概率的energy score区分in-distribution数据和out-of-distribu ...

  9. #排列组合#美团2018年CodeM大赛-决赛 A-Exam

    题目 分析 因为第一名所在的学校一定会发喜报, 所以只有一个学校发喜报说明其它学校都没有发喜报 钦定第一名所在的学校为1,总方案要乘\(n\),那么两个1之间不可能出现两个相同的学校的学生 那么可以分 ...

  10. Git 分支管理:优化版本控制与应急处理的关键策略

    使用 Git 分支:轻松管理不同版本和应对紧急情况的最佳实践 使用 Git 分支 在 Git 中,分支是主仓库的新/独立版本. 假设你有一个大型项目,需要对其进行设计更新. 没有使用 Git 时: 复 ...