Delphi-PRAXiS
Seite 2 von 2     12   

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Algorithmen, Datenstrukturen und Klassendesign (https://www.delphipraxis.net/78-algorithmen-datenstrukturen-und-klassendesign/)
-   -   Delphi Prüfung eines Bitmaps auf Transparenz (gehts noch schneller)? (https://www.delphipraxis.net/188328-pruefung-eines-bitmaps-auf-transparenz-gehts-noch-schneller.html)

Neutral General 24. Feb 2016 08:40

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

Zitat von Amateurprofi (Beitrag 1331161)
m.E. kann die Funktion nur sehr eingeschränkt funktionieren.

1) Überprüfter Bereich der Bitmap:

Das ist mir im Nachhinein auch noch aufgefallen, stimmt.

Zitat:

Zitat von Amateurprofi (Beitrag 1331161)
2) Prüfung von jeweils 4 Pixeln auf Transparenz:

Nachdem ich gerade CMPEQPS nochmal nachgeschlagen habe, muss ich sagen: Auch da hast du Recht.
Ich hatte es so gelesen, dass es entweder nur ein true für "alles ist gleich" oder ein false "irgendwas ist anders" gibt.

Okay dann ist meine SSE-Variante wohl Schrott :mrgreen:
Ein Versuch wars Wert :stupid:

Memnarch 24. Feb 2016 09:37

AW: Prüfung eines Bitmaps auf Transparenz (gehts noch schneller)?
 
Was für ne CPU hast du? AUf meinem i5 @3GHZ

Hat die Ursprungsmethode(XE):

Debug: 30ms
Release: 8ms

Und so:
Delphi-Quellcode:
type
  TRGBA = packed record
    B, G, R, A: Byte;
  end;

  PRGBA = ^TRGBA;

  TScanLine = array[0..100000] of TRGBA;
  PScanLine = ^TScanLine;

function HasTransparentRGBAValues (const bm:TBitmap): Boolean;
var
  x, z: Integer; RGBA: PScanLine;
  LPixel: PRGBA;
begin
  Result := FALSE;
  RGBA := bm.Scanline[bm.Height-1];
  z := bm.Width * bm.Height;
  LPixel := @RGBA[0];
  for x := 0 to z-1 do begin
    if LPixel.A < 255 then
      EXIT (TRUE);
    Inc(LPixel, SizeOf(TRGBA));
  end;
end;
Debug: 7ms
Release: 3ms

Seh da keinen bedarf für Hexenwerk optimierungen

Neutral General 24. Feb 2016 09:46

AW: Prüfung eines Bitmaps auf Transparenz (gehts noch schneller)?
 
@Memnarch: Deine Methode überspringt auch 3/4 der Pixel :mrgreen:
Delphi-Quellcode:
Inc(LPixel, SizeOf(TRGBA));

Bei inc wird ein typisierter Pointer immer um die Größe des Typs inkrementiert. (Auch ohne Angabe des 2. Parameters)
D.h. mit deinem Code springst du nicht SizeOf(TRGBA) Bytes weiter, sondern SizeOf(TRGBA)*SizeOf(TRGBA) Bytes

Uwe Raabe 24. Feb 2016 09:46

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

Zitat von Memnarch (Beitrag 1331182)
Debug: 7ms
Release: 3ms

Delphi-Quellcode:
  LPixel: PRGBA;
...
Inc(LPixel, SizeOf(TRGBA));
Das
Delphi-Quellcode:
Inc
verschiebt den Pointer nun (auf einem 32-Bit System) um 16 Byte weiter. Gemäß der Hilfe:

Zitat:

Wenn X ein Zeigertyp ist, wird X um N-mal der Größe des Typs, auf den gezeigt wird, inkrementiert.
Delphi-Quellcode:
Inc(LPixel);
ist vollkommen ausreichend um das nächste Pixel zu adressieren.

Memnarch 24. Feb 2016 10:04

