Sunteți pe pagina 1din 48

Curso Avanzado de PHP

Unidad 1: Tratamiento de gráficos

Unidad 1. Tratamiento de gráficos

En esta Unidad vamos a introducir los conceptos básicos de HTML 5 y PHP.

Después, aprenderás a tratar gráficos desde PHP. Además, conoceremos y


sabremos aplicar las principales funciones de la biblioteca GD para
incorporar gráficos e imágenes dentro del código PHP.

Finalmente, integraremos PHP con Adobe flash en un sencillo programa.

1.1. HTML 5 y PHP


HTML5 (del inglés, HyperText Markup Language, versión 5) es la quinta
revisión importante del lenguaje básico HTML de la Internet.

Si bien todavía se encuentra en modo experimental, ya lo usan múltiples


desarrolladores web por sus avances, mejoras y ventajas frente a HTML4.

Para que el navegador de Internet interprete correctamente las nuevas


etiquetas es necesario actualizarlo a la versión más moderna para poder
disfrutar de todo el potencial que provee HTML5.

Como debes ya saber, un documento escrito en HTML tiene la siguiente


estructura básica:

<!DOCTYPE html>
<html lang="es">
<head>
<meta charset="utf-8" />
<title>Curso PHP 5</title>
</head>
<body>
<h1>Curso PHP 5</h1>
</body>
</html>

Repasemos un poco el código anterior:

• <!DOCTYPE html>: es la declaración del tipo de documento que se está


mostrando. El DOCTYPE variará según el tipo de documento del que se
trate; en este ejemplo hemos utilizado valor de HTML5.

1
Curso Avanzado de PHP
Unidad 1: Tratamiento de gráficos

• <html>: después, marcamos el inicio del documento HTML. Esta etiqueta


se cierra cuando finalizamos el documento. Hemos incluido el atributo
lang que se utiliza para indicar el idioma del documento (en este caso,
español).
• <head>: cabecera donde colocaremos los metadatos de la página, el
código JavaScript y el CSS que utilizará el navegador para dar formato a
la página.
• <meta charset>: indica el juego de caracteres del documento y es
obligatorio en HTML5. Debería ser siempre utf-8 para que el documento
sea compatible en diferentes sistemas operativos.
• <title>: metadato especial que permite definir el título de la página.
• <body>: en su interior irá el contenido de la página.

Hasta aquí, nada nuevo. Sin embargo, HTML5 soluciona, entre otras cosas, la
falta de un criterio para definir el contenido semántico de una página web
agregando una serie de etiquetas destinadas a facilitar la estructura del
documento desde el punto de vista de su significado.

• <section>:etiqueta que sirve para agrupar elementos relacionados entre


sí de forma temática. Normalmente, se tratará de un bloque de texto al
que perfectamente le podríamos colocar un título o encabezado.
Además, todo el contenido que engloba debe guardar cierta relación
entre sí.
• <article>:se trata de la última etiqueta con significado semántico. Es
decir, habitualmente se utiliza dentro de un bloque <section> para
separar las unidades de contenido con significado semántico. Un
<article> podría considerarse, por tanto, como cada uno de los
elementos en que podemos dividir un bloque <section>.
• <header>: permite incluir información destinada a ayudar al visitante en la
navegación. Suele incluir etiquetas del tipo <H1> con el título de la página
y algún logotipo.
• <nav>: etiqueta que permite incluir el menú de navegación.
• <footer>:etiqueta que se usa para añadir la información sobre el
elemento que lo contiene (autoría, propiedad, enlaces…)
• <aside>:habilita la agrupación del contenido visualizado en la página,
pero que no forma parte del contenido principal de la página.

Estas nuevas etiquetas permiten varios niveles de anidamiento entre sí. Por
ejemplo, un bloque <section> debe tener un <header> y un <footer>, además de
los <article> necesarios. Además, es posible definir otros bloques <section> en
su interior.

Todo esto contribuye a aumentar la complejidad a la hora de estructurar un


documento, si bien aporta también una enorme flexibilidad para estructurar
correctamente el contenido de la página desde el punto de vista semántico.

2
Curso Avanzado de PHP
Unidad 1: Tratamiento de gráficos

Una novedad importante es la posibilidad de tener más de una cabecera <H1>


en el documento.

Según el estándar HTML4, un documento sólo “debía” tener una cabecera <H1>
(titular de primer nivel), pero con la llegada de HTML5 esto ha cambiado y se
permite el uso de una cabecera <H1> para cada una de las etiquetas semánticas
básicas, es decir, dentro de <section> y <article>.

Además, disponemos de la etiqueta <hgroup> que permite agrupar dentro del


<header> varias cabeceras del tipo H1, H2, etcétera.

Teniendo en cuenta todo lo comentado inicialmente, vamos a transformar el


documento HTML anterior agregando información HTML5 conjuntamente con
PHP:

<!DOCTYPE html>
<html lang="es">
<head>
<meta charset="utf-8" />
<title><?php echo 'Curso PHP 5'; ?></title>
</head>
<body>
<header>
<h1><?php echo 'Curso PHP 5'; ?></h1>
</header>
<section>
<article>
<h2><?php echo 'Ejemplo del curso'; ?></h2>
<?php echo 'P&aacute;gina realizada en PHP con
HTML5'; ?>
</article>
</section>
<aside>
<h3><?php echo 'Enlaces relacionados';?></h3>
<ul>
<li><a href="http://www.aulamentor.es/"
target="_blank">
<?php echo 'Aula Mentor'; ?></a></li>
<li><a href="http://www.aulamentor09.blogspot.com.es/"
target="_blank">
<?php echo 'Blog Aula Mentor'; ?></a></li>
</ul>
</aside>
<footer>
<?php echo 'Mentor 2014'; ?>
</footer>
</body>
</html>

En este sencillo ejemplo podemos ver cómo utilizamos la etiqueta <header> para
establecer el titular de la página, la etiqueta <footer> para añadir la información
de la autoría, la etiqueta <aside> para incluir información secundaria y la
combinación de <section> y <article> para colocar el contenido principal de la
página.

3
Curso Avanzado de PHP
Unidad 1: Tratamiento de gráficos

El código de PHP se encuentra, como siempre, entre las etiquetas <?php y ?>.
Esto no es del todo eficiente y práctico por lo que, en la Unidad 5,
estudiaremos cómo estructurar este código siguiendo el patrón MVC (Modelo,
Vista, Controlador), si bien por ahora nos permitimos esta licencia.

Como una imagen vale más que mil palabras, aquí puedes ver el resultado de
la sencilla página anterior al ejecutarla en el servidor XAMPP:

ATENCIÓN: El objetivo de este curso es que el alumno o alumna mejore


sus destrezas a la hora de programar PHP; por lo tanto, avisamos que, por
motivos didácticos a la hora de entender el código fuente, los ejemplos del
curso no cumplen el estándar HTML5.

4
Curso Avanzado de PHP
Unidad 1: Tratamiento de gráficos

1.2. Tratamiento de imágenes y gráficos en PHP


En el Curso de iniciación a PHP 5 hemos usado algunas imágenes y tratado
gráficos sólo de una forma elemental y sin detalle. En esta Unidad 1 del Curso
avanzado de PHP 5 vamos a estudiar con mayor detenimiento este tema.

La incorporación de componentes gráficos y de imágenes a las páginas web


comerciales y profesionales es algo fundamental e imprescindible, no sólo para
mejorar estéticamente la presencia de los portales haciéndoles más atractivos
y sugerentes, sino también para permitir un acceso más rápido e intuitivo o
para presentar la información de una forma más clara y ordenada. En general,
la aparición de elementos gráficos en una página mejora mucho su
presentación y eficacia.

En el Manual de PHP 5, denominado "Procesamiento y generación de


imágenes", se explica que PHP no sólo puede generar páginas dinámicas web
para HTML, sino que, además, permite crear y manipular ficheros de imágenes
en diferentes formatos: PNG, JPG, WBMP, XPM, etcétera. PHP puede incluso
mandar flujos de imágenes directamente al navegador.

Para que esto sea posible, es necesario utilizar la biblioteca de funciones de


imágenes GD Graphics Library. El servidor de XAMPP ya incluye la biblioteca
por defecto, por lo cual el alumno sólo necesita instalarlo para que el servidor
funcione correctamente al crear o tratar ficheros de imagen.

La librería GD Graphics Library no es exclusiva de PHP, sino que puede


usarse con cualquier otro lenguaje de programación. Puede recogerse en la
dirección http://www.libgd.org/ y utilizarse de forma libre y gratuita. Es una
librería de tipo ANSI C que permite, como hemos dicho, crear imágenes
dinámicas en formatos PNG, GIF y JPEG básicamente, si bien también puede
hacerlo en otros formatos, como los citados anteriormente.

El formato JPEG (del inglés, Joint Photographic Experts Group) se usa


ampliamente en Internet para guardar fotografías e imágenes de gran tamaño y
variedad de color. Es un formato comprimido con pérdida de calidad, aunque
ésta se puede ajustar.

El formato GIF (Compuserve GIF) es un formato gráfico utilizado ampliamente


en la World Wide Web, tanto para imágenes como para animaciones. GIF llegó
a ser muy popular porque podía usar el algoritmo de compresión para realizar
la compresión de la imagen y permitía que imágenes de gran tamaño ocupasen
poco espacio. Hasta el año 2003 la patente de compresión exigía un canon por
el uso de este formato.

PNG (Portable Network Graphics) es un formato gratuito con compresión de la


