Y para continuar con la respuesta, te muestro cómo guardar la imagen de un icono localizado por su índice en un archivo png utilizando GDI+ Flat API. El código esta escrito y compilado con delphi7
Código Delphi
[-]
type
{$ALIGN 1}
TICONDIRENTRY = record
bWidth: BYTE; bHeight: BYTE; bColorCount: BYTE; bReserved: BYTE; wPlanes: WORD; wBitCount: WORD; dwBytesInRes: DWORD; dwImageOffset: DWORD; end; PICONDIRENTRY = ^TICONDIRENTRY;
type TICONDIR = record
idReserved: WORD; idType: WORD; idCount: WORD; idEntries: array[0..0] of TICONDIRENTRY; end; PICONDIR = ^TICONDIR;
type tagICONIMAGE= record
icHeader: BITMAPINFOHEADER; icColors: array[0..0] of RGBQUAD; icXORarray: array[0..0] of BYTE; icANDarray: array[0..0] of BYTE; end; PICONIMAGE = ^tagICONIMAGE;
{$ALIGN OFF}
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..0] of TEncoderParameter;
end;
PEncoderParameters = ^TEncoderParameters;
function wcscmp(wstr1, wstr2: PWCHAR): Integer; cdecl external 'crtdll';
function GdiplusStartup(var GdiToken: DWORD; Startup, Output: PBYTE): Cardinal; stdcall external 'gdiplus';
procedure GdiplusShutdown(GdiToken: DWORD); stdcall external 'gdiplus';
function GdipCreateBitmapFromHICON(Icon: HICON; var GBitmap: THANDLE): Cardinal; stdcall external 'gdiplus';
function GdipCreateBitmapFromHBITMAP(hbm: HBITMAP; hpal: HPALETTE; var GBitmap: THANDLE): Cardinal; 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 GdipSaveImageToFile(image: THANDLE; FileName: PWCHAR; var clsidEncoder: TCLSID; encoderParams: Pointer): Cardinal; stdcall external 'gdiplus';
Código Delphi
[-]
procedure GetEncoderParameters(EP: PEncoderParameters; Quality: PULONG);
const
EncoderQuality: TGUID = '{1d5be4b5-fa4a-452d-9cdd-5db35105e7eb}';
begin
EP.Count:= 1;
EP.Parameter[0].Guid:= EncoderQuality;
EP.Parameter[0].Type_:= 4; EP.Parameter[0].NumberOfValues:= 1;
EP.Parameter[0].Value:= Quality;
end;
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;
procedure SaveIconToFile(Icon: HICON; FileName, Format: PWCHAR; Quality: ULONG=100);
var
gdiplusToken: DWORD;
GdiPlusStartupInput: array[0..2] of int64;
Clsid: TCLSID;
EP: TEncoderParameters;
GBitmap: THANDLE;
begin
GdiPlusStartupInput[0]:= 1; GdiPlusStartupInput[1]:= 0;
if GdiplusStartup(gdiplusToken, @GdiPlusStartupInput, nil) <> 0 then exit;
GetEncoderClsid(Format, Clsid);
GetEncoderParameters(@EP, @Quality);
GdipCreateBitmapFromHICON(Icon, GBitmap);
GdipSaveImageToFile(GBitmap, FileName, Clsid, @EP);
GdipDisposeImage(GBitmap);
GdiplusShutdown(gdiplusToken);
end;
function IconToPng(IconFileName, PngFileName: String; index: integer): integer;
var
Stream, SDest: TMemoryStream;
IconDir, IconDirDest: PICONDIR;
AllSize: integer;
SImage, DImage: PBYTE;
Icon: TIcon;
begin
Stream:= TMemoryStream.Create;
SDest:= TMemoryStream.Create;
Stream.LoadFromFile(IconFileName);
IconDir:= Stream.Memory;
Result:= IconDir.idCount;
if (Index >= 0) and (Index < Result) and (PngFileName <> '') then
begin
AllSize:= sizeof(ICONDIR) + IconDir.idEntries[index].dwBytesInRes;
SDest.SetSize(AllSize);
IconDirDest:= SDest.Memory;
IconDirDest.idReserved:= 0;
IconDirDest.idType:= 1;
IconDirDest.idCount:= 1;
IconDirDest.idEntries[0]:= IconDir.idEntries[index];
IconDirDest.idEntries[0].dwImageOffset:= sizeof(TICONDIR) + sizeof(TICONDIRENTRY);
SImage:= Stream.Memory;
inc(SImage, IconDir.idEntries[index].dwImageOffset);
DImage:= SDest.Memory;
inc(DImage, IconDirDest.idEntries[0].dwImageOffset);
CopyMemory(DImage, SImage, IconDir.idEntries[index].dwBytesInRes);
Icon:= TIcon.Create;
SDest.Position:= 0;
Icon.LoadFromStream(SDest);
SaveIconToFile(Icon.Handle, PWChar(WideString(PngFileName)), 'image/png');
Icon.Free;
end;
Stream.Free;
SDest.Free;
end;
En realidad la función SaveIconToFile es mucho más potente pues puede guardar el icono en cualquiera de los formatos que admite GDI+ (BMP, GIF, JPEG, PNG, TIFF, WMF, EMF e ICON).
Saludos.