【问题标题】:How to save an image to BMP/PNG/JPG with GDI+? [duplicate]如何使用 GDI+ 将图像保存为 BMP/PNG/JPG? [复制]
【发布时间】:2013-05-03 22:40:29
【问题描述】:

这里我有一个 BMP 的 GUID:

const      
  GBmp: TGUID =  '{b96b3cab-0728-11d3-9d7b-0000f81ef32e}';

我使用 GdiplusStartup(...) 进行了一些初始化。 然后我加载一个 JPG,ShowMessage 显示“Ok”

  Err :=GdipLoadImageFromFile('C:\a.jpg', GdiImage);
  ShowMessage(ShowError(TGPStatus(err)));

现在我尝试保存到 BMP 中,但得到“FileNotFound”:

  Err :=GdipSaveImageToFile(GdiImage, 'C:\b.bmp', @GBmp, nil);
  ShowMessage(ShowError(TGPStatus(err)));

如何使用 GDI+ 保存为 PNG 或 BMP?我不想使用第三方库,只使用 DLL。

下面是Delphi7+的完整代码:

unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls;

type
  TGDIStartup = packed record
    Version: Integer; // =1
    DebugEventCallback: Pointer; //For debug
    SuppressBackgroundThread: Bool;
    SuppressExternalCodecs: Bool; //Tru to use internal codecs
  end;

type
  TEncoderParameter = record
    Guid : TGUID;
    NumberOfValues : ULONG;
    Type_ : ULONG;
    Value : Pointer;
  end;
  TEncoderParameters = record
    Count : UINT;
    Parameter : array[0..0] of TEncoderParameter;
  end;
  PEncoderParameters = ^TEncoderParameters;

type
  TGPStatus = (
    Ok,
    GenericError,
    InvalidParameter,
    OutOfMemory,
    ObjectBusy,
    InsufficientBuffer,
    NotImplemented,
    Win32Error,
    WrongState,
    Aborted,
    FileNotFound,
    ValueOverflow,
    AccessDenied,
    UnknownImageFormat,
    FontFamilyNotFound,
    FontStyleNotFound,
    NotTrueTypeFont,
    UnsupportedGdiplusVersion,
    GdiplusNotInitialized,
    PropertyNotFound,
    PropertyNotSupported,
    ProfileNotFound
  );

type
  TForm1 = class(TForm)
    Button1: TButton;
    procedure Button1Click(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

  function GdipSaveImageToFile(image: Integer; filename: PWCHAR; clsidEncoder: PGUID; encoderParams: PEncoderParameters): Integer; stdcall;
  function GdipLoadImageFromFile(const Filename: PWideChar; out Image: Integer): Integer; stdcall;
  function GdiplusStartup(var Token: Longword; const Input, Output: Pointer): Integer; stdcall;
  function GdipGetImageHeight(Image: Integer; out Height: Integer): Integer; stdcall;

var
  Form1: TForm1;

implementation

{$R *.dfm}

function GdipSaveImageToFile;    external 'GdiPlus.dll'  name 'GdipSaveImageToFile';
function GdipLoadImageFromFile;  external 'GdiPlus.dll'  name 'GdipLoadImageFromFile';
function GdiplusStartup;         external 'GdiPlus.dll'  name 'GdiplusStartup';
function GdipGetImageHeight;     external 'GdiPlus.dll'  name 'GdipGetImageHeight';

function ShowError(Code: TGPStatus) : String;
begin
  case Code of
    Ok                        : Result := 'Ok';
    GenericError              : Result := 'GenericError';
    InvalidParameter          : Result := 'InvalidParameter';
    OutOfMemory               : Result := 'OutOfMemory';
    ObjectBusy                : Result := 'ObjectBusy';
    InsufficientBuffer        : Result := 'InsufficientBuffer';
    NotImplemented            : Result := 'NotImplemented';
    Win32Error                : Result := 'Win32Error';
    WrongState                : Result := 'WrongState';
    Aborted                   : Result := 'Aborted';
    FileNotFound              : Result := 'FileNotFound';
    ValueOverflow             : Result := 'ValueOverflow';
    AccessDenied              : Result := 'AccessDenied';
    UnknownImageFormat        : Result := 'UnknownImageFormat';
    FontFamilyNotFound        : Result := 'FontFamilyNotFound';
    FontStyleNotFound         : Result := 'FontStyleNotFound';
    NotTrueTypeFont           : Result := 'NotTrueTypeFont';
    UnsupportedGdiplusVersion : Result := 'UnsupportedGdiplusVersion';
    GdiplusNotInitialized     : Result := 'GdiplusNotInitialized';
    PropertyNotFound          : Result := 'PropertyNotFound';
    PropertyNotSupported      : Result := 'PropertyNotSupported';
    ProfileNotFound           : Result := 'ProfileNotFound';
  else
    Result := '<UnKnown>';
  end;
end;

procedure TForm1.Button1Click(Sender: TObject);
const GuidBmp: TGUID = '{b96b3cab-0728-11d3-9d7b-0000f81ef32e}';
      GuidPng: TGUID = '{b96b3caf-0728-11d3-9d7b-0000f81ef32e}';
var Err: Integer;
    Graphics: Integer;

    InitToken: LongWord;
    Startup: TGDIStartup;
    GdiImage: Integer;
    Hei: Integer;
begin
  FillChar(Startup, sizeof(Startup), 0);
  Startup.Version := 1;
  GdiplusStartup(InitToken, @Startup, nil);

  Err := GdipLoadImageFromFile('C:\_MyDat\gdi\a.jpg', GdiImage);
  ShowMessage(ShowError(TGPStatus(Err)));

  GdipGetImageHeight(GdiImage, Hei);
  ShowMessage(IntToStr(Hei));

  Err := GdipSaveImageToFile(GdiImage, 'C:\_MyDat\gdi\b.bmp', @GuidPng, nil);
  ShowMessage(ShowError(TGPStatus(Err)));
end;

end.

【问题讨论】:

  • 你必须提供第三个参数Encoderparametersmsdn.microsoft.com/en-us/library/windows/desktop/…
  • 我会说你的代码应该可以工作。很难提供帮助,因为您没有提供完整的程序。如果你提供了一个完整的程序,我可以将它粘贴到我的开发环境中并像这样运行它。但是为了尝试一下,我需要花时间编写一个您已经编写的程序。而且我没有这样做的愿望。
  • @Tom 您是否尝试将其他类型的文件(例如“C:\b.txt”)保存到同一位置?听起来可能是权限问题;无论如何,如果您尝试过一些调试,请说出哪些有效,哪些无效。
  • @Argalatyr 我还在程序中添加了这一行:ShowMessage(IntToStr(Hei));,正如您在完整列表中所见,它显示了我加载的 JPEG 图像的正确高度。所以图像加载得很好,我可以在那个目录中写入。只有 1 行代码:GdipSaveImageToFile(...) 这行不通,我不知道要调试这一行。
  • 看来你找到了你的错误 - 干得好。

标签: image delphi gdi+


【解决方案1】:

似乎我使用了错误的 GUID-s。这些是正确的:

gGIf: TGUID = '{557CF402-1A04-11D3-9A73-0000F81EF32E}';
gPNG: TGUID = '{557CF406-1A04-11D3-9A73-0000F81EF32E}';
gPJG: TGUID = '{557CF401-1A04-11D3-9A73-0000F81EF32E}';
gBMP: TGUID = '{557CF400-1A04-11D3-9A73-0000F81EF32E}';
gTIF: TGUID = '{557CF405-1A04-11D3-9A73-0000F81EF32E}';

之前的好像只有for reading:

【讨论】:

  • 我认为您应该通过将 MIME 类型传递给 API 来获取 CLSID:msdn.microsoft.com/en-us/library/ms533843(v=vs.85).aspx
  • @DavidHeffernan 我看到了一些基于这种方法的解决方案,但我并没有真正看到使用更多功能的意义。 GUID 无论如何都不应该改变。我认为他们制作这个 GetEncoderClsid() 函数只是为了让程序员更容易使用 GDI+ 编写代码(记住 GUID-s 很难),但无论如何使用没有包装器的 GDI 都是地狱。
  • 如果 GUID 是永久的,Windows 会为各种类型提供一个清单常量。不,我认为它们是要改变的,如果你不希望你的程序在未来的某个 Windows 版本下崩溃,你应该总是列举它们。
猜你喜欢
  • 2012-05-09
  • 1970-01-01
  • 1970-01-01
  • 2017-03-01
  • 2020-09-14
  • 2010-10-19
  • 2017-09-12
  • 2011-01-27
  • 1970-01-01
相关资源
最近更新 更多