AW: Prüfung eines Bitmaps auf Transparenz (gehts noch schneller)?
 
Ach ich vertu mich auch immerwieder :D
Dann sinds auch hier im Release 8ms

Trotzdem, 8ms sind hier noch flott genug. Mich interessiert erstmal die CPU des Threaderstellers o.O

EDIT:
Folgendes braucht im Release 5(-6)ms:
Delphi-Quellcode:
function HasTransparentRGBAValues (const bm:TBitmap): Boolean;
var
  z: Integer; RGBA: PScanLine;
  LPixel, LLastPixel: PRGBA;
begin
  RGBA := bm.Scanline[bm.Height-1];
  z := bm.Width * bm.Height;
  LPixel := @RGBA[0];
  LLastPixel := @RGBA[z - 1];
  while (LPixel.A = 255) and (LPixel <> LLastPixel) do
    Inc(LPixel);
  Result := LPixel.A < 255;
end;

Harry Stahl 24. Feb 2016 17:15

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

Zitat von Memnarch (Beitrag 1331186)
Ach ich vertu mich auch immerwieder :D
Dann sinds auch hier im Release 8ms

Trotzdem, 8ms sind hier noch flott genug. Mich interessiert erstmal die CPU des Threaderstellers o.O

EDIT:
Folgendes braucht im Release 5(-6)ms:
Delphi-Quellcode:
function HasTransparentRGBAValues (const bm:TBitmap): Boolean;
var
  z: Integer; RGBA: PScanLine;
  LPixel, LLastPixel: PRGBA;
begin
  RGBA := bm.Scanline[bm.Height-1];
  z := bm.Width * bm.Height;
  LPixel := @RGBA[0];
  LLastPixel := @RGBA[z - 1];
  while (LPixel.A = 255) and (LPixel <> LLastPixel) do
    Inc(LPixel);
  Result := LPixel.A < 255;
end;

Meine CPU ist schon etwas älter, aber durchaus schnell genug für meine Zwecke:

AMD Athlon 64 X2 Dual Core Processor 5000+, 2600 MHz, 2 Kern(e), 2 logische(r) Prozessor(en)

Die hier gezeigte Variante ist mit ca. 23 MS in etwa so schnell wie meine Lösung (ebenfalls im Release-Mode)

Harry Stahl 24. Feb 2016 17:34

AW: Prüfung eines Bitmaps auf Transparenz (gehts noch schneller)?
 
Liste der Anhänge anzeigen (Anzahl: 1)
Zitat:

Zitat von Amateurprofi (Beitrag 1331162)
Hallo Harry:
Ich hab mir mal die Mühe gemacht, mehrere ASM-Routinen zu schreiben, die alle recht flink arbeiten, und zusätzlich ein kleines Testprogramm.

Wow, bin beeindruckt:thumb:

In der Anlage ein Screenshot mit den Testergebnissen. Meine AMD-CPU ist halt doch ein Ticken langsamer.

Was mich aber wundert, sind die z.T. erheblichen Schwankungen beim gleichen Test (SSE: 13 / 25 MS).

32- oder 64-Bit macht keinen nennenswerten Unterschied.

Valle 24. Feb 2016 18:00

AW: Prüfung eines Bitmaps auf Transparenz (gehts noch schneller)?
 
Eine andere Möglichkeit wäre es, mehrere Threads zur Bearbeitung bereits vorher zu starten und erst bei Bedarf zu aktivieren.

Das sollte den Overhead reduzieren und die Ausführungsgeschwindigkeit durch Parallelisierung dennoch erhöhen. Es wäre nur ein Minimum an Synchronisation nötig. Soweit ich das sehe, würde es reichen das Bild in n halbwegs gleichgroße Abschnitte zu unterteilen und dann auf die n Threads loszulassen. Der Hauptthread könnte darauf warten, bis alle Threads fertig sind.

Vermutlich wäre das noch schneller als die Single-Core Lösungen. Allerdings auch etwas aufwendiger zu implementieren.

