AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Zurück Delphi-PRAXiS Programmierung allgemein Algorithmen, Datenstrukturen und Klassendesign 24-Bit Bitmap um 90 grad drehen - Resourcen-Optimierung

24-Bit Bitmap um 90 grad drehen - Resourcen-Optimierung

Ein Thema von Harry Stahl · begonnen am 18. Okt 2020 · letzter Beitrag vom 23. Okt 2020
Antwort Antwort
Seite 3 von 5     123 45   
Benutzerbild von Harry Stahl
Harry Stahl

Registriert seit: 2. Apr 2004
Ort: Bonn
1.972 Beiträge
 
Delphi 10.4 Sydney
 
#21

AW: 24-Bit Bitmap um 90 grad drehen - Resourcen-Optimierung

  Alt 19. Okt 2020, 02:43
@Harry:

Wenn du auf Performance aus bist, dann versuch doch mal folgendes.
Sollte deutlich schneller sein.

Achtung:
Der 64Bit-Teil in CopyColumn24 ist ungetestet, weil das Projekt mit dem ich gerade herumspiele nicht 64Bit-fähig ist.
Unter 32 Bit (mit relativ kleinen Bitmaps) ergibt meine Messung dass das doppelt so schnell läuft, wie die ursprüngliche Routine.

Delphi-Quellcode:
PROCEDURE CopyColumn24(PSource,PDest:Pointer; Count,LO:NativeInt);
asm
{$IFDEF CPUX86}// RAX=PSource, RDX=PDest, RCX=Count, Stack=LO
               push ebx
               mov ebp,LO
               dec ecx
@Loop: mov ebx,[eax]
               mov [edx],ebx
               add eax,ebp
               add edx,3
               sub ecx,1
               jnz @Loop
               mov bx,[eax]
               mov [edx],bx
               mov bl,[eax+2]
               mov [edx+2],bl
               pop ebx
{$ELSE}        // RCX=PSource, RDX=PDest, R8=Count, R9=LO
               dec r8
@Loop: mov eax,[rcx]
               mov [rdx],eax
               add rcx,r9
               add rdx,3
               sub r8,1
               jnz @Loop
               mov ax,[rcx]
               mov [rdx],ax
               mov al,[rcx+2]
               mov [rdx+2],al
{$ENDIF}
end;
Delphi-Quellcode:
PROCEDURE RotateRight24(Bmp:TBitmap);
var W,H,Y,LoSource,LoDest:NativeInt; PSource,PDest:PByte; Dest:TBitmap;
begin
   W:=Bmp.Height;
   H:=Bmp.Width;
   PSource:=Bmp.ScanLine[W-1];
   LoSource:=NativeInt(Bmp.ScanLine[W-2])-NativeInt(PSource);
   Dest:=TBitmap.Create;
   Dest.PixelFormat:=pf24bit;
   Dest.SetSize(W,H);
   PDest:=Dest.ScanLine[0];
   LoDest:=NativeInt(Dest.ScanLine[1])-NativeInt(PDest);
   for Y:=H-1 downto 0 do begin
      CopyColumn24(PSource,PDest,W,LoSource);
      Inc(PSource,3);
      Inc(PDest,LoDest);
   end;
   Bmp.Assign(Dest);
   Dest.free;
end;
Oh, habe ich gerade erst gesehen (manchmal überholen sich die Beiträge irgendwie), werde ich mir morgen Abend auf jeden Fall auch noch mal ansehen und mich melden.
  Mit Zitat antworten Zitat
Benutzerbild von Harry Stahl
Harry Stahl

Registriert seit: 2. Apr 2004
Ort: Bonn
1.972 Beiträge
 
Delphi 10.4 Sydney
 
#22

AW: 24-Bit Bitmap um 90 grad drehen - Resourcen-Optimierung

  Alt 19. Okt 2020, 02:55
Zu guter letzt noch die Feststellung, dass sich die WorkerThreads eigentlich nur bei ganz großen Dateien lohnen. Bei kleineren Bitmaps (alles so unter 4000 x 4000) ist der Thread-Verwaltungsaufwand wohl zu hoch, da ist das z.T. auch schon mal langsamer als nur eine Routine. Da man auf alle Worker-Threads warten muss, bevor man das Ergebnis zuweist, kann es sich evtl. auch etwas in die Länge ziehen, wenn eine CPU zu sehr belastet ist und daher einen Thread etwas blockiert..

Vielleicht sollte ich auch nicht alle zur Verfügung stehenden CPUs nutzen, sondern immer 1 oder 2 weniger, damit so evtl. die restlichen voll für meine Berechnungsaufgaben zur Verfügung stehen.

Muss ich morgen noch mal testen...

Geändert von Harry Stahl (19. Okt 2020 um 02:58 Uhr)
  Mit Zitat antworten Zitat
striderx

Registriert seit: 11. Feb 2007
Ort: Bergisch Gladbach
185 Beiträge
 
Delphi 10.4 Sydney
 
#23

