AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Thema durchsuchen
Ansicht
Themen-Optionen

Zwei transparente Bitmaps miteinader verrechnen

Ein Thema von Harry Stahl · begonnen am 4. Jun 2017 · letzter Beitrag vom 9. Jun 2017
Antwort Antwort
Seite 2 von 3     12 3      
Benutzerbild von himitsu
himitsu

Registriert seit: 11. Okt 2003
Ort: Elbflorenz
43.136 Beiträge
 
Delphi 12 Athens
 
#11

AW: Zwei transparente Bitmaps miteinader verrechnen

  Alt 4. Jun 2017, 19:31
Es gibt ja mindestens zwei Varianten wie man sowas verrechnet.

* Entweder die Bilder zu 50:50 vemischen, also als wenn man zwei "flüssige" Farben zusammen schüttet.
Das ergibt praktisch ganz billig 'nen Mittelwert und es ist egal was oben oder unten ist
x := (x + y) / 2
Die Transparent natürlich umgekehrt
x := 255 - ((255 - x) + (255 - y)) / 2

* Oder man macht es richtig, so als wenn man zwei bemalte Glasscheiben übereinander legt
die Gesamttransparenz zusammenrechnen (transparenz-unten * trasparenz-oben ... 50% * 50% = 25%)
und bei den Farben die Transparenz des oberen Bildes nehmen, damit den eigenen Farbanteil berechnen (255 - tansparenz)
dann den Farbanteil mit der Transparenz des unteren Bildes (ebenfalls 255 - tansparenz)
dann nochmal von unten den oben durchscheinenden Teil (tansparenz ... also (255 - transparenz-unten) * trasparenz-oben)
und zum Schluß beide Farben addieren



und egal was du tust, du mußt immer auf Überläufe achten, sonst gibt es solche "Farbverfälschungen", wo z.B. aus zwei Mal fast 0% plötzlich 100% Transparenz entsteht
Garbage Collector ... Delphianer erzeugen keinen Müll, also brauchen sie auch keinen Müllsucher.
my Delphi wish list : BugReports/FeatureRequests
  Mit Zitat antworten Zitat
Michael II

Registriert seit: 1. Dez 2012
Ort: CH BE Eriswil
721 Beiträge
 
Delphi 11 Alexandria
 
#12

AW: Zwei transparente Bitmaps miteinader verrechnen

  Alt 4. Jun 2017, 19:41
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...
Michael Gasser

Geändert von Michael II ( 4. Jun 2017 um 20:41 Uhr)
  Mit Zitat antworten Zitat
mensch72

Registriert seit: 6. Feb 2008
838 Beiträge
 
#13

AW: Zwei transparente Bitmaps miteinader verrechnen

  Alt 4. Jun 2017, 19:44
also gilt:

AN:=255-BYTE(DWORD( (DWORD(AU)*DWORD(AO)) div (DWORD(AU)+DWORD(AO)) ));

Gemäß Beispiel
50% & 50% -> 25% ...
(128*128) / (128+128) -> 64 was ja 25% entspricht
  Mit Zitat antworten Zitat
Jens01

Registriert seit: 14. Apr 2009
670 Beiträge
 
#14

AW: Zwei transparente Bitmaps miteinader verrechnen

  Alt 4. Jun 2017, 19:48
Graphhics32?
https://github.com/graphics32/graphi...g/TextureBlend
Achtung: Bin kein Informatiker sondern komme vom Bau.
  Mit Zitat antworten Zitat
Benutzerbild von himitsu
himitsu

Registriert seit: 11. Okt 2003
Ort: Elbflorenz
43.136 Beiträge
 
Delphi 12 Athens
 
#15

AW: Zwei transparente Bitmaps miteinader verrechnen

  Alt 4. Jun 2017, 20:20
Da, wo die zwei Bilder nicht übereinander liegen, dann kann man da für das "fehlende" Bild als Bummywert ein Pixel mit 100% Transparenz verwenden und damit weiterrechen.

