• 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;
    


  • 相关阅读:
    LeetCode Merge Two Sorted Lists 归并排序
    LeetCode Add Binary 两个二进制数相加
    LeetCode Climbing Stairs 爬楼梯
    034 Search for a Range 搜索范围
    033 Search in Rotated Sorted Array 搜索旋转排序数组
    032 Longest Valid Parentheses 最长有效括号
    031 Next Permutation 下一个排列
    030 Substring with Concatenation of All Words 与所有单词相关联的字串
    029 Divide Two Integers 两数相除
    028 Implement strStr() 实现 strStr()
  • 原文地址:https://www.cnblogs.com/del/p/2005583.html
Copyright © 2020-2023  润新知