PHP-TUT-20 Gestión de imágenes (I)

Facebooktwittergoogle_pluslinkedinmailFacebooktwittergoogle_pluslinkedinmail

En este artículo y el siguiente vamos a aprender a gestionar las imágenes que necesitemos presentar en nuestras páginas. Ya sabes que HTML te permite insertar imágenes en un documento web. Sin embargo, PHP te permite actuar sobre las imágenes antes de que sean enviadas al navegador, implementando ciertas funcionalidades que conoceremos en este artículo.

LO QUE NECESITAMOS

Para trabajar con imágenes, PHP implementa una librería con funcionalidades específicas, conocida como GD. Desde la versión 5 del lenguaje se implementa la versión 2 de la librería, conocida como GD2. Si has instalado PHP a partir del paquete Xampp que le comenté en un artículo anetrior debes tener esta librería disponible. Para asegurarte, abra el fichero ,php.ini que encontrarás en el directorio php, dentro del directorio donde tengas tu instalación de Xampp. En el fichero debe haber una línea como la siguiente:

extension = php_gd2.dll

Asegúrate de que esa línea aparece tal cual, sin nada más. En concreto, NO debe llevar nada precediéndola.

Además, dentro del directorio php/ext/ debe haber un archivo llamado php_gd2.dll. Si es así, ya tienes todo lo que necesitas para empezar a trabajar con imágenes. Si has instalado la última versión de Xampp, esta librería existe por defecto, con lo que no te tienes que preocupar de ella.

LO QUE PODEMOS HACER

PHP maneja imágenes, principalmente, para Internet. A través de las funciones que incorpora la librería GD2 podremos crear imágenes a partir de ficheros ya almacenados en el servidor, así como otras completamente nuevas.

PHP maneja imágenes en formatos .gif, .jpg, .jpeg, .png y .bmp. Este último formato no nos interesa especialmente, dado el peso de los archivos en que se almacenan las imágenes. El formato .gif fue suprimido en la librería GD 1.8 que empleaba PHP 4, ya que en aquella époa era un formato propietario, pero en la actual versión también está disponible.

A lo largo de este artículo veremos cómo podemos crear una imagen, copiarla, redimensionarla, cambiar un determinado color por otro, determinar la paleta de colores que forman una imagen e, incluso, modificarla píxel a píxel. También aprenderemos a crear gráficos a partir de datos numéricos, lo que nos será muy útil para representar evoluciones, bien de tipo climatológico, financiero, etc.

PHP proporciona funciones para llevar a cabo todas estas operaciones. De este modo, podemos implementar imágenes muy adecuadas en nuestras páginas, sin necesidad de recurrir a programas de retoque fotográfico, ni de edición de imagen. Por supuesto, no conseguiremos las mismas funcionalidades desde PHP que desde un programa profesional al efecto, pero sí lograremos unos resultados bastante buenos para dinamizar nuestras páginas. Y, lo que es más importante: la edición que llevemos a cabo desde scripts de PHP puede hacerse en base a datos que procedan de otras fuentes de una forma muy cómoda.

EMPEZANDO A TRABAJAR

Lo primero que vamos a hacer es comprobar que nuestro intérprete de PHP (y, más concretamente, la librería GD2 que tenemos instalada) soporta los distintos tipos de imágenes. Para determinadas operaciones con cada imagen existen unas funciones llamadas imagegif(), imagejpeg(), imagepng() e imagewbmp(). De momento no nos importa lo que podemos hacer con ellas. Nos ocuparemos de eso muy pronto. Lo que sí sabemos, porque así nos lo dicen las especificaciones de PHP, es que, si alguna de estas funciones no existe (si no es reconocida por el intérprete) es que el tipo de imagen al que se refiere la función no es soportado. La función function_exists() recibe, como argumento, el nombre de una función cualquiera del lenguaje, y nos devuelve un valor true o false, según esa función exista o no. Esto es válido, no sólo para las funciones de imagen, sino también para comprobar cualquier otra función del lenguaje. Si alguna vez tienes dudas acerca de si su intérprete soporta tal o cual función, utiliza function_exists() para determinarlo. Observa el listado tiposDeImagen.php:

Como ves, se comprueba la existencia de las cuatro funciones que hemos mencionado, cuyo uso, como digo, se comentará más adelante. Lo que importa es el resultado obtenido, que vemos a continuación:

Manejo imágenes GIF.
Manejo imágenes JPG.
Manejo imágenes PNG.
Manejo imágenes BMP.

Si obtienes otro resultado en la página, en el que falte alguna línea, deberás actualizar su versión del intérprete. No obstante, si ha instalado el paquete Xampp, no debes tener ningún problema.

Cuando se trabaja con un script que va a enviar una imagen al navegador es necesario incluir, al principio de dicho script, una cabecera (ver la función header() en este artículo) indicando que el contenido incluye una imagen, y de qué tipo es, tal como aparece en la siguiente línea:

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

Las alternativas a image/jpeg son image/gif, image/png e image/wbmp, dependiendo del tipo de imagen que maneje el script. Yo tengo que anotar que algunos scripts funcionan perfectamente sin necesidad de incluir la cabecera. No obstante, dado que la necesidad de la misma aparece en las especificaciones oficiales del lenguaje, y que no siempre se puede omitir, en lo sucesivo la incluiremos.

Las imágenes se tratan en PHP bajo la misma filosofía de trabajo que usábamos para los ficheros de texto (ver artículo al respecto): primero se “abre” la imagen, que podrá existir como un archivo en el servidor, o en otra parte, pero podrá no existir, si lo que vamos a hacer es crear una nueva imagen. Esta operación genera un manejador, que emplearemos para todas las operaciones que queramos llevar a cabo sobre la imagen. Por último, el equivalente a cerrar un fichero, será destruir el manejador que hemos usado, a fin de liberar recursos en la memoria.

Para crear un manejador, a través del cual trabajaremos con una imagen usaremos las siguientes funciones: imagecreatefromjpeg(), imagecreatefromgif(), imagecreatefrompng() e imagecreatefromwbmp(). Elegiremos una u otra según el tipo de imagen con el que vamos a trabajar. La función recibe, como argumento, el nombre y, en su caso, la ruta del fichero que contiene la imagen con la que queremos trabajar, y devuelve el manejador correspondiente. Si no se puede acceder a la ruta e imagen especificada, la función devuelve un valor false. Por si se da ese caso es interesante preceder la función del operador de errores (@). Por lo tanto, podemos decir que estas funciones sirven para crear un manejador para una imagen ya existente en un archivo.

A continuación, una vez creado el manejador, haremos “algo” con la imagen. De momento, vamos, simplemente, a mostrarla en el navegador. Para ello emplearemos alguna de las cuatro funciones que habíamos mencionado en tiposDeImagen.php, y que eran las siguientes: imagegif(), imagejpeg(), imagepng() e imagewbmp(). Emplearemos una u otra, según sea el tipo de imagen al que se refiere el manejador. La función elegida recibirá, como argumento, la variable que contenga dicho manejador.

Por último, para “cerrar” la imagen (destruir el manejador) y liberar así recursos de la memoria emplearemos la función imagedestroy(), que recibe el manejador que queremos cerrar como parámetro.

Para ver la operativa de estas tres funciones observa el listado del script mostrarRotulo.php:

Este script toma un archivo de imagen que está en una carpeta, llamada imagenes, dentro de la carpeta de tu localhost. Como puedes ver, lo primero que hacemos es enviar la correspondiente cabecera al navegador, siguiendo, como te comenté anteriormente, las especificaciones del lenguaje. A continuación, creamos un manejador que será la referencia al archivo de imagen y que nos permitirá trabajar con ella. Después, enviamos la imagen al navegador y, por último, eliminamos el manejador, a fin de liberar recursos en la memoria del sistema. Es importante que no olvides esto último, ya que, si tu script envía muchas imágenes y no liberas recursos, podría llegar a colapsar el servidor, sobre todo en páginas con muchos visitantes diarios.

Prueba este script en tu navegador. No olvides, previamente, crar la carpeta en tu servidor local, con la imagen deseada, que puedes descargar aquí.

La función imagejpeg(), así como sus homólogas para los otros tipos de imágenes, soporta un segundo parámetro opcional. Mira la siguiente línea en el script:

imagejpeg($imagenJPG, "imagenes/copiaDeImagen.jpg");

Esto copiará el archivo original en otro, cuyo nombre y ruta se especifica en el segundo argumento.

Además, puedes incluir un tercer parámetro (también opcional), indicando la calidad con la que desea mostrar la imagen, o grabarla en el nuevo fichero. Si lo que deseas es lo primero, podrás usar la siguiente línea:

imagejpeg($imagenJPG, "", 40);

Como ves, en el lugar del segundo parámetro ponemos una cadena vacía. De este modo no se grabará la imagen en un fichero, sino que será enviada al navegador. El tercer parámetro es un valor numérico. Cuanto más alto sea, con más calidad se mostrará la imagen, pero también tardará más en descargarse. En el caso de que lo que deseemos sea grabar la imagen en otro archivo, especificando la calidad (y, por tanto, también, el peso del nuevo fichero), usaremos la siguiente línea:

imagejpeg($imagenJPG, "imagenes/copiaDeImagen.jpg", 40);

Cuando un script envía una imagen al navegador, su nombre puede ser incluido como atributo src en la etiqueta img de una página HTML. Observa el listado de cargaExterna.htm, que aparece a continuación:

Mira la línea resaltada. Cuando cargues esta página en el navegador obtendrás, al igual que antes, la imagen en la página.

Otra operación básica que podemos llevar a cabo es obtener la anchura y altura, en píxeles, de una imagen. Para obtener la anchura podemos usar la función imagesx(). La altura nos la proporciona la función imagesy(). Estas dos funciones reciben, como argumento, el manejador de una imagen. Es útil obtener las dimensiones físicas de una imagen, ya que, de este modo, se puede reservar sitio en una celda de una tabla, o decidir una mayor o menor calidad de representación. A mayor tamaño de imagen, menor calidad (dentro de unos límites razonables, por supuesto), para acelerar el proceso de envío de la imagen al navegador. Para ver cómo operan estas propiedades mira el script dimensiones.php:

Este código crea un manejador a partir de la imagen que hemos visto anteriormente y nos muestra la anchura y altura, en píxeles, de la misma. El resultado es el siguiente:

Anchura de la imagen: 250
Altura de la imagen: 125

Puede darse el caso de que necesites la imagen y el texto en la misma página. Lo mejor, en esos casos, es tener una página HTML en la que se incluyan referencias a pequeños scripts de PHP, como hemos visto hace un momento. Observa el listado mostrarDimensiones.php:

Como ves, se combinan dos scripts externos para mostrar ambos tipos de resultados, tanto el gráfico como el textual. Este tipo de uso es muy habitual, ya que permite que, cada vez que se carga la página, se obtengan resultados procedentes de otros scripts que, a su vez, pueden estar actualizándose desde otras fuentes, tales como bases de datos (tema del que hablaremos un artículo posterior).

Para finalizar este apartado conoceremos la función getimagesize(), que nos proporciona ambos parámetros, además del tipo de imagen y algún dato adicional. Esta función recibe, como argumento, el nombre y, en su caso, la ruta, de un archivo de imagen. No recibe un manejador, como otras funciones, sino el nombre del archivo, directamente. La función getimagesize() devuelve una matriz de siete elementos. Para ver cómo operan estas funciones observe el script propiedades.php:

propiedades-de-imagenObserve, en la línea resaltada, como usamos la función que nos interesa. El resultado de este script es la tabla que ves reproducida a la izquierda.

Los resultados obtenidos se interpretan de la siguiente manera:

  • Clave 0. Contiene la anchura de la imagen, en píxeles.
  • Clave 1. Contiene la altura de la imagen en píxeles.
  • Clave 2. El contenido se refiere al formato de la imagen (tipo de imagen), según la siguiente lista: 1 = GIF, 2 = JPG, 3 = PNG, 4 = SWF, 5 = PSD, 6 = BMP, 7 = TIFF (orden de bytes intel), 8 = TIFF (orden de bytes motorola), 9 = JPC, 10 = JP2, 11 = JPX, 12 = JB2, 13 = SWC, 14 = IFF, 15 = WBMP, 16 = XBM, 17 = ICO. Como ves, PHP puede reconocer muchos tipos de imagen diferentes, aunque, para entornos web, sólo usaremos algunos de ellos, como ya sabes. En concreto, nos interesan los cuatro primeros. El cuarto corresponde a animaciones de Flash, que es una tecnología obsoleta hoy día..
  • Clave 3. Contiene una cadena con la altura y la anchura, que puede ser usada, directamente, en etiquetas <img> de HTML.
  • Clave bits. El número de bits por color, es decir, lo que se conoce como profundidad de color.
  • Clave channels. El número de canales de color. Es 3 cuando el color de la imagen es RGB y 4 cuando es CMYK (imágenes para imprenta).
  • Clave mime. La codificación que debemos especificar en el Content_type de la cabecera.

