Direct2D (16) : 蒙版之 FillOpacityMask() 方法
时间:2011-04-05 来源:万一
实现蒙版效果有三种途径:使用 FillOpacityMask()、使用 FillGeometry() 方法、使用图层。
FillOpacityMask() 用于处理图像蒙版。
期间用到 ID2D1Bitmap,因为对图像格式要求较苛刻,我通过 TDirect2DCanvas.CreateBitmap() 建立 ID2D1Bitmap 时没有成功。
后来使用了自定义函数直接使用 WIC 加载并转换格式。
蒙版图片是透明图片,将会透过其着色区域看到下层的图片;蒙版图片是以画刷的方式使用的。
实现蒙版区域计算时,还应设置 AntialiasMode 模式为 D2D1_ANTIALIAS_MODE_ALIASED。
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; fRect: TD2DRectF; fSize: 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(fSize); fRect := D2D1RectF(0, 0, fSize.width, fSize.height); cvs.RenderTarget.BeginDraw; cvs.RenderTarget.SetTransform(TD2DMatrix3x2F.Translation((ClientWidth-fSize.width)/2, (ClientHeight-fSize.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.RenderTarget.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; fRect: TD2DRectF; fSize: 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(fSize); fRect := D2D1RectF(0, 0, fSize.width, fSize.height); cvs.RenderTarget.BeginDraw; cvs.RenderTarget.SetTransform(TD2DMatrix3x2F.Translation((ClientWidth-fSize.width)/2, (ClientHeight-fSize.height)/2)); cvs.RenderTarget.SetAntialiasMode(D2D1_ANTIALIAS_MODE_ALIASED); D2DFactory.CreateRectangleGeometry(fRect, iRectangleGeometry); cvs.RenderTarget.FillGeometry(iRectangleGeometry, iBitmapBrush, iBitmapBrushMark); cvs.RenderTarget.SetAntialiasMode(D2D1_ANTIALIAS_MODE_PER_PRIMITIVE); cvs.RenderTarget.EndDraw; cvs.Free; end; procedure TForm1.FormResize(Sender: TObject); begin Repaint; end;
相关阅读 更多 +
排行榜 更多 +