AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren

Resample oder Resize mit GDI+

Ein Thema von Schwedenbitter · begonnen am 25. Nov 2010 · letzter Beitrag vom 27. Mai 2019
Antwort Antwort
Seite 1 von 3  1 23   
Schwedenbitter

Registriert seit: 22. Mär 2003
Ort: Finsterwalde
622 Beiträge
 
Turbo Delphi für Win32
 
#1

Resample oder Resize mit GDI+

  Alt 25. Nov 2010, 17:28
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 GdipDrawImageRect() hinbekommen könnte. Mein Plan sieht so aus:
  1. TBitmap (Source) habe ich schon.
  2. TBitmap (Destination) lege ich an
  3. Mit 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 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 GdipCreateHBITMAPFromBitmap() wieder zurück?
  8. Beide GDI+ Images mit 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
Alex Winzer
  Mit Zitat antworten Zitat
xaromz

Registriert seit: 18. Mär 2005
1.682 Beiträge
 
Delphi 2006 Enterprise
 
#2

AW: Resample oder Resize mit GDI+

  Alt 25. Nov 2010, 17:40
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
I am a leaf on the wind - watch how I soar
  Mit Zitat antworten Zitat
Benutzerbild von Bummi
Bummi

Registriert seit: 15. Jun 2010
Ort: Augsburg Bayern Süddeutschland
3.470 Beiträge
 
Delphi XE3 Enterprise
 
#3

AW: Resample oder Resize mit GDI+

  Alt 25. Nov 2010, 17:43
Ich schließe mich meinem Vorredner an
Thomas Wassermann H₂♂
Das Problem steckt meistens zwischen den Ohren
DRY DRY KISS
H₂ (wenn bei meinen Snipplets nichts anderes angegeben ist Lizenz: WTFPL)
  Mit Zitat antworten Zitat
Schwedenbitter

Registriert seit: 22. Mär 2003
Ort: Finsterwalde
622 Beiträge
 
Turbo Delphi für Win32
 
#4

AW: Resample oder Resize mit GDI+

  Alt 25. Nov 2010, 18:01
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

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 GdipDrawImageRect() die Größenänderung machen kann.
Quellbitmap in der entsprechenden Größe auf das Zielbitmap malen
bringt mich im Moment da nicht ganz so weiter.

Danke, Alex
Alex Winzer
  Mit Zitat antworten Zitat
xaromz

Registriert seit: 18. Mär 2005
1.682 Beiträge
 
Delphi 2006 Enterprise
 
#5

AW: Resample oder Resize mit GDI+

  Alt 25. Nov 2010, 18:20
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 GdipDrawImageRect(graphics, soucre, x, y, width, height); , wobei graphics das Graphikobjekt Deines Quellbitmaps ist.

Gruß
xaromz
I am a leaf on the wind - watch how I soar
  Mit Zitat antworten Zitat
Benutzerbild von Bummi
Bummi

Registriert seit: 15. Jun 2010
Ort: Augsburg Bayern Süddeutschland
3.470 Beiträge
 
Delphi XE3 Enterprise
 
#6

AW: Resample oder Resize mit GDI+

  Alt 25. Nov 2010, 18:23
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;
Thomas Wassermann H₂♂
Das Problem steckt meistens zwischen den Ohren
DRY DRY KISS
H₂ (wenn bei meinen Snipplets nichts anderes angegeben ist Lizenz: WTFPL)
  Mit Zitat antworten Zitat
EWeiss
(Gast)

n/a Beiträge
 
#7

AW: Resample oder Resize mit GDI+

  Alt 26. Nov 2010, 07:46
Schau hier mal rein
GDIClock
Da mußt auch nichts installieren.

gruss
  Mit Zitat antworten Zitat
Schwedenbitter

Registriert seit: 22. Mär 2003
Ort: Finsterwalde
622 Beiträge
 
Turbo Delphi für Win32
 
#8

AW: Resample oder Resize mit GDI+

  Alt 26. Nov 2010, 12:32
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 "+")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.
Alex Winzer
  Mit Zitat antworten Zitat
Benutzerbild von DeddyH
DeddyH

Registriert seit: 17. Sep 2006
Ort: Barchfeld
27.534 Beiträge
 
Delphi 11 Alexandria
 
#9

AW: Resample oder Resize mit GDI+

  Alt 26. Nov 2010, 12:34
Hast Du mal versucht, vorher den StretchBltMode auf HALFTONE zu setzen? Damit habe ich recht gute Erfahrungen gemacht.
Detlef
"Ich habe Angst vor dem Tag, an dem die Technologie unsere menschlichen Interaktionen übertrumpft. Die Welt wird eine Generation von Idioten bekommen." (Albert Einstein)
Dieser Tag ist längst gekommen
  Mit Zitat antworten Zitat
Schwedenbitter

Registriert seit: 22. Mär 2003
Ort: Finsterwalde
622 Beiträge
 
Turbo Delphi für Win32
 
#10

AW: Resample oder Resize mit GDI+

  Alt 26. Nov 2010, 14:27
Hast Du mal versucht, vorher den StretchBltMode auf HALFTONE zu setzen? Damit habe ich recht gute Erfahrungen gemacht.
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
Alex Winzer
  Mit Zitat antworten Zitat
Antwort Antwort
Seite 1 von 3  1 23   

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 10:12 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