imagen sin pérdida de calidad. Además, es posible definir con este formato
transparencias en la imagen. Se diseñó para reemplazar al GIF en Internet ya
que el formato PNG tenía y tiene licencia de uso.

5
Curso Avanzado de PHP
Unidad 1: Tratamiento de gráficos

En general, la escritura del código necesario para la creación de imágenes no


es demasiado difícil. Utilizando el Ejemplo 1 veamos los pasos que debemos
dar para generar una imagen desde PHP.

1. En la cabecera del script (segunda página de este ejemplo) indicamos que


se va a crear una imagen del tipo que se especifique, en este caso png:

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

2. Creamos la imagen usando alguna de las funciones que realizan esta


operación:

$imagen = imagecreate(400, 150);

La función imagecreate(x,y)devuelve un identificador de imagen de tipo


numérico entero que contiene una imagen en blanco con las medidas
especificadas en los dos parámetros, que representan las coordenadas x
(anchura de izquierda a derecha) e y (altura de arriba abajo) de la imagen. El
valor de este identificador lo asignamos a la variable $imagen.

Las coordenadas dentro de una imagen siempre son positivas y el píxel (0,0)
corresponde a la esquina superior izquierda. Hay que tener en cuenta que, en
una imagen cuyas dimensiones son 400 x 150 pixeles, el píxel de la esquina
inferior derecha corresponde a las coordenadas (399, 149), ya que el primer
píxel (en la esquina superior izquierda) no corresponde a las coordenadas
(1,1), sino a (0,0).

Fíjate en el siguiente dibujo de esta imagen con sus coordenadas:

3. Diseñamos la imagen según la apariencia que debe tener en cuanto a:

 Color

Para poder pintar algo en una imagen es necesario definir algún color
previamente, por ejemplo, para dibujar un rectángulo, hay que definir las
coordenadas de dicho rectángulo así como su color.

En las siguientes sentencias definimos 3 colores:

6
Curso Avanzado de PHP
Unidad 1: Tratamiento de gráficos

$color_azul = ImageColorAllocate($imagen,0,0,255);
$color_blanco = ImageColorAllocate($imagen,255,255,255);
$color_violeta = ImageColorAllocate($imagen,192,192,255);

La función ImageColorAllocate(identificador de imagen,rojo,verde,azul)


devuelve un identificador del color representado por la mezcla de los
componentes RGB (Red, Green, Blue) especificados. Usamos 8 bits por canal.
Más adelante, dentro de esta misma Unidad, se explica cómo crear colores
mixtos mezclando los tres colores básicos.

La siguiente imagen muestra una paleta básica de colores y sus valores RGB
correspondientes:

Luego, rellenamos el fondo de la imagen completo con el color azul:

ImageFilledRectangle($imagen,0,0,400,150,$color_azul);

La función ImageFilledRectangle(id. imagen, x1, y1, x2, y2, id. color)


crea en la imagen un rectángulo relleno con el color indicado comenzando con
la coordenada superior izquierda x1,y1 y acabando en la coordenada inferior
derecha x2,y2. 0,0 es la esquina superior izquierda de la imagen.

Con la misma función dibujamos otro rectángulo en la parte derecha de la


imagen, de color violeta, que al sobreponerse en parte sobre el color azul
anterior queda de color plateado:

ImageFilledRectangle($imagen,200,20,380,130,$color_violeta);

 Puntos

Podemos dibujar puntos en la imagen usando la siguiente sentencia:

imagesetpixel($imagen,0,0,$negro);

La función imagesetpixel (id. imagen, x1, y1, id. color) dibuja un píxel
del color especificado comenzando en la coordenada x1,y1.

 Borde

Por dentro del rectángulo más grande que hemos rellenado de color azul
dibujamos una línea de forma rectangular a modo de reborde:

ImageRectangle($imagen,5,10,390,140,$color_blanco);

7
Curso Avanzado de PHP
Unidad 1: Tratamiento de gráficos

La función ImageRectangle(id. imagen, x1, y1, x2, y2, id. color) dibuja
un rectángulo del color especificado comenzando en la coordenada superior
izquierda x1,y1 y acabando en la coordenada inferior derecha x2,y2. 0,0 es la
esquina superior izquierda del rectángulo.

 Texto

Dentro de la imagen podemos incluir un texto fijo o que pasemos desde otra
página en la que el usuario lo ha escrito a través de un formulario, como
sucede en este ejemplo. En todo caso, hay que cuidar que el tamaño de la
imagen sea adecuado al texto que se quiere mostrar en la misma.

En nuestro ejemplo, en primer lugar escribimos cinco veces con un bucle, el


texto que se ha pasado desde el formulario de la primera página:

for ($i=1; $i <= 5; $i++)


ImageString($imagen,$i,15,$i*20,$_REQUEST["palabra"],$color_blanco
);

La función ImageString(id. imagen,id. fuente,x,y,var,id. color) dibuja la


cadena var dentro de la imagen desde la coordenada x,y (0,0 es la posición
superior) con el color indicado. Si la fuente es 1, 2, 3, 4 o 5, como en este caso,
se emplea una fuente interna.

Después, con el mismo procedimiento dibujamos el texto fijo:

ImageString($imagen,5,235,52,"CURSO DE PHP 5 ",$color_azul);

ImageString($imagen,5,245,72,"(avanzado)",$color_azul);

En este paso, como es lógico, pueden incluirse muchas cosas más, a medida
del usuario, para que la imagen resulte más llamativa, completa o
estéticamente más acertada.

4. Enviamos la imagen al navegador del usuario con la orden

imagepng($imagen);

La función imagepng(id. imagen[, nombre de fichero], índice de calidad])


envía la imagen creada a la pantalla o a un fichero. Los dos últimos parámetros
son opcionales. Más adelante se explica con detalle esta función.

ATENCIÓN: ten en cuenta que, a veces, los errores de la generación de la


imagen no se presentan en la página web directamente (debido a que se
devuelve una imagen al navegador) sino en el fichero de errores siguiente:

C:\xampp\php\logs\php_error_log

8
Curso Avanzado de PHP
Unidad 1: Tratamiento de gráficos

Puedes acceder a este fichero con cualquier editor de texto plano y ver el
contenido del mismo para encontrar los errores de la generación de la imagen.

5. Destruimos la imagen con la orden

ImageDestroy($imagen);

Una vez creada la imagen y mostrada o guardada en un fichero, conviene


eliminar de la memoria ésta liberando espacio que puede ser necesario para
otras operaciones.

Utilizando Eclipse PDT puedes abrir el proyecto Ejemplo 1 (Imagen GD)


de la Unidad 1. Estudia el código fuente y ejecútalo para mostrar en el
navegador el resultado de su interpretación.

Si ejecutas el Ejemplo 1 de la Unidad 1 verás que aparece la siguiente página


PHP:

Puedes probar a cambiar la palabra y ver cómo se regenera la imagen


dinámicamente.

Nota: por compatibilidad entre diferentes sistemas operativos, usamos la


codificación UTF8 en el código fuente. Por lo tanto, hay que cambiar la
codificación al tipo del servidor local donde se ejecuta el script para que se
dibujen bien los caracteres especiales como tildes y el carácter “ñ”. En el

9
Curso Avanzado de PHP
Unidad 1: Tratamiento de gráficos

archivo index.php del Ejemplo 1 de la Unidad 1 usamos la instrucción


siguiente:

mb_convert_encoding($_REQUEST["palabra"], "auto", "UTF-8")

10
Curso Avanzado de PHP
Unidad 1: Tratamiento de gráficos

1.3. Funciones más importantes para tratar


gráficos
En el apartado anterior ya hemos usado y comentado algunas funciones
básicas que permiten crear, dibujar o mostrar gráficos en la pantalla o
mandarlos a un fichero. En este apartado vamos a explicar de una forma más
sistemática las principales funciones de tratamiento de gráficos agrupándolas
según el tipo de operación que llevan a cabo.

En el capítulo Procesamiento de imágenes y GD del Manual de PHP 5 se


abordan todas las funciones que permiten crear imágenes con esta biblioteca.
En este Curso avanzado el alumno debe recurrir al Manual de PHP siempre
que lo precise, pues en los contenidos del curso no pretendemos abordar todas
y cada una de las funciones en detalle.

1. Funciones que permiten crear imágenes

Como ya hemos visto, la función imagecreate(x,y) devuelve un identificador


de imagen de tipo numérico entero que contiene una imagen en blanco con las
medidas especificadas en los dos parámetros, que representan las
coordenadas x (anchura de izquierda a derecha) e y (altura de arriba abajo) de
la imagen. Ya la hemos utilizado y explicado en el Ejemplo 1. Lógicamente, la
usaremos en la mayoría de los ejercicios de esta Unidad.

Esta función debe usarse cuando se quiere partir de cero, es decir, cuando se
crea una imagen que antes no existía. En el Ejemplo 2 también se usa esta
función. A la vez que el alumno lo comprueba, mire cómo creamos una imagen
sencilla que representa un termómetro. En este ejercicio se utilizan, además,
otras funciones que explicaremos después y que sirven para diseñar imágenes,
en este caso la del termómetro. Estudiando el código de este ejercicio el
alumno o alumna puede ver en la práctica cómo se escribe la sintaxis de las
diferentes instrucciones.

Hay también funciones que permiten crear o modificar una imagen a partir
de otra ya existente, archivada en un fichero, o desde una URL. Veamos
algunas de las más usadas.

La función imagecreatefromjpeg(nombre de fichero) devuelve un identificador


de imagen que referencia a la imagen contenida en el parámetro indicado que
puede ser un archivo o una URL. Hay que tener en cuenta que el tipo de la
imagen debe ser JPG. Así pues, se crea una nueva imagen a partir de la
original. Esta función devuelve FALSE si la operación no se ha podido llevar a
cabo, si, por ejemplo, no existiera el fichero especificado. En el Manual de PHP
se ofrece una forma elegante de resolver el mensaje de error que se muestra
en caso de fallo:

11
Curso Avanzado de PHP
Unidad 1: Tratamiento de gráficos

<?php
function CargarJpeg($imagen)
{
/* Intentar abrir */
$im = @imagecreatefromjpeg($imagen);

/* Ver si falló */
if(!$im)
{
/* Crear una imagen en blanco */
$im = imagecreatetruecolor(150, 30);
$fondo = imagecolorallocate($im, 255, 255, 255);
$ct = imagecolorallocate($im, 0, 0, 0);

imagefilledrectangle($im, 0, 0, 150, 30, $fondo);

/* Imprimir un mensaje de error */


imagestring($im, 1, 5, 5, 'Error cargando ' . $imagen, $ct);
}

return $im;
}

header('Content-Type: image/jpeg');

$img = CargarJpeg('falso.image');

imagejpeg($img);
imagedestroy($img);
?>

El resultado del ejemplo sería algo similar a:

El formato de imágenes JPG o JPEG (Joint Photographics Expert Group File


Interchange Format) permite usar hasta 16.777.216 colores (24 bits). Es el
formato más adecuado para comprimir imágenes fotográficas con todo detalle.
Los índices de compresión son mucho mayores que los conseguidos con el
formato GIF. No obstante, al comprimir imágenes de este formato se pierde
información, por lo cual, al descomprimir el fichero donde se han guardado, las
imágenes obtenidas no son exactamente iguales que las originales.

Se puede obtener más información sobre formatos gráficos en


http://es.wikipedia.org/wiki/Joint_Photographic_Experts_Group.

En el Ejemplo 3 (Galería de fotos) se usa también esta función para crear


cuatro nuevas imágenes a partir de otras ya existentes. Conviene estudiar este
código y mirar cómo usamos esta función y otras que se explicarán después.

PHP dispone de funciones que permiten crear imágenes nuevas a partir de


otros formatos gráficos. Funcionan prácticamente de la misma forma que las
imágenes JPG, por lo cual sólo citamos las más importantes.

12
Curso Avanzado de PHP
Unidad 1: Tratamiento de gráficos

La función imagecreatefromgif(nombre de fichero) devuelve un identificador


de imagen que referencia a la imagen contenida en el archivo indicado o URL,
que debe ser de tipo GIF. El formato de imágenes GIF (Graphic Interchange
format), creado por la empresa Compuserve, utiliza un sistema de compresión
(LZW) sin pérdida de información de las imágenes. Hay que tener en cuenta
que el soporte para el formato GIF se eliminó de la librería GD por motivos de
licencia a partir de la versión 1.6 y se ha vuelto a incluir en la versión 2.0.28,
por lo cual esta función está disponible para usarla en el curso ya que
utilizamos la versión de GD más reciente de XAMPP.

La función imagecreatefrompgn(nombre de fichero) devuelve un identificador


de imagen que referencia a la imagen contenida en el archivo indicado o URL,
que debe ser de tipo PNG. El formato de imágenes PNG (Portable Network
Graphic) nace debido a los problemas de patente del algoritmo de compresión
LZW (Lempel-Ziv-Welch) que emplean las imágenes de tipo GIF, utilizadas
desde 1987, para seguir disponiendo de un formato gráfico de difusión gratuita.

La función imagecreatefromwbmp(nombre de fichero) devuelve un identificador


de imagen que referencia a la imagen contenida en el archivo indicado o URL,
que debe ser de tipo BMP. Este formato estándar de imágenes de mapa de bits
se usa en los equipos compatibles con Windows. Las imágenes de mapa de
bits se pueden guardar en sistemas Windows u OS/2 y aceptan colores de 24
bits.

La función imagecreatetruecolor(x,y) devuelve un identificador de imagen de


tipo numérico entero que referencia a una imagen en blanco con las medidas
especificadas en los dos parámetros, que representan las coordenadas x
(anchura de izquierda a derecha) e y (altura de arriba abajo) de la imagen. Es
una función equivalente a la función imagecreate(x,y).

2. Funciones que permiten elaborar imágenes

El segundo paso consiste en elaborar la imagen que se quiere crear. Para ello
hay que determinar con todo tipo de detalle las características de la misma,
como tamaño, color, formas geométricas, dibujos, etcétera. Veamos ahora las
principales funciones que permiten elaborar imágenes.

La función imagearc(id. imagen,x,y,anchura,altura,inicio,final,color)


dibuja una elipse parcial (arco) centrada en x,y (la esquina superior izquierda
es 0,0) según el tamaño indicado en anchura y altura (ambas referidas a la
elipse), desde inicio hasta final (ambos indicados en grados) del color
especificado. Todos los parámetros son de tipo numérico entero.

En el Ejemplo 2 usamos esta función conjuntamente con otras muchas de este


tipo aplicadas para dibujar el termómetro. Por ejemplo, la instrucción
imagearc($imagen, 15, 20, 30, 30, 90, 150, $rojo) dibuja un arco de color
rojo centradas en el punto de las coordenadas 15, 20 de 30 por 30 pixeles (la
elipse completa tendría forma de circunferencia) desde 90 hasta 150 grados.

13
Curso Avanzado de PHP
Unidad 1: Tratamiento de gráficos

Utilizando Eclipse PDT puedes abrir el proyecto Ejemplo 2 (Termómetro)


de la Unidad 1. Estudia el código fuente y ejecútalo para mostrar en el
navegador el resultado de su interpretación.

Si ejecutas el Ejemplo 2 de la Unidad 1 verás que aparece la siguiente imagen


PHP:

La función imageellipse(id. imagen,x,y,anchura,altura,color) dibuja una


elipse centrada en x,y (la esquina superior izquierda es 0,0) según el tamaño
indicado en anchura y altura del color especificado. Todos los parámetros son
de tipo numérico entero. Como vemos, con imagearc() se puede conseguir
prácticamente lo mismo.

La función imagerectangle(id. imagen,x1,y1,x2,y2,color) dibuja un


rectángulo del color especificado cuyo ángulo superior izquierdo está en la
coordenada x1,y1 y cuyo ángulo inferior derecho está en la coordenada x2,y2.

En el Ejemplo 7 usamos esta función conjuntamente con otras muchas de este


tipo aplicadas para dibujar un calendario simple.

Utilizando Eclipse PDT puedes abrir el proyecto Ejemplo 7 (Calendario)


de la Unidad 1. Estudia el código fuente y ejecútalo para mostrar en el
navegador el resultado de su interpretación.

Si ejecutas el Ejemplo 7 de la Unidad 1 verás que aparece la siguiente página:

14
Curso Avanzado de PHP
Unidad 1: Tratamiento de gráficos

La función imageline(id. imagen,x1,y1,x2,y2,color) dibuja una línea recta


continua del color especificado desde la coordenada x1,y1 hasta la
coordenada x2,y2.

La función imagedashedline(id. imagen,x1,y1,x2,y2,color) dibuja una línea


recta discontinua del color especificado desde la coordenada x1,y1 hasta la
coordenada x2,y2.

La función imagechar(id. imagen,fuente,x,y,cadena,color) dibuja horizontal-


mente en la imagen el primer carácter de cadena con su esquina superior
izquierda en x,y (arriba izquierda es 0,0) del color especificado. En el tamaño
de la fuente hay que tener en cuenta lo siguiente:

1. Si el valor de la fuente es 1, 2, 3, 4 ó 5, se usa una fuente predefinida


interna. El tamaño menor de ésta corresponde al valor 1, y el mayor
corresponde al valor 5.

2. Como hemos hecho en el Ejemplo 5, podemos utilizar fuentes externas.


Para esto necesitamos disponer de ese tipo de fuente e indicar el
camino donde puede encontrarse.

La función imagecharup(id. imagen,fuente,x,y,cadena,color) dibuja vertical-


mente en la imagen el primer carácter de cadena con su esquina superior
izquierda en x,y (arriba izquierda es 0,0) del color especificado.

Complementaria delas dos funciones anteriores es la función


ImageLoadFont(fichero), que carga una fuente de mapa de bits definida por el

15
Curso Avanzado de PHP
Unidad 1: Tratamiento de gráficos

usuario. Devuelve un identificador de esa fuente, que siempre debe ser mayor
que 5, para que no pueda entrar en conflicto con las fuentes predefinidas.

El color tanto de las fuentes como de los dibujos o de los fondos es un factor
estético importante de los gráficos. Veamos ahora algunas de las principales
funciones que permiten dar colorido a estos.

La función imagecolorallocate(id. imagen,rojo,verde,azul) devuelve un


identificador del color representado por la mezcla de los componentes RGB
(Red, Green, Blue) especificados.

Los colores se consiguen mezclando los tres colores básicos en el grado que
necesitemos. La mezcla se obtiene asignando a cada uno de los tres últimos
parámetros un valor desde 0 hasta 255. Por ejemplo, el color negro se obtiene
con la instrucción:

$negro= imagecolorallocate(id. imagen, 0, 0, 0);

En cambio, el color blanco se obtiene con la instrucción:

$blanco = ImageColorAllocate(id. imagen,255,255,255);

Los tres colores básicos se obtienen así:

$rojo = ImageColorAllocate(id. imagen, 255 ,0, 0);


$verde = ImageColorAllocate(id. imagen, 0, 255,0);
$azul = ImageColorAllocate(id. imagen, 0, 0, 255);

Los valores numéricos que permiten mezclar los colores pueden expresarse en
base decimal, como hemos hecho, o en base hexadecimal. Por ejemplo,
también podemos fijar los colores así:

$white = imagecolorallocate($imagen, 0xFF, 0xFF, 0xFF);


$navy = imagecolorallocate($imagen, 0x00, 0x00, 0x80);
$black = imagecolorallocate($imagen, 0x00, 0x00, 0x00);
$gray = imagecolorallocate($imagen, 0xC0, 0xC0, 0xC0);

Para una mayor información sobre los valores que hay que asignar de cada
parámetro de esta función a fin de conseguir el color deseado, puede verse la
página http://eies.njit.edu/~kevin/rgb.txt.html, donde se muestra un completo
mapa de colores con los correspondientes valores.

En el Ejemplo 5 puede estudiarse cómo hemos establecido los colores y cómo


los hemos usado, después, en las funciones que los incluyen como
parámetros. Prácticamente en todos los ejemplos y ejercicios de esta Unidad
se usa esta función.

En el Ejemplo 6 puede verse cómo se fijan también los colores directamente


con un número hexadecimal así:

$color_inicio='0000FF';

16
Curso Avanzado de PHP
Unidad 1: Tratamiento de gráficos

$color_inicio_rojo = hexdec(substr($color_inicio, 0, 2));


$color_inicio_verde = hexdec(substr($color_inicio, 2, 2));
$color_inicio_azul = hexdec(substr($color_inicio, 4, 2));

Donde los dos primeros dígitos de la izquierda (00x, 0d) corresponden al color
Rojo, los dos siguientes (00x, 0d) al Verde y los dos últimos (FFx, 255d) al
Azul. La función hexdec() devuelve el equivalente decimal del número
hexadecimal pasado como parámetro.

Utilizando Eclipse PDT puedes abrir el proyecto Ejemplo 6 (Banner) de la


Unidad 1. Estudia el código fuente y ejecútalo para mostrar en el navegador
el resultado de su interpretación.

Si ejecutas el Ejemplo 6 de la Unidad 1 verás que aparece la siguiente imagen


que simula ser un banner degradado por colores:

La función imagecolordeallocate(id. imagen, id. color) elimina de una


imagen el color que se le haya asignado con la función imagecolorallocate().

La función imagecolortransparent(id. imagen[, id. color]) define un color


como transparente para imagen. Devuelve el identificador del color
transparente. Si no se especifica ningún color, devuelve como transparente el
color actual.

Las imágenes se pueden rellenar total o parcialmente con colores. La función


imagefill(id. imagen,x,y,color) permite rellenar una imagen empezando
desde las coordenadas x,y del color que se especifique. En casi todos los
ejemplos y ejercicios de esta Unidad puede encontrarse esta función.

Complementarias de las funciones que permiten dibujar y rellenar imágenes


son las siguientes:

La función imagefilledarc(id. imagen,x,y,anchura,altura,inicio,final,


color,estilo) dibuja una elipse parcial (arco) centrada en x,y (la esquina
superior izquierda es 0,0) según el tamaño indicado en anchura y altura
(ambas referidas a la elipse), desde inicio hasta final (ambos indicados en
grados) y la rellena del color especificado en el estilo indicado. Todos los
parámetros son de tipo numérico entero.

Hay cuatro tipos de estilos:

Valor 1: IMG_ARC_PIE. Rellena con el color indicado el ángulo que va desde


el centro x,y hasta inicio y final trazando una línea entre estos dos puntos
sin rellenar la zona del arco de forma que se da al arco una apariencia de tarta.

Valor 2: IMG_ARC_CHORD. Une con una línea curva del color indicado el
inicio y el final del ángulo trazado. Los valores 1 y 2 se excluyen.

17
Curso Avanzado de PHP
Unidad 1: Tratamiento de gráficos

Valor 3: IMG_ARC_NOFILL. Une con una línea recta del color indicado el
inicio y el final del ángulo trazado

Valor 4: IMG_ARC_EDGED. Rellena por completo con el color indicado el


ángulo que va desde el centro x,y hasta el borde del arco de forma que se da
al arco una apariencia de tarta.

La función imagefilledellipse(id. imagen,x,y,anchura,altura,color) dibuja


una elipse centrada en x,y según el tamaño indicado en anchura y altura
rellena del color especificado.

De la misma forma, la función imagefilledpolygon(id. imagen, matriz de


puntos, número de vértices, color) dibuja un polígono del color
especificado. El parámetro matriz de puntos es un array de PHP que contiene
el valor de los vértices del polígono.

La función imagefilledrectangle(id. imagen,x1,y1,x2,y2,color) dibuja un


rectángulo relleno del color especificado cuyo ángulo superior izquierdo está
en la coordenada x1,y1 y cuyo ángulo inferior derecho está en la coordenada
x2,y2.

La función imagefilledtoborder(id. imagen,x,y,borde,color) rellena del


color especificado un área cuyo ángulo superior izquierdo está en la
coordenada x,y hasta el identificador del color definido para borde.

La función imagecolorat(id. imagen,x,y) devuelve el índice del color del píxel


especificado en la posición de la imagen.

La función imagecolorset(id. imagen, índice, rojo, verde, azul)


establece el índice especificado de la paleta con el color introducido. Esta
función puede resultar útil para crear efectos de rellenado sin tener que usar
estas funciones, que ocupan más memoria. Se usa para reemplazar un color
que ya existe en una imagen por otro que puede usarse para dibujar parte de la
misma. Combinada esta función con imagecolorclosest() no es necesario
conocer el color original para cambiarlo.

La función imagecolorclosest(id. imagen, rojo, verde, azul) devuelve el


índice del color de la paleta de la imagen más próximo al valor RGB
especificado. Esta función es similar a imagecolorexact (id. imagen, rojo,
verde, azul), que devuelve el índice exacto del color especificado.

La función imagecolortotal(id. imagen) devuelve el número total de colores


que hay en la paleta de imagen.

La función imagecolorforindex(id. Imagen, índice) devuelve una matriz


asociativa en la que se guardan los colores de un índice.

18
Curso Avanzado de PHP
Unidad 1: Tratamiento de gráficos

3. Función que permite mostrar imágenes

La función imagegd(id. imagen [, fichero]) produce la salida de una imagen


a la pantalla (explorador del usuario) o permite guardarla en un fichero si se
indica el nombre de éste en el parámetro opcional. Si este parámetro se deja a
NULL, la imagen será enviada directamente a la pantalla. De la misma forma
procede la función imagegd2(id. imagen [, fichero]) en el caso de imágenes
creadas con la versión 2.0 o superiores de la librería GD.

La función imagegif(id. imagen [, fichero]) produce la salida de una


imagen GIF a la pantalla (explorador del usuario) o permite guardarla en un
fichero si se indica el nombre de éste en el parámetro opcional. Si este
parámetro se deja en blanco, la imagen será enviada directamente a la
pantalla. Recordamos aquí que el soporte para imágenes de tipo GIF ha sido
incluido de nuevo en la librería GD a partir de la versión 2.0.28 por lo cual esta
función está disponible en este curso. Si bien, por compatibilidad con otros
servidores que no tengan esta versión, es recomendable sustituirla por
imágenes con formato PNG, que son prácticamente iguales.

La función imagejpeg(id. imagen [, fichero [, calidad]]) produce la salida


de una imagen JPEG a la pantalla (explorador del usuario) o permite guardarla
en un fichero si se indica el nombre de éste en el parámetro opcional
(segundo). Si este parámetro se establece a NULL, la imagen será enviada
directamente a la pantalla. El otro parámetro opcional (tercero) permite indicar
el grado de calidad de la imagen especificando un valor entre 0 (más baja) y
100 (más alta). Por defecto, se toma el valor 75 si no se indica este parámetro.
Cuando se quiere hacer aparecer este parámetro y no el nombre del fichero,
hay que sustituir el nombre de éste por NULL.

La función imagewbmp(id. imagen [, fichero [, color]]) produce la salida


de una imagen WBMP a la pantalla (explorador del usuario) o permite
guardarla en un fichero si se indica el nombre de éste en el parámetro opcional.
Si este parámetro se deja en blanco, la imagen será enviada directamente a la
pantalla. El otro parámetro opcional (tercero) permite indicar el color de la
imagen. Por defecto, se toma el color negro si no se indica este parámetro.
Cuando se quiere hacer aparecer este parámetro y no el nombre del fichero,
hay que sustituir el nombre de éste por NULL.

Similar es la función image2wbmp(id. imagen [, fichero [, borde]]) con la


diferencia de que permite establecer opcionalmente el borde de la imagen en
su parámetro tercero.

4. Función que permiten destruir imágenes

La función imagedestroy(id. Imagen) libera la memoria asociada a la imagen


que hemos creado con la función imagecreate().

19
Curso Avanzado de PHP
Unidad 1: Tratamiento de gráficos

5. Otras funciones de tratamiento de imágenes

La función getimagesize(fichero [, matriz]) determina el tamaño de una


