Delphi-PRAXiS
Seite 5 von 8   « Erste     345 67     Letzte »    

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Algorithmen, Datenstrukturen und Klassendesign (https://www.delphipraxis.net/78-algorithmen-datenstrukturen-und-klassendesign/)
-   -   Geht das noch schneller? - Bitmap-Verrechnung (https://www.delphipraxis.net/182859-geht-das-noch-schneller-bitmap-verrechnung.html)

Harry Stahl 24. Nov 2014 23:24

AW: Geht das noch schneller? - Bitmap-Verrechnung
 
Liste der Anhänge anzeigen (Anzahl: 1)
Zitat:

Zitat von jfheins (Beitrag 1280784)
4. Sagt wir "premultiplied alpha" etwas? Klingt erstmal komisch, ist aber eigentlich die sinnvollere Variante. Würde deinen Rechenaufwand auch hier reduzieren, aber deine Bilddaten müssten dafür natürlich angepasst werden.

Ja, sagt mir was. Wäre durchaus eine Überlegung (gewesen), aber dafür hätte man das dann von Anfang an im Programm (es dreht sich hier um ein Bildbearbeitungsprogramm) berücksichtigen müssen.

Die einzige Verwendung der hier diskutierten Funktion im Programm ist die Anzeige des fertig verrechneten Bitmap-Ebenen-Stapels auf einen Karo-Hintergrund (siehe anliegenden Screenshot).

Ich verwende übrigens dafür nicht die Windows Alphablend-Funktion, da die für bestimmte Bilder fehlerhafte Ergebnisse berechnet (eigentlich schade, denn die ist noch schneller, als die Funktion hier). Insofern stellt die hier diskutierte Funktion einen (Teil-)Ersatz dafür dar.

Harry Stahl 24. Nov 2014 23:28

AW: Geht das noch schneller? - Bitmap-Verrechnung
 
Zitat:

Zitat von Jens01 (Beitrag 1280741)
Schon mal bei/mit Graphics32 versucht?!

Nein, muss gestehen, kannte ich bislang nicht (habe mit GraphicEX, ansonsten teilweise mit ImageEn, aber meistens mit eigenen Lösungen gearbeitet).

Werde ich mir mal ansehen. Gibt es dort so eine spezielle Verrechnungsfunktion wie hier benötigt?

Medium 25. Nov 2014 01:31

AW: Geht das noch schneller? - Bitmap-Verrechnung
 
Alpha-Blending würde ich nun nicht wirklich als speziell bezeichnen, daher ja: Die Graphics32 bietet eine Fülle an Möglichkeiten diesbezüglich. Sogar direkten Support für Layers in Bitmaps (mit den respektiven Kombinationsfunktionen, u.a. standard Alpha-Blending). Vom Gefühl her würde ich fast sagen, dass diese Lib dein Heiland sein könnte.

Blup 25. Nov 2014 08:15

AW: Geht das noch schneller? - Bitmap-Verrechnung
 
Zitat:

Zitat von Harry Stahl (Beitrag 1280962)
Ich verwende übrigens dafür nicht die Windows Alphablend-Funktion, da die für bestimmte Bilder fehlerhafte Ergebnisse berechnet (eigentlich schade, denn die ist noch schneller, als die Funktion hier)

Eigentlich funktioniert die Windowsfunktion bei aktuellen Windowsversionen oder zumindest aktuellem Servicepack ganz gut. Allerdings müssen die transparenten Bitmaps dafür "premultiplied alpha" vorliegen. Das spart schon mal die halbe Rechenzeit.

Harry Stahl 25. Nov 2014 18:09

AW: Geht das noch schneller? - Bitmap-Verrechnung
 
Danke, das war ein wichtiger Hinweis, den ich übersehen hatte: Wenn die Bitmap Premultiplied ist, funktioniert die Alphablend-Funktion auch wie bei allen Bitmaps wie gewünscht!!:oops:

Insgesamt ist dann die Kombination temporäres Premultiplied-Bitmap erzeugen und mit Alphablend benutzen schon schneller als die hier bislang gefundene Lösung.

Das hier ist meine aktuelle PreMultiply-Funktion:

Kann man das auch noch irgendwie beschleunigen?

Delphi-Quellcode:
procedure PreMultiply (bm: TBitmap); inline;
var
  y, x: Integer;
  RGBA: pRGBALine;
begin
  for y := 0 to bm.Height-1 do begin
    RGBA := bm.Scanline[y];
    for x := 0 to bm.Width-1 do begin
      if (RGBA^[x].rgbReserved <> 0) and (RGBA^[x].rgbReserved <> 255) then begin
        if RGBA^[x].rgbRed <> 0 then RGBA^[x].rgbRed := round ((RGBA^[x].rgbReserved * RGBA^[x].rgbRed ) / 255);
        if RGBA^[x].rgbGreen <> 0 then RGBA^[x].rgbGreen := round ((RGBA^[x].rgbReserved * RGBA^[x].rgbGreen ) / 255);
        if RGBA^[x].rgbBlue <> 0 then RGBA^[x].rgbBlue := round ((RGBA^[x].rgbReserved * RGBA^[x].rgbBlue ) / 255);
      end;
    end;
  end;
end;

Dejan Vu 25. Nov 2014 18:36

AW: Geht das noch schneller? - Bitmap-Verrechnung
 
Ja, kann man. Einfach die Beiträge durchlesen (Array vs. Pointer, Integer vs. FP mathematik (Stichwort: 'MulDiv')

Du kannst die Ergebnisse der Rechnung auch vorher einmal in einer Matrix vornehmen und dann nur noch auslesen. Dann hast Du einmalig overhead aber bei vielen Berechnungen könnte sich das lohnen, zumal Du wohl auf FP-Mathematik bestehst. Warum auch immer.
Delphi-Quellcode:
var
  lkup : Array [0..255, 0..255] of Byte;

Begin
  for i:=0 to 255 do for j:=0 to 255 do lkup[i,j] := round(i*j/255);
End;

...
for y := 0 to bm.Height-1 do begin
  RGBA := bm.Scanline[y];
  for x := 0 to bm.Width-1 do begin
    if (RGBA^.rgbReserved <> 0) and (RGBA^.rgbReserved <> 255) then begin
      if RGBA^.rgbRed <> 0 then RGBA^.rgbRed := lk[RGBA^.rgbReserved , RGBA^.rgbRed];
      if RGBA^.rgbGreen <> 0 then RGBA^.rgbGreen := lk[RGBA^.rgbReserved, RGBA^.rgbGreen];
      if RGBA^.rgbBlue <> 0 then RGBA^.rgbBlue := lk[RGBA^.rgbReserved, RGBA^.rgbBlue];
    end;
   inc(RGBA);
  end;
end;

BUG 25. Nov 2014 18:50

AW: Geht das noch schneller? - Bitmap-Verrechnung
 
Die inneren Verzweigungen wegzulassen könnte auch noch was bringen:
Delphi-Quellcode:
var
  lkup : Array [0..255, 0..255] of Byte;

Begin
  for i:=0 to 255 do for j:=0 to 255 do
  begin
    if (j <> 0) and (j <> 255) then // ist j <> 0 überhaupt korrekt hier?
      lkup[i,j] := round(i*j/255)
    else
      lkup[i,j] := j;
  end;
End;

...
for y := 0 to bm.Height-1 do begin
  RGBA := bm.Scanline[y];
  for x := 0 to bm.Width-1 do begin
    RGBA^.rgbRed := lk[RGBA^.rgbReserved , RGBA^.rgbRed];
    RGBA^.rgbGreen := lk[RGBA^.rgbReserved, RGBA^.rgbGreen];
    RGBA^.rgbBlue := lk[RGBA^.rgbReserved, RGBA^.rgbBlue];
   inc(RGBA);
  end;
end;

Harry Stahl 25. Nov 2014 18:59

AW: Geht das noch schneller? - Bitmap-Verrechnung
 
Das hatte ich gerade auch zufälligerweise im Internet gefunden.

Doch Überraschung: Ist deutlich langsamer, als meine Funktion, die ich gepostet hatte. Wahrscheinlich kostet der doppelte Zugriff auf das byte-Array mehr Zeit als die direkte Berechnung der Werte.

Edit: Halt, diese Aussage muss ich evtl. zurückziehen. Wenn ich folgende logische Abfrage wie bei mir oben einbaue, ist es zumindest ähnlich schnell:

Delphi-Quellcode:
  if RGBA^[x].rgbReserved <> 255 then begin
Hängt dann eben davon ab, wieviel Pixel überhaupt Transparent sind, denn nur die müssen ja berechnet werden, die anderen können den Wert behalten.

Dejan Vu 26. Nov 2014 07:04

AW: Geht das noch schneller? - Bitmap-Verrechnung
 
Das Lookup-Array wird nur einmal berechnet, da ist es unerheblich, etwas zu optimieren. Daher würde ich diesen Vorgang nicht in die Performancebetrachtungen mit einbeziehen.
Beim Schreiben des Vorschlags ist mir aber auch aufgefallen, das es bei drei Operationen (*, /, round) nicht allzuviel zu optimieren gibt.
Aber wieso verwendest Du 'MulDiv' nicht? Das Ergebnis ist um höchstens 1 unterschiedlich (Rundungsverhalten).

Mavarik 26. Nov 2014 11:33

AW: Geht das noch schneller? - Bitmap-Verrechnung
 
Zitat:

Zitat von Dejan Vu (Beitrag 1281096)
Aber wieso verwendest Du 'MulDiv' nicht?

MulDiv ist immer ein Far-Call und Jumps und damit auf jeden Fall langsamer. (Auch wenn ich es nicht getestet habe)

Aber ein

C := A * 5 div B;

ist:
Code:
xor eax,eax
mov al,[ebp-$5]
lea eax,[eax+eax*4]
xor edx,edx
mov dl,[ebp-$06]
mov ecx,edx
xor edx,edx
div ecx
mov edx,[ebp-$04]
mov [edx+$002d4],al
ein C := MULDIV(A,5,B) ist:
Code:
xor eax,eax
mov al,[ebp-$6]      
push eax
push $05
xor eax,eax
mov al,[ebp-$5)
Push eax            // bishier schon fast so viele Ticks wie oben
CALL MulDiv
// aus MulDiv
jmp dword ptr[$00896ae8]
mov eax,[esp+$04}
or eax,eax
js $75201b80
mov edx,[esp+$80]
or edx,edx
js $75201c06
mul edx
mov ecx,[eps+$0c]
or ecx,ecx
js $75201c48
sar ecx,1
add eax,ecx
adc edx.$00
cmp edx,[esp+$0c]
jnb $75201b7a
div dword ptr [esp+$0c]
or eax,eay
js $75201b7a
ret $000c
mov edx,[ebp-$04]  // gleich mit oben
mov [edx+$02d4],al // gleich mit oben
Ein C := A * B div 8 ist:
Code:
xor eax,eax        // gleich mit oben
mov al,[ebp-$05]   // gleich mit oben
xor edx,edx        // gleich mit oben
mov dl,[ebp-$06],
imul edx
shr eax, $03        // div 8 erkannt
mov edx,[ebp-$04]  // gleich mit oben
mov [edx+$02d4],al // gleich mit oben

Mavarik


Alle Zeitangaben in WEZ +1. Es ist jetzt 02:39 Uhr.
Seite 5 von 8   « Erste     345 67     Letzte »    

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