Entwickler-Ecke

Multimedia / Grafik - Alphablend zweier TGraphics


elundril - Mo 26.03.07 17:44
Titel: Alphablend zweier TGraphics
Ein überarbeiteter Library-Eintrag ist hier [http://www.delphi-library.de/viewtopic.php?t=109281] zu finden.

Alphablend zweier Bilder

Folgernder Code dient dazu zwei TGraphic typen (also Bitmap, jpeg, usw) mittels Alphablend zu einem Bitmap zu verschmeltzen.
Die Beiden Images (Image1 und Image2) sind typen die von TGraphic abgeleitet sind und müssen existieren.
Ebenso wie das ResultBitmap das übergeben werden muss. In dieses wird dann das Alphablendbild "geschrieben".
Mit den AlphaValue wird dann der Wert beschrieben welches Bild stärker werden soll. Mit 0 wird nur das erste Bild gezeigt und mit 255 nur das zweite.


Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
35:
36:
procedure AlphaImgs(Image1, Image2: TGraphic; ResultBitmap: TBitmap; AlphaValue: Byte);
type pixel = Array [0..2of byte;
var bmpImg1, bmpImg2: TBitmap;
    x,y,h,w: integer;
    p1, p2: ^pixel;
begin
  bmpImg1:=TBitmap.Create;
  bmpImg2:=TBitmap.Create;
  try
    bmpImg1.Height:=Image1.Height;
    bmpImg2.Height:=Image2.Height;
    bmpImg1.Width:=Image1.Width;
    bmpImg2.Width:=Image2.Width;
    bmpImg1.PixelFormat:=pf24bit;
    bmpImg2.PixelFormat:=pf24bit;
    bmpImg1.Canvas.Draw(0,0,Image1);
    bmpImg2.Canvas.Draw(0,0,Image2);
    h := Min(bmpImg1.Height, bmpImg2.height);
    w := Min(bmpImg1.Width, bmpImg2.Width);
    for y :=0 to h-1 do begin
      p1 := bmpImg1.ScanLine[y];
      p2 := bmpImg2.ScanLine[y];
      for x:= 0 to w-1 do begin
        p1^[0] := ((p1^[0]*(AlphaValue+1) + (p2^[0]*(256-AlphaValue))) shr 8);
        p1^[1] := ((p1^[1]*(AlphaValue+1) + (p2^[1]*(256-AlphaValue))) shr 8);
        p1^[2] := ((p1^[2]*(AlphaValue+1) + (p2^[2]*(256-AlphaValue))) shr 8);
        inc(p1);
        inc(p2);
      end;
    end;
    ResultBitmap.Assign(bmpImg1);
  finally
    bmpImg1.Free;
    bmpImg2.Free;
  end;
end;


Aufrufen könnte man nun diese prozedur wiefolgt:

Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
procedure TfrmMain.btnblendClick(Sender: TObject);
var bmpresult:TBitmap;
begin
  ImageResult.Picture.Assign(nil);
  bmpresult:=TBitmap.Create;
  AlphaImgs(Image1.Picture.Graphic,Image2.Picture.Graphic,bmpresult,Byte(sbAlpha.Position));
  ImageResult.Picture.Assign(bmpresult);
  bmpresult.Free;
end;


freu mich auf Kritik.

ToDo: Das erste Bild fix als Hintergrund verwenden und das zweite Darüberblenden, ohne das erste abzuschneiden.
ToDo: Das ganze dann noch variabel machen sodass man dem programm sagen kann bei welchen koordinaten das zweite bild darübergeblendet werden soll

lg elundril

//edit: hab den Code zum Alphablenden der einzelnen Bitmapfarben gekürzt.

//edit: Try-Finally Block eingefügt

//edit: Fehler mit Klammern beseitigt

Angehängt ist ein beispielprogramm. Es wäre nett wenn mein Name erwähnt wird bei Programmen die diese prozedur verwenden.


Blawen - Do 29.03.07 21:20

Zitat:
Angehängt ist ein beispielprogramm. Es wäre nett wenn mein Name erwähnt wird bei Programmen die diese prozedur verwenden.

Hast Du ev. vergessen den Anhang hochzuladen?


elundril - Do 29.03.07 23:44

ups stimmt! :oops: sry!

lg el


elundril - Di 22.05.07 10:44

keine Rückmeldungen? :-(

lg el


Christian S. - Mo 28.05.07 17:32

Hi!

Sorry, Lib-Beiträge zu prüfen ist deutlich aufwendiger als Forenbeiträge zu überfliegen. Da habe ich nicht immer Zeit für.

Jetzt aber:

Zuerst fällt mir auf, dass da try-finally fehlt. Du gibst zwar brav alles wieder frei, aber ein try-finally wäre da der Zuckerguss ;-)

Außerdem: Was passiert, wenn Image1 größer als Image2 ist? Wenn ich richtig sehe, greift man dann auf Speicher zu, von dem man die Finger lassen sollte.

Grüße
Christian


elundril - Mi 30.05.07 19:38

kann man mir mal helfen?

ich hab keine idee wie ich das überprüfen könnte. ich hab mir gedacht das ich vielleicht nachschauen kann ob im pointer was drin ist oder leer.

ne andere idee is halt das ich überprüf welches größer ist aber das würde den Quellcode ungemein vergrößern.

lg el


Christian S. - So 15.07.07 11:45

Also, zum einen schreibt man die "TIrgendwas.Create" immer vor das try und nicht mit rein.

Nun zu der Sache mit der Größe:
Du hast zwei Möglichkeiten
(1) Du kannst eine Exception werfen, wenn das erste Bild größer als das Zweite ist
(2) Du lässt die Schleifen jeweils bis zum Minimum der beiden Seitenlängen laufen


elundril - So 15.07.07 21:55

geht das jetzt so?? ich schau einfach ob in einem der zwei pointer nix drin steht. wenns so ist dann wird das ganze abgebochen.

Oder gibts ne bessere möglichkeit?

lg elundril


Christian S. - So 15.07.07 21:57

Ist denn sichergestellt, dass der Pointer dann nil ist? Oder kann auch nur "Unsinn" drin stehen, als was gerade an der Stelle im Speicher steht.

Außerdem: in der inneren Schleife kannst Du auch weiterhin "rauslaufen".

Wieso läufst Du nicht einfach bis zum Minimum der Seitenlängen?


Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
if image1.Height < image2.Height then
  minHeight := image1.Height
else
  minHeight := image2.Height;

for y := 0 to minHeight-1 do
...


elundril - So 15.07.07 22:01

:autsch: stimmt, stimmt, stimmt!

Jop is ne gute idee!

Gib mir noch ein paar tage zeit bitte und ich werd das ganze nochmal überarbeiten.

lg elundril


Christian S. - Mo 23.07.07 10:39

Baust Du die Änderungen noch ein? :-)


elundril - Mo 23.07.07 11:31

ja natürlich! ich hab nur vergessen wegen dem release von SpeedNotes! Sry!!

lg elundril


Christian S. - Mo 30.07.07 01:37

user profile iconelundril hat folgendes geschrieben:
ja natürlich! ich hab nur vergessen wegen dem release von SpeedNotes!
Der Release muss echt anstrengend gewesen sein :mrgreen:


elundril - Mo 30.07.07 08:33

user profile iconChristian S. hat folgendes geschrieben:
user profile iconelundril hat folgendes geschrieben:
ja natürlich! ich hab nur vergessen wegen dem release von SpeedNotes!
Der Release muss echt anstrengend gewesen sein :mrgreen:


3 Versionen am ersten Tag sind nichts ungewöhnliches! Frag Microsoft! :lol:

lg elundril


Narses - Do 03.07.08 00:19

Moin!

user profile iconChristian S. hat folgendes geschrieben:
Außerdem: Was passiert, wenn Image1 größer als Image2 ist? Wenn ich richtig sehe, greift man dann auf Speicher zu, von dem man die Finger lassen sollte.
user profile iconChristian S. hat folgendes geschrieben:
Wieso läufst Du nicht einfach bis zum Minimum der Seitenlängen?

Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
if image1.Height < image2.Height then
  minHeight := image1.Height
else
  minHeight := image2.Height;

for y := 0 to minHeight-1 do
...
Leider tritt bei deinem Demo-Programm immer noch eine Exception auf, wenn Image1 größer als Image2 ist. user profile iconChristian S. hat dir doch bereits einen Vorschlag gemacht, wie du das Problem lösen kannst. :nixweiss:

Hast du überhaupt noch Interesse, den FAQ-Beitrag weiterzuentwickeln? ;)

