AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Thema durchsuchen
Ansicht
Themen-Optionen

Geht das noch schneller? - Bitmap-Verrechnung

Ein Thema von Harry Stahl · begonnen am 22. Nov 2014 · letzter Beitrag vom 5. Jan 2015
Antwort Antwort
Seite 1 von 2  1 2      
mensch72

Registriert seit: 6. Feb 2008
838 Beiträge
 
#1

AW: Geht das noch schneller? - Bitmap-Verrechnung

  Alt 22. Nov 2014, 10:51
man nehme einfach "MULDIV" für solche Berechnungen in Integer ohne Genauigkeitsverlust.

aus: i := Round (RGBA_Unten^[w].rgbBlue - ((RGBA_Unten^[w].rgbBlue - RGBA_Oben^[w].rgbBlue) / 255 * RGBA_Oben^[w].rgbReserved));
wird dann: i := RGBA_Unten^[w].rgbBlue - MulDiv(RGBA_Unten^[w].rgbBlue - RGBA_Oben^[w].rgbBlue, RGBA_Oben^[w].rgbReserved, 255);

Mit Zusatzvariable und nur einer Dereferenzierung am Schleifenanfang, also "col:=RGBA_Unten^[w]" und dann nur mit "col.rgbXXX" rechnen wird es nochmal schneller.
Die hier oft verwendete "255" finde ich nicht ganz so dolle, denn 0..255 sind 256 Werte, also setze man doch lieber alle "0..255" Werte mit 256 ins Verhältnis, dann gibt es auch keine Resultate > 255...

Ansonsten rechne ich das lieber komplett auf Speicherarrays und verwende simple Indexzugriffe auf vor berechnete Wertetabellen(statt ständiges "MulDiv" von zwei "8Bit" Werten) sowie das Ganze möglichst als vorzeichenlose Ganzzahlarithmetik, das ist noch schneller und damit sind dann auch so Sachen wie SSEx für weiter Filteroperationen und andere Spielereien möglich. Das führt aber hier zuweit. Einen Blick in die SourceCodes von optimierten Grafiklibs würde ich da empfehlen.
  Mit Zitat antworten Zitat
Benutzerbild von himitsu
himitsu
Online

Registriert seit: 11. Okt 2003
Ort: Elbflorenz
44.557 Beiträge
 
Delphi 12 Athens
 
#2

AW: Geht das noch schneller? - Bitmap-Verrechnung

  Alt 22. Nov 2014, 11:19
Ob es dafür bereits fertige Bibliotheken gibt, weiß ich nicht, aber am Ende kommt es auf Assembler hinaus, da Pascal das natürlich nicht direkt unterstützt (ob du das nunb schreibst, oder jemand anderes)

Ich war mal vor Jahren auf die Idee gekommen, die Operationen in einem Record zu kapseln (Record Operatoren und Methoden), aber da ich selber keinen Anwendungsfall und nicht wirklich Zeit hatte .......

Bezüglich des MulDiv:
Jupp, solange du bei Integer-Operationen bleibst, sollte es etwas schneller gehen.
Bezüglich dem (Auf)Runden kann man einfach bissl was Aufaddieren, vor dem Dividieren.
Ein Therapeut entspricht 1024 Gigapeut.

Geändert von himitsu (22. Nov 2014 um 11:23 Uhr)
  Mit Zitat antworten Zitat
Benutzerbild von Harry Stahl
Harry Stahl

Registriert seit: 2. Apr 2004
Ort: Bonn
2.561 Beiträge
 
Delphi 12 Athens
 
#3

AW: Geht das noch schneller? - Bitmap-Verrechnung

  Alt 22. Nov 2014, 11:24
Also, nur statt "/" ein div zu nehmen und das round wegzulassen (also nur mit Integer zu rechnen), benötigt ca. 30% mehr Zeit.

Mit MultiDiv zu arbeiten, dauert gar direkt 100% länger.

Aber die anderen beschriebenen Ansätze werde ich auch mal versuchen.
  Mit Zitat antworten Zitat
Benutzerbild von Harry Stahl
Harry Stahl

Registriert seit: 2. Apr 2004
Ort: Bonn
2.561 Beiträge
 
Delphi 12 Athens
 
#4

AW: Geht das noch schneller? - Bitmap-Verrechnung

  Alt 22. Nov 2014, 11:34
Selbst dieser Versuch, einen lokalen TRGBQuad zu verwenden (cu- und co-Variablen), führt bei 5 Durchläufen, bei einem Bitmap von ca. 3500x2500 Pixel zu 300 MS mehr Zeit:

Delphi-Quellcode:
procedure Draw32BitToBitmapNew(const BitOben: TBitmap; BitUnten: TBitmap);
var
   h,w,i: Integer;
   RGBA_Unten, RGBA_Oben: pRGBALine;
   cu, co : TRGBQuad;
begin
   For h := 0 to BitUnten.Height-1 do begin
     RGBA_Unten := BitUnten.ScanLine[h];
     RGBA_Oben := BitOben.ScanLine[h];

     For w:= 0 to BitUnten.Width-1 do begin
       if RGBA_Oben^[w].rgbReserved = 0 then begin
         // unten bleibt
       end else begin
         cu := RGBA_Unten^[w];
         co := RGBA_Oben^[w];

         i := Round (cu.rgbBlue - ((cu.rgbBlue - co.rgbBlue) / 255 * co.rgbReserved));
         if i < 0 then RGBA_Unten^[w].rgbBlue := 0 else if i > 255 then RGBA_Unten^[w].rgbBlue := 255 else RGBA_Unten^[w].rgbBlue := i;

         i := Round (cu.rgbGreen - ((cu.rgbGreen - RGBA_Oben^[w].rgbGreen) / 255 * co.rgbReserved));
         if i < 0 then RGBA_Unten^[w].rgbGreen := 0 else if i > 255 then RGBA_Unten^[w].rgbGreen := 255 else RGBA_Unten^[w].rgbGreen := i;

         i := Round (cu.rgbRed - ((cu.rgbRed - co.rgbRed) / 255 * co.rgbReserved));
         if i < 0 then RGBA_Unten^[w].rgbRed := 0 else if i > 255 then RGBA_Unten^[w].rgbRed := 255 else RGBA_Unten^[w].rgbRed := i;

         RGBA_Unten^[w].rgbReserved := 255;
       end;
    end;
   end;
end;
  Mit Zitat antworten Zitat
Jens01

Registriert seit: 14. Apr 2009
674 Beiträge
 
#5

AW: Geht das noch schneller? - Bitmap-Verrechnung

  Alt 22. Nov 2014, 11:50
Schon mal bei/mit Graphics32 versucht?!
Achtung: Bin kein Informatiker sondern komme vom Bau.
  Mit Zitat antworten Zitat
Benutzerbild von himitsu
himitsu
Online

Registriert seit: 11. Okt 2003
Ort: Elbflorenz
44.557 Beiträge
 
Delphi 12 Athens
 
#6

AW: Geht das noch schneller? - Bitmap-Verrechnung

  Alt 22. Nov 2014, 12:00
länger:

Ist ein bissl erschreckend, aber liegt auch an deiner Speicherverwaltung. (zuviele ungünstig liegende Variablen)
Integer-Operationen werden in den CPU-Registern (EAX usw.) durchgeführt.
Die Fließkommaoperationen in den FPU-Registern, wobei EAX und Co. frei bleibt.

Das Selbe würde dann auch bei den Streaming-Registern auftreten.

Und warum eigentlich ständig RGBA_Unten^[w] und nicht Anfangs mal in eine Variable?
Ein Therapeut entspricht 1024 Gigapeut.
  Mit Zitat antworten Zitat
Benutzerbild von Harry Stahl
Harry Stahl

Registriert seit: 2. Apr 2004
Ort: Bonn
2.561 Beiträge
 
Delphi 12 Athens
 
#7

AW: Geht das noch schneller? - Bitmap-Verrechnung

  Alt 24. Nov 2014, 23:28
Schon mal bei/mit Graphics32 versucht?!
Nein, muss gestehen, kannte ich bislang nicht (habe mit GraphicEX, ansonsten teilweise mit ImageEn, aber meistens mit eigenen Lösungen gearbeitet).

Werde ich mir mal ansehen. Gibt es dort so eine spezielle Verrechnungsfunktion wie hier benötigt?
  Mit Zitat antworten Zitat
Medium

Registriert seit: 23. Jan 2008
3.689 Beiträge
 
Delphi 2007 Enterprise
 
#8

AW: Geht das noch schneller? - Bitmap-Verrechnung

  Alt 25. Nov 2014, 01:31
Alpha-Blending würde ich nun nicht wirklich als speziell bezeichnen, daher ja: Die Graphics32 bietet eine Fülle an Möglichkeiten diesbezüglich. Sogar direkten Support für Layers in Bitmaps (mit den respektiven Kombinationsfunktionen, u.a. standard Alpha-Blending). Vom Gefühl her würde ich fast sagen, dass diese Lib dein Heiland sein könnte.
"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
Benutzerbild von Harry Stahl
Harry Stahl

Registriert seit: 2. Apr 2004
Ort: Bonn
2.561 Beiträge
 
Delphi 12 Athens
 
#9

AW: Geht das noch schneller? - Bitmap-Verrechnung

  Alt 22. Nov 2014, 11:48
Die hier oft verwendete "255" finde ich nicht ganz so dolle, denn 0..255 sind 256 Werte, also setze man doch lieber alle "0..255" Werte mit 256 ins Verhältnis, dann gibt es auch keine Resultate > 255...
Was meinst Du hiermit genau?

Ich vermute mal, eine x in 0..255 Prüfung braucht mehr Zeit und ich weiß dann immer noch nicht, ob x evtl. kleiner als 0 (dann schwarz) oder größer 255 ist (dann weiß).
  Mit Zitat antworten Zitat
mensch72

Registriert seit: 6. Feb 2008
838 Beiträge
 
#10

AW: Geht das noch schneller? - Bitmap-Verrechnung

  Alt 22. Nov 2014, 12:21
Ich verwende "/256" statt "/255".

MulDiv ist live wegen der internen multiplen 32Bit über Int64 Logik Langsamer als aktuelle FPU Nutzung, aber mit ging es ums erkennen des Prinzips!

wenn aus "Round (RGBA_Unten^[w].rgbBlue - ((RGBA_Unten^[w].rgbBlue - RGBA_Oben^[w].rgbBlue) / 255 * RGBA_Oben^[w].rgbReserved));"
besser "RGBA_Unten^[w].rgbBlue - ((RGBA_Unten^[w].rgbBlue - RGBA_Oben^[w].rgbBlue) * RGBA_Oben^[w].rgbReserved) div 255; //<div 256> oder besser <shr 8>;" wird...
also geht das auch in 32Bit(Integer) ohne Muldiv völlig ohne Genauigkeitsverlust, weil eben ohne Informationsverlust erst multipliziert und dann dividiert wird.

Nochmal im Detail:
- du hast zwei 8Bit (Farb)Werte, die können multipliziert max. einen 16Bit Wert ergeben(0.65535), welcher Locker in eine 32 Bit passt
- ein "SHR 8" ist minimal schneller wie ein "DIV 256"
- mit glatten 2er Potenzen zu rechnen schadet nie

Also:
Du hast 2 Farbwerte welche du multiplizierst und fix wieder durch 255teislt(oder 256 bzw. um 8 rechts schiebst)... das geht, ist aber per möglicher Tabelle 1 aus 65536(2^16) im Indexbereich von 0.65535 mit vor berechneten Einträgen am schnellsten:

RelColResult:=RelColTable[(ColValueA shl 8)+ColValueB];
("RelColTable" sein ein Array 0..65535 of BYTE)



(Ich rechne das irgendwie anders, deshalb erschließt sich mir der Sinn deine nachfolgenden Abfrage aus ">255" nicht, denn mir fällt kein Wertepaar der 2 Ausgangsfarben ein, wo das Ergebnis >255 sein kann... Nur weil Round auch "aufrundet" passiert dir das eventuell... Ich denke wenn du Round durch Floor ersetzt kannst du dir das "if" sparen und Kommafarbwerte gibt es bei 8Bit 0.255 eh nicht )
  Mit Zitat antworten Zitat
Antwort Antwort
Seite 1 von 2  1 2      


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 21:49 Uhr.
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz