Einzelnen Beitrag anzeigen

Amateurprofi

Registriert seit: 17. Nov 2005
Ort: Hamburg
1.041 Beiträge
 
Delphi XE2 Professional
 
#50

AW: Prüfung eines Bitmaps auf Transparenz (gehts noch schneller)?

  Alt 25. Feb 2016, 02:48
Also die Single-Core-Lösung die hier am schnellsten ist, ist die aus "IsPartlyTransparentASM" (unter AQTime wird die in Average-Time ca. 20 MS schneller angezeigt, als meine Standard-Variante. Im Einzeltest sind die aber fast gleichschnell. Keine Ahnung, warum hier so Unterschiede entstehen. Bei AQTime gab es allerdings ca. 26 Durchläufe).

Die Variante habe ich hier mal auf meine Aufrufkonvention umgestaltet, um nicht doppelte Funktionsaufrufe zu haben.

Frage an die ASM-Experten: Kann man das noch etwas schöner machen?
Delphi-Quellcode:
function HasTransparentRGBAValues (const bm:TBitmap): Boolean;
var
  W,H:NativeInt; P0,P1:Pointer;
begin
  P0 := bm.ScanLine[0]; p1 := bm.ScanLine[1];
  w := bm.Width; h:= bm.Height;

  asm
  // EAX=P0, Zeigt auf Zeile 0 der Bitmap
  // EDX=P1, Zeigt auf Zeile 1 der Bitmap
  // ECX=W, Breite der Bitmap
  // Stack=H, Höhe der Bitmap

                 mov EAX,P0 // von mir ergänzt
                 mov EDX,P1 //
                 mov ECX,w //

                 sub edx,eax // Offset von Zeile 1 zu Zeile 0
                 js @BottomUp
                 imul edx,H // Bytes/Zeile*Zeilen
                 add eax,edx // Auf unterste Zeile
  @BottomUp: lea eax,[eax+ecx*4+3] // Hinter letztes Pixel (auf A-Byte)
                 imul ecx,H // Anzahl Pixel
                 neg ecx
  @Loop: cmp byte[eax+ecx*4],$FF
                 jne @True
                 add ecx,1
                 jl @Loop
                 xor al,al
                 jmp @End
  @True: mov al,True
  @End:
  end;
end;
Edit: Hmmmh... irgendwas scheint an der procedure aber noch nicht zu stimmen, denn an einer Stelle des Programmablaufs stimmt plötzlich etwas nicht mehr (beim ersten Ausblenden der Hintergrundebene wird das Schachmuster plötzlich nicht mehr angezeigt, sondern eine weiße Arbeitsfläche, also irgendwo liefert die Funktion anscheinend einmal ein falsches Ergebnis zurück)
Hallo Harry,

das kann so auch nicht funktionieren.
Das Boolean-Resultat einer Funktion wird im Register AL erwartet, also dem unteren Byte von EAX.
Der Asm-Teil stellt deshalb das Resultat in AL.

Bei einer Pascal-Funktion (nicht Pure-Asm) wird eine lokale Variable "Result" angelegt, deren Inhalt vor dem Verlassen der Funktion, i.d.R. vor der Bereinigung des Stacks nach AL kopiert wird.
Was vorher in AL stand, geht dabei verloren.

Ich hab das mal im Debugger angeschaut (siehe weiter unten):
In der Kopie ist leider nicht zu sehen, an welcher Stelle der Haltepunkt ist.
Dehalb :
Der Haltepunkt steht an der Adresse 0052D36D und dort wird das Ergebnis der Prüfung, (hier True) in AL gestellt.
Versuch mal folgendes:
Beim Label True:
Das mov al,True ersetzen durch mov Result,True
Und zwei Zeilen darüber
das xor al,al ersetzen durch mov Result,False
Weiß nicht ob das dann funktioniert.
Meine Enpfehlung ist, ASM und Pascal strikt zu trennen. Der "Doppelte Funktionsaufruf", den du vermeiden möchtest,
kostet nichts (oder so gut wie nichts), er bringt dir aber sauberen Code.

Hier eine Kopie des problematischen Teils:

Transparent_Main.pas.1294: jmp @End
0052D36B EB02 jmp $0052d36f
Transparent_Main.pas.1295: @True: mov al,True
0052D36D B001 mov al,$01 // Hier wird das Ergebis des ASM-Teils definiert
Transparent_Main.pas.1298: end;
0052D36F 8BC3 mov eax,ebx // Und hier gleich danach vom Pascal-Teil überschrieben.
0052D371 5E pop esi
0052D372 5B pop ebx
0052D373 8BE5 mov esp,ebp
0052D375 5D pop ebp
0052D376 C3 ret
Gruß, Klaus
Die Titanic wurde von Profis gebaut,
die Arche Noah von einem Amateur.
... Und dieser Beitrag vom Amateurprofi....
  Mit Zitat antworten Zitat