Nach Wegkürzen aller Parameter bleibt dann das Pixel des anderen Bildes 1:1 übrig.
Garbage Collector ... Delphianer erzeugen keinen Müll, also brauchen sie auch keinen Müllsucher.
my Delphi wish list : BugReports/FeatureRequests
  Mit Zitat antworten Zitat
Benutzerbild von Harry Stahl
Harry Stahl

Registriert seit: 2. Apr 2004
Ort: Bonn
2.479 Beiträge
 
Delphi 11 Alexandria
 
#16

AW: Zwei transparente Bitmaps miteinader verrechnen

  Alt 5. Jun 2017, 00:27
So, danke erst mal für die Hinweise und die erste Umsetzung der Formel.

Habe daran noch ein wenig weiter gearbeitet, das sieht nun so aus:

Delphi-Quellcode:
  alphaA := A/255;
  alphaB := AO/255;
  alphaC := alphaA + (1 - alphaA )* AlphaB;

  R := round((1/alphaC) * (alphaA* (R/255) + (1-alphaA) * alphaB * (Ro/255) ) * 255);
  G := round((1/alphaC) * (alphaA* (G/255) + (1-alphaA) * alphaB * (Go/255) ) * 255);
  B := round((1/alphaC) * (alphaA* (B/255) + (1-alphaA) * alphaB * (Bo/255) ) * 255);

  A := round (AlphaC * 255);
Funktioniert soweit, nur ist die Verrechnung der Farben anscheinend noch nicht ausreichend. Daher habe ich das hier noch mit meiner Ursprungslösung ergänzt:

Delphi-Quellcode:
  alphaA := A/255;
  alphaB := AO/255;
  alphaC := alphaA + (1 - alphaA )* AlphaB;

  B := (ao * (bo - b) shr 8 + b); // hier ergänzt
  G := (ao * (go - g) shr 8 + g); //
  r := (ao * (ro - r) shr 8 + r); //

  R := round((1/alphaC) * (alphaA* (R/255) + (1-alphaA) * alphaB * (Ro/255) ) * 255);
  G := round((1/alphaC) * (alphaA* (G/255) + (1-alphaA) * alphaB * (Go/255) ) * 255);
  B := round((1/alphaC) * (alphaA* (B/255) + (1-alphaA) * alphaB * (Bo/255) ) * 255);

  A := round (AlphaC * 255);
Mit dieser Ergänzung wird das Ergebnis exakt so angezeigt, wie Photoshop die Datei errechnet.

Anliegend mal ein Screenshot, wo eine PSP-Layer-Datei auf eine Ebene reduziert wurde und als PNG-Datei geladen (linke Seite).
Rechts daneben die Original-PSP-Datei, mit den geladenen Layern, wo das Ergebnis dann berechnet mit der o.g. Routine im Programm angezeigt wird (rechte Seite).
Miniaturansicht angehängter Grafiken
result-ok.png  
  Mit Zitat antworten Zitat
Benutzerbild von stahli
stahli

Registriert seit: 26. Nov 2003
Ort: Halle/Saale
4.336 Beiträge
 
Delphi 11 Alexandria
 
#17

AW: Zwei transparente Bitmaps miteinader verrechnen

  Alt 5. Jun 2017, 12:50
Beeindruckend
Stahli
http://www.StahliSoft.de
---
"Jetzt muss ich seh´n, dass ich kein Denkfehler mach...!?" Dittsche (2004)
  Mit Zitat antworten Zitat
Benutzerbild von Harry Stahl
Harry Stahl

Registriert seit: 2. Apr 2004
Ort: Bonn
2.479 Beiträge
 
Delphi 11 Alexandria
 
#18

AW: Zwei transparente Bitmaps miteinader verrechnen

  Alt 5. Jun 2017, 13:42
@Stahli