imagen. Devuelve una matriz que tiene cuatro elementos: bajo el índice 0
contiene la anchura de la imagen en pixeles; bajo el índice 1 contiene su altura;
bajo el índice 2 se indica el tipo de imagen (1=GIF, 2=JPG, 3=PNG); y bajo el
índice 3 contiene una cadena con formato "height=xxx width=xxx" para ser
usado directamente. Si damos nombre a la matriz del parámetro opcional,
podremos extraer información adicional del fichero de imagen. Esta información
se pasa por referencia. La función getimagesize() no requiere la librería GD.

La función imagecopy(id. destino, id. origen, x destino, y destino, x


origen, y origen, anchura origen, altura origen) copia parte de la imagen
id. origen desde las coordenadas x,y origen hasta anchura y altura origen
en la imagen id. destino a partir de las coordenadas x,y destino de ésta. El
identificador de imagen puede ser el mismo. En este caso una misma imagen
quedaría reducida parcialmente.

La función imagecopymerge(id. destino, id. origen, x destino, y destino,


x origen, y origen, anchura origen, altura origen, porcentaje) copia y
mezcla en el porcentaje especificado parte de la imagen id. origen desde las
coordenadas x,y origen hasta anchura y altura origen en la imagen id.
destino a partir de las coordenadas x,y destino de ésta. El porcentaje se
expresa desde 0 (sin mezcla) a 100 (máxima mezcla).

La función imagecopymergegray(id. destino, id. origen, x destino, y


destino, x origen, y origen, anchura origen, altura origen, porcentaje
de color gris) es como la función anterior usando como color de mezcla el
gris.

La función imagecopyresampled(id. destino, id. origen, x destino, y


destino, x origen, y origen, anchura origen, altura origen, anchura
destino, altura destino) copia una porción rectangular de una imagen sobre
otra, suavizando los valores de los píxeles mediante interpolación, de forma
que al reducir el tamaño de una imagen aún mantiene una buena calidad.

La función imagecopyresized(id. destino, id. origen, x destino, y


destino, x origen, y origen, anchura origen, altura origen, anchura
destino, altura destino) copia y redimensiona parte de una imagen. Puede
usarse para copiar regiones dentro de la misma imagen.

Hemos usado esta función, entre otras, en el Ejemplo 3.

Utilizando Eclipse PDT puedes abrir el proyecto Ejemplo 3 (Galería de


imágenes) de la Unidad 1. Estudia el código fuente y ejecútalo para mostrar
en el navegador el resultado de su interpretación.

Si ejecutas el Ejemplo 3 de la Unidad 1 verás que aparece la siguiente página


que crea imágenes en miniatura (thumbnail) de unas fotos del servidor:

20
Curso Avanzado de PHP
Unidad 1: Tratamiento de gráficos

Además, hemos aplicado de nuevo esta función, entre otras, en el Ejemplo 8.

Utilizando Eclipse PDT puedes abrir el proyecto Ejemplo 8 (Galería de


imágenes) de la Unidad 1. Estudia el código fuente y ejecútalo para mostrar
en el navegador el resultado de su interpretación.

Si ejecutas el Ejemplo 8 de la Unidad 1 verás que aparece la siguiente página


que muestra la tierra y permite al usuario ampliar el mapa haciendo clic sobre
la imagen:

Para realizar la funcionalidad que permite al usuario hacer clic sobre la imagen,
hemos utilizar la siguiente etiqueta HTML dentro de un formulario:

<INPUT TYPE="IMAGE" SRC="la_tierra.jpg" NAME="mapa" ALT="Haz clic en


la imagen para ampliarla" BORDER="0" style="cursor:zoom-in">

Puedes ver que se trata de una etiqueta INPUT de tipo IMAGE y en el estilo CSS
cambiamos el cursor del ratón a una lupa. Así, en la página destino, se generan

21
Curso Avanzado de PHP
Unidad 1: Tratamiento de gráficos

automáticamente las variables $_REQUEST["mapa_x"] y $_REQUEST["mapa_y"]


que indican dónde ha hecho clic el usuario.

Ten en cuenta que en este ejemplo usamos 2 imágenes: la primera, más


pequeña, que es la que aparece en la página inicialmente y una segunda de
mayor resolución que utilizamos para ampliar la imagen recortando un trozo de
la misma.

La función imagefontheight(fuente) devuelve la altura de la fuente de un


carácter de una imagen. Por defecto, el tamaño de la altura se especifica en
pixeles usando una fuente predefinida interna que tiene los valores 1, 2, 3, 4 y
5. El tamaño menor de ésta corresponde al valor 1 y el mayor corresponde al
valor 5.

La función imagefontwidth(fuente) devuelve la anchura de la fuente de un


carácter de una imagen. El tamaño de la anchura se especifica en píxeles
usando una fuente predefinida interna que tiene los valores mismos que la
función anterior.

Hemos usado estas dos funciones anteriores, entre otras, en el Ejemplo 4 para
calcular el tamaño que ocuparán los textos en una imagen en base al tamaño
de la fuente y la longitud del texto.

Utilizando Eclipse PDT puedes abrir el proyecto Ejemplo 4 (Encuestas) de


la Unidad 1. Estudia el código fuente y ejecútalo para mostrar en el
navegador el resultado de su interpretación.

Si ejecutas el Ejemplo 5 de la Unidad 1 verás que aparece la siguiente página:

22
Curso Avanzado de PHP
Unidad 1: Tratamiento de gráficos

En este programa puedes seleccionar una encuesta y hacer una votación cada
de 10 segundos mediante un sencillo control con una Cookie. Es importante
que estudies en profundidad el código fuente que dibuja la gráfica ya que
puede servirte para realizar la actividad del curso.

La función imagettfbbox(tamaño fuente, ángulo rotación, fuente TrueType,


texto) calcula y devuelve un rectángulo en pixeles que encierra un texto
escrito con fuente TrueType del tamaño especificado y con la inclinación
dada. Esta función devuelve una matriz con ocho elementos que representan
los cuatro puntos que delimitan la caja que enmarca el texto, según la tabla
siguiente:

23
Curso Avanzado de PHP
Unidad 1: Tratamiento de gráficos

Elemento 0 Posición X de la esquina inferior izquierda.


Elemento 1 Posición Y de la esquina inferior izquierda.
Elemento 2 Posición X de la esquina inferior derecha.
Elemento 3 Posición Y de la esquina inferior derecha.
Elemento 4 Posición X de la esquina superior derecha.
Elemento 5 Posición Y de la esquina superior derecha.
Elemento 6 Posición X de la esquina superior izquierda.
Elemento 7 Posición Y de la esquina superior izquierda.

Hemos usado esta función, entre otros, en el Ejemplo 5.

Utilizando Eclipse PDT puedes abrir el proyecto Ejemplo 5 (Botón) de la


Unidad 1. Estudia el código fuente y ejecútalo para mostrar en el navegador
el resultado de su interpretación.

Si ejecutas el Ejemplo 5 de la Unidad 1 verás que aparece la siguiente imagen:

A partir de la versión 4.1.0 de PHP se puede usar la función parecida


imageftbbox(tamaño fuente, ángulo rotación, fuente FreeType, texto[,
matriz ]), que hace lo mismo con fuentes de tipo FreeType2. Además,
opcionalmente se puede usar un quinto parámetro con la misma finalidad que
desempeña en la función getimagesize(fichero [, matriz]).

La función imagettftext(id. imagen, tamaño fuente, ángulo rotación, x,


y, color, fuente TrueType, texto) escribe la cadena texto en imagen,
comenzando en las coordenadas x,y (arriba izquierda igual a 0,0), con un el
ángulo de rotación (medido en grados) y el color especificados usando la
fuente TrueType identificada en el fichero. Hay que tener en cuenta que las
coordenadas dadas por x,y definen el punto base del primer carácter (esquina
inferior izquierda del primer carácter de texto). El valor 0 en el ángulo de
rotación hace que el texto se escriba de izquierda a derecha y el valor 90, de
arriba abajo. Esta función devuelve una matriz con ocho elementos que
representan los cuatro puntos que delimitan la caja que enmarca el texto, como
hemos indicado en la función imagettfbbox().

A partir de la versión 4.1.0 de PHP se puede usar la función parecida


imageftttext(id. imagen, tamaño fuente, ángulo rotación, x, y, color,
fuente FreeType, texto [, matriz ]), que hace lo mismo con fuentes de tipo
FreeType2. Además, opcionalmente se puede usar un quinto parámetro con la
misma finalidad que desempeña en la función getimagesize(fichero [,
matriz]).

24
Curso Avanzado de PHP
Unidad 1: Tratamiento de gráficos

La función imagetypes() determina el tipo de imagen (formato) soportado por


PHP. Crea una variable que fija el tipo de imagen según la tabla siguiente:

Tipo de imagen Constante


GIF IMG_GIF
JPEG IMG_JPG
PNG IMG_PNG
WBMP IMG_WBMP

Esta función nos permite determinar previamente si un tipo de imagen es


soportado por las versiones de PHP y de la librería GD utilizadas. Por ejemplo,
si queremos saber si el formato de imagen GIF está soportado, podemos
escribir el código:

if (imagetypes() & IMG_GIF) {


echo "El formato GIF sí está soportado.";
} else {
echo " El formato GIF no está soportado.";
}

Similar a la función anterior es la función exif_imagetype(fichero), que lee los


primeros bits de una imagen y busca su formato. En el Manual de PHP pueden
verse los valores que corresponden a cada tipo de imagen. Devuelve el valor
entero correspondiente al formato encontrado o False en el caso contrario. No
exige la librería GD.