Harry Stahl 24. Feb 2016 18:37

AW: Prüfung eines Bitmaps auf Transparenz (gehts noch schneller)?
 
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)

Amateurprofi 25. Feb 2016 02:48

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

Zitat von Harry Stahl (Beitrag 1331261)
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

Amateurprofi 25. Feb 2016 02:55

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

Zitat von Harry Stahl (Beitrag 1331256)
Zitat:

Zitat von Amateurprofi (Beitrag 1331162)
Hallo Harry:
Ich hab mir mal die Mühe gemacht, mehrere ASM-Routinen zu schreiben, die alle recht flink arbeiten, und zusätzlich ein kleines Testprogramm.

Wow, bin beeindruckt:thumb:

In der Anlage ein Screenshot mit den Testergebnissen. Meine AMD-CPU ist halt doch ein Ticken langsamer.

Was mich aber wundert, sind die z.T. erheblichen Schwankungen beim gleichen Test (SSE: 13 / 25 MS).

32- oder 64-Bit macht keinen nennenswerten Unterschied.

Hallo Harry,
zu "Was mich aber wundert, sind die z.T. erheblichen Schwankungen beim gleichen Test (SSE: 13 / 25 MS)."

Ich habe (bei allen Funktionen) ähnliche Schwankungen gesehen, allerdings nur, wenn ich das als "Release" compiliert hatte.
Bei "Debug" waren die Schwankungen eher im Normalbereich.

Memnarch 25. Feb 2016 08:26

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

Zitat von Harry Stahl (Beitrag 1331254)
Meine CPU ist schon etwas älter, aber durchaus schnell genug für meine Zwecke:

AMD Athlon 64 X2 Dual Core Processor 5000+, 2600 MHz, 2 Kern(e), 2 logische(r) Prozessor(en)

Die hier gezeigte Variante ist mit ca. 23 MS in etwa so schnell wie meine Lösung (ebenfalls im Release-Mode)

Ahh also etwas betagter und auch noch AMD^^".
(Release 2007 wenn ichs recht sehe?)

Uwe Raabe 25. Feb 2016 08:37

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

Zitat von Harry Stahl (Beitrag 1331254)
Meine CPU ist schon etwas älter, aber durchaus schnell genug für meine Zwecke:

Zitat:

Zitat von Harry Stahl (Beitrag 1330912)
...benötigt die Routine hier auf meinem Rechner ca. 80 MS um das ganze Bitmap zu prüfen, was ziemlich viel Zeit ist.

:wiejetzt:

Memnarch 25. Feb 2016 09:48

AW: Prüfung eines Bitmaps auf Transparenz (gehts noch schneller)?
 
Ach sach ma:
Wie misst du eigentlich die Zeit? Doch hoffentlich nicht mit Now() ;)

Nochmal genauer gemessen:
Meine alte Variante brauchte ~ 5.8ms
Nen bisschen was umgestellt und jetzt läuft sie bei mir zwischen 3.9 - 4.1ms
(Vielleicht ist nen off by one error drin nicht genau geprüft *hust*)
Delphi-Quellcode:

type
  TRGBA = packed record
    B, G, R, A: Byte;
  end;

  PRGBA = ^TRGBA;

  TRGBA4 = array[0..3] of TRGBA;
  PRGBA4 = ^TRGBA4;

  TScanLine = array[0..100000] of TRGBA;
  PScanLine = ^TScanLine;

function HasTransparentRGBAValues(const bm:TBitmap): Boolean;
var
  z: Integer;
  RGBA: PScanLine;
  LPixels, LLastPixels: PRGBA4;
  LPixel: PRGBA;
  i: Integer;