Danke, aber das Kompliment geht an all die netten Kollegen, die mir hier geholfen haben, alleine hätte ich das nicht hinbekommen.
Hatte zuvor bestimmt einen halben Tag lang versucht, das selbst zu backen, aber ohne Erfolg.

Da sieht man mal wieder, wie super hilfreich und unverzichtbar dieses Forum ist (insofern mal ein herzliches Danke an Daniel und die anderen Forenunterstützer)!
  Mit Zitat antworten Zitat
Michael II

Registriert seit: 1. Dez 2012
Ort: CH BE Eriswil
721 Beiträge
 
Delphi 11 Alexandria
 
#19

AW: Zwei transparente Bitmaps miteinader verrechnen

  Alt 6. Jun 2017, 14:36
Hallo Harry

du hast hier mal ein Testprogramm gepostet. - Kannst du (falls dein Projekt nun nicht geheim eingestuft ) dein aktualisiertes Projekt hochladen (oder mir per PN senden)? Besten Dank.


Zitat:
Funktioniert soweit, nur ist die Verrechnung der Farben anscheinend noch nicht ausreichend.
Das hängt von den Quellbildern ab.

In deinen Beispielbildern A und B wurde der weiche Rand erzeugt, indem
1. der Alphawert am Rand abnimmt UND zusätzlich
2. mit einem Farbverlauf Farbe -> schwarz

Oder etwas anders ausgedrückt: Der Originalfarbwert wurde wahrscheinlich mit dem Alphawert multipliziert - und dieser Farbwert wurde in A, B gespeichert.

Du könntest also in solchen Fällen vor dem Berechnen des Zielbilds für die Bitmaps A und B die Originalfarben [die Farben für intransparente Versionen von A und B] ermitteln.

_____
Manchmal liegen A und B mit Alphakanal aber auch in Originalfarben vor (also nicht wie bei deinen Beispielbildern "Farbe=alpha*Originalfarbe"); in solchen Fällen (grösserer Farbraum fürs Bild möglich) müsstest du natürlich auf den oben erwähnten Vorprozess verzichten.

[Wenn deine Grafikobjekte keine Auskunft (oder keine korrekte) über das AlphaFormat geben, hilft nur testen (oder raten, indem du AlphaVerläufe und Farbverläufe miteinander vergleichst).]

Gruss
Michael
Michael Gasser
  Mit Zitat antworten Zitat
Benutzerbild von Harry Stahl
Harry Stahl

Registriert seit: 2. Apr 2004
Ort: Bonn
2.479 Beiträge
 
Delphi 11 Alexandria
 
#20

AW: Zwei transparente Bitmaps miteinader verrechnen

  Alt 6. Jun 2017, 23:02
Hallo Michael,

klar, kein Problem, habe das Demo kurzerhand mit meiner Endlösung aktualisiert und hier noch mal hochgeladen.

Ja, das Problem mit den vormultiplizierten Farbwerten basierend auf den Alphawerten ist mir bekannt und führt immer wieder zu Verwirrungen. In meinem Projekt verwende ich keine vorberechneten Farbwerte auf Alphabasis, sondern die reinen Farbwerte und berechne die Ausgabe dann auf der Basis der Alphawerte.

Wie bereits oben mal erwähnt, gibt es hier beim Demoprojekt im Ergebnis eine Farbverfälschung, weil ich die PNG-Dateien aus den TImage-Containern über einen Umweg wieder in das TBitmap holen musste. In meinem Programm tritt das nicht auf, zum Laden der Dateien verwende ich die ImageEn-Komponenten, die das soweit alles schon richtig berücksichtigen.

Nur konnte ich das hier nicht posten, weil die meisten Anwender diese Kompos wohl eher nicht haben.
Angehängte Dateien
Dateityp: zip ImgMix.zip (831,7 KB, 12x aufgerufen)
  Mit Zitat antworten Zitat
Antwort Antwort
Seite 2 von 3     12 3      


Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 09:47 Uhr.
Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz