Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Win32/Win64 API (native code) (https://www.delphipraxis.net/17-win32-win64-api-native-code/)
-   -   Delphi Alternative zu StretchBlt gesucht (https://www.delphipraxis.net/183034-alternative-zu-stretchblt-gesucht.html)

Harry Stahl 5. Dez 2014 18:07

Alternative zu StretchBlt gesucht
 
Hallo, kennt jemand noch eine gute UND schnelle Alternative zur Windows API-Funktion StretchBlt?

Google-Suche brachte nur das hier zu Tage:

http://swissdelphicenter.ch/de/showcode.php?id=1946

Die dort dargestellte Funktion ist zwar wirklich schnell, aber die Qualität ist im Vergleich zu StretchBlt sichtbar schlechter. Verwenden möchte ich das mit einem TBitmap, Graphics32 wäre wohl da keine Hilfe (davon abgesehen habe ich es dort nicht geschafft ein Stretch aufzurufen).

Harry Stahl 7. Dez 2014 14:34

AW: Alternative zu StretchBlt gesucht
 
Versuche noch einmal nachzufragen. Keiner eine Idee?

Medium 7. Dez 2014 15:11

AW: Alternative zu StretchBlt gesucht
 
Wo ist das Problem dabei, die Graphics32 einzusetzen? Du kannst ein Bitmap ziemlich zügig in ein TBitmap32 bringen, welches im Gegenzug u.a. auch direkt auf einen beliebigen Canvas gezeichnet werden kann. Ich nutze bei mir intern mittlerweile fast nur noch TBitmap32, allein schon weil die Lib so dermaßen viele Möglichkeiten mehr bietet, und praktisch alle Operationen zig mal schneller sind als alles was die WinAPI so bietet. Und gerade beim Resamplen hat man sogar noch die Wahl zwischen viel besseren Filtern als Nearest-Neighbour und stumpem bilinearen Interpolieren.

Harry Stahl 7. Dez 2014 16:22

AW: Alternative zu StretchBlt gesucht
 
Graphics 32 hatte ich mal ein Stretching / Resample probiert, aber nicht hinbekommen. Die Beispiele, die man im Netz findet, beziehen sich alle auf eine ältere Version von Graphics32.

Hast Du evtl. ein funktionierendes Beispiel für ein Resample einer TBitmap(32) mit GRaphics 32?

Jens01 7. Dez 2014 17:54

AW: Alternative zu StretchBlt gesucht
 
Geht das hier nicht mehr?

Medium 7. Dez 2014 18:07

AW: Alternative zu StretchBlt gesucht
 
Schau dir mal das Beispiel unter \graphics32\Examples\Vcl\Resampling\Resamplers_Ex\ an. Ich gebe zu, dass die Hilfe der GR32 hier recht unbrauchbar ist, und dass das Verfahren deutlich zur alten Version verkompliziert wurde. Vor allem scheint es keine fertigen DrawResized() Methoden o.ä. zu geben, sondern man muss eine Resampler-Klasse mit seinem Bitmap verknüpfen, und mit deren Hilfe selbst in einem Schleifchen seine Pixel zeichnen.
Ich muss gestehen, ich hatte auch noch die alte Version im Hinterkopf, da ich mit der neuen bisher noch keine Resizes benötigt hatte.

In dem o.g. Beispiel ist vor allem die Methode ScrChanged() interessant, dort wird genau diese Schleife gemacht. Ansonsten sind die Ereignishandler zu den Auswahllisten wichtig, in denen die entsprechenden Resampler erzeugt und parametriert werden. Scheint alles sehr mächtig geworden zu sein, für einfach mal gefiltert vergrößern aber doch etwas überladener als ich dachte :?. Das meiste wird man davon wohl gar nicht brauchen für dein Vorhaben.

Edit: Ha, der Link von Jens ist prima! Da wird das ja doch auf das nötigste eingedampft. Genau sowas hätte ich mir in der Hilfe-Datei auch gewünscht!

Harry Stahl 7. Dez 2014 18:49

AW: Alternative zu StretchBlt gesucht
 
Vielen Dank Euch Beiden!

Ja, mit dem Link vom Jens01 kam ich zurecht.

Der TLanczosKernel Resample-Filter ist nicht ganz so schnell, werde mal testen, ob in der gegebenen Situation die temporäre Verwendung eines TBitmaps32 eine Steigerung der Geschwindigkeit insgesamt bewirken kann.

Welches ist ein noch guter aber auch schneller Resample-Filter?

Kann man eigentlich mit einer Bitmap32 direkt auf den Windows-Canvas (z.B. einer Paintbox) zeichnen?

Hier mal kurz eine Möglichkeit das Bitmap in die TBitmap32 zu bekommen und das Ergebnis wieder in eine normale Bitmap zurück zugeben. Vielleicht kann man das noch optimieren?

Delphi-Quellcode:

procedure DrawSrcToDst(Src, Dst: TBitmap32);
var
  R: TKernelResampler;
begin
  R := TKernelResampler.Create(Src);
  R.Kernel := TLanczosKernel.Create;
  Dst.Draw(Dst.BoundsRect, Src.BoundsRect, Src);
end;

procedure TForm3.Button5Click(Sender: TObject);
var
  winbit1, winbit2: TBitmap;
  GR32bitSrc, GR32bitDest: TBitmap32;
begin
  WinBit1 := TBitmap.Create;
  WinBit2 := TBitmap.Create;

  WinBit1.LoadFromFile ('\\ew1\D\APic\PixPD\Market_Colors.bmp');

  GR32BitSrc := TBitmap32.create;
  Gr32BitSrc.Assign(WinBit1);

  GR32bitDest := TBitmap32.create;
  GR32bitDest.SetSize(GR32BitSrc.Width div 2, GR32BitSrc.Height div 2); // Bild auf die Hälfte

  DrawSrcToDst(GR32bitSrc, GR32BitDest);

  image2.Picture.bitmap.Assign(GR32BitDest);

  //.... diverse frees

end;

Harry Stahl 7. Dez 2014 19:14

AW: Alternative zu StretchBlt gesucht
 
Edit: Bei dem Link von Jens01 stand etwas zur Qualität der Resample-Filter dabei, habe ich jetzt erst gesehen...

Harry Stahl 7. Dez 2014 19:25

AW: Alternative zu StretchBlt gesucht
 
Also nur zur Vervollständigung, vielleicht braucht das Jemand mal:

Delphi-Quellcode:
procedure DoStretch (Const src: TBitmap; dst: TBitmap);
var
  //R: TKernelResampler;
  R: TLinearResampler;
  GR32bitSrc, GR32bitDest: TBitmap32;
begin
  GR32BitSrc := TBitmap32.create;
  Gr32BitSrc.Assign(src);

  GR32bitDest := TBitmap32.create;
  GR32bitDest.SetSize(dst.width, dst.Height);

  R := TLinearResampler.Create(GR32BitSrc);
  //R.Kernel := TLanczosKernel.Create;
  GR32bitDest.Draw(GR32bitDest.BoundsRect, GR32bitSrc.BoundsRect, GR32bitSrc);

  dst.Assign(GR32BitDest);

  GR32BitSrc.Free;
  GR32bitDest.Free;
end;
Allerdings dauert es deutlich länger als StretchBlt, das ist wohl derzeit nicht zu toppen.

Jens01 7. Dez 2014 21:36

AW: Alternative zu StretchBlt gesucht
 
Zitat:

Allerdings dauert es deutlich länger als StretchBlt, das ist wohl derzeit nicht zu toppen.
Liegt das vielleicht am Resampler? Der TNearestResampler soll am schnellsten sein.

Harry Stahl 7. Dez 2014 22:27

AW: Alternative zu StretchBlt gesucht
 
Ja, liegt daran. Der Nearest-Resampler hat aber eine nicht akzeptable Qualität. Der Linear-Resampler ist so gut wie StretchBlt, aber eben deutlich langsamer.

Namenloser 7. Dez 2014 22:54

AW: Alternative zu StretchBlt gesucht
 
Es liegt vermutlich eher am Hin- und Herkonvertieren zwischen TBitmap und TBitmap32. Graphics32 ist eigentlich extrem flott, kann mir nicht vorstellen, dass die WinAPI da wesentlich schneller ist. Nach meinen Erfahrungen ist es meistens eher umgekehrt.

Harry Stahl 7. Dez 2014 23:10

AW: Alternative zu StretchBlt gesucht
 
Beim Zeitmessen hab ich natürlich auch mal nur den Draw-Aufruf der Graphics32 gemessen und mit StretchBlt verglichen (32-Bit-Bitmap mit teiltransparentem Inhalt). Da war nur der Aufruf mit der schlechten Qualität besser, mit der mittleren war schon StretchBlt schneller.

Medium 8. Dez 2014 09:09

AW: Alternative zu StretchBlt gesucht
 
Das ist in der Tat seltsam, bisher kenne ich die GR32 auch eher als super-turbo im Direktvergleich mit den GDI Operationen. Was natürlich insgesamt sehr sparen kann, wäre die Verwendung von nur GR32 programmweit, so dass das Umkopieren weg fällt. Bei schon bestehenden größeren Werken natürlich keine Option.
Du kannst aber durchaus direkt ein TBitmap32 auf einen GDI Canvas zeichnen: TBitmap32.DrawTo() - Damit ließe sich, wenn es nur um die Anzeige geht, ein Mal kopieren schon sparen.

Dejan Vu 8. Dez 2014 11:44

AW: Alternative zu StretchBlt gesucht
 
Zitat:

Zitat von Medium (Beitrag 1282595)
Bei schon bestehenden größeren Werken natürlich keine Option.

Gerade diese Einstellung verhindert sinnvolles Refactoring und das Weiterleben von legacy Anwendungen :-). *Natürlich* ist es eine Option, die bewertet werden muss.

Harry Stahl 8. Dez 2014 18:31

AW: Alternative zu StretchBlt gesucht
 
Hab noch mal ein wenig weiter getestet:

3548 x 2558 Pixel-Grafik, Shrink auf ca. 1/8-Größe:

TLinear: 266 MS
TKernel: 140 MS
TDraft: 30 MS
TNearest: 0 MS

"Draft" ist übrigens von der Qualität besser als der Name vermuten lässt.

In der Summe "wäre" die Sache mit "Draft" sogar noch ein wenig schneller als Stretchblt, jedenfalls wenn die Reduzierung auf ca. 25% oder kleiner erfolgt. Bei Vergrößerungen ist Stretchblt in allen Fällen schneller. Da ich an anderen Stellen aber auch noch mit StretchBlt zeichne (z.T. in Regions des gleichen Bilds) unterscheiden sich die Renderergebnisse ganz leicht. Man muss schon genau hinsehen, aber es fällt eben doch auf. Wenn ich auch in den Regions mit TBitmap32 zeichne, wird es leicht langsamer.

Da ich vorerst hier nichts umstellen möchte (Programmcode immerhin über 500.000 Zeilen), passt eine nur teilweise Zeichnung mit Graphics32 nicht so richtig ins Konzept.

Die erwähnte Option "alle Stellen" im Programm auf TBitmap32 umzustellen, wäre eine Überlegung für das nächste große Update, momentan versuche ich mich noch an kleineren Optimierungen.

Generell macht die Graphics32 einen guten Eindruck.

EWeiss 8. Dez 2014 21:23

AW: Alternative zu StretchBlt gesucht
 
DrawImageRectRectI

gruss


Alle Zeitangaben in WEZ +1. Es ist jetzt 01:45 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