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)?

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 4 von 7   « Erste     234 56     Letzte » 
Benutzerbild von Harry Stahl
Harry Stahl

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

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

  Alt 22. Feb 2016, 18:58
Hast du an andere Wege der Optimierung gedacht, wird die Information für jede Bildebene irgendwo gespeichert?
Ja, für jede Ebene gibt es ein Ebenen-Objekt, wo verschiedene Informationen zu den Bildern der Ebene gespeichert werden.

Aber bei einem 32-Bitmap-Bild sich einmal zu merken, ob es (Teil-)transparente Pixel hat, bringt wahrscheinlich nicht soviel, denn man müsste bei jeder Änderung, die potentiell Transparenz erzeugen kann (Löschen, Einfügen, Filter, Verläufe, Malen mit unterschiedlicher Deckkraft, usw.) wieder jedes mal prüfen, ob das Bild weiterhin ohne Transparenz ist. Das ist aufwändig und bei der Kombination der unterschiedlichen Ebenen müsste auch wieder geprüft werden, ob irgendwo eine Transparenz eines Ebenenbildes eine Transparenz auch für das Ergebnisbild erzeugt.

Da rechne ich das lieber gleich einmal durch, wenn ich das Ebenenbild verwende.

Die ganze Berechnung und Verrechnung der Ebenen, auch in räumlicher Anordnung, Transparenzen, Filter und Masken und Einstellungsebenen etc. ist eh schon sehr komplex und stößt bei mir allmählich an die Grenze der logischen Verarbeitungsfähgikeit. Da bin ich eigentlich ganz froh über jede simple und schnelle Lösung, die mir hilft ohne eine weitere Erhöhung der Komplexität auszukommen.
  Mit Zitat antworten Zitat
Amateurprofi

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

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

  Alt 23. Feb 2016, 00:18
@Harry:
Versuche mal das:

Code:
FUNCTION IsPartlyTransparentAsm(P0,P1:Pointer; W,H:NativeInt):Boolean;
asm
               sub     edx,eax
               js      @BottomUp
               imul    edx,H
               add     eax,edx
@BottomUp:    lea     eax,[eax+ecx*4+3]
               imul    ecx,H
               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;
Delphi-Quellcode:
FUNCTION IsPartlyTransparent(Bmp:TBitMap):Boolean;
begin
   with Bmp do
      Result:=IsPartlyTransparentAsm(ScanLine[0],ScanLine[1],Width,Height);
end;
Gruß, Klaus
Die Titanic wurde von Profis gebaut,
die Arche Noah von einem Amateur.
... Und dieser Beitrag vom Amateurprofi....
  Mit Zitat antworten Zitat
Medium

Registriert seit: 23. Jan 2008
3.679 Beiträge
 
Delphi 2007 Enterprise
 
#33

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

  Alt 23. Feb 2016, 00:52
Ich bin gerade etwas verwirrt bzgl. des konkreten Anwendungsfalls. Wenn doch im eigenen Programm ganz klar definiert ist welche Operationen das Zufügen von Transparenz bewirken können, ist es doch ein vergleichsweise simples Unterfangen eine entsprechende OnChange-Methode zu implementieren, die ein simples Flag setzt, dass man dann beim Zeichnen bloß immer wieder nur auswerten muss. Dabei sollten dann selbst die ursprünglichen 80ms kaum noch ins Gewicht fallen.

Wenn aber doch, dann wäre ggf. ein Blick auf die Zeichenroutinen am Ende viel zielführender als solch eine "quasi-early-out" Prüfung. Im Zweifel schaue man sich mal an, wie die GR32 dies bei ihrer Implementierung von Layers im TImage32 macht. Diese Lib ist da imho mit das schnellste was man ohne Parallelisierung bekommen kann (obwohl hier SIMD-Routinen in ASM eingesetzt werden). (Wenn ich mich recht erinnere benutzen die zudem u.a. ein per-Pixel-Skipping bei nicht- und volltransparenten Pixeln um das Verrechnen zu sparen.)
Es sollte auf halbwegs aktuellen PCs ein sprichwörtlicher Pups sein, zahlreiche Layer halbtransparent übereinander zu zeichnen. Eine Vorab-Prüfung kann meiner Einschätzung nach fast nur eine verschlechternde "Optimierung" werden, egal wie pfiffig man sie implementiert.
(Bei der GR32 spielt sicherlich auch eine sehr große Rolle, dass alle Rechnungen Integer-Basiert sind! Vielleicht lohnt sich am Ende sogar der Einsatz der ganzen Lib.)

