Debe quedar claro que hasta el momento no funciona salvo para archivos.tif pues M$ no lo ha implementado para gif en la versión GDI+ 1.0.
delphi
uses Windows; type TCLSID = TGUID; PCLSID = ^TCLSID; TImageCodecInfo = packed record Clsid: TCLSID; FormatID: TGUID; CodecName: PWCHAR; DllName: PWCHAR; FormatDescription: PWCHAR; FilenameExtension: PWCHAR; MimeType: PWCHAR; Flags: DWORD; Version: DWORD; SigCount: DWORD; SigSize: DWORD; SigPattern: PBYTE; SigMask: PBYTE; end; PImageCodecInfo = ^TImageCodecInfo; TEncoderParameter = packed record Guid: TGUID; NumberOfValues: ULONG; Type_: ULONG; Value: Pointer; end; PEncoderParameter = ^TEncoderParameter; TEncoderParameters = packed record Count : UINT; Parameter : array[0..1] of TEncoderParameter; end; PEncoderParameters = ^TEncoderParameters; function wcscmp(wstr1, wstr2: PWCHAR): Integer; cdecl external 'crtdll'; // GDI+ Flat API... function GdiplusStartup(var GdiToken: DWORD; Startup, Output: PBYTE): Cardinal; stdcall external 'gdiplus'; procedure GdiplusShutdown(GdiToken: DWORD); stdcall external 'gdiplus'; function GdipCreateBitmapFromHBITMAP(hbm: HBITMAP; hpal: HPALETTE; var GBitmap: THANDLE): Cardinal; stdcall external 'gdiplus'; function GdipCreateHBITMAPFromBitmap(GBitmap: THANDLE; var hBitmap: HBITMAP; BKColor: DWORD): DWORD; stdcall external 'gdiplus'; function GdipGetImageEncodersSize(var numEncoders: DWORD; var size: DWORD): Cardinal; stdcall external 'gdiplus'; function GdipGetImageEncoders(numEncoders, size: DWORD; encoders: PImageCodecInfo): Cardinal; stdcall external 'gdiplus'; function GdipDisposeImage(image: THANDLE): Cardinal; stdcall external 'gdiplus'; function GdipCreateBitmapFromFile(lpFileName: PWCHAR; var GBitmap: THANDLE): DWORD; stdcall external 'gdiplus'; function GdipSaveImageToFile(image: THANDLE; FileName: PWCHAR; var clsidEncoder: TCLSID; encoderParams: Pointer): Cardinal; stdcall external 'gdiplus'; function GdipImageGetFrameDimensionsList(image: THANDLE; var dimensionIDs: TGUID; count: DWORD): DWORD; stdcall external 'gdiplus'; function GdipImageGetFrameCount(image: THANDLE; var dimensionID: TGUID; var count: DWORD): DWORD; stdcall external 'gdiplus'; function GdipImageSelectActiveFrame(image: THANDLE; var dimensionID: TGUID; frameIndex: DWORD): DWORD; stdcall external 'gdiplus'; function GdipSaveAddImage(image: THANDLE; newImage: THANDLE; encoderParams: Pointer): DWORD; stdcall external 'gdiplus'; function GdipSaveAdd(image: THANDLE; encoderParams: Pointer): DWORD; stdcall external 'gdiplus'; // Obtener el CLSID para la codificación de un formato gráfico function GetEncoderClsid(Format: PWCHAR; var Clsid: TCLSID): boolean; var i, N, Size: Cardinal; ICInfo: array of TImageCodecInfo; begin i:= 0; N:= 0; Size:= 0; GdipGetImageEncodersSize(N, Size); if Size > 0 then begin SetLength(ICInfo, Size); GdipGetImageEncoders(N, Size, @ICInfo[0]); while (i<N) and (wcscmp(ICInfo[i].MimeType, Format)<>0) do inc(i); if i<N then Clsid:= ICInfo[i].Clsid; end; Result:= boolean(i<N); end; function CreateHBITMAPFromFilePage(FileName: PWCHAR; Index: DWORD): HBITMAP; var GBitmap: THANDLE; DimensionID: TGUID; Frames: DWORD; begin Result:= 0; GdipCreateBitmapFromFile(PWCHAR(FileName), GBitmap); GdipImageGetFrameDimensionsList(GBitmap, dimensionID, 1); GdipImageGetFrameCount(GBitmap, dimensionID, Frames); GdipImageSelectActiveFrame(GBitmap, dimensionID, Index mod Frames); GdipCreateHBITMAPFromBitmap(GBitmap, Result, 0); end; //--------------------------------------------------------------------------- // Guarda un HBITMAP en un archivo con un formato gráfico determinado type ABITMAP = array of HBITMAP; procedure SaveBitmapToMultipageFileW(Bitmaps: ABITMAP; FileName, Format: PWCHAR; Quality: ULONG=100); const EncoderQuality: TGUID = '{1d5be4b5-fa4a-452d-9cdd-5db35105e7eb}'; EncoderSaveFlag: TGUID = '{292266fc-ac40-47bf-8cfc-a85b89a655de}'; EncoderParameterValueTypeLong = 4; EncoderValueMultiFrame = 18; EncoderValueLastFrame = 19; EncoderValueFlush = 20; EncoderValueFrameDimensionPage = 23; var i: integer; Clsid: TCLSID; EP: TEncoderParameters; Image, newImage: THANDLE; parameterValue: ULONG; begin EP.Count:= 2; EP.Parameter[0].Guid:= EncoderQuality; EP.Parameter[0].Type_:= EncoderParameterValueTypeLong; EP.Parameter[0].NumberOfValues:= 1; EP.Parameter[0].Value:= @Quality; EP.Parameter[1].Guid:= EncoderSaveFlag; EP.Parameter[1].Type_:= EncoderParameterValueTypeLong; EP.Parameter[1].NumberOfValues:= 1; EP.Parameter[1].Value:= @parameterValue; parameterValue:= EncoderValueMultiFrame; GetEncoderClsid(Format, Clsid); GdipCreateBitmapFromHBITMAP(Bitmaps[0], 0, Image); GdipSaveImageToFile(Image, FileName, Clsid, @EP); parameterValue:= EncoderValueFrameDimensionPage; for i:= 1 to Length(Bitmaps)-1 do begin GdipCreateBitmapFromHBITMAP(Bitmaps[i], 0, newImage); GdipSaveAddImage(Image, newImage, @EP); end; parameterValue:= EncoderValueFlush; GdipSaveAdd(Image, @EP); GdipDisposeImage(Image); GdipDisposeImage(newImage); end;
SaveBitmapToMultipageFileW recibe un array de HBITMAPS y los guarda en un archivo con calidad de compresión ajustable. Dado que sólo funciona para tif, quizás el argumento Format sobre, pero si en un futuro se añaden los gif, es muy posible que funcione sin cambios en el código.
Un ejemplo de uso:
delphi
var gdiplusToken: DWORD; GdiPlusStartupInput: array[0..2] of int64; Bitmaps: ABITMAP; i: integer; begin // Inicializamos GDI+. GdiPlusStartupInput[0]:= 1; GdiPlusStartupInput[1]:= 0; if GdiplusStartup(gdiplusToken, @GdiPlusStartupInput, nil) <> 0 then exit; // lo que sigue es para conseguir varias imágenes... SetLength(Bitmaps, 5); for i:=0 to 4 do begin Bitmaps[i]:= CreateHBITMAPFromFilePage('Fax1.tif', i); end; // El ejemplo de uso. Solo funciona con Tif, no con Gif SaveBitmapToMultipageFileW(Bitmaps, 'Imagen.tif', 'image/tiff'); // Shutdown GDI+ GdiplusShutdown(gdiplusToken); end.
Saludos.