Delphi-PRAXiS
Seite 1 von 3  1 23      

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Win32/Win64 API (native code) (https://www.delphipraxis.net/17-win32-win64-api-native-code/)
-   -   Resample oder Resize mit GDI+ (https://www.delphipraxis.net/156268-resample-oder-resize-mit-gdi.html)

Schwedenbitter 25. Nov 2010 16:28

Resample oder Resize mit GDI+
 
Hallo,

ich möchte gern größere Bilder mithilfe der Funktionen aus der GDI+ -Bibliothek verkleinern. Leider habe ich keine Ahnung, wie ich das so recht anstellen soll. Auch möchte ich, um Resourcen zu schonen, auf fertige Units verzichten.
Ich bin soweit, dass ich die GDI+ initialisiert, Bitmaps angelegt und deren Speicher wieder freigegeben habe. Ich finde aber nichts genaues, mit welchen Funktionen ich ein Resample erreichen kann.

Aufgrund meiner Recherchen vermute ich, dass ich die Größenänderung mit mit
Delphi-Quellcode:
GdipDrawImageRect()
hinbekommen könnte. Mein Plan sieht so aus:
  1. TBitmap (Source) habe ich schon.
  2. TBitmap (Destination) lege ich an
  3. Mit
    Delphi-Quellcode:
    GdipCreateBitmapFromHBITMAP()
    erzeuge ich ein GDI+konformes Image von Source
  4. Dasselbe mit Destination
  5. Problem 1: Bei welchem der beiden GDI+ Images muss ich jetzt mit
    Delphi-Quellcode:
    GdipSetInterpolationMode()
    den Modus festlegen, damit es etwas wird? Oder muss ich das für beide GDI+ Images machen?
  6. Problem 2: Wie Resample ich?
  7. Problem 3: Bekomme ich das Ergebnis mit
    Delphi-Quellcode:
    GdipCreateHBITMAPFromBitmap()
    wieder zurück?
  8. Beide GDI+ Images mit
    Delphi-Quellcode:
    GdipDisposeImage()
    wieder freigeben

Ich denke auch, dass ich kein zweites TBitmap brauchte. Ich finde aber keine Funktion, mit der ich einfach so ohne Bezug zur (normalen) GDI ein GDI+ Bitmap erstellen kann. Auch insoweit wäre ich für Hilfe dankbar.
Ich möchte das ganze später in einem von TBitmap abgeleiteten Object unterbringen und würde mir gern das Hilfsbitmap sparen.

Gruß, Alex

xaromz 25. Nov 2010 16:40

AW: Resample oder Resize mit GDI+
 
Hallo,

erstens würde ich Dir dringend dazu raten, fertige Klassen für GDI+ zu verwenden, z. B. die von Progdigy. Damit ersparst Du Dir jede Menge Ärger, und die Größe Deines Programms sollte doch heutzutage nicht mehr ausschlaggebend sein, oder?

Zweitens, So musst Du vorgehen:
  • Quellbitmap laden
  • Zielbitmap in der entsprechenden Größe erstellen
  • InterpolationMode des Zielbitmaps setzen
  • Quellbitmap in der entsprechenden Größe auf das Zielbitmap malen
Wie gesagt, mit den entsprechenden Units ist das ein Vierzeiler (Fünfzeiler mit Speichern).

//Edit:
Ach ja, ohne Zweitbitmap geht es nicht, und natürlich kannst Du auch einfach direkt ein GDI+ Bitmap erstellen.

Gruß
xaromz

Bummi 25. Nov 2010 16:43

AW: Resample oder Resize mit GDI+
 
Ich schließe mich meinem Vorredner an:thumb:

Schwedenbitter 25. Nov 2010 17:01

AW: Resample oder Resize mit GDI+
 
Danke. Das bringt mich schon einmal auf Kurs!

Ich möchte keine fertige Klasse verwenden. Und ja, die Größe spielt bei uns eine Rolle, weil mein fertiges Programm aus bestimmten Gründen regelmäßig neu geladen und gestartet werden muss. Bei uns hängen mehrere Leute an einem VPN. Wenn ich die Datei größer mache, gibt es mit denen Ärger.
Außerdem experimentiere ich gern :lol:

Zitat:

Zitat von xaromz (Beitrag 1064037)
Ach ja, ohne Zweitbitmap geht es nicht, und natürlich kannst Du auch einfach direkt ein GDI+ Bitmap erstellen.

Könntest Du das bitte genauer erklären? Dass ich ein zweites GDI+ Bitmap brauche, ist mir klar. Aber wenn ich das richtig verstehe, muss ich nicht zuvor ein zweites TBitmap erstellen und dem eigentlichen GDI+ Ziel-Image zuweisen, oder?
Könntest Du mir bitte die Funktion verraten. Das würde mir sehr helfen. Hier habe ich dazu leider nichts gefunden.

Dann würde ich mich noch freuen, wenn jemand bestätigen oder dementieren könnte, dass ich mit
Delphi-Quellcode:
GdipDrawImageRect()
die Größenänderung machen kann.
Zitat:

Zitat von xaromz (Beitrag 1064037)
Quellbitmap in der entsprechenden Größe auf das Zielbitmap malen

bringt mich im Moment da nicht ganz so weiter.

Danke, Alex

xaromz 25. Nov 2010 17:20

AW: Resample oder Resize mit GDI+
 
Hallo,

ein Bitmap bekommst Du mit
Delphi-Quellcode:
var bitmap: Pointer;
...
bitmap := nil;
lastResult := GdipCreateBitmapFromScan0(width, height, 0, pixelFormat, nil, bitmap);
Danach steckt in bitmap Dein GDI+ Bitmap.

Ein Bitmap malst Du mit
Delphi-Quellcode:
GdipDrawImageRect(graphics, soucre, x, y, width, height);
, wobei graphics das Graphikobjekt Deines Quellbitmaps ist.

Gruß
xaromz

Bummi 25. Nov 2010 17:23

AW: Resample oder Resize mit GDI+
 
ein Fetzen Code sagt mehr als 1000 Worte :)
muß nichts installiert werden

Delphi-Quellcode:
unit ExGraphicUtils;
//2010 Thomas Wassermann www.explido-software.de
interface
uses Windows, Classes, Sysutils, Graphics,GDIPAPI,GDIPOBJ, StdCtrls, jpeg, ActiveX;

procedure SetCanvasZoomFactor(Canvas: TCanvas; AZoomFactor: Integer);
Procedure SetCanvasZoomAndRotation(ACanvas:TCanvas;Zoom:Double;Angle:Double;CenterpointX,CenterpointY:Double);
Procedure ScaleImage(source:String;dest:TCanvas;DestRect:Trect;Center:Boolean=true);overload;
Procedure ScaleImage(source:TGraphic;dest:TCanvas;DestRect:Trect;Center:Boolean=true);overload;
function CreateGraphicFromFile(const Filename: string): TGraphic;
procedure MirrorBitmap(Bmp, MBmp: TBitmap;Horizonal:Boolean=true);
implementation


Procedure ScaleImage(source:String;dest:TCanvas;DestRect:Trect;Center:Boolean=true);overload;
var
  graphics : TGPGraphics;
  image: TGPImage;
  width, height: Integer;
  faktor:Double;
  X, Y:Double;
begin
  image:= TGPImage.Create(source);
  try
  width := image.GetWidth;
  height := image.GetHeight;
  if ((DestRect.Right - DestRect.Left) / width) < ((DestRect.Bottom -DestRect.Top)/Height) then faktor := (DestRect.Right - DestRect.Left) / width else faktor:= ((DestRect.Bottom -DestRect.Top)/Height);
  Faktor := ABS(Faktor);
  if Center then
      begin
        X := ((Destrect.Right - Destrect.Left) - faktor * width ) / 2;
        Y := ((Destrect.Bottom - Destrect.Top) - faktor * Height ) / 2;
      end
  else
      begin
        X := Destrect.Left;
        Y := Destrect.Top;

      end;
  graphics := TGPGraphics.Create(dest.Handle);
  try
    graphics.SetInterpolationMode(InterpolationModeHighQualityBicubic);
    graphics.DrawImage( image, MakeRect(X, Y , faktor * width, faktor * height), 0, 0, width, height, UnitPixel);
  finally
    graphics.Free;
  end;
  finally
  image.Free;
  end;
end;

Procedure ScaleImage(source:TGraphic;dest:TCanvas;DestRect:Trect;Center:Boolean=true);overload;
var
  graphics : TGPGraphics;
  image: TGPImage;
  width, height: Integer;
  faktor:Double;
  STR : TMemoryStream;
  X, Y:Double;
begin
  STR := TMemoryStream.Create;
  source.SaveToStream(STR);
  STR.Position := 0;
  image:= TGPImage.Create(TStreamAdapter.Create(Str));
  try
  width := image.GetWidth;
  height := image.GetHeight;
  if ((DestRect.Right - DestRect.Left) / width) < ((DestRect.Bottom -DestRect.Top)/Height) then faktor := (DestRect.Right - DestRect.Left) / width else faktor:= ((DestRect.Bottom -DestRect.Top)/Height);
  Faktor := ABS(Faktor);
  if Center then
      begin
        X := ((Destrect.Right - Destrect.Left) - faktor * width ) / 2;
        Y := ((Destrect.Bottom - Destrect.Top) - faktor * Height ) / 2;
      end
  else
      begin
        X := Destrect.Left;
        Y := Destrect.Top;

      end;
  graphics := TGPGraphics.Create(dest.Handle);
  try
    graphics.SetInterpolationMode(InterpolationModeHighQualityBicubic);
    graphics.DrawImage( image, MakeRect(X, Y , faktor * width, faktor * height), 0, 0, width, height, UnitPixel);
  finally
    graphics.Free;
  end;
  finally
  STR.Free;
  image.Free;
  end;
end;

EWeiss 26. Nov 2010 06:46

AW: Resample oder Resize mit GDI+
 
Schau hier mal rein ;)
GDIClock
Da mußt auch nichts installieren.

gruss

Schwedenbitter 26. Nov 2010 11:32

AW: Resample oder Resize mit GDI+
 
Zitat:

Zitat von EWeiss (Beitrag 1064190)
Schau hier mal rein ;)
GDIClock

Genau damit habe ich angefangen. Großes Lob im übrigen dafür. Zwar läuft die Uhr nicht bei mir (Zeiger und Untergrund passen nicht übereinander). Aber ich hatte das damals bestens für meine Experimente zum Drehen eines Bitmaps verwenden können und auch hier meine Anfänge gemacht.

Aus diesem Grunde bin ich ja auch dazu gekommen, dass ich keine fette Unit für das Resizen brauche, sondern mir das ganze selbst schlank und schnell zusammen bauen kann.
Aus schnell ist - wie man an diesem Thema sieht - nichts geworden. Aber ich habe keine andere Wahl. Denn im Moment mache ich das Scaling mit der GDI-Funktion (ohne "+")
Delphi-Quellcode:
StretchBlt()
und da leidet die Lesbarkeit unserer Dokumente erheblich. Beim Vergrößern (z.B. beim Ausdrucken mittels Printer.Canvas) ist das kein Problem. Aber wenn ich z.B. mit 300 oder 400 dpi eingescannte Bilder anwendungskonform auf 200 dpi bringen will, habe ich wirklich ein Problem.

DeddyH 26. Nov 2010 11:34

AW: Resample oder Resize mit GDI+
 
Hast Du mal versucht, vorher den StretchBltMode auf HALFTONE zu setzen? Damit habe ich recht gute Erfahrungen gemacht.

Schwedenbitter 26. Nov 2010 13:27

AW: Resample oder Resize mit GDI+
 
Zitat:

Zitat von DeddyH (Beitrag 1064258)
Hast Du mal versucht, vorher den StretchBltMode auf HALFTONE zu setzen? Damit habe ich recht gute Erfahrungen gemacht.

:duck: Wenn Du so direkt fragst: Nö!

Cool. Ich sehe grad, dass ich mich dann vermutlich bloß noch wegen des Speicherns als png-Datei mit GDI+ rumschlagen muss. Aber geschadet hat es trotzdem nichts und ich bleibe mal dran: womöglich sind die Ergebnisse mit GDI+ noch besser ;-)


Alle Zeitangaben in WEZ +1. Es ist jetzt 05:27 Uhr.
Seite 1 von 3  1 23      

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