Nur um das nochmals klar zu stellen: Wenn es rein um die Prüfung ginge, wären die hier gemachten Anstrengungen sicherlich sinnvoll. Für die Anwendung des Übereinanderzeichnens hingegen, meiner Einschätzung nach, nicht.
"When one person suffers from a delusion, it is called insanity. When a million people suffer from a delusion, it is called religion." (Richard Dawkins)
  Mit Zitat antworten Zitat
Rollo62

Registriert seit: 15. Mär 2007
3.896 Beiträge
 
Delphi 12 Athens
 
#34

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

  Alt 23. Feb 2016, 10:36
Mich würde generell interessieren ob man solche Abläufe nicht auch in der GPU machen kann.

Ich denke das ist genau der Gund warum GPU-unterstützte Software soviel schneller ist.
Habe aber 0-Erfahrung damit.

Als Vorraussetzung wäre dann vielleicht das die GPU direkt im Haupsspeicher (shared) arbeiten kann, weil sonst wieder kopiert werden müssten.

Kennt sich da jemand aus ?

Rollo
  Mit Zitat antworten Zitat
Benutzerbild von Neutral General
Neutral General

Registriert seit: 16. Jan 2004
Ort: Bendorf
5.219 Beiträge
 
Delphi 10.2 Tokyo Professional
 
#35

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

  Alt 23. Feb 2016, 12:52
So ich habe mich mal an SSE versucht.
Es scheint zu funktionieren (hab jetzt keine Bilder wo ichs richtig testen könnte), aber wie schnell/langsam das ist und ob der
Code wirklich fehlerfrei ist kann ich nicht sagen. Habe bisher noch nie was mit SSE gemacht.

Und das Bitmap sollte ein Vielfaches von 4 Pixeln groß sein, sonst knallts wahrscheinlich bzw. man müsste das abfangen.

Delphi-Quellcode:
function IsPartlyTransparent(fromScanline: Pointer; toScanline: Pointer): Boolean;
const pattern: Array[0..3] of Cardinal = ($FF000000, $FF000000, $FF000000, $FF000000);
label schleife, transparent, ende;
var IsTransparent: Array[0..15] of Byte; // "GigaBool" (128 Bit)
asm
  movups xmm2, pattern
schleife:
  movups xmm1, [eax]
  ANDPS xmm1, xmm2
  CMPEQPS xmm1, xmm2
  movntps IsTransparent, xmm1
  cmp dword ptr IsTransparent, 0
  jz transparent
  add eax, $10
  cmp eax, edx
  jb schleife
  mov Result, false
  jmp ende
transparent:
  mov Result, true
ende:
end;
Aufruf:

IsPartlyTransparent(bmp.ScanLine[bmp.Height-1],bmp.ScanLine[0]) Du kannst ja einfach mal schauen was dabei rum kommt.
Michael
"Programmers talk about software development on weekends, vacations, and over meals not because they lack imagination,
but because their imagination reveals worlds that others cannot see."
  Mit Zitat antworten Zitat
Benutzerbild von Harry Stahl
Harry Stahl

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

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

  Alt 23. Feb 2016, 18:17
Vielen Dank für die weiteren Bemühungen.

Deine vorletzte Variante ist nun ca. 1 MS schneller als meine.
Die letzte Variante stürzt immer ab.

Du kannst übrigens auch mit Delphi 2010 mein Demo, dass ich hier hochgeladen habe, verwenden, entfernst halt nur System.Threading und System.syncobjects und die Variante mit TParallel, dann hast Du eine 32-Bit-Bitmap und kannst diese per Schalter auch mit Transparenz versehen.
  Mit Zitat antworten Zitat
Benutzerbild von Harry Stahl
Harry Stahl

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

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

  Alt 23. Feb 2016, 18:28
Ich bin gerade etwas verwirrt bzgl. des konkreten Anwendungsfalls. Wenn doch im eigenen Programm ganz klar definiert ist welche Operationen das Zufügen von Transparenz bewirken können, ist es doch ein vergleichsweise simples Unterfangen eine entsprechende OnChange-Methode zu implementieren, die ein simples Flag setzt, dass man dann beim Zeichnen bloß immer wieder nur auswerten muss. Dabei sollten dann selbst die ursprünglichen 80ms kaum noch ins Gewicht fallen.
Es ist halt ein simples Flag, das an vielen Stellen gesetzt werden müsste und wenn ich jetzt nur eine Stelle übersehe, dann kann es schon falsch laufen. Außerdem könnten letztlich viele Funktionen aufeinanderwirken, so dass ich letztlich auch mehrmals prüfen müsste, ob eine Grafik einer Bildebene nun teiltransparent ist oder nicht und dann stellt sich die Frage, ob hier in der Summe von mehr oder weniger gleichzeitig stattfindenden Bildbearbeitungsfunktionen und Bildanzeige noch ein Geschwindigkeitsvorteil entsteht.

