Registriert seit: 3. Sep 2004
434 Beiträge
Delphi 10.4 Sydney
|
TBitmap32 PolygonFS Alpha falsch
17. Sep 2024, 12:46
Hallo zusammen,
ich muss ein abgerundetes Rechteck zeichnen. Einmal gefüllt (Hintergrund) und einmal nur als Umrandung (Rahmen).
Da dies im Rahmen der Arbeit mit einem TBitmap32 erfolgt, muss ich natürlich auch dessen Funktionen verwenden.
Es ist nun so, dass es keine mir bekannte Funktion in TBitmap32 für ein abgerundetes Rechteck gibt (korrigiert mich gerne!), insbesondere bei dem man den Radius der Kurven festlegen kann. Also setze ich das abgerundete Rechteck aus mehreren Kreise und Rechtecken selbst zusammen.
Das Problem ist nun, dass ich den Rahmen nur wie folgt zeichnen kann:
1) Zeichne das massive, abgerundete Rechteck in der Rahmenfarbe
2) Zeichne das massive, abgerundete Rechteck in jede Richtung einen Pixel weniger weit (von der Mitte aus gesehen) in der Farbe Weiß mit Alpha=0=voll transparent in dem Modus, der den Alpha-Kanal *ersetzt*.
Mir ist schon klar, dass wenn ich im falschen Modus etwas mit Alpha=0 zeichne, dieses genau *gar nicht* sichtbar sein wird. Hier soll es jedoch darum gehen, in der Alpha-Maske des TBitmap32 alle Alpha-Bytes explizit auf "0" zu setzen, damit das Bild an dieser Stelle 100% durchsichtig wird.
Mit normalen Rechtecken (FillRect) funktioniert es problemlos. Das selbe Verfahren mit PolygonFS funktioniert nicht.
Der zusammengekürzte Code, bei dem ich nur ein Rechteck und nur einen Kreis zeichne, schaut wie folgt aus:
Delphi-Quellcode:
procedure ZeichneRahmen(_TargetBitmap: TBitmap32; _x: integer);
var
Center, Radius: TPoint;
Points: TArrayOfFloatPoint;
a1, a2, b1, b2: integer;
const
Rundung = 20;
begin
if not assigned(_TargetBitmap) then Exit;
if Alpha_Border < 1 then Exit;
_TargetBitmap.CombineMode := cmBlend;
_TargetBitmap.DrawMode := dmOpaque;
// Bitmap komplett löschen und auf "Weiß, voll transparent" setzen
_TargetBitmap.Clear(color32(255,255,255,0));
// Techdemo zum Vergleich:
// Zeichne ein massives Rechteck in Rot
_TargetBitmap.FillRect(_x, 10, _x + 100, 80, Color32(255, 0, 0, 255));
// Zeichne ein massives Rechteck in Transparent, das zu allen Seiten 1 kleiner ist, als das vorherige
_TargetBitmap.FillRect(_x + 1, 11, _x + 99, 79, Color32( 0, 0, 0, 0));
// ^-- das funktioniert
// Natürlich hier ENTWEDER Alternative 1 ODER 2 nur verwenden:
// Kreis Alternative 1:
// Punkte für den Kreis berechnen
Points := Ellipse(100,100,50,50);
// Kreis massiv schwarz zeichnen
PolygonFS(_TargetBitmap, Points, Color32(0, 0, 0, 255));
// Punkte für den 1px kleineren Kreis berechnen
Points := Ellipse(100,100,49,49);
// Kreis massiv Transparent zeichnen
PolygonFS(_TargetBitmap, Points, Color32(0, 0, 0, 0));
// ^-- geht nicht, nur ein großer, schwarzer Kreis
// Kreis Alternative 2
// Punkte für den Kreis berechnen
Points := Ellipse(100,100,50,50);
// Kreis massiv schwarz zeichnen
PolygonFS(_TargetBitmap, Points, Color32(0, 0, 0, 255));
// Beim kombinieren von Pixeln nun die Alpha-Berechnung bitte mir überlassen!
_TargetBitmap.DrawMode := dmCustom;
_TargetBitmap.OnPixelCombine := Self.ReplaceBlend;
// Punkte für den 1px kleineren Kreis berechnen
Points := Ellipse(100,100,49,49);
// Kreis massiv Transparent zeichnen mit der ReplaceBlend-Methode
PolygonFS(_TargetBitmap, Points, Color32(0, 0, 0, 0));
// Für weitere Verarbeitung wieder in den Standard-Modus wechseln
_TargetBitmap.DrawMode := dmBlend;
_TargetBitmap.OnPixelCombine := NIL;
...
end;
procedure TBeispiel.ReplaceBlend(F: TColor32; var B: TColor32; M: Cardinal);
begin
// B := F; // Ersetzt den Zielpixel B durch den Quellpixel F
B := Color32(0,0,0,0);
end;
Laut Haltepunkt wird meine ReplaceBlend-Methode nie aufgerufen.
Auch eine Änderung von _TargetBitmap.CombineMode zu cmMerge bringt keine Besserung.
Wie kann ich nun also einen Kreis zeichnen, der bei allen Pixel statt die Farbe zu setzen und/oder das Alpha zu kombinieren, den Alpha-Wert explizit festlegt?
Danke im Voraus!
Delphi 10.4 32-Bit auf Windows 10 Pro 64-Bit, ehem. Delphi 2010 32-Bit auf Windows 10 Pro 64-Bit
|