Ver Mensaje Individual
  #5  
Antiguo 08-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
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;               // 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}



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';

// GDI+ Flat API...
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 [-]
// Calidad de imagen y factor de compresión
// Quality = 100 es la maxima calidad.
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; //Gdiplus::EncoderParameterValueTypeLong;
  EP.Parameter[0].NumberOfValues:= 1;
  EP.Parameter[0].Value:= Quality;
end;
 
// 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;

//---------------------------------------------------------------------------
// Guarda un HBITMAP en un archivo con un formato gráfico determinado
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
  // Inicializamos GDI+.
  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);

  // Shutdown GDI+
  GdiplusShutdown(gdiplusToken);
end;



// Encuentra una imagen de icono y la guarda como png
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.

Última edición por escafandra fecha: 08-03-2020 a las 00:06:34.
Responder Con Cita