begin
  RGBA := bm.Scanline[bm.Height-1];
  z := bm.Width * bm.Height;
  LPixels := @RGBA[0];
  LLastPixels := @RGBA[z div 4 * 4];
  while (LPixels <> LLastPixels) and ((LPixels[0].A and LPixels[1].A and LPixels[2].A and LPixels[3].A) = 255) do
    Inc(LPixels);
  Result := ((LPixels[0].A and LPixels[1].A and LPixels[2].A and LPixels[3].A) <> 255);
  if not Result then
  begin
    Inc(LPixels);
    LPixel := PRGBA(LPixels);
    for i := 0 to z mod 4 - 1 do
    begin
      if LPixel.A < 255 then
        Exit(True);
      Inc(LPixel);
    end;
  end;
end;

Harry Stahl 25. Feb 2016 17:02

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

Zitat von Memnarch (Beitrag 1331300)

Ahh also etwas betagter und auch noch AMD^^".
(Release 2007 wenn ichs recht sehe?)

Ja, korrekt. Aber durch eine Giga-SSD und zügige NVIDIA-Karten eigentlich noch gut nutzbar.

Harry Stahl 25. Feb 2016 17:21

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

Zitat von Uwe Raabe (Beitrag 1331302)
Zitat:

Zitat von Harry Stahl (Beitrag 1331254)
Meine CPU ist schon etwas älter, aber durchaus schnell genug für meine Zwecke:

Zitat:

Zitat von Harry Stahl (Beitrag 1330912)
...benötigt die Routine hier auf meinem Rechner ca. 80 MS um das ganze Bitmap zu prüfen, was ziemlich viel Zeit ist.

:wiejetzt:

Also die erste Messung meiner Standard-Methode war im Debug-Modus mit AQTime, da habe ich wohl mal 80 MS gemessen. Das scheint aber relativ zu schwanken, jetzt kriege ich DEBUG-Modus immer um die 60 MS. Im Release-Modus um die 50 MS.

Im Unterschied dazu sind die Messungen mit der Demo-Anwendung, die ich geschrieben und hier ja mal hochgeladen hatte etwas anders.

Im Debug-Modus erhalte ich dort ca. 50 MS und im Release-Modus ca.23 MS.

Warum hier diese Abweichungen in der Messung zwischen AQTime und Queryperformancecounter sind, weiß ich leider auch nicht.

Harry Stahl 25. Feb 2016 17:24

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

Zitat von Memnarch (Beitrag 1331310)
Ach sach ma:
Wie misst du eigentlich die Zeit? Doch hoffentlich nicht mit Now() ;)

Nochmal genauer gemessen:

Messe mit

QueryPerformanceFrequency(iTimerFreq);
QueryPerformanceCounter(iTimerStart);

Das sollte doch OK sein, oder?

Sir Rufo 25. Feb 2016 17:40

AW: Prüfung eines Bitmaps auf Transparenz (gehts noch schneller)?
 
Gemütlicher geht das mit Delphi-Referenz durchsuchenTStopWatch :stupid:

Harry Stahl 25. Feb 2016 18:19

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

Zitat von Amateurprofi (Beitrag 1331273)
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.

Meine ASM-Kenntnisse sind leider sehr rudimentär. Scheint aber mit Deinen Änderungen jetzt zu funktionieren, jedenfalls fällt mir nichts ungewöhnliches mehr auf. Scheint wohl insgesamt die schnellste Variante zu sein. Unter AQTime kommt die so zwischen 35 und 45 MS (meine Demo-Version ca. 22 MS).

Insgesamt glaube ich aber inzwischen, dass man hier per ASM oder sonstige Prüf-Optimierungen wohl nicht mehr viel machen kann (wenn es denn DEN Super-ASM-Befehl nicht gibt).

Harry Stahl 25. Feb 2016 18:29

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

Zitat von Sir Rufo (Beitrag 1331380)
Gemütlicher geht das mit Delphi-Referenz durchsuchenTStopWatch :stupid:

Klar, das kannte ich auch schon, denn wenn man unter FMX was messen will (insbesondere andere OS), dann ist es da die angesagte Funktion.

