Quizás esto te aclare un poco más las cosas. Te presento una función que extrae un icono determinado de un archivo de icono que porta más de una imagen.
Quizás lo apetecible sea hacerlo con la API
ExtractIcon o incluso con
ExtractIconEx pero ninguna de las dos acierta con el numero exacto de imágenes que tiene un archivo ico. Así que he escrito una función a bajo nivel que los busca, identifica uno por su índice y lo guarda en solitario en otro archivo ico.
Este es el código y las estructuras necesarias:
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}
Código Delphi
[-]
function ExtractIconFromFile(SourceFileName, DestFileName: String; Index: integer): integer;
var
Stream, SDest: TMemoryStream;
IconDir, IconDirDest: PICONDIR;
AllSize: integer;
SImage, DImage: PBYTE;
begin
Stream:= TMemoryStream.Create;
SDest:= TMemoryStream.Create;
Stream.LoadFromFile(SourceFileName);
IconDir:= Stream.Memory;
Result:= IconDir.idCount;
if Index < Result 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);
SDest.SaveToFile(DestFileName);
end;
Stream.Free;
SDest.Free;
end;
La función devuelve el número de iconos encontrado, si el índice es menor que ese número, guarda ese icono en un archivo. Si el indice es -1 o el no hay nombre de archivo de salida, simplemente devuelve el número de iconos encontrado.
Ejemplo de uso:
Código Delphi
[-]
var
IconCount: integer;
begin
IconCount:= ExtractIconFromFile('icon.ico', 'p2.ico', 2);
end;
Saludos.