Delphi-PRAXiS
Seite 1 von 8  1 23     Letzte »    

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Algorithmen, Datenstrukturen und Klassendesign (https://www.delphipraxis.net/78-algorithmen-datenstrukturen-und-klassendesign/)
-   -   Geht das noch schneller? - Bitmap-Verrechnung (https://www.delphipraxis.net/182859-geht-das-noch-schneller-bitmap-verrechnung.html)

Harry Stahl 22. Nov 2014 02:00

Geht das noch schneller? - Bitmap-Verrechnung
 
Mit dieser Funktion wird eine 32-Bitmap - unter Berücksichtigung der Transparenz auf einen Konstanten Untergrund (die Hintergrund-Bitmap) gemalt.

Mal abgesehen von Parallel-Berechnung mit TParallel (was ich schon erledigt habe, hier die einfache Version, um die Funktion leichter nachvollziehen zu können), kann man das noch irgendwie schneller berechnen?

Delphi-Quellcode:
// Setz vorraus, dass die Bitmaps die gleiche Größe haben!!!
procedure Draw32BitToBitmapold(const BitOben: TBitmap; BitUnten: TBitmap);
var
  h,w,i: Integer;
  RGBA_Unten, RGBA_Oben: pRGBALine;
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
        i := Round (RGBA_Unten^[w].rgbBlue - ((RGBA_Unten^[w].rgbBlue - RGBA_Oben^[w].rgbBlue) / 255 * RGBA_Oben^[w].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 (RGBA_Unten^[w].rgbGreen - ((RGBA_Unten^[w].rgbGreen - RGBA_Oben^[w].rgbGreen) / 255 *  RGBA_Oben^[w].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 (RGBA_Unten^[w].rgbRed - ((RGBA_Unten^[w].rgbRed - RGBA_Oben^[w].rgbRed) / 255 * RGBA_Oben^[w].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;

hstreicher 22. Nov 2014 08:21

AW: Geht das noch schneller? - Bitmap-Verrechnung
 
schneller wird es wenn man die Formeln umbau so dass mit Integer anstatt Floats gerechnet wird,

und die geschachtelten Abfragen so umstellen dass das wahrscheinlich häuftigste Ergebnis zuerst abgeprüft wird
um den 2. Vergleich zu vermeiden

Harry Stahl 22. Nov 2014 08:52

AW: Geht das noch schneller? - Bitmap-Verrechnung
 
Mhh, wenn ich integer verwende, wird es ungenau. Aber wäre vielleicht akeptabel, wenn es nur um Anzeige eines Ergebnisses geht ( im Unterschied zu einem konkret weiterverwendbaren Ergebnis).

Das wahrscheinlichste Ergebis ist, dass der Wert zwischen 0 und 255 liegt, aber das muss ich zuvor durch Überprüfung sicherstellen, komme da also nicht dran vorbei...

Bernhard Geyer 22. Nov 2014 09:10

AW: Geht das noch schneller? - Bitmap-Verrechnung
 
Hast du eigentlich schon mal mit AQTime geprüft?

Ich vermute wenn du für RGBA_Unten^[w] und Co. Lokale Variablen verwendest wird es auch schneller

himitsu 22. Nov 2014 09:38

AW: Geht das noch schneller? - Bitmap-Verrechnung
 
Parallele Berechnung mehrerer Bytes = Streaming-Funktionen ala 3DNow!, MMX, SSE, AVX, FMA :stupid:

Da kann man "gleichzeitig", in einem Thread, mit 128 Bit (z.B. 8 Byte) oder gar 256 Bit rechnen, also mit mindestens 2 Color-Dingern (a 4 Bytes) in einem Rutsch.

Harry Stahl 22. Nov 2014 10:37

AW: Geht das noch schneller? - Bitmap-Verrechnung
 
@ Berhard: Klar, AQTime (Prof) ist mein ständiger Begleiter.

Lokale Variablen zu verwenden, bringt im vorliegenden Fall leider nichts, weil die Zuweisung an die lokalen Variablen in der Summe länger braucht (ca. 30%), als der Zugriff auf den Speicher:

Delphi-Quellcode:
procedure Draw32BitToBitmapNew(const BitOben: TBitmap; BitUnten: TBitmap);
var
   h,w,i: Integer;
   rublue, rugreen, rured, rureserved,
   roblue, rogreen, rored, roreserved: Byte;
   RGBA_Unten, RGBA_Oben: pRGBALine;
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
         rublue := RGBA_Unten^[w].rgbBlue;
         rugreen := RGBA_Unten^[w].rgbGreen;
         rured := RGBA_Unten^[w].rgbred;
         rureserved := RGBA_Unten^[w].rgbreserved;

         roblue := RGBA_Oben^[w].rgbBlue;
         rogreen := RGBA_Oben^[w].rgbGreen;
         rored := RGBA_Oben^[w].rgbred;
         roreserved := RGBA_Oben^[w].rgbreserved;

         i := Round (ruBlue - ((ruBlue - roBlue) / 255 * roReserved));
         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 (ruGreen - ((ruGreen - roGreen) / 255 * roReserved));
         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 (ruRed - ((ruRed - roRed) / 255 * roReserved));
         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;

Harry Stahl 22. Nov 2014 10:38

AW: Geht das noch schneller? - Bitmap-Verrechnung
 
@himitsu:

MMX,SSE Streaming-Funktionen: Noch nie verwendet. Wie nutzt man das?
Muss ich Assembler verwenden? Gibt es Beispiele für Bitmap-Verwendung?

mensch72 22. Nov 2014 10:51

AW: Geht das noch schneller? - Bitmap-Verrechnung
 
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.

himitsu 22. Nov 2014 11:19

AW: Geht das noch schneller? - Bitmap-Verrechnung
 
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.

Harry Stahl 22. Nov 2014 11:24

AW: Geht das noch schneller? - Bitmap-Verrechnung
 
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.


Alle Zeitangaben in WEZ +1. Es ist jetzt 21:25 Uhr.
Seite 1 von 8  1 23     Letzte »    

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