EL COLOR

Es necesario comprender cómo son los colores en una imagen, ya que PHP nos proporciona algunas funciones para manejarlos, pero no podremos usarlas adecuadamente si no comprendemos su naturaleza. Al final del apartado anterior hemos hecho alguna mención al color. Ahora aprenderemos todo lo que necesitamos al respecto.

Las imágenes que se muestran en la pantalla de un ordenador se forman a partir de tres colores básicos: el rojo, el verde y el azul. De ahí que a este modo de trabajar con el color se le llame, en términos informáticos, RGB (de los nombres en inglés: Red, Green y Blue). Seguramente, si recuerdas tus tiempos de estudiante, tus profesores le enseñaron que, por ejemplo, el verde es un color compuesto, que se forma a partir del azul y el amarillo. Esto es cierto para las mezclas de tintas para imágenes impresas, lo que se conoce como colores-tinta. Pero las imágenes en una pantalla se forman a partir de otras combinaciones, conocidas como colores-luz. En este entorno, siguiendo con el ejemplo mencionado, el amarillo es un color compuesto, formado a partir de rojo y verde. Debido a estas diferencias a la hora de formar el color, las imágenes en una página web pueden no ser iguales, en lo que a tonalidades se refiere, a las mismas imágenes cuando son volcadas a la impresora. Cuando queremos que una imagen, en la pantalla, muestre un aspecto más similar al que tendrá una vez impresa, es necesario cambiar su formato de colores al conocido como CMYK (los equipos actuales hacen esto de modo automático, casi siempre).

Realmente, lo que nos interesa aquí es el formato de colores RGB, ya que estamos trabajando para la creación de páginas web que serán visualizadas en un monitor. Cualquier color que podamos montar en una imagen se forma a partir de una combinación de dos de los colores básicos, o de los tres. Cada uno de estos colores puede adoptar uno de 256 posibles valores (de 0 a 255). Esto nos ofrece un total de más de dieciséis millones de posibles combinaciones, lo que satisface completamente las necesidades de cualquier imagen. La ausencia total de los tres colores básicos (valor 0 para cada uno) da, como resultado, el negro. La presencia total de los tres (valor 255 para cada uno) muestra el blanco. Distintas combinaciones de valores dan como resultado diferentes colores.

Algo que debemos saber es que cada imagen lleva asociada su propia paleta de colores. Ésta es una referencia de todas las tonalidades que forman dicha imagen. Cada tonalidad está compuesta por unos determinados valores de rojo, verde y azul. Estas combinaciones se almacenan en posiciones numeradas de la paleta, lo que permite acceder a cada color individualmente y manipularlo, si fuera necesario. A continuación vamos a conocer un par de funciones destinadas a descubrir cada uno de los tonos de la paleta correspondiente a una imagen. La primera de ellas nos devuelve el número total de colores que forman la paleta. Se trata de imagecolorstotal(), que recibe, como argumento, el manejador con el que se ha abierto la imagen. Observa el script totalDeColores.php, que hace uso de esta función:

Cuando ejecutes este script obtendrás el siguiente resultado:

La imagen imagenes/logo.gif tiene un total de 255 colores.

Esto significa que en la paleta de la imagen hay un total de 255 tonalidades diferentes.

ATENCIÓN. Esta función podría no funcionar adecuadamente con algunas imágenes en concreto. De hecho, si la imagen no es .gif, podría dar un resultado 0. No es completamente fiable, por lo tanto.

Como complemento de esta función contamos con imagecolorsforindex(). Ésta recibe dos argumentos, separados por una coma. El primero es el manejador de la imagen con la que estamos trabajando. El segundo es un número que corresponde a un índice de la paleta de la imagen. Por ejemplo, para el resultado del script anterior, el segundo argumento de esta función deberá estar entre 0 y 254. La función devuelve una matriz con los valores de rojo, verde y azul del índice especificado. Además, la matriz contiene un cuarto valor que corresponde a la transparencia del color en la imagen (lo que se conoce como factor alfa). Para ver cómo opera esto, vamos a crear una página que nos muestre todos los colores de la paleta, con sus correspondientes valores. Es decir, que obtendremos 255 matrices, cada una de ellas con cuatro elementos. Observe el siguiente script, que hace uso de esta función. Se llama paleta.php:

Lee los comentarios incluidos en el código. Lo que hacemos es que, una vez determinado el número total de colores de la paleta, los recorremos todos mediante un bucle. En cada iteración obtenemos la matriz con los tres componentes básicos del color que estamos analizando (Rojo, Verde y Azul) y el factor alfa del mismo. En el caso de esta imagen, todos los colores tienen un factor alfa de 0, es decir, son totalmente opacos, sin transparencias. Pero eso no importa a los efectos que buscamos. Una vez obtenidos los componentes de cada color, mostramos sus valores en una tabla. Además, formamos una cadena hexadecimal con los valores del rojo, verde y azul, y le añadimos a cada fila de la tabla una celda con el correspondiente color de fondo. Ejecuta el script para ver el resultado. Yo no lo he reproducido aquí debido a su tamaño. Además, observarás que muchas de las tonalidades son parecidas entre sí, a simple vista, diferenciándose muy poco en sus valores. Esto se debe a que la imagen contiene varios degradados suaves, que generan muchos colores similares.

Ya conocemos cómo determinar cuántos colores tiene una imagen y sabemos cómo extraer toda la información posible de la paleta asociada. Sabemos que cada uno de los colores está identificado por un índice y tiene una composición RGB. Lo mejor de esto es que, a partir de ahí, podemos modificar cada uno de los tonos que forman la paleta. Para ello usamos la función imagecolorset(). Esta función recibe, nada menos, que cinco argumentos, que son los siguientes:

  • El manejador con el que se ha abierto la imagen.
  • El número de índice que tiene en la paleta el color que queremos modificar.
  • El valor de rojo que queremos darle al nuevo color.
  • El valor de verde que queremos darle al nuevo color.
  • El valor de azul que queremos darle al nuevo color.

Para ver cómo funciona vamos a escribir un script que muestre el negativo de una imagen. Lo que haremos es recorrer cada tonalidad de la paleta, e invertir los valores de rojo, verde y azul. Para ello, tomaremos el valor actual de cada componente y lo restaremos de 255, que es el máximo que puede tener ese componente. Así pues, suponte que tienes un tono rojo puro (255, 0, 0). Restaremos los valores actuales de 255 para cada componente individual, como hemos dicho, obteniendo 0, 255, 255, es decir, la mezcla de verde y azul, que da como resultado el color cyan. Entonces asignamos el nuevo color obtenido al correspondiente índice en la paleta. Por último, mostramos la imagen para comprobar el resultado. El script que hace esto es cambiarColores.php:

Al ejecutar el script se obtiene un negativo de la imagen, que puedes ver, comparado con el original, a continuación:

Una imagen y su negativo.

Una imagen y su negativo.

La paleta de colores puede tener un máximo de 256 colores. Si hay menos, se pueden añadir nuevos colores a la paleta con la función imagecolorallocate(). Esta recibe cuatro argumentos, según la siguiente relación:

  • El manejador con el que se ha abierto la imagen.
  • El valor de rojo que queremos darle al nuevo color.
  • El valor de verde que queremos darle al nuevo color.
  • El valor de azul que queremos darle al nuevo color.

El nuevo color se coloca en la primera posición que queda libre. La función devuelve el número de índice correspondiente a esa posición. Si no se ha podido ejecutar correctamente, se obtiene como resultado el valor -1.

Esta función se complementa con imagecolordeallocate(), cuya finalidad es eliminar un color de la paleta actual. Esta función recibe dos argumentos: el manejador de la imagen y el número de índice que corresponde al color que queremos eliminar de la tabla. Pero recuerda. Esta función sólo puede eliminar un color previamente insertado con imagecolorallocate(). No se puede usar para eliminar los colores que forman parte de la paleta original.

La función imagecolorallocate() no permite establecer la transparencia de un color (el factor alfa). Para ello, tenemos la función imagecolorallocatealpha(). Ésta funciona igual que la anterior, pero recibiendo un quinto argumento, que es el nivel de transparencia que le queremos asignar al color. Dicho color podrá ser también eliminado con imagecolordeallocate().

En este artículo hemos aprendido a manejar, parcialmente, imágenes con PHP. En el próximo artículo continuaremos estudiando este apasionante aspecto del lenguaje, y veremos la enorme cantidad de posibilidades que tenemos. Nos vemos en el siguiente post.

     

Un comentario:

  1. Pingback: PHP-TUT-24 Configuración de PHP. Directivas y extensiones. » eldesvandejose.com

Deja un comentario

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *