文档章节

Direct2D (16) : 蒙版之 FillOpacityMask() 方法

涂孟超
 涂孟超
发布于 2014/09/26 15:36
字数 616
阅读 16
收藏 0

实现蒙版效果有三种途径:使用 FillOpacityMask()、使用 FillGeometry() 方法、使用图层。

FillOpacityMask() 用于处理图像蒙版。
期间用到 ID2D1Bitmap,因为对图像格式要求较高,我通过 TDirect2DCanvas.CreateBitmap() 建立 ID2D1Bitmap 时没有成功。
后来使用了自定义函数直接使用 WIC 加载并转换格式。
蒙版图片是透明图片,将会透过其着色区域看到下层的图片;蒙版图片是以画刷的方式使用的。

实现蒙版区域计算时,还应设置 AntialiasMode 模式为 D2D1_ANTIALIAS_MODE_ALIASED。

FillOpacityMask() 方法的第三个参数(D2D1_OPACITY_MASK_CONTENT 类型):
  //描述蒙板是否包含图形或文本,Direct2D 使用此信息来确定在混合不透明蒙板时要使用哪个 gamma 空间。
D2D1_OPACITY_MASK_CONTENT_GRAPHICS            = 0;
  //蒙板包含图形,在混合时使用 gamma 2.2 颜色空间。
D2D1_OPACITY_MASK_CONTENT_TEXT_NATURAL        = 1;
  //蒙板包含非 GDI 文本,用于混合的 gamma 空间源自呈现目标的文字呈现参数。
D2D1_OPACITY_MASK_CONTENT_TEXT_GDI_COMPATIBLE = 2; 
  //蒙板包含使用 GDI 兼容呈现模式呈现的文本,在混合时使用 GDI 呈现的 gamma 空间。


uses Direct2D, D2D1, Wincodec, ActiveX;

{从指定文件建立 ID2D1Bitmap 的函数}
function GetD2D1Bitmap(RenderTarget: ID2D1RenderTarget; imgPath: string): ID2D1Bitmap;
var
  iWicFactory: IWICImagingFactory;
  iWICDecoder: IWICBitmapDecoder;
  iWICFrameDecode: IWICBitmapFrameDecode;
  iFormatConverter: IWICFormatConverter;
begin
  CoCreateInstance(CLSID_WICImagingFactory, nil, CLSCTX_INPROC_SERVER, IID_IWICImagingFactory, iWicFactory);
  iWicFactory.CreateDecoderFromFilename(PWideChar(imgPath), GUID_NULL, GENERIC_READ, WICDecodeMetadataCacheOnLoad, iWICDecoder);
  iWicDecoder.GetFrame(0, iWICFrameDecode);
  iWicFactory.CreateFormatConverter(iFormatConverter);
  iFormatConverter.Initialize(iWICFrameDecode, GUID_WICPixelFormat32bppPBGRA, WICBitmapDitherTypeNone, nil, 0, WICBitmapPaletteTypeMedianCut);
  RenderTarget.CreateBitmapFromWicBitmap(iFormatConverter, nil, Result);
end;

procedure TForm1.FormPaint(Sender: TObject);
var
  cvs: TDirect2DCanvas;
  iBitmapBrush: ID2D1BitmapBrush;
  iBitmapPic, iBitmapMark: ID2D1Bitmap;
  rSizeF: TD2DSizeF;
