6 de junio de 2015

Convertir BMP a ICONO - Parte 1

Artículo original: Convert BMP to ICON - Part 1
http://weblogs.foxite.com/vfpimaging/archive/2007/07/13/4346.aspx
Autor: Cesar Ch.
Traducido por: Luis María Guayán


Se sabe que GDI+ no trae soporte total para los archivos de iconos. Por lo tanto, no podemos hacer ninguna conversión sencilla para crear archivos .ICO directamente.

Pero hay algunos trucos fáciles que podemos utilizar para hacer esto. El primer paso es tomar el handle del icono de nuestro BITMAP, el "hIcon".

El planteamiento más sencillo es utilizar la API OleCreatePictureIndirect para obtener una referencia al objeto OLE de la imagen. El paso siguiente es enviar este objeto a la función SAVEPICTURE() para guardarla en el disco.

Pero el problema de esta técnica es que los iconos están generados en una mala calidad, 4bpp (4 bits por pixel). Esto significa que los iconos pueden tener como máximo 2^4 = 16 colores, esto trae resultados realmente feos y de mala calidad.

Abajo está el código:

IMPORTANTE

Requiere VFP9 y GdiPlusX para funcionar.

¡Por favor asegúrese que tiene la última versión!

http://www.codeplex.com/VFPX/Wiki/View.aspx?title=GDIPlusX&referringTitle=Home

* API Declarations
DECLARE SHORT DestroyIcon IN user32 INTEGER hIcon 
DECLARE LONG OleCreatePictureIndirect IN oleaut32 ;
   STRING @PictDesc , STRING @riid , LONG Own , OBJECT @Obj

* Initialize GdiPlusX
_SCREEN.AddProperty("System", NEWOBJECT("xfcSystem", LOCFILE("system.vcx")))

LOCAL lcPict, lcIconFile
lcPict = GETPICT("bmp")
lcIconFile = "c:\" + JUSTSTEM(lcPict) + ".ico"

WITH _SCREEN.System.Drawing
   LOCAL lhIcon
   LOCAL loBmp as xfcBitmap
   loBmp = .Bitmap.FromFile(lcPict)
   lhIcon = loBmp.GetHicon()
ENDWITH 
 
IF lhIcon # 0 
   *!* typedef struct tagPICTDESC 
   *!* { 
   *!* UINT cbSizeofstruct; 
   *!* UINT picType; 
   *!* HICON hicon; 
   *!* } icon; 
   *!* struct 
   *!* { 
   *!* HENHMETAFILE hemf; 
   *!* } emf; 
   *!* } ; 
   *!* } PICTDESC;

   #DEFINE PICTYPE_ICON 3
   #DEFINE GUID_Icon2 0h0004020000000000C000000000000046 && "{00020400-0000-0000-C000-000000000046}"
   #DEFINE GUID_Icon 0h8109F87B32BF1A108BBB00AA00300CAB && "{7BF80981-BF32-101A-8BBB-00AA00300CAB}"

   LOCAL lcPictDesc, lqGuid, loIconObj
   lcPictDesc = BINTOC(16,"4RS") + ; && Size of Structure
      BINTOC(PICTYPE_ICON, "4RS") + ; && Type of Image
      BINTOC(lhIcon, "4RS") + ; && Image Handle
      BINTOC(0, "4RS")

   lqGuid = GUID_Icon
   loIconObj = 0 

   *!* http://msdn2.microsoft.com/en-us/library/ms694511.aspx
   *!* STDAPI OleCreatePictureIndirect( 
   *!* PICTDESC* pPictDesc, //Pointer to the structure of parameters for picture
   *!* REFIID riid, //Reference to the identifier of the interface
   *!* BOOL fOwn, //Whether the picture is to be destroyed
   *!* If TRUE, the picture object is to destroy its picture when the object is destroyed. 
   *!* If FALSE, the caller is responsible for destroying the picture.
   *!* VOID** ppvObj //Address of output variable that receives the 
   *!* // interface pointer requested in riid
   *!* );

   * Create the picture OLE object
   OleCreatePictureIndirect(@lcPictDesc, @lqGuid, 1, @loIconObj)

   IF VARTYPE(loIconObj) = 'O'
      * Save the picture using VFP native function 'savepicture()' 
      IF SAVEPICTURE(loIconObj, lcIconFile) 
         MESSAGEBOX('Icon created successfully !', 64) 
      ENDIF 
   ELSE 
   MESSAGEBOX('OleCreatePictureIndirect() Error', 16) 
ENDIF 

* Free the memory handle allocated for the hIcon
= DestroyIcon(lhIcon) 
ENDIF 
RETURN
Imagen original .BMPImagen .ICO (16 colores)

Puedes intentarlo sin ejecutar este código: Abrir MsPaint, y cargar una de las cuatro imágenes a la izquierda. Luego, seleccionar guardar la imagen como un bitmap de 16 colores, y obtendrás exactamente el mismo resultado que generó OLECreatePictureIndirect. Esta utilizará solamente la paleta de colores de abajo para convertir la imagen.

De manera, como el resultado no es tan bueno como deseamos, ¿por qué puse este códigos aquí?

Esto está porque la libreria original del .NET "System.Drawing" utiliza un planteamiento similar como el mostrado arriba, para crear iconos en el método Icon.Save().

En el siguiente artículo mostraré cómo podemos convertir nuestros BitMaps a iconos de alta calidad, pero utilizando algunas buenas y viejas técnicas de GDI (no Gdi+). ¡El código no será sencillo ni corto como el mostrado aquí, pero el funcionamiento será similar y la calidad será perfecta!


1 comentario :

  1. Hola Luis cual es el método para guardar los iconos con una mejor calidad

    ResponderBorrar

Los comentarios son moderados, por lo que pueden demorar varias horas para su publicación.