Unter Windows benutzt TStopwatch aber auch QueryPerformanceCounter und hier hatte ich mir schon vor langer Zeit mal die benötigten MS-Funktionen in eigene Start- und Stop-Funktionen gekapselt.

Aber wer das noch nicht gemacht hat, kann hier Dank der neueren Delphi-Versionen direkt bequem per Einbindung der Systems.Diagnostics drauf zugreifen.

Amateurprofi 25. Feb 2016 19:15

AW: Prüfung eines Bitmaps auf Transparenz (gehts noch schneller)?
 
Zu #54 von Memnarch:
Ich hätte da noch eine super superschnelle Funktion anzubieten, sehr kurz, unkompliziert und übersichtlich:

Delphi-Quellcode:
function HasTransparentRGBAValues(const bm:TBitmap): Boolean;
begin
   Result:=True;
end;
@Memnarch:
Ist natürlich nicht ernst gemeint, deshalb bitte nicht böse sein.
Aber genau das liefert Deine in #54 gepostete Funktion.
Ich habe mal versucht, zu verstehen was Deine Funktion genau macht und habe eine kommentierte Version erstellt.
Hoffentlich hab ich mich da nicht vertan.
Delphi-Quellcode:
function HasTransparentRGBAValues(bmp:TBitmap): Boolean;
type
   TRGBA = packed record
     B, G, R, A: Byte;
   end;
   PRGBA = ^TRGBA;
   TRGBA4 = array[0..3] of TRGBA;
   PRGBA4 = ^TRGBA4;
   TScanLine = array[0..100000] of TRGBA;
   PScanLine = ^TScanLine;
var
   z: Integer;
   RGBA: PScanLine;
   LPixels, LLastPixels: PRGBA4;
   LPixel: PRGBA;
   i: Integer;
begin
   RGBA := bmp.Scanline[bmp.Height-1]; // Zeigt auf erstes Pixel der Bitmap
   z := bmp.Width * bmp.Height; // Anzahl Pixel
   LPixels := @RGBA[0]; // Adresse des ersten Pixels
   LLastPixels := @RGBA[z div 4 * 4]; // Zeigt hinter das letzte durch 4 teilbare Pixel
   while (LPixels <> LLastPixels) and ((LPixels[0].A and LPixels[1].A and LPixels[2].A and LPixels[3].A) = 255) do
     Inc(LPixels);
   // LPixels zeigt jetzt
   //  1) entweder auf das erste von 4 Pixeln, von denen mindestens eins transparent ist.
   //  2) oder, wenn Z nicht durch 4 teilbar ist, hinter das letzte durch 4 teilbare Pixel.
   //  3) oder, wenn Z durch 4 teilbar ist, hinter das letzte Pixel der Bitmap.
   Result := ((LPixels[0].A and LPixels[1].A and LPixels[2].A and LPixels[3].A) <> 255);
   // Die obige Ermittlung des Resultats ist für die Fälle 2 und 3 fehlerhaft
   // weil hier auf Speicherbereiche zugegriffen wird, die nicht mehr zur
   // Bitmap gehören.
   // Im Fall (2), weil ab LPixels maximal 3 Pixel folgen
   // Im Fall (3), weil LPixels bereits außerhalb der Bitmap liegt
   // Wenn in diesem Bereich mit undefiniertem Inhalt NICHT zufällig das 4te und
   // 8te und 12te und 16te Byte = 255 sind (was in der Regel nicht vorkommt),
   // wird als ergebnis TRUE geliefert.
   if not Result then
   begin
     Inc(LPixels);
     LPixel := PRGBA(LPixels);
     for i := 0 to z mod 4 - 1 do
     begin
       if LPixel.A < 255 then
         Exit(True);
       Inc(LPixel);
     end;
   end;
end;

Memnarch 25. Feb 2016 23:52

AW: Prüfung eines Bitmaps auf Transparenz (gehts noch schneller)?
 
Bin nicht böse, hatte ja erwähnt ich könnte nen off by one haben ;)

