Я изо всех сил пытаюсь нарисовать TBitmap
с прозрачностью на TDirect2DCanvas
без потери прозрачности.Delphi, Direct2D, TBitmap и Transparency
Создав 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
интерфейсов, поэтому я могу попытаться создать ID2D1Bitmap
из TBitmap
, используя следующий код (и предполагая, что формат пикселя копируется через):
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
? Или нужна ли эта боль для поддержания прозрачности?
Update
Итак, после того, как делать немного больше, рытье вокруг, теперь я могу преобразовать 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);
И результат по-прежнему является непрозрачным растровым изображением.
Итак, последнее, что я рассмотрел, это PixelFormat ID2D1RenderTarget, который является основной целью рендеринга 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 игнорирует альфа.
> * ".. прозрачность, которая присутствует в TBitmap .." *> Это то, что вы ошибались все время. У этого растрового изображения нет прозрачности. Это VCL делает это прозрачным * с информацией, которую вы передаете через свойства TBitmap (см. «TransparentStretchBlt» в «графике»). –