G A C E T A   D E   L I N U X
...haciendo a Linux un poco más divertido!
Creando/Manipulando imágenes con gd
Por Shuveb Hussain
Traducción al español por Jorge Eduardo Ibarra Esquer
el día 23 de Junio 2003, para La Gaceta de Linux
 

gd es una biblioteca de código abierto escrita para permitir la creación/manipulación de imágenes de una manera sencilla. Con gd se pueden trabajar formatos como jpeg,png,xpm y algunos otros. Se puede ver a gd de la siguiente forma: abre imágenes en distintos formatos y los convierte a imágenes genéricas de mapas de bit en memoria. Con ellas se pueden realizar operaciones gráficas como dibujar líneas, arcos, elipses o rectángulos, y finalmente se puede guardar la imagen resultante en cualquiera de los formatos mencionados. Por ejemplo, podrías escribir un simple programa para la línea de comando que convierta un archivo en formato JPEG a formato PNG utilizando gd. Pero gd puede hacer más cosas. Puede cambiar los colores en la imagen, copiar, cortar, mezclar o rotarla. Otra área donde gd es útil es cuando se quieren crear imágenes al vuelo. Con gd, se puede crear una imagen por programación, colorearla, dibujar sobre ella y guardarla en el disco. gd es más conocido por su uso en la creación de imágenes al vuelo que van a ser usadas en páginas web. Esto se ha hecho posible con la ayudad de PHP.

Si tienes un sistema GNU/Linux que use RPM para el manejo de paquetes, intenta lo siguiente

	rpm -q gd
para ver si gd está instalado. Puedes obtener la versión más reciente en www.boutell.com

Creando Imágenes

El siguiente programa crea una imagen negra de 100x100 pixeles con una línea blanca en diagonal a través de ella.

100x100 imagen creada por gd

Si quieren ahorrarse teclearlo, usen este listado

/* File : gd-eg1.c */
#include < gd.h >
#include < stdio.h >

int main() {
	gdImagePtr im; //declaración de la imagen
	FILE *out; //archivo de salida
	int black,white;

	im = gdImageCreate(100,100); //crea una imagen, 100
por 100 pixeles

	black = gdImageColorAllocate(im, 0, 0, 0); //
asignar color negro
	white = gdImageColorAllocate(im, 255, 255, 255);	//
asignar color blanco
	gdImageLine(im, 0, 0,100,100, white); // dibuja una línea
utilizando el color blanco.

	out = fopen("test.jpg", "w"); //abre un archivo
	gdImageJpeg(im, out, -1); //guarda la imagen en el 
archivo utilizando la calidad por default

	/* sean buenos, dejen todo como estaba */
	fclose(out); 
	gdImageDestroy(im);
}

Compilen el programa con el siguiente comando:

$ gcc gd-eg1.c -lgd

Ejecuten el archivo a.out resultante y deberán tener un archivo test.jpg creado en el directorio actual. Si lo ven, entonces tienen una imagen negra de 100 x 100 pixeles con una línea blanca atravesándola. Estoy seguro que ese programa está muy sencillo, pero voy a explicar un poco del código.
	gdImagePtr im; //declaración de la imagen
	
esto declara un apuntador a un contenedor de imagen de gd.
	
	im = gdImageCreate(100,100); //crea una imagen, 100
por 100 pixeles
	
ahora creamos una imagen de 100 por 100 pixeles y almacenamos la referencia que regresa en la variable im. Esto es muy parecido a un manejador de archivo. Todas las operaciones que se hagan sobre esta imagen, deben realizarse utilizando esta referencia.
	
	black = gdImageColorAllocate(im, 0, 0, 0); //
asignar color negro
	white = gdImageColorAllocate(im, 255, 255, 255);	//
asignar color blanco
	
antes de poder dibujar cualquier cosa sobre la imagen, se debe asignar un color. El primer color que se asigne para una imagen recién creada, será el color de fondo de la imagen. La función gdImageColorAllocate utiliza cuatro parámetros. El primero es el apuntador a la imagen y los siguientes tres son los valores de rojo, verde y azul (Red, Green, Blue), respectivamente. Así, al llamar a gdImageColorAllocate(im, 0, 0, 0) para una nueva imagen, el fondo de ésta se pintará de negro. Los índices de los colores se almacenan en variables porque las funciones gráficas de dibujos o fuentes llevan un parámetro de 'color'.
	
	gdImageLine(im, 0, 0,100,100, white); // dibuja una línea
usando el color blanco asignado.
	
Esta función dibuja una línea desde la esquina superior izquierda (0,0) hasta la esquina inferior derecha (100,100) usando el color blanco sobre la imagen a la que hace referencia im.
	gdImageJpeg(im, out, -1); //guarda la imagen en el
archivo usando la calidad por default.
	
esta es la función que guarda la imagen en un archivo del disco en formato JPEG. El último parámetro de esta función es la calidad de la imagen en formato JPEG. Este valor puede estar entre 1 y 100, donde 100 es la más alta calidad. Usando -1 se obtiene la calidad predefinida.. De manera similar, hay otras funciones que almacenan imágenes en distintos formatos.
	GdImagePng(im,out) // guarda como PNG (aqui no se usa
el parámetro de calidad)
	GdImageGd y gdImageGd2 son funciones que guardan
las imágenes en formatos especificados por la biblioteca.

	gdImageDestroy(im);
	

y finalmente liberan la memoria asignada para mantener los datos de la imagen.