begin
  cvs := TDirect2DCanvas.Create(Canvas, ClientRect);
  iBitmapMark := GetD2D1Bitmap(cvs.RenderTarget, 'C:\Temp\Mark.png');
  iBitmapPic := GetD2D1Bitmap(cvs.RenderTarget, 'C:\Temp\Fern.png');
  cvs.RenderTarget.CreateBitmapBrush(iBitmapPic, nil, nil, iBitmapBrush);

  iBitmapMark.GetSize(rSizeF);
  cvs.BeginDraw;
  cvs.RenderTarget.SetTransform(TD2DMatrix3x2F.Translation((ClientWidth-rSizeF.width)/2, (ClientHeight-rSizeF.height)/2));
  cvs.RenderTarget.SetAntialiasMode(D2D1_ANTIALIAS_MODE_ALIASED);
  cvs.RenderTarget.FillOpacityMask(iBitmapMark, iBitmapBrush, D2D1_OPACITY_MASK_CONTENT_GRAPHICS);
  cvs.RenderTarget.SetAntialiasMode(D2D1_ANTIALIAS_MODE_PER_PRIMITIVE);
  cvs.EndDraw;
  cvs.Free;
end;

procedure TForm1.FormResize(Sender: TObject);
begin
  Repaint;
end;


测试图片:C:\Temp\Fern.png



蒙版图片:C:\Temp\Mark.png



蒙版效果:



通过 FillGeometry() 也可以实现上面的效果,但它擅长的是几何蒙版,在这里不如 FillOpacityMask() 简洁:

uses Direct2D, D2D1, Wincodec, ActiveX;

{从指定文件建立 ID2D1Bitmap 的函数}
function GetD2D1Bitmap(RenderTarget: ID2D1RenderTarget; imgPath: string): ID2D1Bitmap;
var
  iWicFactory: IWICImagingFactory;
  iWICDecoder: IWICBitmapDecoder;
  iWICFrameDecode: IWICBitmapFrameDecode;
  iFormatConverter: IWICFormatConverter;
begin
  CoCreateInstance(CLSID_WICImagingFactory, nil, CLSCTX_INPROC_SERVER, IID_IWICImagingFactory, iWicFactory);
  iWicFactory.CreateDecoderFromFilename(PWideChar(imgPath), GUID_NULL, GENERIC_READ, WICDecodeMetadataCacheOnLoad, iWICDecoder);
  iWicDecoder.GetFrame(0, iWICFrameDecode);
  iWicFactory.CreateFormatConverter(iFormatConverter);
  iFormatConverter.Initialize(iWICFrameDecode, GUID_WICPixelFormat32bppPBGRA, WICBitmapDitherTypeNone, nil, 0, WICBitmapPaletteTypeMedianCut);
  RenderTarget.CreateBitmapFromWicBitmap(iFormatConverter, nil, Result);
end;

procedure TForm1.FormPaint(Sender: TObject);
var
  cvs: TDirect2DCanvas;
  iBitmapBrush,iBitmapBrushMark: ID2D1BitmapBrush;
  iBitmapPic, iBitmapMark: ID2D1Bitmap;
  rRectF: TD2DRectF;
  rSizeF: TD2DSizeF;
  iRectangleGeometry: ID2D1RectangleGeometry;
begin
  cvs := TDirect2DCanvas.Create(Canvas, ClientRect);
  iBitmapMark := GetD2D1Bitmap(cvs.RenderTarget, 'C:\Temp\Mark.png');
  iBitmapPic := GetD2D1Bitmap(cvs.RenderTarget, 'C:\Temp\Fern.png');

  cvs.RenderTarget.CreateBitmapBrush(iBitmapPic, nil, nil, iBitmapBrush);
  cvs.RenderTarget.CreateBitmapBrush(iBitmapMark, nil, nil, iBitmapBrushMark);

  iBitmapMark.GetSize(rSizeF);
  rRectF := D2D1RectF(0, 0, rSizeF.width, rSizeF.height);
  cvs.BeginDraw;
  cvs.RenderTarget.SetTransform(TD2DMatrix3x2F.Translation((ClientWidth-rSizeF.width)/2, (ClientHeight-rSizeF.height)/2));
  cvs.RenderTarget.SetAntialiasMode(D2D1_ANTIALIAS_MODE_ALIASED);
  D2DFactory.CreateRectangleGeometry(rRectF, iRectangleGeometry);
  cvs.RenderTarget.FillGeometry(iRectangleGeometry, iBitmapBrush, iBitmapBrushMark);
  cvs.RenderTarget.SetAntialiasMode(D2D1_ANTIALIAS_MODE_PER_PRIMITIVE);
  cvs.EndDraw;
  cvs.Free;