Aber danke, dass Du dies als mögliche Lösungsvariante ins Spiel gebracht hast. Generell ist das ja auch eine richtige Überlegung, Berechnungen zu vermeiden, wo sie nicht nötig sind. Aber irgendwann muss die Prüfung geschehen und wenn sie dann schneller geht, ist das halt willkommen.
  Mit Zitat antworten Zitat
Medium

Registriert seit: 23. Jan 2008
3.679 Beiträge
 
Delphi 2007 Enterprise
 
#38

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

  Alt 23. Feb 2016, 22:16
Hmm, ich glaube da ist dann dein interner Aufbau im Nachgang dafür etwas ungünstig ausgelegt. In meinem Kopf stellte sich die Struktur ganz grob so dar:
Delphi-Quellcode:
type
  TMyLayeredImage = class;

  TMyLayer = class
  public
    procedure Changed; // Führt Prüfung aus und setzt FHasTransparency und FChanged in der folgenden Image-Klasse (Es muss hierfür eine Owner-Beziehung geben, daher die Forward-Deklaration)
    property BMP: TBitmap read FBMP;
    property HasTransparency: Boolean read FHasTransparency;
    property Bounds: TRect read GetBounds write SetBounds; // SetBounds würde Changed im Owner auslösen, nicht aber eine Prüfung für den Layer selbst
  end;

  TMyLayeredImage = class
  private
    FImage: TBitmap; // Container für das fertige Bild
    FLayers: TObjectlist; // Beinhaltet die TMyLayer-Instanzen, Index 0 ist die unterste
    procedure Compose; // Fügt die Layer in FImage zusammen
  public
    property Image: TBitmap read GetImage; // In GetImage() dann "if FChanged then Compose; result := FImage;"
    // Und dann noch so nette Helfer (Komfortfunktionen halt) wie:
    property LayerAtPoint[x, y: Integer]: TMyLayer read GetLayerAtPoint; // Gibt den obersten Layer zurück, der den Punkt (x,y) beinhaltet, oder nil bei keinem
  end;
Wie gesagt ganz ganz grob. Jedes Layer würde einfach sein Transparenz-Bit mitführen, jede Operation auf dem Layer löst das Changed Ereignis aus, welches auch an den Owner (die zusammenfügende LayeredImage Klasse) gereicht wird. Beim Zeichnen wird dann einfach das fertige Image angefordert, und allen am Bild beteiligten ist klar ob überhaupt neu Komponiert werden muss, und welche Layer zu diesem Zeitpunkt Transparenzen haben.
Ob sich sowas jetzt noch überhaupt in deine Struktur hineinfiedel lässt kann ich natürlich nicht beurteilen. Aber das wäre in etwa mein erste Gedanke wenn ich an ein Layered-Image gehen würde. Die Prüf-Routine würde lediglich nur in genau den gerade geänderten Layern gebraucht.

Letztlich würde ich aber, wenn so etwas anstünde, direkt zur GR32 greifen und die einfach immer stumpf alles zeichnen lassen - weil das ist schnell genug, wenn man nicht gerade mehrere hundert Layer in 12 Megapixel hat. (Dafür gäbe es aber auch eigentlich schon keine performante Lösung mehr, egal wie. Speicher wird dann auch schnell rare Ware.)


@Rollo62:
Gehen würde das mit der GPU, und sogar sehr flott. Aber du hast ein Problem dabei bereits bemerkt: Es bringt kaum etwas, wenn man NUR diese Funktion in der GPU machen würde, da man stets alle Daten immer hin und her schaufeln müsste. (Ein Sharing gibt es nicht.) Zwar geht das meist schon irre schnell, gemessen an den Mengen, aber der Gewinn steht dem Mehraufwand fast nur dann in gutem Verhältnis gegenüber, wenn man praktisch alles über die GPU macht.
Mittlerweile ist das sogar viel viel einfacher als früher. Zu Zeiten von DirectX 9 und so musste man Pixel-Shader bemühen, und recht fummelig ein Quasi-3D Programm bauen um das von hinten durch die Brust zweckzuentfremden. Dank CUDA und OpenCL stehen hier mittlerweile aber Werkzeuge zur Verfügung, bei denen man sich um die Herkunft der GPU als reinen 3D- und Shader-Knecht nicht mehr scheren muss, und sie wie einen echten Vektorprozessor ansprechen kann. Leider weiss ich nicht wie es um Implementierungen der beiden großen APIs für Delphi steht. Und man muss sich an eine doch sehr andere Art der Programmierung gewöhnen, als man sie von Delphi im Alltag gewohnt ist.
"When one person suffers from a delusion, it is called insanity. When a million people suffer from a delusion, it is called religion." (Richard Dawkins)
  Mit Zitat antworten Zitat
