Ver Mensaje Individual
  #4  
Antiguo 07-03-2020
Avatar de escafandra
[escafandra] escafandra is offline
Miembro Premium
 
Registrado: nov 2007
Posts: 2.197
Reputación: 20
escafandra Tiene un aura espectacularescafandra Tiene un aura espectacular
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;               // Width of the image
   bHeight: BYTE;              // Height of the image (times 2)
   bColorCount: BYTE;          // Number of colors in image (0 if >=8bpp)
   bReserved: BYTE;            // Reserved
   wPlanes: WORD;              // Color Planes
   wBitCount: WORD;            // Bits per pixel
   dwBytesInRes: DWORD;        // how many bytes in this resource?
   dwImageOffset: DWORD;       // where in the file is this image
end; PICONDIRENTRY = ^TICONDIRENTRY;

type TICONDIR = record
   idReserved: WORD; // Reserved
   idType: WORD;     // resource type (1 for icons)
   idCount: WORD;    // how many images?
   idEntries: array[0..0] of TICONDIRENTRY; // the entries for each image
end; PICONDIR = ^TICONDIR;

type tagICONIMAGE= record
   icHeader: BITMAPINFOHEADER;       // DIB header
   icColors: array[0..0] of RGBQUAD; // Color table
   icXORarray: array[0..0] of BYTE;  // DIB bits for XOR mask
   icANDarray: array[0..0] of BYTE;  // DIB bits for AND mask
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.
Responder Con Cita