【发布时间】:2016-11-22 03:43:39
【问题描述】:
我很难在不丢失透明度的情况下将具有透明度的 TBitmap 绘制到 TDirect2DCanvas 上。
创建了一个TBitmap 作为我的绘图操作的后台缓冲区,如下所示:
bmp := TBitmap.Create;
bmp.Canvas.Brush.Handle := 0;
bmp.SetSize(100, 100);
bmp.Canvas.Brush.Color := clRed;
bmp.Transparent := true;
bmp.TransparentColor := clRed;
bmp.Canvas.Rectangle(bmp.Canvas.ClipRect);
bmp.Canvas.Pen.Color := clGreen;
bmp.Canvas.Ellipse(bmp.Canvas.ClipRect);
然后我需要将它绘制到我的TDirect2DCanvas 上,但是下面会绘制TBitmap 但会删除所有透明度 - 背景颜色绘制为红色,而如果我只是绘制到TForm.Canvas 上,则背景是透明的.
// Drawing onto the TDirect2DCanvas results in a red background
AEventArgs.Canvas.Draw(0, 0, bmp);
// Drawing onto the TForm.Canvas gives the correct result
Self.Canvas.Draw(0, 0, bmp);
我的理解现在将我引向ID2D1Bitmap 和IWICBitmap 接口,因此,我可以尝试使用以下代码从TBitmap 创建一个ID2D1Bitmap(并且假设像素格式被复制):
var
bmp : TBitmap;
temp : ID2D1Bitmap;
begin
// Code to initialize the TBitmap goes here (from above)
// Create an ID2D1Bitmap from a TBitmap
temp := AEventArgs.Canvas.CreateBitmap(bmp);
// Draw the ID2D1Bitmap onto the TDirect2DCanvas
AEventArgs.Canvas.RenderTarget.DrawBitmap(temp);
现在我有了ID2D1Bitmap,结果还是一样的——没有透明度的红色背景。我猜 Direct2D 方面使用不同的透明度方法是完全可行的,但查看 ID2D1Bitmap 的属性并没有提供任何线索。
我的下一个猜测是去IWICBitmap接口。
最后,我的问题是:有没有我从上面遗漏的更直接或更明显的事情可以让透明的TBitmap 被绘制到TDirect2DCanvas 表面上?或者为了保持透明度,所有这些痛苦都是必要的?
更新
好的,所以在进行了更多挖掘之后,我现在可以将TBitmap 转换为IWICBitmap,然后转换为ID2D1Bitmap,但是问题仍然存在-TBitmap 中存在的透明度是渲染到 TDirect2DCanvas 时未复制。
// Create the IWICBitmap from the TBitmap
GetWICFactory.CreateBitmapFromHBITMAP(bmp.Handle, bmp.Palette, WICBitmapUsePremultipliedAlpha, wic);
wic.GetPixelFormat(pif);
// The PixelFormat is correct as `GUID_WICPixelFormat32bppPBGRA` which is
// B8G8R8A8_UNORM and PREMULTIPLIED
// Create the IWICFormatConverter
GetWICFactory.CreateFormatConverter(fc);
fc.Initialize(wic, GUID_WICPixelFormat32bppPBGRA, WICBitmapDitherTypeNone, nil, 0.0, WICBitmapPaletteTypeCustom);
// Now, create the ID2D1Bitmap
AEventArgs.Canvas.RenderTarget.CreateBitmapFromWicBitmap(fc, nil, temp);
temp.GetPixelFormat(fmt);
// Here, PixelFormat is correct matching the PixelFormat from the IWICBitmap
// Draw the bitmap to the Canvas
AEventArgs.Canvas.RenderTarget.DrawBitmap(temp);
结果仍然是不透明的位图。
所以我最后研究的是 ID2D1RenderTarget 的 PixelFormat,它是 TDirect2DCanvas 的底层渲染目标。
// Create the canvas
fCanvas := TDirect2DCanvas.Create(Self.Handle);
fCanvas.RenderTarget.GetPixelFormat(pf);
// This gives me a PixelFormat of
// B8G8R8A8_UNORM but D2D1_ALPHA_MODE_IGNORE
所以我猜真正的问题在于ID2D1RenderTarget PixelFormat 忽略了 alpha。
【问题讨论】:
-
> ".. TBitmap 中存在的透明度.." > 这就是你一直以来的错误。该位图没有透明度。 VCL 使用您通过 TBitmap 的属性提供的信息透明地绘制它(参见“图形”中的
TransparentStretchBlt)。
标签: delphi transparent direct2d wic