本文告诉大家如何通过 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. drf(认证、权限、频率)

    一. 认证组件 1. 流程 1. 写一个类,继承BaseAuthentication,重写authenticate,认证的逻辑写在里面. 认证通过,返回两个值,一个值最终给了包装以后的request对 ...

  2. Csharp学习Linq

    Linq的学习 这里继续使用之前文章创建的学生类,首先简单介绍一下linq的使用. Student.cs public class Student { public int Id { get; set ...

  3. js原型详解

    js中的原型毫无疑问一个难点,学习如果不深入很容易就晕了! 任何一个js知识点,比如事件流,闭包,继承等,都有许许多多的说法,对于这些知识点我们都应该先熟练的使用,然后自己整理一套属于自己的理解说辞, ...

  4. EVENG导入Win7镜像以后可以启动无法VNC打开

    原因:未安装支持 eveng 的 vncviewer 解决方法:下载 vncviewer: https://pan.eve-ng.cn/Tools/EVE-NG/Client/EVE-NG-Win-C ...

  5. KingbaseES V8R6集群运维案例之---sys_hba.conf限制客户端访问数据库

    KingbaseES V8R6集群运维案例之---sys_hba.conf限制客户端访问数据库 案例说明: 客户端认证是由一个配置文件(通常名为sys_hba.conf并被存放在数据库集簇目录中)控制 ...

  6. Python爬取国家统计局2009至2020统计用区划和城乡划分代码(省市区/县三级)并存入mysql数据库

    国家统计局->统计标准网址:http://www.stats.gov.cn/tjsj/tjbz/tjyqhdmhcxhfdm/ 获取资源请关注公众号 [靠谱杨阅读人生]回复[城乡分类]获取 流程 ...

  7. 取消掉远程桌面mstsc顶部(侧面)连接栏

    在进行mstsc远程桌面连接电脑或者虚拟机的时候,总是会出现一个连接栏.虽然点左边的图钉可以自动隐藏,但是每次鼠标滑到上面的时候,还是会冒出来,这个就有点闹心了. 查了下相关资料,解决了,特写下相关教 ...

  8. #莫队,根号分治#洛谷 5071 [Ynoi2015] 此时此刻的光辉

    题目传送门 分析 约数个数就是 \(\prod{(c+1)}\),但是带 \(log\) 会TLE, 考虑将每个数分成 \(\leq \sqrt[3]{n}\) 和 \(>\sqrt[3]{n} ...

  9. #搜索,树剖,set#洛谷 3322 JZOJ 4049 [SDOI2015]排序&洛谷 3320 JZOJ 4050 [SDOI2015]寻宝游戏

    洛谷 3322 [SDOI2015]排序 题目 小A有一个\(1\sim 2^N\)的排列\(A[1\sim 2^N]\),他希望将A数组从小到大排序,小A可以执行的操作有\(N\)种,每种操作最多可 ...

  10. Jchardet——支持检测并输出文件编码方式的组件

      简介 Jchardet是OpenAtom OpenHarmony(以下简称"OpenHarmony")系统的一款检测文本编码的组件.当上传一个文件时,组件可以检测并输出该文件中 ...