A partir de la versión 4.2.0 de PHP se ha incorporado la función


exif_read_data(fichero [, secciones [, matriz [, thumbnail]]]), que lee
las cabeceras de los ficheros de imagen de tipo JPEG o TIFF y devuelve una
matriz asociativa que tiene como índices los nombres de las cabeceras y como
valores los asociados a cada cabecera. Si no se encuentran, se devuelve
False. El parámetro secciones, que es opcional, incluye los datos siguientes,
que deben ir separados por comas:

FILE Nombre, Tamaño, Fecha, Secciones encontradas.


COMPUTED html, Largo, Ancho, Imagen con color y alguna cosa más.
Lista las etiquetas que contienen cualquier información. Por
ANY_TAG
ejemplo, IFD0, EXIF...
Contiene todos los datos de la etiqueta IFD0. En imágenes
IFD0 típicas contiene el tamaño de la imagen, comentarios, copyright,
etcétera.
Una imagen contiene un thumbnail (la misma imagen más
pequeña) si su fichero contiene un secundo IFD. Toda la
THUMBNAIL
información referida a este thumbnail está contenida en este
campo.

25
Curso Avanzado de PHP
Unidad 1: Tratamiento de gráficos

Contiene los comentarios de la cabecera de imágenes tipo


COMMENT
JPEG.
El campo EXIF está contenido en el IFD0. Contiene información
EXIF más detallada de una imagen. Sobre todo se usa para
almacenar datos cuando se toman fotos con una cámara digital.

Utilizando Eclipse PDT puedes abrir el proyecto Ejemplo 9 (Leer datos EXIF
de fotos) de la Unidad 1. Estudia el código fuente y ejecútalo para mostrar en
el navegador el resultado de su interpretación.

Si ejecutas el Ejemplo 9 de la Unidad 1 verás que aparece la siguiente página


PHP:

Hay otras funciones de la librería GD, casi todas usadas en las diferentes
actividades de esta Unidad, que el alumno puede consultar en el Manual de
PHP y ver cómo se usan.

26
Curso Avanzado de PHP
Unidad 1: Tratamiento de gráficos

1.4. Sistema Captcha


Captcha es el acrónimo en inglés de Completely Automated Public Turing
Test to tell Computers and Humans Apart (Prueba de Turing pública y
automática para diferenciar máquinas y humanos).

La siguiente imagen es un test para la secuencia "d1d0q1k" que dificulta el


reconocimiento de un ordenador distorsionando las letras y añadiendo un
degradado de fondo:

Se trata de una prueba desafío-respuesta utilizada en informática para


determinar cuándo el usuario es o no humano.

La típica prueba consiste en que el usuario introduzca un conjunto de


caracteres que se muestran en una imagen distorsionada que aparece en
pantalla. Se “supone” que una máquina no es capaz de comprender e introducir
la secuencia de forma correcta por lo que sólo el humano podría leer
correctamente el texto.

