本文告诉大家如何通过 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. Retrofit源码分析

    目录介绍 1.首先回顾Retrofit简单使用方法 2.Retrofit的创建流程源码分析 2.1 Retrofit对象调用Builder()源码解析 2.2 Retrofit对象调用baseUrl( ...

  2. 记录--前端实现电子签名(web、移动端)通用

    这里给大家分享我在网上总结出来的一些知识,希望对大家有所帮助 前言 在现在的时代发展中,从以前的手写签名,逐渐衍生出了电子签名.电子签名和纸质手写签名一样具有法律效应.电子签名目前主要还是在需要个人确 ...

  3. Oracle限制某个帐号只能在特定机器上访问数据库

    CREATE OR REPLACE TRIGGER logon_ip_control AFTER logon ON user_test.schema BEGIN IF USER IN ('user_t ...

  4. Windows上部署spring boot jar项目

    1.下载地址:https://github.com/winsw/winsw/releases 下载红色框内三个文件就够了. sample-allOptions.xml 所有配置参考 sample-mi ...

  5. 21 JSONP

    JSONP 为了解决浏览器跨域问题. jquery提供了jsonp请求. 在网页端如果见到了服务器返回的数据是: ​ xxxxxxxxxxdjsfkldasjfkldasjklfjadsklfjasd ...

  6. #树上启发式合并,位运算#CF570D Tree Requests

    题目 给定一个以 \(1\) 为根的 \(n\) 个结点的树,每个点上有一个字母\((a-z)\),每个点的深度定义为该节点到 \(1\) 号结点路径上的点数. 每次询问 \(a, b\) 查询以 \ ...

  7. XML 简介及用法详解

    XML 是一种用于存储和传输数据的与软件和硬件无关的工具. 什么是XML? XML代表eXtensible Markup Language(可扩展标记语言).XML是一种与HTML非常相似的标记语言. ...

  8. Java 继承与多态:代码重用与灵活性的巧妙结合

    Java 继承(子类和超类) 在 Java 中,可以从一个类继承属性和方法到另一个类.我们将"继承概念"分为两类: 子类(child): 从另一个类继承的类 超类(parent): ...

  9. 一文告诉你如何使用java调用http接口

    程序如下: 添加apache相关maven依赖: 1 <dependency> 2 <groupId>org.apache.commons</groupId> 3 ...

  10. jenkins安装卸载和下载

    环境 :docker容器 卸载 jenkins 1.rpm卸载rpm -e jenkins 2.检查是否卸载成功rpm -ql jenkins 3.彻底删除残留文件:find / -iname jen ...