Amateurprofi 26. Feb 2016 14:54

AW: Prüfung eines Bitmaps auf Transparenz (gehts noch schneller)?
 
Liste der Anhänge anzeigen (Anzahl: 5)
Ich habe einmal die hier geposteten Funktionen in mein Testprogramm kopiert und alle Funktionen mit gleichen Parametern (4244x2819 Pixel, alle Pixel intransparent) laufen lassen.
Die Ergebnisse seht ihr in anhängenden Screenshots.
Das Testprogramm selbst habe ich noch ein wenig aufgehübscht und ebenfalls incl. SourceCodes angehängt.
Die in der .zip enthaltene Exe ist die 32Bit-Release Version.

@Harry:
Für Dich sollte die "IsPartlyTransParentEx" interessant sein, sowohl als 32Bit wie auch als 64Bit-Version.

Interessant ist vielleicht auch die Möglichkeit Screenshots zu machen und entweder als Bitmap ins Clipboard zu stellen oder als .bmp oder .jpg zu speichern.
Screenshots werden mit P, B oder J plus Shift, Ctrl, Alt erzeugt.
P stellt das Bild ins Clipboard, B speichert es als Bitmap und J speichert es als Jpeg.
Die Kombination der Shift, Ctrl, Alt Tasten bestimmt, was kopiert wird. Was die verschiedenen Tasten-Kombinationen machen, ist am Anfang der Main-Form beschrieben.

Harry Stahl 26. Feb 2016 22:42

AW: Prüfung eines Bitmaps auf Transparenz (gehts noch schneller)?
 
Liste der Anhänge anzeigen (Anzahl: 1)
Wenn Du so weiter machst, hast Du bald so eine Art Test-Suite im Angebot...:wink:

Die Ex und SSEex erscheinen recht schnell, jedoch weichen die Messungen relativ stark voneinander ab, wenn ich einfach ein paar mal hintereinander die gleiche Funktion aufrufe (siehe anliegenden Screenshot).

Woran könnte denn so etwas liegen?

Amateurprofi 27. Feb 2016 03:00

AW: Prüfung eines Bitmaps auf Transparenz (gehts noch schneller)?
 
Liste der Anhänge anzeigen (Anzahl: 1)
Zitat:

Zitat von Harry Stahl (Beitrag 1331516)
Wenn Du so weiter machst, hast Du bald so eine Art Test-Suite im Angebot...:wink:

Die Ex und SSEex erscheinen recht schnell, jedoch weichen die Messungen relativ stark voneinander ab, wenn ich einfach ein paar mal hintereinander die gleiche Funktion aufrufe (siehe anliegenden Screenshot).

Woran könnte denn so etwas liegen?

@Harry:
nee, ich werde garantiert nichts im Angebot haben.
Ich mach das alles nur aus Jux und Dallerei, aus Spaß an der Sache eben.

Das mit den Abweichungen ist bei mir nicht anders, allerdings nur bei der Release-Version.
Bei der Debug-Version sind die Abweichungen (bei mir) eher vernachlässigbar.

Eigentlich sollte man ja vermuten, dass es genau anders herum wäre.
Vielleicht liegt des Rätsels Lösung ja darin, dass bei EMBA die als Release kompilierte Version die Debug-Version ist und vice versa.
Aber ich möchte mich nicht einreihen, in die Gruppe, die an EMBA kein gutes Haar läßt.
Mein Rechner läuft im 7/24 Modus und mein Delphi auch.
Der letzte Neustart ist bestimmt schon 2 Monate her und Delphi Abstürze habe ich äußerst selten erlebt.
Ich bin damit sehr zufrieden.

Ich habe das Testprogramm gleich noch etwas erweitert, so dass man die Funktionen automatisch mehrfach ausführen kann und eine Option hinzugefügt, die bei mehrfach, mit gleichen Parametern, ausgeführten Funktionen die Min-, Max- und Avg-Werte ermittelt und dann nur noch diese anzeigt.
Der Testlauf kann mit der Escape Taste abgebrochen werden.