AW: 24-Bit Bitmap um 90 grad drehen - Resourcen-Optimierung

  Alt 19. Okt 2020, 07:55
[Nicht] Anliegend ein Testprojekt, es funktioniert weder unter Delphi XE7 (was ich derzeit noch für das Programm verwende), noch unter dem aktuellsten 10.4.1...

Wegen der Dateigröße von 14 MB (das 24-bit-Bild) musste ich das Demo kurz auf meine eigene Seite laden, lasse es solange drauf, bis Du entweder sagst, Du willst es Dir nicht ansehen oder dass Du es geladen hast:

https://www.hastasoft.de/GDITest.zip
Da ich hier immer mit quadratischen Bildern arbeite, ist mir das bislang nicht aufgefallen: Man muss bei nicht quadratischen Vorlagen natürlich auch die Dimensionen der Ziel-Bitmap entsprechend anpassen.

Delphi-Quellcode:
function GDIPRotateFlipBitmap(ABitmap: tBitmap; Mode: RotateFlipType): Boolean;

var
  BM: tBitmap;
  GR: tGPGraphics;
  AGPBitmap: tGPBitmap;
  AStatus: Status;
  W: Integer;

begin
  if Mode = RotateNoneFlipNone then begin
     Result := True;
     Exit;
  end;
  
  BM := tBitmap.Create;
  BM.Assign(ABitmap);
  AGPBitmap := tGPBitmap.Create(BM.Handle, 0);
  
  AGPBitmap.RotateFlip(Mode);
> if ABitmap.Width <> ABitmap.Height then begin
> W := ABitmap.Width;
> ABitmap.Width := ABitmap.Height;
> ABitmap.Height := W;
> end;
  GR := tGPGraphics.Create(ABitmap.Canvas.Handle);
  GR.DrawImage(AGPBitmap, 0, 0);
  AStatus := GR.GetLastStatus;
  
  Result := (AStatus = OK);
  
  AGPBitmap.Free;
  BM.Free;
  GR.Free;
end;
Viel Spaß beim weiteren Basteln.
  Mit Zitat antworten Zitat
venice2

Registriert seit: 5. Dez 2019
318 Beiträge
 
Delphi 2010 Architect
 
#24

AW: 24-Bit Bitmap um 90 grad drehen - Resourcen-Optimierung

  Alt 19. Okt 2020, 08:59
Zitat:
Viel Spaß beim weiteren Basteln.
Dito!

Delphi-Quellcode:
procedure TForm34.Button1Click(Sender: TObject);
var
  bm: Tbitmap;
  Start, Stop: Cardinal;
begin
  Start := GetTickCount;
  bm := TBitmap.Create;
  bm.Assign(image1.Picture.Bitmap);
// GDIPRotateFlipBitmap (bm, Rotate90FlipY);
  bm := FastAARotatedBitmap(bm.Handle, 90.0, TColor($FFFF),
    true, true, false, 1.0);
  Image2.Picture.Bitmap.Assign(bm);
  Image2.Refresh;
  Stop := GetTickCount - Start;
  Caption := Format('%d ms', [Stop]); // 656 ms ..
end;

Geändert von venice2 (20. Okt 2020 um 12:13 Uhr)
  Mit Zitat antworten Zitat
dummzeuch

Registriert seit: 11. Aug 2012
Ort: Essen
767 Beiträge
 
Delphi 2007 Professional
 
#25

AW: 24-Bit Bitmap um 90 grad drehen - Resourcen-Optimierung

  Alt 19. Okt 2020, 09:08
Ich habe ja die Original-Routine von Doberenz schon um ca. 20% Speed gesteigert, indem ich das

PEnd := Bm.scanline[bm.height-1];

vor die Schleife gesetzt habe und in der Schleife nur den gespeicherten Wert zuweisen muss. Aber "rowout := help.scanline [y];" brauche ich doch weiterhin und kann es nicht ersetzen.
Du kannst Die Adressen der Zeilen jeweils selbst berechnen. Das sind dann nur noch zwei Aufrufe von Scanline[]. Das macht einen riesigen Unterschied.

Ich habe darüber vor einiger Zeit mal geblogt.

Edit: Ich sehe gerade, Renate Schaaf hatte das auch schon geschrieben, incl. Code. Sorry für das Duplikat.
Thomas Mueller

Geändert von dummzeuch (19. Okt 2020 um 09:10 Uhr)
  Mit Zitat antworten Zitat
striderx

Registriert seit: 11. Feb 2007
Ort: Bergisch Gladbach
185 Beiträge
 
Delphi 10.4 Sydney
 
#26

AW: 24-Bit Bitmap um 90 grad drehen - Resourcen-Optimierung

  Alt 19. Okt 2020, 10:20
Nachtrag der Vollständigkeit halber

Delphi-Quellcode:
function GDIPRotateFlipBitmap(ABitmap: tBitmap; Mode: RotateFlipType): Boolean;

var
  BM: tBitmap;
  GR: tGPGraphics;
  AGPBitmap: tGPBitmap;
  AStatus: Status;
  W: Integer;

