2016-07-19 53 views
1

Ich habe Mühe, eine TBitmap mit Transparenz auf eine TDirect2DCanvas zu zeichnen, ohne die Transparenz zu verlieren.Delphi, Direct2D, TBitmap und Transparenz

ein TBitmap erstellt, die für meinen Ziehvorgang als Back-Puffer wirkt wie folgt:

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

Ich brauche dann auf meine TDirect2DCanvas zu ziehen, jedoch folgenden die TBitmap zieht aber entfernt alle Transparenz - die Hintergrundfarbe wird als rot gezeichnet, wohingegen, wenn ich einfach auf die TForm.Canvas zeichne, der Hintergrund transparent ist.

// 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); 

Mein Verständnis jetzt führt mich zu ID2D1Bitmap und IWICBitmap Schnittstellen, so kann ich versuchen, ein ID2D1Bitmap vom TBitmap mit dem folgenden Code zu erstellen (und unter der Annahme, dass das Pixelformat über kopiert wird):

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

Nun, da ich ein ID2D1Bitmap, ist das Ergebnis immer noch der gleiche - ein roter Hintergrund ohne Transparenz. Ich denke, es ist durchaus machbar, dass die Direct2D-Seite der Dinge eine andere Methode für Transparenz verwendet, aber die Eigenschaften der ID2D1Bitmap bietet keine Hinweise.

Meine nächste Schätzung ist die IWICBitmap Schnittstelle zu gehen.

Letztendlich ist meine Frage: Gibt es eine einfachere oder offensichtliche Sache, die ich von oben vermisst habe, die die transparente TBitmap auf die TDirect2DCanvas Oberfläche gezogen werden könnte? Oder sind all diese Schmerzen notwendig, um die Transparenz zu erhalten?

aktualisieren

Ok, so dass nach ein wenig mehr zu graben um zu tun, kann ich jetzt die TBitmap auf ein IWICBitmap konvertieren und dann auf eine ID2D1Bitmap aber die Frage bleibt - Transparenz, die vorhanden ist in der TBitmap ist nicht kopiert beim Rendern auf 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); 

Und das Ergebnis ist immer noch eine nicht transparente Bitmap.

Also das letzte, was ich untersucht habe, ist das PixelFormat des ID2D1RenderTarget, welches das zugrundeliegende Renderziel des TDirect2DCanvas ist.

// 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 

So vermute ich, dass das eigentliche Problem mit der Tatsache zu tun, dass das ID2D1RenderTarget Pixelformat der Alpha ignoriert.

+0

> * ".. Transparenz, die in der TBitmap vorhanden ist." *> Das ist, was Sie falsch verstanden haben. Diese Bitmap hat keine Transparenz. Es ist die VCL, die es * transparent * mit den Informationen zeichnet, die Sie über die Eigenschaften der TBitmap liefern (siehe 'TransparentStretchBlt' in 'Grafiken'). –

Antwort

2

Das eigentliche Problem ist nicht in den Methoden, die Sie aufrufen, aber die Scherung Tatsache, dass TBitmap in der VCL-Anwendung standardmäßig 24bit RGB Pixelformat verwendet, die keinen Alphakanal für Alpha-Transparenz benötigt.

Wenn Sie Alpha-Transparenz mit TBitmap verwenden möchten, müssen Sie zunächst das Pixelformat auf pf32bit setzen.

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

Vergessen Sie auch nicht Alpha-Kanal auf 0 für jedes Pixel zu setzen, dass Sie es transparent sein wollen.

Sie sehen, Direct2D unterstützt nicht die gleiche Transparenz wie in VCL verwendet, wo Sie einfach die transparente Farbe festlegen und jedes Pixel dieser bestimmten Farbe einfach ignoriert wird.

+0

@SilverWarrior danke für Ihre Kommentare. Irgendwelche Hinweise, wie ich zwischen der VCL TBitmap und Direct2D unter Beibehaltung der Transparenz gehen kann? Ich habe mir ein GDI-kompatibles Render-Ziel angesehen, aber das funktioniert immer noch nicht, obwohl das Alpha sowohl auf der TBitmap als auch auf dem Render-Ziel richtig eingestellt ist - es wird immer noch ignoriert. Es scheint nicht viel hilfreiche Informationen zu geben. Danke – weblar83

+0

Vielleicht sollten Sie FMX.Graphics.TBitmap anstelle von regulären VCL TBitmap verwenden, wie ich in einer anderen Frage für verschiedene Zwecke vorgeschlagen habe, die Sie hier finden können: http://StackOverflow.com/a/38551815/3636228 Beachten Sie, dass Ich habe das nie versucht oder gesehen und es sonst nicht tun, aber basierend auf der Tatsache, dass FireMonkey DirectX für das Rendern unter Windows verwendet, könnte es tatsächlich funktionieren. Ich werde ein paar Tests machen, wenn ich nach Hause komme. – SilverWarior