cu
Narses


elundril - Do 03.07.08 02:13

jop, natürlich, sorry das ich da bis jetzt nichts gemacht habe, Schule ist in den letzten beiden Jahren etwas für mich vor gegangen und da hatte ich keine Zeit. Aber jetzt mit neuem Laptop und mehr Zeit mach ich mich wieder ans werk. danke fürs erinnern.

lg elundril


Tilman - Mi 23.07.08 00:14
Titel: Re: Alphablend zweier TGraphics
user profile iconelundril hat folgendes geschrieben:


Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
      for x:= 0 to bmpImg1.width-1 do begin 
        p1^[0] := ((p1^[0]*(AlphaValue+1)) + (p2^[0]*(256-AlphaValue))) shr 8); 
        p1^[1] := ((p1^[1]*(AlphaValue+1)) + (p2^[1]*(256-AlphaValue))) shr 8); 
        p1^[2] := ((p1^[2]*(AlphaValue+1)) + (p2^[2]*(256-AlphaValue))) shr 8); 

        inc(p1); 
        inc(p2); 
      end;



funzt nicht, habs mal so geändert, ist das richtig?


Delphi-Quelltext
1:
2:
3:
  p1^[0] := ((p1^[0]*(AlphaValue+1) + (p2^[0]*(256-AlphaValue))) shr 8);
  p1^[1] := ((p1^[1]*(AlphaValue+1) + (p2^[1]*(256-AlphaValue))) shr 8);
  p1^[2] := ((p1^[2]*(AlphaValue+1) + (p2^[2]*(256-AlphaValue))) shr 8);


