http://weblogs.foxite.com/vfpimaging/2006/03/18/drawing-on-gifs-or-indexed-pixel-format-images-with-gdi-/
Autor: Cesar Ch.
Traducido por: Ana María Bisbé York
Es muy común que necesitemos dibujar algunas formas, textos o aplicar algunos efectos a las imágenes.
Pero GDI+ tiene limitaciones al trabajar con imágenes creadas en formatos de índices pixelados, tales como 1 bppIndexed (0x00030101), 4bppIndexed (0x00030402) and 8bppIndexed (0x00030803). Estos son formatos de pixel utilizados también por GIF (Graphics Interchange Format). Si intenta dibujar en este tipo de imágenes puede recibir un error de este tipo:
Una solución muy sencilla es cargar el GIF utilizando GpImage, y obtener algunas propiedades, tales como Width y Height. Luego, crea un objeto imagen nuevo y vacío con el mismo tamaño que el GIF original; pero utilizando formato indizado pixel. _gdiplus.vcx utiliza PIXELFORMAT_32bppPARGB como predeterminado.
El siguiente paso es "dibujar" el GIF original en el bitmap creado en un formato pixel no indizado utilizando el procedimiento DrawImage. Ahora puede dibujar libremente sobre esta nueva imagen.
Finalmente, puede guardar la imagen nueva como GIF o cualquier otro tipo.
Un detalle importante que debe conocer es que cuando le pide a GDI+ que lo almacene como GIF, lo convertirá automáticamente la imagen nuevamente 8 a un formato 8bppIndexed, que es el predeterminado para GDI+.
He aquí un ejemplo de código que realiza esto, dibujando dos elipses y un rectángulo sobre una imagen.
#DEFINE GDIPLUS_PIXELFORMAT_1bppIndexed 0x00030101 #DEFINE GDIPLUS_PIXELFORMAT_4bppIndexed 0x00030402 #DEFINE GDIPLUS_PIXELFORMAT_8bppIndexed 0x00030803 #DEFINE GDIPLUS_PIXELFORMAT_16bppGrayScale 0x00101004 #DEFINE GDIPLUS_PIXELFORMAT_16bppRGB555 0x00021005 #DEFINE GDIPLUS_PIXELFORMAT_16bppRGB565 0x00021006 #DEFINE GDIPLUS_PIXELFORMAT_16bppARGB1555 0x00061007 #DEFINE GDIPLUS_PIXELFORMAT_24bppRGB 0x00021808 #DEFINE GDIPLUS_PIXELFORMAT_32bppRGB 0x00022009 #DEFINE GDIPLUS_PIXELFORMAT_32bppARGB 0x0026200A #DEFINE GDIPLUS_PIXELFORMAT_32bppPARGB 0x000E200B #DEFINE GDIPLUS_PIXELFORMAT_48bppRGB 0x0010300C LOCAL lcSource, lcDest lcSource = GETPICT("gif") IF EMPTY(lcSource) RETURN ENDIF lcDest = ADDBS(JUSTPATH(lcSource))+ "_" + JUSTSTEM(lcSource) *** Carga la imagen y verifica si está indizada : LOCAL loImage AS GPIMAGE OF ffc/_gdiplus.vcx loImage = NEWOBJECT('gpImage',HOME() + 'ffc/_gdiplus.vcx') loImage.CreateFromFile(lcSource) wImg = loImage.Imagewidth hImg = loImage.ImageHeight lcPixFormat = GetPixFormatName(loImage.PixelFormat) IF NOT "INDEXED" $ UPPER(lcPixFormat) MESSAGEBOX("Dibuje directamente sobre la imagen, ya que no tiene formato " + ; "de pixel indizado !",64, "UTILICE LA TÉCNICA HABITUAL") RETURN ENDIF *** Crea un nuevo bitmap con las mismas dimensiones : LOCAL loBitmap AS GpBitmap OF ffc/_gdiplus.vcx loBitmap = NEWOBJECT("GpBitmap", HOME() + "ffc/_gdiplus.vcx") LOCAL loGraph AS GpGraphics OF HOME() + ffc/_gdiplus.vcx loGraph = NEWOBJECT('GpGraphics', HOME() + "ffc/_gdiplus.vcx") loBitmap.CREATE(wImg, hImg, GDIPLUS_PIXELFORMAT_16bppRGB555 ) *** Pega la imagen original sobre la nueva imagen recién creada : loGraph.CreateFromImage(loBitmap) loGraph.DrawImageScaled(loImage, 0, 0, wImg, hImg) *** Ahora podemos dibujar lo que deseemos sobre la imagen : LOCAL loBlue, loRed, loGreen AS GpColor OF ffc/_gdiplus.vcx LOCAL loPen AS GpPen OF HOME() + ffc/_gdiplus.vcx loBlue = NEWOBJECT("GpColor", HOME() + "ffc/_gdiplus.vcx","",40,40,240 ) loRed = NEWOBJECT("GpColor", HOME() + "ffc/_gdiplus.vcx","",240,40,40 ) loGreen = NEWOBJECT("GpColor", HOME() + "ffc/_gdiplus.vcx","",40,230,40 ) loPen = NEWOBJECT("GpPen", HOME() + "ffc/_gdiplus.vcx") loPen.CREATE(loBlue, 12) loGraph.DrawEllipse( loPen, 0, 0, wImg, hImg) loPen.PenColor = loRed loGraph.DrawEllipse( loPen, 0+12, 0+12 , wImg-24 , hImg-24) loPen.PenColor = loGreen loGraph.DrawRectangle( loPen, 0+30, 0+30 , wImg-60 , hImg-60) *** Guarda la imagen en GIF y JPG : loBitmap.SaveToFile(lcDest+".jpg","image/jpeg","quality=100") loBitmap.SaveToFile(lcDest+".gif","image/gif") RETURN PROCEDURE GetPixFormatName(nPix) DO CASE CASE nPix = 0x00030101 RETURN "1bppIndexed" CASE nPix = 0x00030402 RETURN "4bppIndexed" CASE nPix = 0x00030803 RETURN "8bppIndexed" CASE nPix = 0x00101004 RETURN "16bppGrayScale" CASE nPix = 0x00021005 RETURN "16bppRGB555" CASE nPix = 0x00021006 RETURN "16bppRGB565" CASE nPix = 0x00061007 RETURN "16bppARGB1555" CASE nPix = 0x00021808 RETURN "24bppRGB" CASE nPix = 0x00022009 RETURN "32bppRGB" CASE nPix = 0x0026200A RETURN "32bppARGB" CASE nPix = 0x000E200B RETURN "32bppPARGB" CASE nPix = 0x0010300C RETURN "48bppRGB" CASE nPix = 0x001C400E RETURN "64bppPARGB" OTHERWISE RETURN "No identificado" ENDCASE ENDPROCEste procedimiento tiene un gran inconveniente, ya que en esta conversión automática, GDI+ escribe el archivo utilizando una paleta de medio tono por lo que el objeto imagen tendrá el color reducido. GDI+ hace la conversión a color desde 32 bits-por-pixel (32 BPP) al escribir la imagen al archivo.
De acuerdo con Szaak Priester: "Cuando GDI+ guarda un bitmap en formato GIF, realiza una forma cruda de determinación de los valores (cuantización) de los colores. Siempre emplea la misma paleta de colores, se rellena fundamentalmente con los 216 "colores Web-safe" Al inicio de Internet, estos colores eran los únicos mostrados consistentemente por la mayoría de los examinadores, de ahí su nombre... los 216 colores web-safe fueron escogidos básicamente por sus méritos técnicos (dividen uniformemente el espacio d color RGB) y no debido a sus cualidades visuales. Como consecuencia, la paleta web-safe (llamada también "paleta de medio tono") contiene fundamentalmente púrpuras casi perceptibles, muchos verdosos y marrones turbios, por tato, mucha parte utilizable del espectrum es seriamente poco poplado."
Debajo, puede ver el resultado que se obtiene utilizando la técnica que se ha comentado aquí.
GIF - Imagen original | GIF - 8bppIndexed Image | JPEG - 32bppARGB |
Preste atención a la diferencia entre la calidad de estas tres imágenes.
Esta técnica puede ser utilizada también para redimensional cualquier imagen, incluyendo GIFs. Con el objeto de redimensionar, todo lo que necesitamos es cambiar en el código anterior las instrucciones que tratan del tamaño de imagen, loBitmap.Create(NewWidth, NewHeight, PixelFormat) y al pegar la imagen original en la creada nueva, loGraph.DrawImagePortionat(loOriginalImage, 0, 0, NewWidth, newHeight).
Necesitas solamente conocer las limitaciones de GIFs y decidir si guardará la imagen como GIF o como otro formato de imagen.
He aquí algunas diferencias entre formatos GIFs y JPEGs, de acuerdo con MSDN:
GIF vs. JPEG
¿Debe guardar las imágenes en formato GIF o JPEG? Aunque esta pregunta no está relacionada directamente con la administración de la paleta, confunde a mucha gente, y es de alguna manera relevante para nuestro tema.
Existen dos diferencias fundamentales entre imágenes GIF y JPEG:
Las imágenes GIF están comprimidas de forma que conservan todos sus datos, mientras las imágenes JPEG están comprimidas de forma que pierden muchos de sus datos.Pero ... ¿existe una forma de convertir una imagen en un formato GIF sin emplear una paleta de colores mejor distribuida en lugar de una paleta de medio tono que estropea las imágenes? Por supuesto; pero esto ya es tema para otro artículo ...
Las imágenes GIF están limitadas como máximo a 256 colores, mientras las imágenes JPEG no están limitadas por la cantidad de colores que utilizan.
No hay comentarios. :
Publicar un comentario
Los comentarios son moderados, por lo que pueden demorar varias horas para su publicación.