本文告诉大家如何通过 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. django(模版层)

    一 模板语法传值 {{}}: 变量相关.过滤器 {%%}: 逻辑相关(静态文件配置.反向解析.标签相关.模版继承和 导入) def index(request): # 模板语法可以传递的后端pytho ...

  2. 手把手制作mobileconfig文件,在iphone上创建h5网页桌面图标

    1,下载mobileconfig文件制作工具 下载地址:点击关注公众号,回复appicon, 获取工具的下载地址 新建配置描述文件,填写通用信息 填写Web Clip信息 点击菜单栏的导出,注意这里一 ...

  3. 灰狼优化算法(MOGWO)

    灰狼优化算法(MOGWO) 摘要 固定大小的外部档案用来保存帕累托优化解 在多目标搜索空间中,这个档案被用来定义狼群社会等级和捕猎行为 这个算法在10个多目标测试集进行测试,并与MOEA/D和MOPS ...

  4. 《.NET内存管理宝典 》(Pro .NET Memory Management) 阅读指南 - 第3章

    本章勘误: 暂无,等待细心的你告诉我哦. 本章注解: 暂无 本章释疑: 暂无,等待你的提问 致谢: MVP 林德熙 MVP 吕毅 sPhinX 相关链接 试读记录

  5. 关于SQL Server数据库中的用户权限和角色管理

    简介 在SQL Server数据库系统中,管理用户权限和角色对于确保数据安全.完整性和可访问性至关重要.在本文中,我们将探讨在SQL Server数据库中创建用户.分配权限和管理角色的过程.我们将涵盖 ...

  6. Spring Cloud导入Spring Boot项目当作子模块微服务IDEA不识别子module问题

    1.在父工程下面引入module. <modules> <module>study-design-mode</module> </modules> 2. ...

  7. KingbaseES 原生XML系列三--XML数据查询函数

    KingbaseES 原生XML系列三--XML数据查询函数(EXTRACT,EXTRACTVALUE,EXISTSNODE,XPATH,XPATH_EXISTS,XMLEXISTS) XML的简单使 ...

  8. KingbaseES V8R6 集群运维案例-- sys_internal.init.*文件引起sys_basebackup失败

    案例说明: KingbaseES V8R6集群在执行'repmgr standby clone'或sys_basebackup克隆备库时出现如下图相关sys_internal.init文件错误: 适用 ...

  9. python爬虫等获取实时数据+Flume+Kafka+Spark Streaming+mysql+Echarts实现数据动态实时采集、分析、展示

    使用爬虫等获取实时数据+Flume+Kafka+Spark Streaming+mysql+Echarts实现数据动态实时采集.分析.展示 [获取完整源码关注公众号:靠谱杨阅读人生 回复kafka获取 ...

  10. #线段树#洛谷 4269 [USACO18FEB]Snow Boots G

    题目传送门 分析 模型转换一下,能通过当且仅当最长的无法通过段小于 \(d\),(这点应该是此题的精华吧) 那么按照最大深度从小到大排序,双指针在线段树上删除无法通过段,求最长区间即可 代码 #inc ...