2 de julio de 2007

Convertir imágenes a color monocromático con GdiPlusX

Artículo original: Convert Images to Monochrome with GdiPlus X
http://weblogs.foxite.com/vfpimaging/archive/2007/05/26/3857.aspx
Autor: Cesar Ch.
Traducido por: Ana María Bisbé York


Cada cierto tiempo, alguien pregunta sobre la creación de imágenes monocromáticas, que en la mayoría de los casos se utilizarán para enviar por Fax.

Desafortunadamente, GDI+ no brinda soporte para imágenes indexadas a 1 bpp (bipmaps monocromos)

Pero con la ayuda de Anatoliy Mogylevets y Mike Gagnon pude encontrar que la buena y vieja GDI (no GdiPlus) ofrece algunas funciones (CopyImage y LoadImage) para hacerlo en un flash. Entonces, estuvimos de acuerdo en añadir esta importante funcionalidad a la biblioteca como un método nuevo agregado a las clases Image y Bitmap: GetMonochrome().

Pasos para obtener la versión 1bpp monocromática de cualquier imagen utilizando las clases GDI+X
  1. Cargar la imagen con GdiPlus
  2. Llamar a Image.GetMonochrome para obtener un objeto nuevo que contenga la imagen 1bpp.
  3. Guardar normalmente como Bmp.
IMPORTANTE:
Todos los ejemplos siguientes utilizan la nueva biblioteca GdiPlus-X, que está en versión ALPHA; pero que es muy estable y fiable para hacer la mayoría de las tareas GDI+. Descargue la versión más actualizada desde Codeplex:

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

Este es el código de ejemplo:
_SCREEN.AddProperty("System", NEWOBJECT("xfcSystem", LOCFILE("system.vcx","vcx")))
WITH _SCREEN.System.Drawing
  * Crear un objeto Bitmap basado en un archivo BMP.
  LOCAL loOriginalBmp AS xfcBitmap
  loOriginalBmp = .Bitmap.New(GETPICT())
  LOCAL loMonoChrBmp as xfcBitmap
  loMonoChrBmp = loOriginalBmp.GetMonochrome()
  * Guardar el Bmp monocromático que ha sido creado
  loMonoChrBmp.Save("c:\Monocromatico.bmp", .Imaging.ImageFormat.Bmp)
ENDWITH
RETURN
Y este es el resultado para dos imágenes:





La primera imagen tiene buen aspecto, a que si?

Pero el logo VFPX no aparece en color monocromático. Esto ocurre porque el fondo naranja del texto es oscuro y GDI lo convierte en negro.

Pero utilizando un truco podemos arreglarlo, al convertir la imagen en escala de grises antes de convertirlo en monocromático. No está dentro del alcance de este corto artículo explicar cómo hacer esto, porque ya me dediqué a esto profundamente en dos artículos publicados en UTMAG Special effects on images with new GDIPlus-X classes - Part 1 y Special effects on images with new GDIPlus-X classes - Part 2.

Para convertir a escala de grises, podemos utilizar una matriz de color que va a convertir cada píxel en un promedio entre sus componentes rojo, azul y verde. Para escala de grises normalmente multiplicamos cada componente de color con 0.33 (1/3). Para obtener una imagen más brillante tenemos que multiplicar cada componente por un factor más alto.

Por tanto, he aquí los pasos para convertir a color monocromático:
  1. Crear la imagen originar con GDI+
  2. Crear un Bitmap nuevo temporal del mismo tamaño que el original
  3. Crear un objeto ImageAttributes
  4. Aplicar una matriz de color con escala de grises a la imagen Attributes
  5. Dibujar la imagen original utilizando ImageAttributes
  6. Guardar la imagen
Para este ejemplo he creado un lazo utilizando un factor con rango .10 a 1, para obtener imágenes diferentes.
_SCREEN.AddProperty("System", NEWOBJECT("xfcSystem", LOCFILE("system.vcx","vcx")))
WITH _SCREEN.System.Drawing
  LOCAL lcImgFile
  lcImgFile = GETPICT()
  * Crea un objeto Bitmap basado en un archivo BMP.
  LOCAL loOriginalBmp AS xfcBitmap
  loOriginalBmp = .Bitmap.FromFile(lcImgFile)
  LOCAL loTempBmp as xfcBitmap
  loTempBmp = .Bitmap.New(loOriginalBmp.Width, loOriginalBmp.Height)
  LOCAL loGfx as xfcGraphics
  loGfx = .Graphics.FromImage(loTempBmp)
  LOCAL loAttr as xfcImageAttributes
  LOCAL loGreyScaleMatrix as xfcColorMatrix
  LOCAL loMonoChrBmp as xfcBitmap
  LOCAL loRectBounds as xfcRectangle
  loRectBounds = loOriginalBmp.GetBounds()
  FOR lnFactor = .10 TO 1 STEP .10
    loGreyScaleMatrix = _Screen.System.Drawing.Imaging.ColorMatrix.New( ;
      lnFactor, lnFactor, lnFactor, 0.0, 0.0, ;
      lnFactor, lnFactor, lnFactor, 0.0, 0.0, ;
      lnFactor, lnFactor, lnFactor, 0.0, 0.0, ;
      0.0 , 0.0 , 0.0 , 1.0, 0.0, ;
      0.0 , 0.0 , 0.0 , 0.0, 1.0)
    loAttr = NULL
    loAttr = .Imaging.ImageAttributes.New()
    loAttr.SetColorMatrix(loGreyScaleMatrix)
    * Dibujar una imagen con las transformaciones en la matriz de colores
    loGfx.DrawImage(loOriginalBmp, loRectBounds, loRectBounds, 2, loAttr)
    loMonoChrBmp = loTempBmp.GetMonochrome()
    * Guarda el Bmp monocromático que ha sido creado
    loMonoChrBmp.Save("c:\" + JUSTSTEM(lcImgFile) + ;
      TRANSFORM(lnFactor * 100) + ".bmp", .Imaging.ImageFormat.Bmp)
  ENDFOR
ENDWITH
RETURN
Y esta vez podemos obtener mejores resultados, acorde con el factor deseado.

Imagen Original
Factor = 10 Factor = 20 Factor = 30 Factor = 40 Factor = 50
Factor = 60 Factor = 70 Factor = 80 Factor = 90 Factor = 100


Imagen Original
Factor = 10 Factor = 20 Factor = 30 Factor = 40 Factor = 50
Factor = 60 Factor = 70 Factor = 80 Factor = 90 Factor = 100

Enlaces relacionados:

Artículos en UTMAG

No hay comentarios. :

Publicar un comentario