Delphi-PRAXiS
Seite 2 von 3     12 3      

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 29. Nov 2010 09:55

AW: Resample oder Resize mit GDI+
 
Folgender Code funktioniert bei mir:
Delphi-Quellcode:
Procedure TBitmapEx.StretchGDI(Const NewWidth, NewHeight: Integer);
Var
  ScaleDown   : Boolean;
  W, H         : Integer;
  oldW, oldH   : Integer;
Begin
  If (self.Empty) Or
    ((NewWidth = 0) And (NewHeight = 0)) Or
    ((NewWidth = self.Width) And (NewHeight = self.Height)) Then
      Exit;

  W:=NewWidth;
  H:=NewHeight;
  oldW:=self.Width;
  oldH:=self.Height;

  If (W = 0) Then W:=H * self.Width Div self.Height;
  If (H = 0) Then H:=W * self.Height Div self.Width;

  ScaleDown:=True;
  If (W < self.Width) Or (H < self.Height) Then
    SetStretchBltMode(self.Canvas.Handle, Halftone)
  Else
  Begin
    ScaleDown:= False;
    self.Width:= W;
    self.Height:=H;
  End;
  StretchBlt(self.Canvas.Handle, 0, 0,   W,   H,
             self.Canvas.Handle, 0, 0, oldW, oldH,
             SRCCOPY);
  If (ScaleDown) Then
  Begin                                    
    self.Width:= W;
    self.Height:=H;
  End;
End;
Leider hatte ich am Wochenende wenig Zeit und den Code über GDI+ (noch) nicht zum Laufen bekommen. Ich scheitere im Moment daran, dass mir
Delphi-Quellcode:
GdipSetInterpolationMode(Dest, 4);
erklärt, ich würde falsche Parameter übergeben. Dabei ist
Delphi-Quellcode:
Type Dest: Pointer
und 4 sollte eigentlich
Delphi-Quellcode:
Type InterpolationModeBicubic: Integer
sein. Letztere sollte auch anstelle von
Delphi-Quellcode:
Cardinal
laufen, wie es wiederum in der uGDIUnit von Cardinal Emil Weiss definiert ist.

Dazu wieder 2 Fragen:
  1. Wenn GDI ohne zusätzliches Bitmap resizen kann, sollte das nicht auch mit GDI+ funktionieren? Dann brauchte ich doch kein
    Delphi-Quellcode:
    Var Source, Dest: Pointer
    , sondern es sollte dann einfach eines reichen.
  2. Wo ist der Unterschied zwischen
    Delphi-Quellcode:
    GdipDrawImageRect()
    und
    Delphi-Quellcode:
    GdipDrawImageRectI()
    ? Einfach nur, dass die eine Funktion mit Gleitkommazahlen und die andere mit Integer funktioniert?
  3. Wo ist bei den Funktionen unter 2. der Unterschied zwischen
    Delphi-Quellcode:
    Graphics
    und
    Delphi-Quellcode:
    Image
    ? Beides ist laut den Erläuterungen zu GDI+ von MS ein Pointer bzw. bei Emil Weiss Cardinal.

Gruß & Dank, Alex

xaromz 29. Nov 2010 10:42

AW: Resample oder Resize mit GDI+
 
Hallo,
Zitat:

Zitat von Schwedenbitter (Beitrag 1064735)
Dazu wieder 2 Fragen:
  1. Wenn GDI ohne zusätzliches Bitmap resizen kann, sollte das nicht auch mit GDI+ funktionieren? Dann brauchte ich doch kein
    Delphi-Quellcode:
    Var Source, Dest: Pointer
    , sondern es sollte dann einfach eines reichen.
  2. Wo ist der Unterschied zwischen
    Delphi-Quellcode:
    GdipDrawImageRect()
    und
    Delphi-Quellcode:
    GdipDrawImageRectI()
    ? Einfach nur, dass die eine Funktion mit Gleitkommazahlen und die andere mit Integer funktioniert?
  3. Wo ist bei den Funktionen unter 2. der Unterschied zwischen
    Delphi-Quellcode:
    Graphics
    und
    Delphi-Quellcode:
    Image
    ? Beides ist laut den Erläuterungen zu GDI+ von MS ein Pointer bzw. bei Emil Weiss Cardinal.

(1) Du kannst schon mit einem Bitmap arbeiten, wenn Du das Bitmap verkleinert auf sich selbst zeichnest. Ob das richtig funktioniert oder Bildfehler erzeugt, kann ich Dir aber nicht sagen, das habe ich nie ausprobiert.

(2) Genau, der Unterschied ist, dass Du einmal Float und einmal Integer verwenden kannst.

(3) Image und Graphics sind zwei völlig unterschiedliche Klassen. Das ist quasi Bitmap und Canvas in der VCL. Ein Image hat immer ein Graphics, welches zum Manipulieren der Bitmapdaten dient. Ich vermute, dass deshalb Deine Interpolation fehlschlägt, weil Du der Funktion das Image übergibst, und nicht das entsprechende Graphics-Objekt.

Gruß
xaromz

Schwedenbitter 29. Nov 2010 15:44

AW: Resample oder Resize mit GDI+
 
Danke für diesen wertvollen Hinweis!
Zitat:

Zitat von xaromz (Beitrag 1064740)
... Image und Graphics sind zwei völlig unterschiedliche Klassen. ... Ich vermute, dass deshalb Deine Interpolation fehlschlägt, weil Du der Funktion das Image übergibst, und nicht das entsprechende Graphics-Objekt.

Ich habe nun folgendes versucht, was aber nicht funktioniert. Ich komme sowei, dass ich ein GDI+ Image ausgehend von meinem TBitmap anlegen und ausgehend davon einen Zeiger auf das GDI+ Graphics bekomme. Trotzdem lässt sich der InterpolationMode nicht setzen mit dem Hinweis auf falsche Parameter:
Delphi-Quellcode:
Function GdipSetInterpolationMode(Out graphics: GdipImage;
  interpolationMode: GdipInterpolationMode): GdipStatus; Stdcall;
  External Gdip;
// GdipImage = Pointer; GdipInterpolationMode = Integer

Procedure TBitmapEx.StretchGdip(Const NewWidth, NewHeight: Integer;
  Const PreserveAspectRatio: Boolean = True);
Var
  Source : GdipImage; // = Pointer
  Dest   : GdipGraphics; // = Pointer
  Stat   : GdipStatus;
Begin
 If (Self.Empty) Then Exit;

  If (GdipCreateBitmapFromHBITMAP(self.Handle, self.Palette, Source) = Ok) Then
  Begin
    If (GdipGetImageGraphicsContext(Source, Dest) = Ok) Then
    Begin
      // Bis hierhin ist alles OK!
      Stat:=GdipSetInterpolationMode(Dest, 4);
      // Hier kommt der Hinweis auf falsche Parameter; leider nicht genau welcher der beiden möglichen...
      ShowMessage(GdipStatusMessage[Stat]);

    End;
    GdipDisposeImage(Source);
  End;
End;
Was mache in denn da falsch?

Ich scheitere nun schon seit letzter Woche an
Delphi-Quellcode:
GdipSetInterpolationMode()
. Ich habe alle möglichen Deklarationen angefangen von GDIPlus über IGDIPlus bis hin zu dem Uhr-Beispiel von EWeiss probiert. Im Grunde fehlen doch nur noch 3 Zeilen ((1)Interpolation Mode setzen (2) Bild zeichnen mit Draw und (3) ggf. auf das TBitmap zurückschieben).

EWeiss 30. Nov 2010 06:41

AW: Resample oder Resize mit GDI+
 
Die Vorgehensweise ist folgende..
1. Ein graphic obj erstellen
Code:
GdipCreateFromHDC(Hdc, graphics);
2. Setzen der Optimierungsmodis
Verschiedene modis die du verwenden kannst.
Smoothing, Interpolation, PixelOffset, CompositingMode..

Code:
GdipSetInterpolationMode(graphics, InterpolationModeHighQualityBicubic);
wobei InterpolationModeHighQualityBicubic den Wert 7 enthält..
QualityModeHigh := 2;
InterpolationModeHighQualityBicubic := QualityModeHigh + 5;

erst dann die Bilddatei als solche öffnen!

EDIT:
Zitat:

// Hier kommt der Hinweis auf falsche Parameter; leider nicht genau welcher der beiden möglichen...
Logisch ..

Du kannst ein img nicht in ein graphic object konvertieren..
Source und Destination müssen von typ graphics sein.

Zitat:

bzw. bei Emil Weiss Cardinal.
Spielt keine Rolle ist doch auslegungssache wie ich meine Function definiere. ;)
Aber davon abgesehen ist es bei MS auch ein Cardinal .. "Pointer of Cardinal"

Bei mir gehts siehe Picture :)

gruss

EWeiss 30. Nov 2010 10:17

AW: Resample oder Resize mit GDI+
 
Hier der Source zum Bild!
Vielleicht hilft es dir ja weiter :)

gruss

Schwedenbitter 30. Nov 2010 10:17

AW: Resample oder Resize mit GDI+
 
Liste der Anhänge anzeigen (Anzahl: 1)
Zitat:

Zitat von EWeiss (Beitrag 1064949)
Die Vorgehensweise ist folgende..
1. Ein graphic obj erstellen
Code:
GdipCreateFromHDC(Hdc, graphics);

Ich komme genau bis hierher und dann nicht mehr weiter. Ich habe ein TBimap erstelle, dorthinein eine Datei geladen und dann
Delphi-Quellcode:
GdipCreateFromHDC(TBitmap.Canvas.Handle, graphics);
aufgerufen.

Zitat:

Zitat von EWeiss (Beitrag 1064949)
2. Setzen der Optimierungsmodis
Verschiedene modis die du verwenden kannst.
Smoothing, Interpolation, PixelOffset, CompositingMode..

Das bekomme ich eben nicht hin :wall:.
Ich übergebe jetzt graphics mit
Delphi-Quellcode:
GdipSetInterpolationMode(graphics, 7)
, wobei gilt:
Delphi-Quellcode:
Type
  GdipGraphics = Pointer;
  GdipInterpolationMode = Integer;

Function GdipSetInterpolationMode(Out graphics: GdipGraphics;
  interpolationMode: GdipInterpolationMode): GdipStatus; Stdcall;
  External Gdip;
Ich habe jetzt mal aus lauter Verzweiflung einen kurzen Testcode beigefügt mit der GdipAPI.inc, die ich selbst gebastelt und bislang benutzt habe. Vielleicht sieht ja jemand auf Anhieb meinen Fehler.

[EDIT]
Mist! Du warst schneller ;-)
[/EDIT]

Gruß, Alex

EWeiss 30. Nov 2010 10:20

AW: Resample oder Resize mit GDI+
 
Siehe mein Source ;)

gruss

EWeiss 30. Nov 2010 10:40

AW: Resample oder Resize mit GDI+
 
Schmeiss mal das shit OUT aus "Out graphics: GdipGraphics" raus.

Dann funktioniert es auch.

gruss

Bummi 30. Nov 2010 10:51

AW: Resample oder Resize mit GDI+
 
Liste der Anhänge anzeigen (Anzahl: 1)
@Eweiss

Hi,

Ich hatte Ihn so verstanden daß er ein bestehenden GraphicObject direkt skalieren will ohne Umweg über ein File.

Ich habe mal eine Prozedur:
Delphi-Quellcode:
function DrawImageFromGraphic(source:TGraphic;
  DrawHdc: HDC;
  Percent: Integer;
  Interpolation: InterpolationMode = InterpolationModeDefault;
  Smoothing : SmoothingMode = SmoothingModeNone;
  PixelOffset : PixelOffsetMode = PixelOffsetModeNone;
  CompositingQuality: CompositingQualityMode = CompositingQualityDefault;
  CompositingMode: CompositingModeMode = CompositingModeSourceOver): Boolean;
in Deinen Code mit eingebaut, erfordert allerdings Classes,ActiveX wg.

function GdipLoadImageFromStreamICM(stream: ISTREAM;
out image: Cardinal): Integer; stdcall;
{$EXTERNALSYM GdipLoadImageFromStreamICM}

ist nur eine Quickhack, Du darfst falls Du es brauchen kannst das ganze gern optimieren.

EWeiss 30. Nov 2010 10:55

AW: Resample oder Resize mit GDI+
 
@Bummi
Zitat:

ist nur eine Quickhack, Du darfst falls Du es brauchen kannst das ganze gern optimieren.
Werde es mir mal anschauen.. ;)

Das Problem war aber eher das setzen des InterpolationMode
Die übergebenen Parameter müssen identisch sein sonst klappt das nicht :)
Er kann nicht bei Out graphis nicht einfach einen Pointer graphics übergeben ...
Wenn schon dann bitte das OUT entfernen dann funktioniert das auch.

gruss


Alle Zeitangaben in WEZ +1. Es ist jetzt 18:17 Uhr.
Seite 2 von 3     12 3      

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