Hallo Harry
die Formel darf dich nicht abschrecken. Du musst eigentlich nur zwei Dinge tun für jedes Pixel:
1. Den neuen Alphawert berechnen
2. Die neuen Farbwerte für R,G,B.
Ich hab's rasch getan und das Resultat sieht wirklich gut aus.
In diesem Beispiel siehst du, wie du es für zwei gleich grosse Bitmaps A, B tun kannst, welche direkt übereinander gelegt werden.
( Du willst dann natürlich Code schreiben für A an Position x, y über B legen oder ähnlich. )
Delphi-Quellcode:
procedure AueberB( a, b, c : TBitMap );
var lineA, lineB, lineC : PRGB32Array;
x, y : integer;
alphaA, alphaB, alphaC : extended;
begin
a.PixelFormat := pf32Bit;
b.PixelFormat := pf32Bit;
c.PixelFormat := pf32bit;
for y := 0 to a.Height-1 do
begin
lineA := a.ScanLine[y];
lineB := b.ScanLine[y];
lineC := c.ScanLine[y];
for x := 0 to a.Width-1 do
begin
// Test
(* lineA[x].A := 255;
lineB[x].A := 0; *)
alphaA := lineA[x].A/255;
alphaB := lineB[x].A/255;
// 0 = Transparent - 1 = instransparent
alphaC := alphaA + ( 1 - alphaA )*alphaB; // (den Fall alphaA=0 UND alphaB=0 musst du hier noch sep. behandeln)
lineC[x].A := round(alphaC*255);
lineC[x].R := round(1/alphaC*(alphaA*lineA[x].R + (1-alphaA)*alphaB*lineB[x].R ));
lineC[x].G := round(1/alphaC*(alphaA*lineA[x].G + (1-alphaA)*alphaB*lineB[x].G ));
lineC[x].B := round(1/alphaC*(alphaA*lineA[x].B + (1-alphaA)*alphaB*lineB[x].B ));
end;
end;
end;
Testen:
So rufe ich die Prozedur auf:
Ich lade in diesem Beispiel in A und B das gleiche Bild, in A um 10,10 versetzt.
Ins Bild A schreibe ich den Buchstaben 'A' rein, ins Bild B den Buchstaben 'B'. (Damit sehe ich im Resultatbild C in etwa, wie A und B zum Resultat C beitragen.)
In der Prozedur AueberB (siehe Code oben) habe ich zwei Zeilen
lineA[x].A := 255;
lineB[x].A := 0;
"auskommentiert". Dort kannst du globale Alpha-Werte setzen und sehen, wie sich diese Werte aufs Resultatbitmap C auswirken.
Delphi-Quellcode:
procedure TForm100.Button1Click(Sender: TObject);
var a,b,c : TBitMap;
begin
a := TBitMap.Create;
b := TBitMap.Create;
c := TBitMap.Create;
a.LoadFromFile( 'C:\Users\Michael\Desktop\thun.bmp' );
b.LoadFromFile( 'C:\Users\Michael\Desktop\thun.bmp' );
a.Canvas.Draw( 10,10,b );
a.Canvas.Font.Size := 100;
a.Canvas.TextOut( 10,10, 'A' );
b.Canvas.Font.Size := 100;
b.Canvas.TextOut( 10,210, 'B' );
c.SetSize( a.Width, a.Height );
AueberB( a, b, c );
c.SaveToFile( 'C:\Users\Michael\Desktop\thun2.bmp');
a.Free;
b.Free;
c.Free;
end;
Natürlich kann man die ganze Sache auch in den "Integer Bereich" verlegen. Bei modernen Prozessoren gewinnt man aber (leider
) häufig gar nicht mehr viel Zeit; auf älteren Kisten jedoch sehr...