Harry Stahl 27. Feb 2016 10:20

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

Zitat von Amateurprofi (Beitrag 1331520)
Ich mach das alles nur aus Jux und Dallerei, aus Spaß an der Sache eben.

Kann ich verstehen, betriebswirtschaftlich ist das für mich auch wenig sinnvoll, aber ist eben interessant.

Mir ist bei Deinem Testprogramm noch aufgefallen, dass bei SSEex die falsche Prozedur aufgerufen wird:

Delphi-Quellcode:
{------------------------------------------------------------------------------}
{ IsPartlyTransparentSSEex                                                    }
{------------------------------------------------------------------------------}
FUNCTION IsPartlyTransParentSSEex(Bmp:TBitMap):Boolean;
var P1,P2:Pointer;
begin
   with Bmp do begin
      if PixelFormat<>pf32bit then raise Exception.Create('Keine 32 Bit Bitmap');
      P1:=ScanLine[0];
      if Height>1 then P2:=ScanLine[1] else P2:=P1;
      Result:=IsPartlyTransparentAsm(P1,P2,Width,Height);
   end;
end;
Die SSEex ist hier übrigens bei mir die schnellste Variante, im Vergleich zu meiner Standard-Variante mit ca. 23 MS braucht die SSEex ziemlich zuverlässig nur ca. 17 MS, das ist schon eine erhebliche Steigerung.:thumb:

Ab wann kann man SSE nutzen, bzw. wie kann ich das prüfen, ob diese Funktionalität auf dem Rechner vorhanden ist?

Memnarch 28. Feb 2016 02:35

AW: Prüfung eines Bitmaps auf Transparenz (gehts noch schneller)?
 
Die schwankungen zwischen Debug/Release kann ich mir nur so erklären:

Die Bitmap braucht im speicher mehr als 30MB. Der debugcode läuft (zumindest bei mir) langsamer. Fluktuationen beim fetchen der Daten und inteferenzen durch andere Prozesse die gerade arbeiten verlaufen auf dem längeren Zeitraum. Release ist aber (bei meiner Variante) dann deutlich schneller. Wenn es dann beim durchlaufen des speichers verzögerungen gibt sieht man das eher.

Amateurprofi 28. Feb 2016 02:55

AW: Prüfung eines Bitmaps auf Transparenz (gehts noch schneller)?
 
Liste der Anhänge anzeigen (Anzahl: 1)
Zitat:

Zitat von Harry Stahl (Beitrag 1331532)
Zitat:

Zitat von Amateurprofi (Beitrag 1331520)
Ich mach das alles nur aus Jux und Dallerei, aus Spaß an der Sache eben.

Kann ich verstehen, betriebswirtschaftlich ist das für mich auch wenig sinnvoll, aber ist eben interessant.

Mir ist bei Deinem Testprogramm noch aufgefallen, dass bei SSEex die falsche Prozedur aufgerufen wird:

Delphi-Quellcode:
{------------------------------------------------------------------------------}
{ IsPartlyTransparentSSEex                                                    }
{------------------------------------------------------------------------------}
FUNCTION IsPartlyTransParentSSEex(Bmp:TBitMap):Boolean;
var P1,P2:Pointer;
begin
   with Bmp do begin
      if PixelFormat<>pf32bit then raise Exception.Create('Keine 32 Bit Bitmap');
      P1:=ScanLine[0];
      if Height>1 then P2:=ScanLine[1] else P2:=P1;
      Result:=IsPartlyTransparentAsm(P1,P2,Width,Height);
   end;
end;
Die SSEex ist hier übrigens bei mir die schnellste Variante, im Vergleich zu meiner Standard-Variante mit ca. 23 MS braucht die SSEex ziemlich zuverlässig nur ca. 17 MS, das ist schon eine erhebliche Steigerung.:thumb:

Ab wann kann man SSE nutzen, bzw. wie kann ich das prüfen, ob diese Funktionalität auf dem Rechner vorhanden ist?

Hallo Harry,
oh wie peinlich, das mit dem Aufruf von IsPartlyTransparentAsm statt IsPartlyTransparentAsmSSEex, andererseits schön, dass da jemand ist, der meine Machwerke anschaut.

Ja, was "kann" die CPU?
Ich hab heute Nacht meine zweite Doktorarbeit geschrieben - über CPUID!
Also:
Diese Infos kriegst du über den Asm-Befehl CPUID.
Aber zunächst mal musst du prüfen, ob der überhaupt unterstützt wird.
Mit PUSHFD und POP EAX bzw. bei 64Bit mit PUSHFQ und POP RAX kopierst du das EFLAGS Register nach EAX bzw. RAX.
Wenn dann in EAX Bit 21 = 1 ist wird CPUID unterstützt.
Interessanterweise ist bei mir im 64 Bit Mode Bit 21 = 0, aber CPUID wird trotzdem unterstützt.
Das folgende gilt sowohl für 32 wie auch 64 Bit.
Mit
MOV EAX,1
CPUID
werden diverse Infos in EAX,EBX,ECX und EDX gestellt.
EDX Bit 0 : Auf dem Chip ist eine FPU
EDX Bit 23 : MMX wird unterstützt
EDX Bit 25 : SSE wird unterstützt
EDX Bit 26 : SSE2 wird unterstützt
ECX Bit 0 : SSE3 wird unterstützt
EBX Bits 16..23 : Anzahl logische CPUs
Das ganze ist etwa tricky, weil EBX bzw. RBX nicht verändert werden darf, musst also EBX/RBX vorher pushen und vor verlassen der Funktion wieder popen (nicht zu verwechseln mit "poppen").
Ich hab mein Programm aktualisiert.
In der Caption steht jetzt auch, was unterstützt wird und wieviel logische CPUs vorhanden sind.
Letzteres hole ich aber nicht über CPUId sondern über GetSystemInfo.

Bei Interesse kannst Du Dir bei Intel oder auch bei AMD die Manuals runterladen.
Bei Intel : "Intel 64 and IA-32 Architectures Software Developer's Manual Volume 2A und 2B"

Dann war da ja noch das Problem mit den recht großen Abweichungen.
Dass liegt daran dass das Programm auf mehreren CPUs läuft und jede CPU ihren eigenen Time Stamp Counter hat.
Ich wollte ja bisher nie so recht glauben, dass sich das auswirkt.
Aber nachdem ich den Hauptthread auf eine CPU festgelegt hatte, war das Problem mit den Abweichungen verschwunden.
Schau die die Prozedur TMain.btTestClick an, da siehst du wie das funktioniert.

Amateurprofi 28. Feb 2016 03:04

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

Zitat von Memnarch (Beitrag 1331584)
Die schwankungen zwischen Debug/Release kann ich mir nur so erklären:

Die Bitmap braucht im speicher mehr als 30MB. Der debugcode läuft (zumindest bei mir) langsamer. Fluktuationen beim fetchen der Daten und inteferenzen durch andere Prozesse die gerade arbeiten verlaufen auf dem längeren Zeitraum. Release ist aber (bei meiner Variante) dann deutlich schneller. Wenn es dann beim durchlaufen des speichers verzögerungen gibt sieht man das eher.

Nee, wie in meinem vorigen Beitrag beschrieben liegt das wohl eher daran dass das Programm auf mehreren CPUs läuft und jede der CPUs einen eigenen TSC hat. Harry verwendet ja QPF, ich sowohl QPF wie auch TSC.
Nach Fixieren des Hauptthreads auf eine CPU ist das Problem beseitigt, na ich bin mal vorsichtig, also : scheint das Problem beseitigt zu sein.


Alle Zeitangaben in WEZ +1. Es ist jetzt 18:33 Uhr.
Seite 2 von 2     12   

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