Es importante que vean que actualmente, el formato PNG está teniendo bastante soporte ya que usa mejores algoritmos de compresión. También ofrece una característica que el formato JPEG no tiene: Transparencia. Las imágenes en formato GIF, aunque son lo suficientemente buenas, usan el algoritmo de compresión LZW, patentado por Unisys, al aplicar la máxima compresión a las imágenes. Debido a eso, recientemente, gd dejó de utilizar el formato GIF. De seguro deben haber escuchado acerca de las protestas en contra de las patentes de software..... Algunos sitios web incluso aseguran estar libres de GIF, como latas de spray que aseguran estar "libres de CFC, el cual daña al amigable ozono". Pueden encontrar más información acerca de este tema en www.burnallgifs.org

Manipulando Imágenes

Además de la creación de nuevas imágenes, gd también permite abrir y manipular imágenes existentes. Para ilustrar ésto, tenemos el siguiente programa, el cual abre una imagen de Tux, la hace un poco más grande y escribe sobre ella la cadena "Tux, the Linux Penguin". Además de escribir texto en la imagen, este programa se utilizará para explicar algunas otras funciones que nos serán de utilidad.

Ahorren algo de escritura, usen este listado
AntesDespués
Before manipulationAfter
manipulation

/* File : gd-eg2.c */
#include < gd.h >
#include < stdio.h >

int main() 
{
	gdImagePtr oldtux, newtux; //declaración de los apuntadores a la imagen
	FILE *out, *in;
	int red,white;
	int brect[8];
	char *err;
	
	in = fopen("tuxin.jpg","r");
	oldtux = gdImageCreateFromJpeg(in);
	newtux = gdImageCreate(150,165); //crea una imagen,
150 por 165 pixeles

	white = gdImageColorAllocate(newtux, 255, 255,
255);// asigna el color blanco	
	red = gdImageColorAllocate(newtux, 255, 0, 0); //
asigna el color rojo

gdImageCopyResized(newtux,oldtux,0,0,0,0,150,150,oldtux->sx,oldtux->sy);
	
	err=gdImageStringFT(newtux,brect,
red,"/usr/X11R6/lib/X11/fonts/TTF/luxisr.ttf",10,0,0,160,"Tux
,The Linux Penguin");
	if(err)	fprintf(stderr,"Error : %s\n",err);

	out = fopen("tuxout.jpg", "w"); //abre un archivo
	gdImagePng(newtux, out); //guarda la imagen en el archivo
con formato PNG

	/* sean buenos, dejen todo como estaba */
	fclose(out); 
	fclose(in);
	gdImageDestroy(oldtux);
	gdImageDestroy(newtux);
}

Como pueden ver, este programa utiliza unas pocas más llamadas a funciones. Dichas funciones se describen a continuación

gdImageCopyResized

Esta función de gd, copia partes rectangulares de una imagen dentro de otra. En el proceso de copiado, puede cambiar el tamaño de la imagen. El prototipo de la función es:

void gdImageCopyResized(gdImagePtr dst, gdImagePtr
src, int dstX, int dstY, int srcX, int srcY, int
destW, int destH, int srcW, int srcH);

Los parámetros sx y sy de la estructura gdImagePtr almacenan el ancho y alto de la imagen, respectivamente.

Se habrán dado cuenta que la imagen se distorsiona un poco como resultado del estiramiento. Si tienen gd versión 2.0 o superior, pueden utilizar gdImageCopyResampled, la cual suaviza los bordes cuadrados que se forman debido al estirar o encoger las imágenes. Si quieren copiar porciones de la imagen sin modificar su tamaño, entonces prueben gdImageCopy. Para rotar la imagen mientras la copian, prueben la nueva función gdImageCopyRotated.

gdImageStringFT

Esta función escribe texto sobre la imagen usando la biblioteca freetype, por eso se agrega "FT" al final del nombre de la función. Para usarla deben tener instalada freetype y haber compilado gd con soporte para freetype.

El prototipo es:
char *gdImageStringFT(gdImagePtr im, int *brect, int
fg, char *fontname, double ptsize, double angle, int
x, int y, char *string)

Si se presentan problemas, la función regresa un apuntador tipo char que hace referencia a un mensaje de error, de lo contrario regresa 0. El arreglo brect se llena con el tamaño del rectángulo que rodea a la cadena impresa. También pueden determinar el tamaño de ese rectángulo sin imprimir la cadena. Para ésto, usen como argumento del apuntador a la imagen el valor NULL. Por alguna extraña razón, es necesario usar la ruta absoluta del archivo de la fuente que se utilizará en esta función. Incluso si el archivo se encuentra en el directorio actual, es necesario proporcionar la ruta completa. Esta función solo acepta fuentes TTF. Si sus necesidades son sencillas, pueden usar la función gdImageString. Freetype no es necesario para el correcto funcionamiento de esta función, ya que utiliza cualquiera de las cinco fuentes incluídas en gd.

 

[BIO] Shuveb es un pervertido por obligación social viviendo en una pequeña pero histórica ciudad en el sureste de la India. El piensa que la vida no es ni un Sueño de una Noche de Verano, ni una Tempestad, sino simplemente una Comedia de Errores, para ser vivida Como tu Quieras. Además de ser un filósofo de medio tiempo, es un programador temporal de C que está en constante confusión acerca de lo que el * le hace a una variable tipo puntero.... La compañía que le paga por aprender Linux se llama APR Bristol.


Copyright © 2003, Shuveb Hussain. Licencia de copia http://www.linuxgazette.com/copying.html
Publicado en la edición 91 de Linux Gazette, Junio 2003