Delphi-PRAXiS
Seite 8 von 8   « Erste     678   

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)

manfred42 30. Nov 2014 17:47

AW: Geht das noch schneller? - Bitmap-Verrechnung
 
Nach flüchtigem Verfolgen der Diskussion meine ich:
Es geht hier, wie schon anklang, um Alphablending.
Da gab es doch 2005 das Thema
Alphablending mit MMX / SSE Befehle

Aber zur jetzigen Diskussion
Wenn man anstatt 255 durch 256 per Shift dividiert,
dann geht das nur bei nichnegativem Nenner.

Für den Datentyp Int32 kann man den Trick mit der
magischen Zahl $8081 zur Division durch 255 verwenden.

const
Magic: UInt16 = $8081;
var
n: Integer;

Dann ist für -Sqr(255) <= n<=Sqr(255)
( n * Magic) div (1 shl 23) = n div 255
Der Compiler erzeugt für den ersten Ausdruck
einen arithmetische Rechtsshift um 23.
Müsste mal mit RDTSC timen.

Manfred

arnof 30. Nov 2014 19:34

AW: Geht das noch schneller? - Bitmap-Verrechnung
 
nur mit einem Auge das hier verfolgt, aber ist folgender Blog nicht genau das Thema:

http://www.delphifeeds.com/go/f/1217...hiFeeds.com%29


Die haben hier ein VCL Beispiel und hinweise für die Firemonkey Umsetzung

Harry Stahl 30. Nov 2014 22:05

AW: Geht das noch schneller? - Bitmap-Verrechnung
 
Zitat:

Zitat von arnof (Beitrag 1281724)
nur mit einem Auge das hier verfolgt, aber ist folgender Blog nicht genau das Thema:

http://www.delphifeeds.com/go/f/1217...hiFeeds.com%29


Die haben hier ein VCL Beispiel und hinweise für die Firemonkey Umsetzung

Nun ja, TParallel hatten wir hier ja auch schon. Der Link zeigt zwar die Parallel-For-Verwendung aber mit canvas.pixel, das ist ja so ziemlich das Langsamste, was man machen kann.

Dejan Vu 1. Dez 2014 07:00

AW: Geht das noch schneller? - Bitmap-Verrechnung
 
Man muss ja nicht gleich TParallel mit Canvas.Pixel verbinden. Vielleicht muss man auch manuell skalieren, d.h. durch Ausprobieren herausfinden, wo der break even zwischen Bildgröße und Anzahl der Threads ist.

manfred42 1. Dez 2014 20:45

AW: Geht das noch schneller? - Bitmap-Verrechnung
 
Ein Versuch in Vorbereitung einer MMX-Version
Delphi-Quellcode:
procedure Draw32BitToBitmapPreMMX(const BitOben: TBitmap; BitUnten: TBitmap);
const
  Magic: UInt16 = $8081;
var
  W, x, y:     Integer;
  Stride, ORes: Integer;
  RowO,     RowU,
  RGBA_Oben, RGBA_Unten: ^TRGBQuad;
begin
  RowU := BitUnten.ScanLine[0];
  RowO := BitOben.ScanLine[0];

  W := BitUnten.Width;
  Stride := 4 * W;

  for y := 0 to BitUnten.Height - 1 do
  begin
    RGBA_Unten := RowU;
    RGBA_Oben := RowO;
    for x := 0 to W - 1 do
    begin
      ORes := RGBA_Oben^.rgbReserved;
      with RGBA_Unten^ do
      begin
        rgbBlue := (ORes * (RGBA_Oben^.rgbBlue - rgbBlue)) *
          Magic div (1 shl 23) + rgbBlue;
        rgbGreen := (ORes * (RGBA_Oben^.rgbGreen - rgbGreen)) *
          Magic div (1 shl 23) + rgbGreen;
        rgbRed := (ORes * (RGBA_Oben^.rgbRed - rgbRed)) *
          Magic div (1 shl 23) + rgbRed;
        rgbReserved := 255;
      end;
      Inc(RGBA_Unten);  Inc(RGBA_Oben);
    end;
    Dec(Cardinal(RowU), Stride);
    Dec(Cardinal(RowO), Stride);
  end;
end;

manfred42 1. Jan 2015 21:22

AW: Geht das noch schneller? - Bitmap-Verrechnung
 
Hier mein letztes Angebot
Delphi-Quellcode:
unit UAlphaSSE;
{
   SSE-Version von Harry Stahls

       procedure Draw32BitToBitmap(const BitOben: TBitmap; BitUnten: TBitmap);
}
interface

uses
  Winapi.Windows, Vcl.Graphics;

procedure Draw32BitToBitmapSSE(const BitOben: TBitmap; BitUnten: TBitmap);

implementation

procedure Draw32BitToBitmapSSE(const BitOben: TBitmap; BitUnten: TBitmap);
const
  //                                 bbggrr
  RGBFF: array[0..1] of UInt64 = ($FF000000, 0);
  // src bytes                   ......01......00   ......03......02
  UMsk: array[0..1] of UInt64 = ($8080800180808000, $8080800380808002);
  // res bytes                   .......... 8 4 0   ................
  PMsk: array[0..1] of UInt64 = ($8080808080080400, $8080808080808080);
  C255: array[0..3] of Single = (1/255, 1/255, 1/255, 0);
var
  BmpO, BmpU: PRGBQuad;
  N: Integer;
begin
  N   := BitOben.Height;
  BmpO := BitOben.ScanLine[N - 1];
  BmpU := BitUnten.ScanLine[N - 1];
  N   := N * BitOben.Width - 1;     // size of bitmap - 1
  asm
    PUSH    EBX
    MOV     EAX, BmpO
    MOV     EDX, BmpU
    MOV     ECX, N