Amateurprofi

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

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

  Alt 23. Feb 2016, 23:42
So ich habe mich mal an SSE versucht.
Es scheint zu funktionieren (hab jetzt keine Bilder wo ichs richtig testen könnte), aber wie schnell/langsam das ist und ob der
Code wirklich fehlerfrei ist kann ich nicht sagen. Habe bisher noch nie was mit SSE gemacht.

Und das Bitmap sollte ein Vielfaches von 4 Pixeln groß sein, sonst knallts wahrscheinlich bzw. man müsste das abfangen.

Delphi-Quellcode:
function IsPartlyTransparent(fromScanline: Pointer; toScanline: Pointer): Boolean;
const pattern: Array[0..3] of Cardinal = ($FF000000, $FF000000, $FF000000, $FF000000);
label schleife, transparent, ende;
var IsTransparent: Array[0..15] of Byte; // "GigaBool" (128 Bit)
asm
  movups xmm2, pattern
schleife:
  movups xmm1, [eax]
  ANDPS xmm1, xmm2
  CMPEQPS xmm1, xmm2
  movntps IsTransparent, xmm1
  cmp dword ptr IsTransparent, 0
  jz transparent
  add eax, $10
  cmp eax, edx
  jb schleife
  mov Result, false
  jmp ende
transparent:
  mov Result, true
ende:
end;
Aufruf:

IsPartlyTransparent(bmp.ScanLine[bmp.Height-1],bmp.ScanLine[0]) Du kannst ja einfach mal schauen was dabei rum kommt.
Hallo Neutral General,

m.E. kann die Funktion nur sehr eingeschränkt funktionieren.

1) Überprüfter Bereich der Bitmap:
Als Parameter werden der Funktion die Adressen des jeweils ersten Pixels der ersten und letzten Zeile übergeben.
Du prüfst die Pixel ab Anfang der "ersten" Zeile bis zum Anfang der "letzten" Zeile.
Wenn also ein transparentes Pixel irgendwo in der letzten Zeile ist, wird das nicht erkannt.

2) Prüfung von jeweils 4 Pixeln auf Transparenz:
Du liest 4 Pixel=16 Bytes in XMM1 machst ein AND mit dem Pattern und vergleichst das Ergebnis mittels CMPEQPS mit dem Pattern.
Bei diesem Vergleich werden alle Bits der Singles, bei denen der Vergleich True ergibt, = 1 gesetzt, andernfalls = 0.
Dann schreibst Du XMM1 in das 16 Byte Array "IsTransparent" und prüfst das erste DWord dieses Array auf 0.
Das heißt du prüfst immer nur das erste von jeweils 4 Pixeln auf Transparenz, die übrigen 3 von 4 Pixeln bleiben ungeprüft.
Gruß, Klaus
Die Titanic wurde von Profis gebaut,
die Arche Noah von einem Amateur.
... Und dieser Beitrag vom Amateurprofi....
  Mit Zitat antworten Zitat
Amateurprofi

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

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

  Alt 23. Feb 2016, 23:45
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.

Zu den Asm-Routinen:
1) IsPartlyTransparentAsm
Als 32 Bit und als 64 Bit Version vorhanden.
Die Routine prüft ganz simpel Pixel für Pixel

2) IsPartlyTransparentAsmQW
Nur als 64 Bit Version vorhanden.
Die Routine nutzt die 64 Bit Register und prüft jeweils 2 Pixel auf einmal.

3) IsPartlyTransparentAsmSSE
Als 32 Bit und als 64 Bit Version vorhanden.
Die Routine nutzt sie 128 Bit Register und prüft jeweils 4 Pixel auf einmal.

Bei einer Bitmap in der von dir vorgeschlagenen Größe von 4244 x 2819 werden folgende Zeiten genannt:

8 ms IsPartlyTransparentAsm 32 Bit
4 ms IsPartlyTransparentAsmSSE 32 Bit
8 ms IsPartlyTransparentAsm 64 Bit
5 ms IsPartlyTransparentAsmQW 64 Bit
4 ms IsPartlyTransparentAsmSSE 64 Bit

Vielleicht schaust Du dir das mal an.
Ich habe die Routinen mit verschiedenen Parametern getestet und keine Fehler bemerkt.
Angehängte Dateien
Dateityp: zip Transparent.zip (744,9 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
Themen-Optionen Thema durchsuchen
Thema durchsuchen:

Erweiterte Suche
Ansicht

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 00:52 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