martes, junio 15, 2010

GD library PHP

Libreria GD

Para entender perfectamente esta librería, les viene muy bien leer los siguientes apuntes (si no lo tienen muy claro):


También, estas funciones otorgan las propiedades de la imagen:

Código
imagesx($im); //devuelve el ancho de la imagen

imagesy($im); //devuelve el alto de la imagen

getimagesize($direccion);

La función getimagesize devuelve un array con los datos de la imagen. Por ejemplo, aplicándolo a la imagen http://blog.nuestroclima.com/wp-content/uploads/2007/08/imagen_satelital_hires.jpg devuelve:
Código:
Array

(

    [0] => 4096       Ancho

    [1] => 4096       Altura

    [2] => 2

    [3] => width="4096" height="4096"

    [bits] => 8

    [channels] => 3

    [mime] => image/jpeg

)


Perfecto, empecemos. Para crear una imagen se utilizan estos siguientes:

Para crear desde un archivo sea en tu servidor o en uno externo:
Código
$im = imagecreatefrompng("dirección"); //para imágenes png

$im = imagecreatefromgif("dirección"); //para imagenes gif

$im = imagecreatefromjpeg("dirección"); //para imagenes jpg y jpeg
Si se carga una imagen con transparencias, para conservarlas, hace falta agregar estas dos lineas despues de crearla.
Código
imagealphablending($im, true);

imagesavealpha($im, true);

 

Ahora, para crear una imagen de cero basta con las funciones:

Código
$im = imagecreate($ancho, $alto);

//para imagenes con una paleta de colores, 

//osea, no tan buena calidad del color.

//

//

$im = imagecreatetruecolor($ancho, $alto);

//para imagenes con un color real, esta es la más usada...
Bueno, ya utilizando estas funciones habremos creado la imagen. No se olviden que siempre se tiene que asignar el valor reslutante de esta fuincion a una nueva variable (no hace falta que sea nueva ¬¬ jajaj).



Datos a tener en cuenta:


Antes de seguir, tiene que quedarles algo claro fundamental mente, y es la visualizacion de la imagen y la DESTRUCCION de la misma. Por qué destruir? Porque sino queda guardada la imagen en la memoria RAM del servidor y eso no es muy agradable. Entonces, para visualizarla basta con agregar el header correspondiente para el tipo:
Código
header("Content-type: image/".$imagenextension.);
Y para imprimir la imagen se usa el comando "image" seguido del tipo de imagen. por ejemplo para una imagen png:
Código
imagepng($im);
Seguido de esta función le va:
Código
imagedestroy($im);



Contenido de las imagenes:


Ahora que tenemos la imagen, vamos a darle el contenido. Para ellos se puede dibujar lineas, puntos, rectángulos (solo el borde) o rectángulos rellenos (no de dulce de leche!! ;D), así como los rectángulos, elipses y polígonos indicando cantidad de puntos y posición de los mismos. También se pueden crear colores de toda la gamma RGB con o sin transparencia. Se puede agregar texto de fuentes por defecto de la librería o fuentes del tipo "True Type", "Free type" y "PostScript" importándolas de un enlace externo. Primeramente vamos por partes y comenzamos por el principio, los colores ;D.


Colores:


Para las creaciones de colores tenemos dos funciones y un verso sin esfuerzo.
Código
$nombreDelColor = imagecolorallocate($r, $g, $b);

$nombreDelColor = imagecolorallocatealpha($r, $g, $b, $valorAlfa);



Por ejemplo podemos crear el color rojo, el amarillo y el violeta:
Código
$rojo = imagecolorallocate(255, 0, 0);

$amarillo = imagecolorallocate(255, 255, 0);

$violeta = imagecolorallocate(0, 255, 255);
Y si se quiere agregar opacidad a uno de estos colores:
Código
$azul = imagecolorallocate(0, 0, 255, 50); //ahí tenemos un 50% de opacidad...



Además de crear colores, se puede tomar el color de un píxel determinado de una imagen determinada con la función imagecolorat();, su sintaxis es
Código
imagecolorat($im, $x, $y);
Código
//por ejemplo en la imagen utilizada es una rápida que encontré por internet de un "mundo"

$im = imagecreatefromjpeg("http://www.hyparion.com/web/diccionari/dics/astronomia/imatges/tierra.jpg");

$color = imagecolorat($im, 100, 100);
Ahora, acá se nos complica un poco. La variable "color" recibe el valor de 9146518 y decimos: "Qué carajo!?". Bueno, para que ese es un valor que para nosotros trabajarlo como rgba (Red Green Blue Alpha, osea, rojo verde azul y transparencia). Para "convertirlo" a ese (rgba) o hexadecimal tenemos las posibilidades de:
Código
//esto se cumple una vez realizado el proceso anterior...

//automático para rgba, el más fácil y practico de todos!

$color = imagecolorsforindex($im, $color);

/*este devuelve un array con los valores:

Array

(

   [red] => 255

   [green] => 0

   [blue] => 0

   [alpha] => 0

)

*/

//

//

//este es simple, se le da un formato y devuelve el valor del color en hexadecimal.

$hex = sprintf("%06X", $color); //devuelve FF0000

//

//

//manualmente para rgba, el más complicado de entender y es lo 

//mismo que la función imagecolorsforindex() pero igualmente se los explico...

$colores = array();

$colores['red'] = ($color >> 16) & 0xFF;

$colores['green'] = ($color >> 8) & 0xFF;

$colores['blue'] = $color & 0xFF;

$colores['alpha'] = ($color >> 24) & 0xFF;

 
Ahora paso a explicar esas cosas raras que nos da php.net sin decirnos que es ¬¬.
Los caracteres ">>" cumplen el rol de operador y recibe el nombre de operador bitwise. Lo que hace este operador es correr determinadas veces la posición del valor indicado en binario. Osea, la variable $color toma un píxel de color rojo puro (a puro me refiero a rgb(255,0,0)) el valor retornado va a ser igual a: 16711680 :o mientras que el valor en rgb es 255. Entonces, diciéndole que me corra 16 lugares los bits de 16711680 me va a dar como resultado un numero decimal igual a 255. Ahora, si no colocamos el 0xFF en el valor del rojo, nos damos cuenta que no hay diferencia, pero cuando tratamos valores rgba, el 0xFF delimita la cantidad de bits para cada valor. Es como decir, para cada valor (rgb) corresponden 8 bits (por eso siempre los corremos para que queden los 8 primeros bits) en cambio, para el valor de alpha le corresponden solo 7 bits, pero como lo corremos 24 lugares quedando solo 7 bits (es como un substring a una cadena de 7 caracteres, aunque le indiques 8, siempre devuelve 7). Se entendió esto? Bueno, sigamos que apenas vamos por los colores!!!

Fondo:

Una cosa muy molesta de la libreria gd, es el color de fondo que por defecto lo pone negro. para eso esta la funcion imagefill() que rellena la imagen desde donde se le indique con el color establecido. Su sintaxis es:
Código
imagefill($im, $x, $y, $color)
Para que rellene por completo la imagen, los valores de $x,$y son igual a 0,0.



Trazados:

Puntos:


Ahora que tenemos los colores, vamos a dibujar. Primero vamos a empezar por un punto, que aunque sea de solo un píxel, es muy útil como para un ejemplo, un captcha. No hace falta demásiada explicación, dibuja un píxel en x,y del color $color
Código
imagesetpixel($im, $x, $y, $color); //$color es igual a el resultado de la función imagecolorallocate()

Líneas:

Para poder dibujar una linea, se indica el x,y de inicio y el x,y de final:
Código
imageline($im, $xInicio, $yInicio, $xFin, $yFin, $color);
Por ejemplo si $im es una imagen de color real de 100x100 y con fondo blanco (ya va a llegar esa parte) podría realizar esto:



Con esto:
Código
$im = imagecreatetruecolor(100, 100);

$color = imagecolorallocate($im, 0,0,0);

imageline($im, 10, 35, 76, 85, $color);



Poligonos, rectángulos y elipses:[/b]

Una vez entendido esto! nos vamos con los polígonos, primero lo primero! el rectángulo
para dibujar un rectángulo se puede dibujar solo su contorno (el borde va a medir 1px) o el rectángulo relleno de color (filled).
Sinceramente la sintaxis es idéntica a la de imageline además, son iguales entre si, solo el borde, o relleno.
Código
imagefilledrectangle($im, $xInicio, $yInicio, $xFin, $yFin, $color);