Los Captchas son utilizados para evitar que programas informáticos puedan
usar automáticamente ciertos servicios. Por ejemplo, para que no puedan
participar en encuestas, registrarse para usar cuentas de correo electrónico (o
su uso para envío de spam (correo basura), etcétera.

En el Ejemplo 10 de esta Unidad vamos a estudiar cómo implementar esta


medida de seguridad utilizando la biblioteca GD de PHP.

Los pasos básicos para generar un sistema de control de tipo Captcha son los
siguientes:

1. Generar una clave aleatoria e incluirla en una cookie o variable de


sesión.
2. Generar la imagen de tipo catcha cuyo texto es la clave anterior.
3. Mostrar la imagen al usuario que quiera acceder al recurso.
4. Mostrar un formulario donde el usuario introduzca la clave y la pueda
enviar.
5. Verificar la clave enviada coincide con la almacenada en la sesión o
cookie y permitir el acceso en el caso correcto.

27
Curso Avanzado de PHP
Unidad 1: Tratamiento de gráficos

A continuación, estudiaremos el código necesario para crear el control captcha.


Es importante que abras el código en Eclipse PDT para analizarlo en detalle.

1. Generar una clave aleatoria e incluirla en una cookie o variable de


sesión

Como hemos mencionado, el primer paso es generar una cadena de texto con
la clave aleatoria. Existen múltiples formas de conseguir esto, si bien se debe
cumplir dos requisitos: el texto tiene que cambiar constantemente y es
necesario cifrarlo.

Por ejemplo, un valor que cambia constantemente puede ser la fecha y la hora
del servidor: para ello, nos serviremos de las funciones microtime() y time()
de PHP. Una vez obtenido un texto aleatorio con la orden rand(), lo cifraremos
con la función hash md5() de PHP. Finalmente, en la última línea del código,
almacenaremos la clave en una variable de sesión:

// Esta función genera una cadena con n letras aleatorias


function cadenaAleatoria($longitud=6)
{
$_rand_src = array(
array(48,57) //dígitos
, array(97,122) //caracteres en minúscula
// , array(65,90) // caracteres en mayúscula
);
// Iniciamos la semilla aleatoria
srand ((double) microtime() * time());
$random_string = "";
for($i=0;$i<$longitud;$i++){
// Generamos un número aleatorio
$i1=rand(0,sizeof($_rand_src)-1);
// Añadimos un caracter aleatorio
$random_string .=
chr(rand($_rand_src[$i1][0],$_rand_src[$i1][1]));
}
return $random_string;

} // end función cadenaAleatoria

// Sólo necesitamos 7 caracteres


$clave = cadenaAleatoria($longitud_captcha);

// Guardamos la clave en la variable de sesión. La clave está cifrada


con md5.
$_SESSION['clave'] = md5($clave);

El algoritmo MD5 genera, a partir de una cadena de texto o un fichero, un


número único de 32 dígitos en hexadecimal. En inglés, este tipo de funciones
se denomina “hash”. Teóricamente, este número no es reversible, es decir, no
se puede obtener el texto original. Por lo tanto, este tipo de algoritmo es ideal
para cifrar contraseñas o claves como es este caso.

28
Curso Avanzado de PHP
Unidad 1: Tratamiento de gráficos

2. Generar la imagen de tipo catcha cuyo texto es la clave anterior

Una vez generada la clave captcha y almacenado correctamente en la sesión


del usuario, creamos la imagen y la mostramos al usuario:

// Cargamos la imagen que servirá de fondo.

$captchaImagen = imagecreatefromjpeg( "recursos/textura.jpg" );

/*
Seleccionamos un color para el texto. Como el fondo es rojizo,
escogeremos un rosáceo para el texto. El color del texto debe ser,
idealmente, el mismo que el del fondo, aunque un poco más oscuro para
poder distinguirlo.

*/
$textColor = imagecolorallocate( $captchaImagen, 240, 118, 92 );

// Seleccionamos un color para las líneas que queremos se dibujen en


nuestro captcha. En este caso usaremos una mezcla entre verde y azul.

$lineaColor = imagecolorallocate( $captchaImagen, 255, 103, 103 );

Una vez hemos seleccionado los colores, vamos a pintar algunas líneas que
aumenten la dificultad para que un sistema automático lea la clave (texto
aleatorio):

// Recuperamos el tamaño de la imagen.

$imageInfo = getimagesize( "recursos/textura.jpg" );

// Añadimos las líneas de manera aleatoria


for( $i = 0; $i < $n_lineas; $i++ ) {
// Seleccionamos el inicio y el final de la línea aleatoriamente
en el largo de ésta
$xInicio = mt_rand( 0, $imageInfo[0] );
$xFin = mt_rand( 0, $imageInfo[0] );

// Dibujamos la línea en el captcha


imageline($captchaImagen, $xInicio, 0, $xFin, $imageInfo[1],
$lineaColor);
}

Finalmente, escribimos el texto de la clave aleatoria en la imagen mostrándola


en el navegador del visitante. Hemos utilizado imagen de fondo prediseñada ya
que así podemos cambiar fácilmente este fondo y generar un captcha más
complejo.

Por lo tanto, para escribir la clave aleatoria aplicamos la función


imagettftext() usando una fuente True Type. De igual forma, podríamos
haber utilizado cualquier otra fuente o, aún mejor, mezclado fuentes al azar
para hacer todavía más difícil que un sistema automático lea la imagen:

29
Curso Avanzado de PHP
Unidad 1: Tratamiento de gráficos

//Escribimos nuestro texto aleatoriamente, utilizando una fuente true


type.
imagettftext($captchaImagen, 50, 0, 35, 65, $textColor,
"recursos/Texture Road.ttf", $clave);

// Indicamos al navegador que vamos a devolver una imagen.


Header ('Content-type: image/jpeg');
// Le indicamos al navegador que no cachee nada.
header("Cache-Control: no-cache, must-revalidate");
header("Expires: Fri, 19 Jan 1994 05:00:00 GMT");
header("Pragma: no-cache");
// Liberamos la imagen.
imagejpeg($captchaImagen,NULL,100);
// Destruimos la imagen.
ImageDestroy($captchaImagen);

En la parte final del código anterior puedes ver que indicamos al navegador que
vamos a devolver una imagen con este script e indicamos al navegador que no
cachee nada.

3. Mostrar la imagen al usuario que quiera acceder al recurso

Una vez disponemos de una imagen captcha que incluye una clave aleatoria
asociada a una sesión del usuario, vamos a crear un formulario que permita al
usuario ver la clave, escribirla en un campo de texto y enviarla pulsando un
botón:

echo 'CAPTCHA: (protecci&oacute;n antispam)<br>


<img src="captcha.php" border="0" />
<form name="captcha-form" method="POST" action="index.php">
<input type="text" name="clave" width="25" />
<input type="submit" name="enviar" value="Enviar" />

</form>';

Cuando el usuario envía el formulario verificamos que el texto escrito coincide


con la clave aleatoria almacenada cifrada con md5 en la sesión del usuario:

// Iniciamos la sesión del usuario.


session_start();
// Si el usuario hace clic en el botón enviar entonces...
if (isset($_POST['enviar'])){
// Si la variable $_SESSION['captcha'] creada en captcha.php
// coincide con lo que escribe el usuario -> OK
if( md5( $_POST[ 'clave' ] ) == $_SESSION[ 'clave' ] ) {
echo '<b><font color=green>¡Captcha correcto! </font></b>';
} else { // Captcha incorrecto
echo '<b><font color=red>¡Captcha incorrecto!</font></b>';
}
echo ' <input type="button" value="Volver atrás"
onclick="history.back()" style="font-family: Verdana;
font-size: 10 pt">';
}

Hacemos notar que la imagen captcha se podría hacer mucho más compleja,
por ejemplo:

30
Curso Avanzado de PHP
Unidad 1: Tratamiento de gráficos

 Combinando imágenes de foto reales con números y letras para


hacerlo semilegible y dificultar que un sistema automático lea la imagen.
 Girando el texto y modificando el espaciado entre letras.
 Cambiando la ubicación del texto en imagen.
 Modificando las fuentes y colores del texto.
 Utilizando fondos de imagen aleatorios.

Atención: hay que tener cuidado a la hora de generar un captcha ya que, si


lo hacemos muy complejo, puede ocurrir que los propios usuarios no
puedan entenderlo.

Utilizando Eclipse PDT puedes abrir el proyecto Ejemplo 10 (Captcha) de


la Unidad 1. Estudia el código fuente y ejecútalo para mostrar en el
navegador el resultado de su interpretación.

Si ejecutas el Ejemplo 10 de la Unidad 1 verás que aparece la siguiente


página:

Si el visitante escribe correctamente el desafío (captcha) entonces aparece el


mensaje en pantalla “¡Captcha correcto!”. En caso contrario mostramos el
mensaje “¡Captcha incorrecto!”.

Volvemos a insistir en que, a veces, los errores de la generación de la imagen


no se presentan en la página web directamente (debido a que se devuelve una
imagen al navegador) sino en el fichero de errores de PHP siguiente:

C: \XAMPP\php\logs\php_error_log

Puedes acceder a este fichero con cualquier editor de texto plano y ver el
contenido del mismo para encontrar los errores de la generación de la imagen.

31
Curso Avanzado de PHP
Unidad 1: Tratamiento de gráficos

Adobe Flash
Adobe Flash es el nombre o marca comercial oficial que recibe uno de los
programas más famosos de Adobe. Se trata de una aplicación de creación y
manipulación de gráficos vectoriales con posibilidades de incluir código
mediante el lenguaje ActionScript de tipo script. En realidad, Flash es un
estudio de animación que trabaja con "fotogramas" y se usa para producir
contenido interactivo multimedia en Internet.

PHP 5 dispone de dos bibliotecas diferentes que permiten la creación de


películas Flash:

• En el capítulo "Shockwave Flash Functions" del Manual de PHP 5 se


explican las funciones necesarias para la creación de este tipo de
animaciones. Esta librería fue creada por Paul Haeberli.

• En el capítulo "Ming functions for Flash" del Manual de PHP 5 se


exponen también las funciones necesarias para la creación de este tipo
de animaciones usando la librería Ming. Por cierto, Ming es el enemigo
de Flash Gordon .

La biblioteca Ming es un conjunto de funciones de código abierto (GPL)


que permiten la creación de ficheros Flash (extensión SWF). No es
exclusiva de PHP, sino que puede usarse con cualquier otro lenguaje de
programación. Puede recogerse en la dirección
http://ming.sourceforge.net/ y utilizarse de forma libre y gratuita.

Desafortunadamente, estas dos bibliotecas tienen cada vez menos soporte y,


sobre todo en Windows, no existen versiones compiladas para las últimas
versiones de PHP. Teniendo en cuenta que cada vez se usan menos en PHP y
dada la complicada compilación en Windows, no vamos a estudiarlas en el
curso. Además, hay que tener en cuenta que se trata de bibliotecas
experimentales por lo que su estabilidad no está garantizada en entornos de
producción.

1.5. Integración PHP y Flash


Sin embargo, sí es posible integrar PHP en películas flash utilizando una
interfaz XML. En este apartado vamos a estudiar, a modo de ejemplo, cómo
integrar PHP en una película flash.

Aunque el objeto de este curso no es tratar el desarrollo de una película flash,


vamos a ver de forma muy sencilla cómo hacerlo para aplicarlo a un ejemplo
con PHP.

32
Curso Avanzado de PHP
Unidad 1: Tratamiento de gráficos

Es importante tener en cuenta que, aunque HTML 5 puede sustituir a Flash en


muchas aplicaciones y aunque esta tecnología no está disponible en
dispositivos móviles, todavía a día de hoy sigue siendo muy utilizada en
algunos proyectos, por lo que es conveniente conocer cómo funciona.
Lo primero que debemos hacer es descargar la versión de prueba (30 días) de
Flash Professional CC de la web de Adobe en este enlace. En la página que
aparece debemos pulsar el botón “Descargar versión de prueba”:

A continuación, debemos tener un usuario registrado para poder descargar


este software, por lo que pulsaremos el botón que corresponda para contar con
este usuario:

Si ya hemos obtenido este usuario gratuito, iniciamos la sesión en la página:

Al hacer clic en el botón “INICIAR SESIÓN” pueden aparecer varias pantallas


intermedias pidiendo confirmación de algunos datos personales que podemos
rellenar o no.

33
Curso Avanzado de PHP
Unidad 1: Tratamiento de gráficos

Finalmente, aparecerá una página que descargará el instalador del programa:

¡Advertimos que este instalador no funciona en Windows XP!

Una vez hemos descargado el instalador debemos ejecutarlo en Windows y se


iniciará el programa:

Al finalizar la instalación, aparece la aplicación “Creative Cloud” e introducimos


de nuevo las credenciales de Adobe que hemos utilizado anteriormente:

34
Curso Avanzado de PHP
Unidad 1: Tratamiento de gráficos

Después, se inicia la instalación de Flash Professional:

35
Curso Avanzado de PHP
Unidad 1: Tratamiento de gráficos

Ten en cuenta que la instalación puede ser muy lenta, unos 20-30 minutos.

Finalmente, se acaba la instalación:

Desde el menú de aplicaciones de Windows podemos iniciar Adobe Flash


Professional CC 2014:

36
Curso Avanzado de PHP
Unidad 1: Tratamiento de gráficos

A continuación, se indicará el usuario que tiene 30 días para probarlo:

37
Curso Avanzado de PHP
Unidad 1: Tratamiento de gráficos

Pulsamos el botón “Iniciar versión de prueba”. Una vez arracanda la aplicación,


pulsamos en la opción “Desactivar configuración de sincronización”:

Para crear un nuevo proyecto de Action Script 3.0 hacemos clic en el botón
indicado en la siguiente imagen:

A continuación, hacemos clic en el botón señalado para añadir la clase que


definirá la película:

38
Curso Avanzado de PHP
Unidad 1: Tratamiento de gráficos

Después, escribimos el nombre “main” y pulsamos el botón “Aceptar”:

Incluimos el código fuente Action Script:

39
Curso Avanzado de PHP
Unidad 1: Tratamiento de gráficos

Nota: El código se puede obtener del archivo “main.as” del Ejemplo 11 de esta
Unidad.

Finalmente, guardamos los archivos con el atajo de teclado [CTRL + S] en el


directorio donde tendremos el script PHP del programa.

Para probar la película podemos hacer clic en la siguiente opción del menú:
(atajo del teclado [CTRL + INTRO]):

A continuación aparecerá la película Flash que hemos programado:

40
Curso Avanzado de PHP
Unidad 1: Tratamiento de gráficos

A continuación, mostramos la estructura de la tabla MySQL de usuarios que


usaremos en este programa:

-- Script que crea la BD de este ejemplo


SET NAMES UTF8;
CREATE DATABASE IF NOT EXISTS ejercicios;
USE ejercicios;

DROP TABLE IF EXISTS usuarios;


CREATE TABLE IF NOT EXISTS usuarios (
id int(5) NOT NULL DEFAULT '0',
usuario varchar(13) DEFAULT NULL,
password varchar(50) NOT NULL DEFAULT '',
PRIMARY KEY (id),
UNIQUE KEY usuario (usuario)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

-- Fíjate que guardamos la contraseña con SHA1 incluido. Sólo el


usuario que sepa la contraseña podrá acceder al servidor
INSERT INTO usuarios VALUES("1", "admin", SHA1('12345'));

Hay que tener en cuenta que guardamos la contraseña usando de nuevo el


algoritmo SHA1 para guardar el hash en la base de datos. Así, sólo el usuario
que sepa la contraseña podrá acceder al servidor y si algún hacker obtiene
acceso al servidor, no podrá revertir la contraseña en texto claro.

El proyecto consta además de dos archivos PHP: index.php que se encarga de


mostrar la película flash y recrear la base de datos del proyecto y valida.php
que gestiona las peticiones que hará la película flash.

41
Curso Avanzado de PHP
Unidad 1: Tratamiento de gráficos

Como el código de index.php es bastante sencillo de entender, a continuación,


presentamos únicamente el archivo valida.php:

<?php
// No dejamos que se envíe al navegador del usuario. Es decir, activamos el
buffer de salida de PHP.
ob_start();

$DBHost="localhost";
$DBUser="root";
$DBPass="";
$DB="ejercicios";

// Función que ejecuta una SQL


function ejecuta_SQL($sql) {
global $db;
// Preparamos la consulta para evitar SQL Injection
$resultado = $db->prepare($sql);
// Ejecutamos la consulta
$resultado->execute();
if (!$resultado)
{
imprimeXML("ERROR", "No se ha podido ejecutar la consulta:\n
$sql.");
die ();
}
return $resultado;
} // end ejecuta_SQL

// Función que genera el archivo XML que usamos para intercambio de


información
function imprimeXML($codigo, $dato) {
// Indicamos al cliente que este script devuelve un archivo XML
header("Content-Type: text/xml");
echo "<?xml version='1.0' encoding='utf-8'?>\n";
echo "<authentication>\n";
echo "<resultado>\n";
echo "<CODIGO>$codigo</CODIGO>\n";
echo "<DATO>$dato</DATO>\n";
echo "</resultado>\n";
echo "</authentication>";
}

/* Intentamos establecer una conexión con el servidor.*/


try {
$db = new PDO("mysql:host=" . $DBHost .
";dbname=".$DB.";charset=utf8", $DBUser, $DBPass);
$db->setAttribute(PDO::MYSQL_ATTR_USE_BUFFERED_QUERY, true);
// Indicamos como atributo que se debe devolver una cadena vacía para
los valores nulos
$db->setAttribute(PDO::NULL_TO_STRING, true);

$resultado=ejecuta_SQL("show tables like 'usuario'");


// Si no existe la base de datos, la creamos
if (($resultado->rowCount())<2) {
$sql = file_get_contents('base_datos.sql');
ejecuta_SQL($sql);
}

42
Curso Avanzado de PHP
Unidad 1: Tratamiento de gráficos

} catch (PDOException $e) {


imprimeXML("ERROR", "No se ha podido establecer la conexión. \n"
. "Compruebe si está activado el servidor de bases de "
. "datos MySQL.\n Error: " . $e->getMessage());
exit;
} // end try

// Validamos si se ha indicado el usuario/contraseña


if (!isset($_POST['usuario'])) {
imprimeXML("ERROR", "Es obligatorio indicar el nombre del usuario");
exit;
}
else
if (!isset($_POST['contrasena'])){
imprimeXML("ERROR", "Es obligatorio indicar la contraseña del
usuario");
exit;
}

// Obtenemos las variables usuario y contrasena


$usuario = $_POST['usuario'];
// ¡Hacemos SHA1 del contenido de esta variable!
$contrasena = sha1($_POST['contrasena']); // Usamos el hash SHA1.

// SQL que selecciona el id del usuario y contraseña


$strSQL = "SELECT id FROM usuarios WHERE usuario = '$usuario' AND password =
'$contrasena'";
$resultado=ejecuta_SQL($strSQL);

// Si el resultado da alguna línea, devolvemos un OK a la operación. Si no,


indicamos un error genérico.
if ($resultado->rowCount()==1)
imprimeXML("OK", "El usuario $usuario se ha validado correctamente y
tiene el ID " . $resultado->fetchAll()[0][0]);
else imprimeXML("ERROR", "¡El usuario o la contraseña no es correcto!");
?>

Aunque en el apartado Seguridad en PHP de la Unidad 6 veremos los


principios sobre desarrollo seguro de aplicaciones PHP, hemos utilizado en
este ejemplo consultas SQL preparadas de la biblioteca PDO.

Así, evitamos el ataque de tipo inyección SQL (ver teoría de la Unidad 6) al


utilizar prepared statements (consultas preparadas) ya que el intérprete PHP
“limpia” el código SQL antes de que sea ejecutado. Esto lo usamos en la
función ejecuta_SQL().

Dado que Adobe Flash dispone nativamente integrado el formato XML, para
definir la interfaz entre la película y el script PHP vamos a generar un fichero
XML en memoria del servidor Apache para enviar el resultado de la petición
HTTP.

Este script PHP hace una consulta a la base de datos para saber si el
usuario/contraseña son correctos y construye un archivo XML para devolver el
resultado.

43
Curso Avanzado de PHP
Unidad 1: Tratamiento de gráficos

El código presentado anteriormente no implementa las buenas prácticas


de programación PHP y se usa únicamente con fines pedagógicos. Por lo
tanto, no es recomendable utilizarlo en entornos reales.

No es una implementación segura porque el nombre del usuario y su


contraseña (aunque usamos el algoritmo SHA1) se envían en texto plano hacia
el servidor PHP y un hacker podría “escuchar” esta información. La manera de
evitar este tipo de ataque consiste en utilizar un servidor seguro del tipo HTTPS
que use certificados digitales o cifrar la contraseña en el navegador del usuario
antes de enviarla como veremos en el Ejemplo 8 de la Unidad 2.

Utilizando Eclipse PDT puedes abrir el proyecto Ejemplo 11 (Integración


PHP en Flash) de la Unidad 1. Estudia el código fuente y ejecútalo para
mostrar en el navegador el resultado de su interpretación.

Si ejecutas el Ejemplo 11 de la Unidad 1 verás que aparece la siguiente


página:

Si el usuario no escribe el nombre y contraseña correctos aparecerá este


mensaje:

44
Curso Avanzado de PHP
Unidad 1: Tratamiento de gráficos

Por el contrario, si el usuario escribe el nombre (admin) y contraseña (12345)


correctos aparecerá este mensaje:

Para finalizar este apartado vamos a ver lo sencillo que resulta integrar
bibliotecas flash de terceros en un proyecto PHP. En este caso vamos a utilizar
la biblioteca gratuita y de libre uso Open Flash Chart que permite dibujar
gráficos con flash e integrarlos en aplicaciones PHP.

45
Curso Avanzado de PHP
Unidad 1: Tratamiento de gráficos

Como verás, la implementación es sumamente sencilla. En el archivo


index.php del Ejemplo 12 puedes ver que incluimos únicamente el código
fuente:

<?php
// Cargamos la biblioteca Open Flash Chart
include_once 'ofc-library/open_flash_chart_object.php';
// Creamos la imagen con los datos en el fichero datos_grafico.php
open_flash_chart_object( 700, 400, 'http://'. $_SERVER['SERVER_NAME'].
$_SERVER['REQUEST_URI'] .'datos_grafico.php', false);
?>

Como puedes ver, utilizamos la biblioteca Open Flash Chart para crear un
gráfico del tamaño 700x400 e indicamos que los datos se encuentran en el
fichero datos_grafico.php que contiene las siguientes sentencias:

<?php
// Cargamos la biblioteca Open Flash Chart
include_once( 'ofc-library/open-flash-chart.php' );
// Objeto que define el nuevo gráfico
$g = new graph();

// Establecemos los colores del gráfico


$g->bg_colour = '#F2F2F2';
$g->x_grid_colour = '#BDBDBD';
$g->y_grid_colour = '#BDBDBD';
$g->x_axis_colour= '#088A08';
$g->y_axis_colour= '#088A08';
// Leyendas del gráfico
$g->set_y_legend( 'Clientes (x 1000)', 15, '#088A08' );
$g->set_x_legend( 'Año', 15, '#088A08' );
// Título del gráfico
$g->title( 'Evolución penetración de móviles en España', '{font-size: 26px;}'
);
// Etiquetas y datos del gráfico
$g->set_x_labels(
array('2002','2003','2004','2005','2006','2007','2008','2009','2010','2011','
2012','2013') );
$g->set_data(
array(33531,37220,38623,42694,45676,48442,49623,51086,51601,56189,55742,55191
) );
// Máximo de la ordenadas (eje Y)
$g->set_y_max( 60000 );
// Cada 6 pasos se escribe una etiqueta
$g->y_label_steps( 6 );
// Generamos el gráfico
echo $g->render();
?>

Como puedes ver, simplemente, establecemos las propiedades, características


y datos del gráfico que se debe generar.

Utilizando Eclipse PDT puedes abrir el proyecto Ejemplo 12 (Integración


PHP en Flash - Gráfico) de la Unidad 1. Estudia el código fuente y
ejecútalo para mostrar en el navegador el resultado de su interpretación.

46
Curso Avanzado de PHP
Unidad 1: Tratamiento de gráficos

Si ejecutas el Ejemplo 12 de la Unidad 1 verás que aparece la siguiente


página:

Como puedes ver, es muy sencillo integrar bibliotecas de terceros para


desarrollar aplicaciones complejas y vistosas de forma fácil y rápida.

47
Curso Avanzado de PHP
Unidad 1: Tratamiento de gráficos

Resumen

Hay que saber al final de esta unidad…

• Tratar gráficos desde PHP dando los pasos necesarios


para crear imágenes, diseñarlas, mostrar el resultado
en la pantalla o guardarlo en un fichero y,
finalmente, eliminar de la memoria las imágenes
tratadas.

• Aplicar las principales funciones de la biblioteca GD


para incorporar gráficos e imágenes dentro del código
PHP.

• Usar la biblioteca GD de PHP para crear controles


Captcha en la validación de un usuario.

• Integrar PHP en películas Adobe Flash.

48

S-ar putea să vă placă și