begin
  if Mode = RotateNoneFlipNone then begin
     Result := True;
     Exit;
  end;
  
  BM := tBitmap.Create;
  BM.Assign(ABitmap);
  AGPBitmap := tGPBitmap.Create(BM.Handle, 0);
  
  AGPBitmap.RotateFlip(Mode);
  
  if (ABitmap.Width <> ABitmap.Height) and
> (Mode in [Rotate90FlipNone, Rotate270FlipNone,
> Rotate90FlipX, Rotate270FlipX,
> Rotate90FlipY, Rotate270FlipY,
> Rotate90FlipXY, Rotate270FlipXY]) then begin
     W := ABitmap.Width;
     ABitmap.Width := ABitmap.Height;
     ABitmap.Height := W;
  end;
  
  GR := tGPGraphics.Create(ABitmap.Canvas.Handle);
  GR.DrawImage(AGPBitmap, 0, 0);
  AStatus := GR.GetLastStatus;
  
  Result := (AStatus = OK);
  
  AGPBitmap.Free;
  BM.Free;
  GR.Free;
end;
  Mit Zitat antworten Zitat
Benutzerbild von haentschman
haentschman

Registriert seit: 24. Okt 2006
Ort: Seifhennersdorf / Sachsen
4.577 Beiträge
 
Delphi 10.1 Berlin Professional
 
#27

AW: 24-Bit Bitmap um 90 grad drehen - Resourcen-Optimierung

  Alt 19. Okt 2020, 10:26
Zitat:
der Vollständigkeit halber
Vollständig wäre es mit try/finally Blocks...

  Mit Zitat antworten Zitat
Jens01

Registriert seit: 14. Apr 2009
604 Beiträge
 
#28

AW: 24-Bit Bitmap um 90 grad drehen - Resourcen-Optimierung

  Alt 19. Okt 2020, 11:03
Wenn ich das eben richtig nachgelesen habe, kann man für Bitmap-Veränderungen auch die Intel-Prozessoren direkt ansteuern, was der Bearbeitung noch mal Schub verleihen soll.
Intel Integrated Performance Primitives for Intel Architecture
Hier ist ein Header.
Ich weiß nur nicht genau, wie man den Header ansteuert.
Achtung: Bin kein Informatiker sondern komme vom Bau.
  Mit Zitat antworten Zitat
striderx

Registriert seit: 11. Feb 2007
Ort: Bergisch Gladbach
185 Beiträge
 
Delphi 10.4 Sydney
 
#29

AW: 24-Bit Bitmap um 90 grad drehen - Resourcen-Optimierung

  Alt 19. Okt 2020, 11:07
Zitat:
der Vollständigkeit halber
Vollständig wäre es mit try/finally Blocks...

Grundsätzlich richtig, aber an welcher Stelle meinst du denn, dass hier eine Exception 'durchschlägt'?. Seitens GDI+ m. W. nicht, da kann man nur mit GetLastStatus den Status der letzten Operation abfragen. Könnte man natürlich verschachteln mit mehreren if AStatus = OK , aber bei dem Größenbug von FlipRotate ist der Status OK. Und selbst wenn man das tBitmap.Create wegläßt, knallt es nicht.

Aber vielleicht übersehe ich ja etwas.
  Mit Zitat antworten Zitat
venice2

Registriert seit: 5. Dez 2019
318 Beiträge
 
Delphi 2010 Architect
 
#30

AW: 24-Bit Bitmap um 90 grad drehen - Resourcen-Optimierung

  Alt 19. Okt 2020, 12:24
Zitat:
der Vollständigkeit halber
Vollständig wäre es mit try/finally Blocks...

Grundsätzlich richtig, aber an welcher Stelle meinst du denn, dass hier eine Exception 'durchschlägt'?. Seitens GDI+ m. W. nicht, da kann man nur mit GetLastStatus den Status der letzten Operation abfragen. Könnte man natürlich verschachteln mit mehreren if AStatus = OK , aber bei dem Größenbug von FlipRotate ist der Status OK. Und selbst wenn man das tBitmap.Create wegläßt, knallt es nicht.

Aber vielleicht übersehe ich ja etwas.
Alles gut und schön.
Nur die Funktion im GDITest Projekt spiegelt das Bild es wird nicht korrekt dargestellt.
GDIPRotateFlipBitmap (bm, Rotate90FlipY);

GDIPRotateFlipBitmap (bm, Rotate90FlipNone);
wäre korrekt!
Ist zwar schnell aber das Ergebnis zu meiner Funktion ist nur schlecht.
Vergleiche beide Bilder das von mir hochgeladene und das hier.
Das vergleichen kann man hier vergessen da die Konvertierung des Bitmap (*.png) zu *.jpg (Hier im Forum) das original verfälscht.

Geändert von venice2 (20. Okt 2020 um 12:13 Uhr)
  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 01:01 Uhr.
Powered by vBulletin® Copyright ©2000 - 2020, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2020 by Daniel R. Wolf