Delphi-PRAXiS
Seite 7 von 7   « Erste     567   

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)

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 09:22 Uhr.
Seite 7 von 7   « Erste     567   

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