![]() |
AW: Geht das noch schneller? - Bitmap-Verrechnung
Liste der Anhänge anzeigen (Anzahl: 1)
Zitat:
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. |
AW: Geht das noch schneller? - Bitmap-Verrechnung
Zitat:
Werde ich mir mal ansehen. Gibt es dort so eine spezielle Verrechnungsfunktion wie hier benötigt? |
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.
|
AW: Geht das noch schneller? - Bitmap-Verrechnung
Zitat:
|
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; |
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; |
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; |
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:
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.
if RGBA^[x].rgbReserved <> 255 then begin
|
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). |
AW: Geht das noch schneller? - Bitmap-Verrechnung
Zitat:
Aber ein C := A * 5 div B; ist:
Code:
ein C := MULDIV(A,5,B) ist:
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
Code:
Ein C := A * B div 8 ist:
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
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 13:28 Uhr. |
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz