zoukankan      html  css  js  c++  java
  • Direct2D (16) : 蒙版之 FillOpacityMask() 方法


    实现蒙版效果有三种途径:使用 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;
    


  • 相关阅读:
    bzoj3622: 已经没有什么好害怕的了
    BSGS
    LOJ#2320 生成树计数
    ??? cliquers
    生成函数
    洛谷P5206 数树
    01分数规划
    差分约束系统
    51nod1238 最小公倍数之和 V3
    51nod1237 最大公约数之和 V3
  • 原文地址:https://www.cnblogs.com/del/p/2005583.html
Copyright © 2011-2022 走看看