2016-07-19 21 views
1

Я изо всех сил пытаюсь нарисовать 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 игнорирует альфа.

+0

> * ".. прозрачность, которая присутствует в TBitmap .." *> Это то, что вы ошибались все время. У этого растрового изображения нет прозрачности. Это VCL делает это прозрачным * с информацией, которую вы передаете через свойства TBitmap (см. «TransparentStretchBlt» в «графике»). –

ответ

2

Реальная проблема не в методах, которые вы вызываете, а в том, что в приложении VCL по умолчанию TBitmap использует 24-битный формат изображения RGB, который не имеет альфа-канала, необходимого для альфа-прозрачности.

Если вы хотите использовать альфа-прозрачность с TBitmap, вам сначала нужно установить его формат пикселей в pf32bit.

https://stackoverflow.com/a/4680460/3636228

Также не забудьте установить альфа-канал 0 для каждого пикселя, который вы хотите быть прозрачным.

Вы видите, что Direct2D не поддерживает ту же прозрачность, что и в VCL, где вы можете просто установить прозрачный цвет, и каждый пиксель этого конкретного цвета просто игнорируется.

+0

@SilverWarrior благодарит за комментарии. Любые указания относительно того, как я могу идти между VCL TBitmap и Direct2D при сохранении прозрачности? Я посмотрел на использование GDI-совместимого объекта рендеринга, но это все еще не работает, даже если альфа настроена правильно как на TBitmap, так и на целевой рендеринг - она ​​по-прежнему игнорируется. По всей видимости, не так много полезной информации. Спасибо – weblar83

+0

Возможно, вам стоит попробовать использовать FMX.Graphics.TBitmap вместо обычного VCL TBitmap, как я предложил в другом вопросе для разных целей, которые вы можете найти здесь: http://stackoverflow.com/a/38551815/3636228 Обратите внимание, что Я никогда не пробовал этого или замеченного anboddy, но делаю это, но на основании того, что FireMonkey использует DirectX для рендеринга в Windows, он может действительно работать. Когда я приеду домой, я проведу тестирование. – SilverWarior

 Смежные вопросы

  • Нет связанных вопросов^_^