AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Zurück Delphi-PRAXiS Programmierung allgemein Algorithmen, Datenstrukturen und Klassendesign Delphi Prüfung eines Bitmaps auf Transparenz (gehts noch schneller)?
Thema durchsuchen
Ansicht
Themen-Optionen

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

Ein Thema von Harry Stahl · begonnen am 21. Feb 2016 · letzter Beitrag vom 28. Feb 2016
Antwort Antwort
Seite 7 von 7   « Erste     567   
Amateurprofi
Online

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

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

  Alt 25. Feb 2016, 20:15
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;
Gruß, Klaus
Die Titanic wurde von Profis gebaut,
die Arche Noah von einem Amateur.
... Und dieser Beitrag vom Amateurprofi....
  Mit Zitat antworten Zitat
Benutzerbild von Memnarch
Memnarch

Registriert seit: 24. Sep 2010
737 Beiträge
 
#62

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

  Alt 26. Feb 2016, 00:52
Bin nicht böse, hatte ja erwähnt ich könnte nen off by one haben
Da man Trunc nicht auf einen Integer anwenden kann, muss dieser zuerst in eine Float kopiert werden
  Mit Zitat antworten Zitat
Amateurprofi
Online

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

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

  Alt 26. Feb 2016, 15:54
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.
Miniaturansicht angehängter Grafiken
debug32.jpg   debug64.jpg   release32.jpg   release64.jpg  
Angehängte Dateien
Dateityp: zip Transparent.zip (825,8 KB, 15x aufgerufen)
Gruß, Klaus
Die Titanic wurde von Profis gebaut,
die Arche Noah von einem Amateur.
... Und dieser Beitrag vom Amateurprofi....
  Mit Zitat antworten Zitat
Benutzerbild von Harry Stahl
Harry Stahl

Registriert seit: 2. Apr 2004
Ort: Bonn
2.537 Beiträge
 
Delphi 11 Alexandria
 
#64

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

  Alt 26. Feb 2016, 23:42
Wenn Du so weiter machst, hast Du bald so eine Art Test-Suite im Angebot...

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?
Miniaturansicht angehängter Grafiken
messungen.jpg  
  Mit Zitat antworten Zitat
Amateurprofi
Online

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

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

  Alt 27. Feb 2016, 04:00
Wenn Du so weiter machst, hast Du bald so eine Art Test-Suite im Angebot...

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.
Angehängte Dateien
Dateityp: zip Transparent.zip (828,7 KB, 14x aufgerufen)
Gruß, Klaus
Die Titanic wurde von Profis gebaut,
die Arche Noah von einem Amateur.
... Und dieser Beitrag vom Amateurprofi....
  Mit Zitat antworten Zitat
Benutzerbild von Harry Stahl
Harry Stahl

Registriert seit: 2. Apr 2004
Ort: Bonn
2.537 Beiträge
 
Delphi 11 Alexandria
 
#66

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

  Alt 27. Feb 2016, 11:20
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.

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

Registriert seit: 24. Sep 2010
737 Beiträge
 
#67

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

  Alt 28. Feb 2016, 03:35
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.
Da man Trunc nicht auf einen Integer anwenden kann, muss dieser zuerst in eine Float kopiert werden
  Mit Zitat antworten Zitat
Amateurprofi
Online

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

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

  Alt 28. Feb 2016, 03:55
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.

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.
Angehängte Dateien
Dateityp: zip Transparent.zip (830,0 KB, 25x aufgerufen)
Gruß, Klaus
Die Titanic wurde von Profis gebaut,
die Arche Noah von einem Amateur.
... Und dieser Beitrag vom Amateurprofi....
  Mit Zitat antworten Zitat
Amateurprofi
Online

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

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

  Alt 28. Feb 2016, 04:04
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.
Gruß, Klaus
Die Titanic wurde von Profis gebaut,
die Arche Noah von einem Amateur.
... Und dieser Beitrag vom Amateurprofi....
  Mit Zitat antworten Zitat
Antwort Antwort
Seite 7 von 7   « Erste     567   


Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 09:40 Uhr.
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