Ansonsten super Sache, genau das was ich gerade brauche =) hab allerdings die Parameter auf TBitmap geändert anstelle von TGraphic.


elundril - Do 24.07.08 14:56

Jop, is richtig so. Heut abend kommt dann eh eine neue Version mit den Bugfixes.

Freut mich das es dir hilft.

lg elundril


Narses - Mi 06.08.08 00:10

Moin!

Ein weiterer Monat ist seit meiner letzten Anfrage unwiederbringlich im Abgrund der Vergessenheit versunken... :)
user profile iconelundril am Do 24.07.08 14:56 hat folgendes geschrieben:
Heut abend kommt dann eh eine neue Version mit den Bugfixes.

Wie sieht´s aus, kommst du voran? ;)

cu
Narses


Tilman - Mi 06.08.08 17:17

Hm, möglicherweise dachte eldunril ich sei ein Moderator oder Bibliothekar; natürlich meinte ich mit "ich habs mal so geändert" eigentlich "ich habs mal so geändert - in meinem Projekt". Da ist also noch was zu tun ;)


elundril - Do 07.08.08 13:11

es ist leider etwas dringendes dazwischen gekommen. (die entscheidung über meine zukunft aber ich bin noch am ball!)

lg elundril


Narses - Mo 15.12.08 16:23

Moin!

Wie sieht´s aus, speziell in den anstehenden Weihnachtsferien und mit diesem FAQ-Beitrag... :D

cu
Narses


Christian S. - So 08.02.09 13:05

Hallo!

Könntest Du diesem FAQ-Beitrag noch den letzten Schliff verpassen? :-)

Grüße
Christian


Narses - Mi 23.12.09 00:33

Moin!

Meinst du, du kriegst das hier noch jemals fertig? :| :nixweiss:

cu
Narses