//           XMM7  free
    LDDQU   XMM6, UMsk
    LDDQU   XMM5, PMsk
    LDDQU   XMM4, C255
    LDDQU   XMM3, RGBFF
{$IFOPT O+}
    DB      $66,$90          // 2-Byte-NOP
{$ELSE}
    DB      $66,$0F,$1F,$44,0,0 // 6-Byte-NOP
{$ENDIF}
@Loop:
    MOVD    XMM0, [EAX+4*ECX]// XMM0 = | 0 |&#945;|B|G|R
    PEXTRW  EBX, XMM0, 1     // EBX = &#945; | B
    SHR     EBX, 8           // EBX = 0 | &#945;
    JZ      @LoopEnd        // test &#945; &#8801; RGBA_O.rgbReserved = 0 ?

    PSHUFB  XMM0, XMM6       // unpack to Int32
    CVTDQ2PS XMM0, XMM0       // convert RGB_O to single FP

//  SHUFPS  XMM1, XMM0, $FF // !!! useless result
    MOVAPD  XMM1, XMM0       // copy RGB_O  (necessary !)
    SHUFPS  XMM1, XMM1, $FF // XMM1 = &#945; |  &#945;   |  &#945;   |  &#945;
    MULPS   XMM1, XMM4       // XMM1 = 0 | &#945;/255 | &#945;/255 | &#945;/255

    MOVD    XMM2,[EDX+4*ECX] // XMM2 = | 0 |&#945;|B|G|R
    PSHUFB  XMM2, XMM6       // unpack to Int32
    CVTDQ2PS XMM2, XMM2       // convert RGB_U to single FP

    SUBPS   XMM0, XMM2       // RGB_O - RGB_U
    MULPS   XMM0, XMM1       // &#945; * (RGB_O - RGB_U) / 255
    ADDPS   XMM0, XMM2       // &#945; * (RGB_O - RGB_U) / 255 + RGB_U

    CVTPS2DQ XMM0, XMM0       // convert FP to Int32 with rounding
    PSHUFB  XMM0, XMM5       // pack into TRGBQuad
    POR     XMM0, XMM3       // RGB_U.rgbReserved = $FF
    MOVD    [EDX+4*ECX],XMM0 // restore RGB_U
@LoopEnd:
    SUB     ECX, 1
    JNS     @Loop
    POP     EBX
  end;
end;
end.
QUOTE=Harry Stahl;1281742]
Zitat:

Zitat von arnof (Beitrag 1281724)
nur mit einem Auge das hier verfolgt, aber ist folgender Blog nicht genau das Thema:

http://www.delphifeeds.com/go/f/1217...hiFeeds.com%29
Die haben hier ein VCL Beispiel und hinweise für die Firemonkey Umsetzung

Nun ja, TParallel hatten wir hier ja auch schon. Der Link zeigt zwar die Parallel-For-Verwendung aber mit canvas.pixel, das ist ja so ziemlich das Langsamste, was man machen kann.[/QUOTE]

Mit anonymen Threads habe ich hier nichts machen können. Sie laufen schön langsam
nacheinander auf dem selben Prozessorkern. Könnte vor Wut das CPU-Gatget pulversisieren

Manfred

Ursa 5. Jan 2015 06:46

AW: Geht das noch schneller? - Bitmap-Verrechnung
 
Da kann man "gleichzeitig", in einem Thread.




samsung galaxy A3 schutzhülle

Dejan Vu 5. Jan 2015 06:56

AW: Geht das noch schneller? - Bitmap-Verrechnung
 
Bitte antworte in vollständigen Sätzen, also: Subjekt, Prädikat, Objekt. Es ist ein wenig dadaistisch, was Du da von Dir gibst und von einfachen Menschen wie mir so nicht zu verstehen.

Thomasl 5. Jan 2015 21:30

AW: Geht das noch schneller? - Bitmap-Verrechnung
 
Soll das nur übereinander Angezeigt werden?
Da hätte ich auch ein Beispiel mit GDI+
da rechnet das ja die GPU zusammen?

Thomasl 5. Jan 2015 23:26

AW: Geht das noch schneller? - Bitmap-Verrechnung
 
Liste der Anhänge anzeigen (Anzahl: 1)
Hier ein Beispiel mit GDI+
Die ganze Unit ist im Anhang incl. drehen und interpolation
einfach in ein Package einbinden und ausprobieren
Die GDI+ Units sind im XE4 bei mir schon enthalten

Einen Geschwindigkeitsvergleich habe ich noch nicht gemacht

Mit Transparenten PNG´s klappt das wohl, aber 32Bit BMP´s nicht

Kann ich noch Optimieren zb. Ram sparen, wenn ich den Stream Plattmache funktionieren JPG´s nicht mehr

Delphi-Quellcode:
uses GDIPOBJ, GDIPAPI;
...
  TTestImage = class(TGraphicControl)
  private
    { Private declarations }
    fImageA1: TGPImage;
    fImageB1: TPicture;
    fStream1: TMemoryStream;
    fImageA2: TGPImage;
    fImageB2: TPicture;
    fStream2: TMemoryStream;
...

procedure TTestImage.Paint;
var
  Graphics: TGPGraphics;
begin
  Graphics := TGPGraphics.Create(Canvas.Handle);
  try
    Graphics.DrawImage(fImageA1, 0, 0, Width, Height);
    Graphics.DrawImage(fImageA2, 0, 0, Width, Height);
  finally
    Graphics.Free;
  end;
end;


Alle Zeitangaben in WEZ +1. Es ist jetzt 12:55 Uhr.
Seite 8 von 8   « Erste     678   

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