imagerectangle($im, $xInicio, $yInicio, $xFin, $yFin, $color);
Para el elipse, circulo u ovalo (cambia según los valores dados), al igual que el rectángulo y el polígono que lo vamos a ver posteriormente, se puede solo el borde o relleno. su sintaxis es:
Código
imageellipse($im, $centroX, $centroY, $ancho, $altura, $color);

imagefilledellipse($im, $centroX, $centroY, $ancho, $altura, $color);
Donde $centroX,Y son la posición del punto medio del elipse.
Bueno, para el polígono, se complica otra vez un poco. En la sintaxis del polígono:
Código
imagepolygon($im, $puntosArray, $cantidadPuntos, $color);

imagefilledpolygon($im, $puntosArray, $cantidadPuntos, $color);
La variable $puntosArray es un array, porque no le puse ese nombre al pedo xD jajaja. La estructura del array tiene que ser, cada dos valores corresponden a los valores x,y de un punto, osea:
Código
$puntosArray= array (

/*

x  y  */

10, 10,  //punto 1

15, 26,  //punto 2

50, 36,  //punto 3

68, 10   //punto 4, este ultimo numero va sin coma al final!!

);
En realidad no es tan complicado :P. y para $cantidadPuntos, lógicamente se indica la cantidad de los puntos. pero para no contarlos, basta con un:
Código
$cantidadPuntos = count($puntosArray) / 2;
Y listo. Ahora, el resultado de esta función es una imagen parecida a esta:






Agregar textos:


Ya terminamos con las formás y esas cosas. Ahora vamos por el texto. Para escribir en una imagen se puede utilizar las fuentes que trae por defecto la librería gd o fuentes del "True type", "Free type" o "PostScript Type1". La sintaxis para las postscript se ponen un poco jodidas, además, no conozco las fuentes del tipo postscript. Así que paso a explicar principalmente el imagestring(), además de escribir horizontalmente, también esta la función imagestringup() que escribe verticalmente:
Código
imagestring($im, $fuente, $x, $y, $cadenaTexto, $color);

imagestringup($im, $fuente, $x, $y, $cadenaTexto, $color);
Para la variable $fuente se puede usar los números del 1 al 6. Los ejemplos serian:



Fijense como a partir del numero 5 se repite el tipo de fuente. El problema de imagestring es que tienen el tamaño de fuente fija.

Con funciones donde se indica una fuente externa, se puede indicar el ángulo del texto (ahora lo van a entender) y el tamaño de la fuente. Yo les voy a explicar nomás imagettftext y sus derivados.

(Para descargar fuentes, aca en el foro tenemos una excelente recopilación. )

Primero van a necesitar un archivo del tipo ttf y conocer su link xD, puede estar en el mismo directorio o en uno externo, pero como cualquier cosa, recomiendo que este en tu mismo servidor para que no haya problemás. Yo por ejemplo voy a usar la fuente Hemi Head la cual es utilizada por el foro.
Antes que nada, la sintaxis de esta función es:
Código
$fuente = "hemihead.ttf";

imagettftext($im, $tamanio, $ángulo, $x, $y, $color, $fuente, $texto)
La variable fuente indica donde se encuentra el archivo de la fuente.
Por ejemplo este código,
Código


header("Content-type: image/png");

$im = imagecreatetruecolor(100, 100);

$color = imagecolorallocate($im, 255, 255, 255);

$fuente = "HEMIHEAD.TTF";

imagettftext($im, 15, 0, 15, 20, $color, $fuente, "Wiki");

imagepng($im);

imagedestroy($im);

?>
Da como resultado esta imagen:



Ahora, si yo cambio el ángulo que en caso anterior es 0 por 315:
Código
imagettftext($im, 15, 315, 15, 20, $color, $fuente, "Wiki");
Da como resultado:






Centrar textos:



Una gran necesidad al momento de usar textos en la librería gd, es el tema de centrar el texto. Acá es donde entra en acción la matemática. piensen, primeramente vamos a necesitar conocer el tamaño que ocupa el texto. Para una fuente utilizada con imagestring() se utilizan las funciones:
Código
imagefontheight($fuente);

imagefontwidth($fuente);
Estas funciones devuelven la altura y el ancho en píxeles respectivamente de un carácter de la fuente especificada. como devuelve las propiedades de un solo carácter (es el mismo valor para cualquier carácter) hay que multiplicar los valores obtenidos por la cantidad de caracteres implementados. Entonces podemos hacer algo así:
Código
$fuente = 1;

$cantidadCaracteres = strlen($texto);

$textoAltura = imagefontheight($fuente) * $cantidadCaracteres;

$textoAncho = imagefontwidth($fuente) * $cantidadCaracteres;
Y listo!, pero eso es nomás para las fuentes por defecto, ahora si se quiere con una fuente que usamos en imagettftext, tenemos la función imagettfbbox, su sintaxis:
Código
imagettfbbox($tamanio, $ángulo, $fuente, $texto);
El resultado de esta función es un array con 8 puntos:


0 esquina inferior izquierda, posición X

1 esquina inferior izquierda, posición Y

2 esquina inferior derecha, posición X

3 esquina inferior derecha, posición Y

4 esquina superior derecha, posición X

5 esquina superior derecha, posición Y

6 esquina superior izquierda, posición X

7 esquina superior izquierda, posición Y

Los datos que nosotros necesitamos son, abajo a la derecha y cumplirán el rol de x = ancho y y = altura.

Ahora que tenemos el valor que ocupa el texto tenemos que averiguar cual tiene que ser la posición del texto en la imagen. Cuando usamos una de las funciones para agregar texto, las posiciones x,y que indicamos van a ser las de arriba a la izquierda, por eso no podemos simplemente indicarle el centro de la imagen. Por eso, tenemos que restarle las medidas del texto a las medidas de la imagen. Obviamente hay que hacer ancho de la imagen - (menos) ancho del texto y alto imagen - alto texto. El resultado de estas operaciones dividido dos ( / 2) va a ser la posición x,y que le vamos a asignar al texto. Esto quedaría más o menos así:
Código


header("Content-type: image/png");

$im = imagecreatetruecolor(100, 100);

$color = imagecolorallocate($im, 255, 255, 255);

$fuente = "HEMIHEAD.TTF";

$cajaTexto = imagettfbbox(15, 0, $fuente, "Wiki");

$xCentrado = (imagesx($im) - $cajaTexto[2]) / 2;

$yCentrado = (imagesy($im) - $cajaTexto[3]) / 2;

imagettftext($im, 15, 0, $xCentrado, $yCentrado, $color, $fuente, "Wiki");

imagepng($im);

imagedestroy($im);

?>
Entonces podemos observar que el texto quedo centrado:



Entonces terminamos con suerte la implementacion del texto en imagenes.



Redimensionar:

Una de las otras herramientas que nos da GD es la posibilidad de redimensionar y copiar imagenes.
Para redimensionar lo único que se hace es copiar una imagen a otra indicándole desde donde copiar y pegar, y que tamaño se quiere. Además, tenemos dos funciones una que redimensiona como el paint( osea como que faltan píxeles), es imagecopyresize(). Y otra que rredimensiona suavizando los valores de los píxeles. Esa función es:
Código
imagecopyresampled($im_original, $im_detino, $x_destino, $y_destino, $x_original, $y_original, $ancho_destino, $alto_destino, $ancho_orginal, $alto_orginal);
Donde los x,y son desde donde se quiere copiar la imagen, y los de destino son desde donde se quiere ubicar la imagen.
Si yo tengo esta imagen:



Y quiero que mida la mitad como esto:



Tengo que hacer esto:
Código


header("Content-type: image/jpg");

$im_original = imagecreatefromjpeg("http://www.foroswebgratis.com/fotos/1/3/9/3/5//595440elhacker.jpg");

$im_destino = imagecreatetruecolor(imagesx($im_original) / 2 ,imagesy($im_original) / 2 );

$blanco = imagecolorallocate($im_destino, 255, 255, 255);

imagefill($im_destino, 0, 0, $blanco);

imagecopyresampled($im_destino, $im_original, 0, 0, 0, 0, imagesx($im_destino), imagesy($im_destino), imagesx($im_original), imagesy($im_original));

imagejpeg($im_destino);

imagedestroy($im_destino);

imagedestroy($im_original);

?>


Y listo. por ultimo dejo claro que con imagecopyresize() permite copiar partes dentro de una misma imagen...



Fuente:

http://wiki.elhacker.net/programacion/php/libreria-gd