end;

procedure TForm1.FormResize(Sender: TObject);
begin
  Repaint;
end;


本文转载自:http://www.cnblogs.com/del/archive/2011/04/05/2005583.html

共有 人打赏支持
涂孟超
粉丝 12
博文 2011
码字总数 14107
作品 0
深圳
程序员
私信 提问
Windows桌面应用程序(1-2-4-7th) DPI和设备无关的像素

要使用Windows图形进行有效编程,您必须了解两个相关的概念: 每英寸点数(DPI) 设备无关像素(DIP)。 我们从DPI开始。这将需要短暂的绕行排版。在印刷术中,类型的大小以称为点的单位来测量。一点...

qq_37422196
01/12
0
0
使用 Direct2D 绘制分层窗口

这是我关于Direct2D的第三篇介绍了,今天主要讲下其无可比拟的互操作性。为了避免繁缛末节的讲述,我们从一个实例入手:层级窗口。相对于windows的其它众多功能。层级窗口并未做相应的更新,...

Dy_
2014/01/16
8.2K
10
Direct2D教程(十)绘制文本

概述 在Direct2D中,文本的绘制是通过DirectWrite来实现的,DirectWrite实际上已经是一个独立的DirectX组件了。关于DirectWrite,我摘录了MSDN的一段文字。 DirectWrite介绍 当今的应用程序应...

吞吞吐吐的
2017/10/17
0
0
关于Direct3D11里汉字显示的一些思考

本系列文章由zhmxy555(毛星云)编写,转载请注明出处。 http://blog.csdn.net/zhmxy555/article/details/8147234 作者:毛星云 邮箱: happylifemxy@163.com 这篇文章里,浅墨希望与大家一起...

长平狐
2012/11/12
794
0
WinForms篇:DevExpress v16.1新功能介绍

TreeMap Control 在上一个版本(2015.1)中,DevExpress在WPF中增加了 TreeMap Control ,一种用嵌套矩形展示分层和平面数据的方式。此控件推出后,有大批Winforms版用户建议我们将其加入Win...

百mumu
2016/06/28
25
0

没有更多内容

加载失败,请刷新页面

加载更多

开源 java CMS - FreeCMS2.8会员我的评论

项目地址:http://www.freeteam.cn/ 我的评论 从左侧管理菜单点击我的评论进入。在这里可以查看当前登录会员的所有评论记录。 删除评论 选择评论然后点击删除按钮可以完成删除操作。 为了防止...

freeteam
31分钟前
1
0
Eureka Server启用 https服务指北

文章共 591字,阅读大约需要 2分钟 ! 概 述 在我的前文《Eureka Server 开启Spring Security Basic认证》中已经给 Eureka Server 开启了最基本的鉴权措施,本文则让 HTTPS加持于 Eureka Ser...

CodeSheep
今天
17
0
OSChina 周二乱弹 —— 其实我在地板也睡不着

Osc乱弹歌单(2018)请戳(这里) 【今日歌曲】 @witt-z :分享歌词: 阴天 在不开灯的房间,当所有思绪都一点一点沉淀。 分享莫文蔚的单曲《阴天》: 《阴天》- 莫文蔚 手机党少年们想听歌,...

小小编辑
今天
813
12
微服务分布式事务实现

https://www.processon.com/view/link/5b2144d7e4b001a14d3d2d30

WALK_MAN
今天
5
0
《大漠烟尘》读书笔记及读后感文章3700字

《大漠烟尘》读书笔记及读后感文章3700字: 在这个浮躁的社会里,你有多久没有好好读完一本书了? 我们总觉得自己和别人不一样,所以当看到别人身上的问题时,很少有“反求诸己”,反思自己。...

原创小博客
今天
5
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部