PHP-TUT-21 Gestión de imágenes (II)

Facebooktwittergoogle_pluslinkedinmailFacebooktwittergoogle_pluslinkedinmail

En el artículo anterior empezamos a ver las posicbilidades que PHP nos ofrece para la gestión de imágenes. En este artículo seguiremos aprendiendo todo lo que podemos hacer con estos elementos gráficos. Por ejemplo, hasta el momento hemos visto algunas posibilidades que nos ofrece PHP para manejar y mostrar imágenes existentes. Pero esto es sólo parte de lo que podemos hacer. El lenguaje nos permite crear imágenes nuevas, que no existen en el disco.

CREAR IMÁGENES

Para crear imágenes usaremos la función imagecreatetruecolor(). Antes se usaba imagecreate(), que sigue existiendo por razones de compatibilidad. Sin embargo, la librería GD2 nos permite usar la nueva función, que nos ofrece la posibilidad de crear imágenes con color verdadero (8 bits por canal más alfa). Esta función recibe dos argumentos numéricos que representan la anchura y la altura de la nueva imagen, expresadas en píxeles. La función crea una nueva imagen sin contenido y devuelve un manejador para trabajar con ella.

Una vez creada la nueva imagen (que, aún, no muestra nada) deberemos crear una paleta de colores para ella. Esto lo haremos con la función imagecolorallocate(), que hemos comentado al final del post anterior. El primer color que se asigne a la paleta será el color de fondo de la imagen.

PHP nos permite trabajar con el color de los píxeles de una imagen de modo individual. Para ello necesitamos conocer las coordenadas x e y del píxel que nos interesa. Ten en cuenta que las coordenadas x e y empiezan en 0, 0, en la esquina superior izquierda de la imagen, contando hacia la derecha y hacia abajo. Para darle un determinado color a un píxel usaremos la función imagesetpixel(). ¿Te haces una idea de los argumentos que recibe esta función? Son los siguientes:

El manejador de la imagen, obtenido con imagecreatetruecolor().

La coordenada x del píxel que nos interesa.

La coordenada y del píxel que nos interesa.

El índice que ocupa el color deseado en la paleta, y que ha sido obtenido mediante imagecolorallocate().

Por último, una vez creada la imagen, podemos enviarla al navegador, o almacenarla en un archivo de disco.

Para comprender la operativa conjunta de estas funciones vamos a crear una imagen nueva mediante un script. Se llama crearNuevaImagen.php, y su listado es el siguiente:

Como ves, este script hace uso de las funciones que hemos descrito, en el orden adecuado, para generar una imagen. Una vez creada esta, primero se graba en el disco y luego es enviada al navegador. La parte de grabarla en el disco se podría haber omitido, si no fuera necesario conservar una copia de la imagen para usos posteriores. Por ejemplo, si creamos imágenes que representen estadísticas en tiempo real y no es necesario conservarlas, se pueden mostrar en el navegador, sin más.

ATENCIÓN. Si quieres grabar la imagen en el disco, deberás, por supuesto, asegurarte de que el directorio en el que vas a grbar tiene el correspondiente permiso de escritura, o no se podrá grabar. Recuerda lo que hemos publicado sobre permisos en directorios y ficheros.

Observa una cosa. Al crear la paleta de colores he usado una matriz para referirme a cada una de las tonalidades de la misma, a fin de facilitar luego el acceso en el bucle de una manera cómoda. El resultado de este script puedes verlo en tu navegador.

Sabiendo movernos por una imagen en términos de coordenadas x e y podemos determinar el color de un píxel de la imagen que nos interese. Para ello usaremos la función imagecolorat(), que recibe tres argumentos: el primero es el manejador de la imagen, y los otros dos corresponden a las coordenadas x e y del píxel que nos interesa. La función devuelve el índice que tiene ese color en la paleta empleada.

NOTA. Evidentemente, esta forma de crear imágenes sólo es válida para aquellas imágenes cuyos píxeles, y los colores de estos, puedan determinarse mediante funciones matemáticas, bucles, o algún otro sistema más o menos automatizable. Está claro que no vamos a crear una copia de La Gioconda píxel a píxel.

COPIA DE IMÁGENES

Podemos copiar una imagen, o un fragmento de ella, en otra imagen para conseguir resultados curiosos. Para ello usaremos la función imagecopy(). Esta función recibe, nada menos, que ocho parámetros, según se detalla en la lista que aparece a continuación:

  • El manejador de la imagen de destino.
  • El manejador de la imagen de origen.
  • La coordenada x de la imagen de destino donde se iniciará la copia.
  • La coordenada y de la imagen de destino donde se iniciará la copia.
  • La coordenada x de la imagen de origen desde donde se empezará a copiar.
  • La coordenada y de la imagen de origen desde donde se empezará a copiar.
  • La anchura del fragmento de la imagen de origen que deseamos copiar.
  • La altura del fragmento de la imagen de origen que deseamos copiar.

Para entender la mecánica de esta función nada mejor que crear un ejemplo que nos lo aclare. Vamos a partir de una imagen cualquiera en el disco. Tomaremos un fragmento de la misma y lo copiaremos en otra imagen, nueva, que no será guardada, sino, solamente, enviada al navegador.

Queremos un trozo de la imagen original, así que, lo primero que tenemos que hacer es determinar sus coordenadas con respecto a la imagen. La esquina superior izquierda del fragmento que deseamos, con respecto a la esquina superior izquierda de la imagen tiene las coordenadas x = 20 e y = 20. La anchura del fragmento es de 80 píxeles, y su altura es de 50 píxeles. Observa el script copiarFragmento.php, listado a continuación:

Ejecuta el script para ver el resultado. Observa, cómo se ha copiado el fragmento elegido en la nueva imagen, que es la que se muestra al final. Fíjate también que, al terminar el script, destruimos los dos manejadores que hemos usado, para liberar correctamente los recursos empleados.

Existe una variante de esta función que, además de permitir copiar un fragmento (o la totalidad) de una imagen, nos permite redimensionarla. Esto es especialmente útil cuando se cuenta con una galería de imágenes y hay que montar una página de miniaturas. Se trata de imagecopyresized(). La lista de parámetros que recibe empieza a alargarse: nada menos que 10 (para una función, es bastante). Éstos son los siguientes:

  • El manejador de la imagen de destino.
  • El manejador de la imagen de origen.
  • La coordenada x de la imagen de destino donde se iniciará la copia.
  • La coordenada y de la imagen de destino donde se iniciará la copia.
  • La coordenada x de la imagen de origen desde donde se copiará.
  • La coordenada y de la imagen de origen desde donde se copiará.
  • Anchura del fragmento copiado en la imagen de destino.
  • Altura del fragmento copiado en la imagen de destino.
  • La anchura del fragmento de la imagen de origen que deseamos copiar.
  • La altura del fragmento de la imagen de origen que deseamos copiar.

Para comprobar cómo opera este mecanismo, vamos a escribir un script que toma la imagen que hemos usado antes, y crea una miniatura de la misma. El código, llamado miniatura.php, nos mostrará la miniatura en la página para que comprobemos el resultado.

Observa, en la línea resaltada, cómo hemos hecho uso de esta función. Como te he comentado antes, esta función es imprescindible, cuando hay que crear miniaturas de imágenes, para no tener que hacerlo a mano. Lo suyo es crear la miniatura y guardarla, en otra carpeta, con el nombre de la imagen original.

Un comentario acerca de la copia de imágenes. El intérprete trata de copiar la paleta de la imagen original en la nueva imagen. Esto funciona casi siempre. Si, en algún caso concreto, no te funciona, crea una copia de la paleta tú mismo. Puedes escribir un script que lo haga, leyendo cada uno de los colores de la paleta original y luego incluyéndolo en la nueva paleta mediante el uso de la función imagecolorallocate(), que ya conoces.

ATENCIÓN. Al reescalar una imagen, es muy posible que se pierda calidad. Esto se llama pixelización, y consiste en que los píxeles siempre tienen el mismo tamaño, por lo que la miniatura no tiene píxeles más pequeños, sino menos píxeles que la imagen original. Este fenómeno se aprecia, incluso, con los mejores programas de retoque fortográfico, pero es más evidente cuando se realiza por programación. Si tu miniatura tiene demasiada pixelización es posible que hayas reducido demasiado el original.

En ocasiones nos encontramos conque tenemos que reescalar imágenes que tenemos en el servidor, bien porque sus dimensiones sean demasiado grandes y tengamos que crear una galería de miniaturas, o porque pesen demasiado y debamos limitar el peso de las mismas. Recientemente mem encontré con un problema así en una aplicación que tuve que desarrollar en mi trabajo habitual. El usuario sube determinadas imágenes al servidor, mediante un formulario, que se almacenan en un directorio específico. Esto es algo que aprendimos a hacer en este artículo. Las imágenes deben tener unas dimensiones máximas determinadas, y también un peso máximo. Si exceden las dimensiones o el peso, deben escalarse, para que entren en los parámetros establecidos. Es algo muy habitual, que te encontrarás muchas veces. Dado que es un problema tan común, he creado una clase para solucionarlo. La tienes a tu disposición en este artículo.

FIGURAS PREDEFINIDAS

Hasta ahora hemos aprendido a establecer el color de píxeles individuales. Sin embargo, las prestaciones de PHP para trabajar con imágenes van más allá de esto. El intérprete (y, más concretamente, la librería GD2) ofrece la posibilidad de crear formas geométricas predefinidas mediante determinadas funciones que vamos a conocer en este apartado. Con la combinación de las distintas formas básicas se podrán lograr resultados muy interesantes, como veremos en este mismo artículo.

Quizás la forma más simple, después de un píxel aislado, desde luego, es una línea recta. Para dibujarla contamos con la función imageline(), que recibe los siguientes parámetros:

  • Manejador de la imagen en la que vamos a dibujar.
  • Coordenada x del origen de la línea.
  • Coordenada y del origen de la línea.
  • Coordenada x del final de la línea.
  • Coordenada y del final de la línea.
  • Índice del color deseado en la paleta de colores.

El ancho de la línea es de un píxel. Si deseas que tu línea sea más gruesa, puedes trazar varias líneas paralelas. También hay otra manera que veremos enseguida, en este mismo apartado.

Esta función tiene una alternativa llamada imagedashedline(), que recibe los mismos argumentos y opera de modo similar. La diferencia es que esta última traza una línea discontinua, mientras que la primera dibuja líneas continuas.

Con PHP podemos dibujar rectángulos. Para ello contamos con la función imagerectangle(). A esta función hay que darle las coordenadas de la esquina superior izquierda e inferior derecha del rectángulo. La forma geométrica obtenida es hueca, es decir, sólo obtenemos el borde, de un píxel de ancho, sin relleno. Aunque, como veremos, también hay alternativas para esto. Los argumentos que recibe esta función son los siguientes:

  • El manejador de la imagen sobre la que vamos a trabajar.
  • La coordenada x de la esquina superior izquierda del rectángulo.
  • La coordenada y de la esquina superior izquierda del rectángulo.
  • La coordenada x de la esquina inferior derecha del rectángulo.
  • La coordenada y de la esquina inferior derecha del rectángulo.
  • El índice del color deseado dentro de la paleta de la imagen.

No siempre querremos líneas rectas. PHP nos permite también dibujar circunferencias, elipses, o arcos; en definitiva, líneas curvas. Para ello, contamos con la función imagearc(). Ésta es muy configurable, según los parámetros que le pasemos. Así, podremos determinar si queremos una circunferencia, una elipse vertical u horizontal o si queremos una línea curva cerrada o sólo un arco de la misma. Los argumentos que recibe esta función son los siguientes:

  • El manejador de la imagen en la que vamos a dibujar.
  • La coordenada x del centro de la circunferencia o elipse.
  • La coordenada y del centro de la circunferencia o elipse.
  • La anchura. Es el radio horizontal de la circunferencia o elipse.
  • La altura. Es el radio vertical de la circunferencia o elipse. En el caso de una circunferencia, ambos parámetros son iguales.
  • El ángulo en el que se empieza a dibujar, expresado en grados sexagesimales. El ángulo 0 es el punto más a la derecha de la circunferencia o elipse.
  • El ángulo en el que se termina de dibujar. Los grados crecen en sentido de las agujas del reloj: si creas un arco, con el ángulo inicial a 0 y el final a 180, estarás dibujando la mitad inferior de la circunferencia o la elipse.
  • El índice de color en la paleta de la imagen.

Si quieres dibujar una línea curva cerrada puede usar, alternativamente, la función imageellipse(). Ésta recibe los siguientes argumentos:

  • El manejador de la imagen en la que vamos a dibujar.
  • La coordenada x del centro de la circunferencia o elipse.
  • La coordenada y del centro de la circunferencia o elipse.
  • La anchura. Es el radio horizontal de la circunferencia o elipse.
  • La altura. Es el radio vertical de la circunferencia o elipse. En el caso de una circunferencia, ambos parámetros son iguales.
  • El índice de color en la paleta de la imagen.

Como ves, esta función no requiere ángulo de inicio ni de final, ya que dibuja una figura completa, no sólo un arco, así que, en muchos casos, es más cómoda de usar.

También podemos crear formas poligonales. Para ello usamos la función imagepolygon(). Ésta recibe los siguientes argumentos:

  • El manejador de la imagen en la que vamos a dibujar.
  • Una matriz indexada con las coordenadas de todos los vértices del polígono. Los dos primeros elementos contendrán las coordenadas x e y del primer vértice. Los elementos tercero y cuarto contendrán las coordenadas x e y del segundo vértice y, así, sucesivamente.
  • El número total de vértices. PHP se encarga de trazar las líneas entre los mismos, y una línea final uniendo el último con el primero, cerrando la línea.
  • El índice del color deseado dentro de la paleta de la imagen.

Las formas creadas hasta ahora son huecas, como ya he mencionado anteriormente. Están formadas por un borde de un solo píxel de ancho. Si alguna forma queremos rellenarla de color usaremos la función imagefill(). La operativa es la siguiente. Se le asigna a la función un punto de la imagen y, a partir de ahí, rellena, en el color establecido, hasta que encuentre unos bordes que delimitan la zona de relleno. Es decir, se usa para rellenar figuras cerradas. Si la figura no está cerrada se rellena con el color indicado toda la imagen.

Esta función recibe los siguientes argumentos:

  • El manejador de la imagen con la que vamos a trabajar.
  • La coordenada x del punto donde se inicia el relleno.
  • La coordenada y del punto donde se inicia el relleno.
  • El índice del color deseado dentro de la paleta de la imagen.

Si quieres dibujar rectángulos o polígonos rellenos del mismo color que el borde que los delimita, puede usar las funciones imagefilledrectangle(), imagefilledpolygon() o imagefilledellipse(), que reciben los mismos argumentos que imagerectangle(), imagepolygon() e imageellipse(), respectivamente.

Una consideración que debes tener siempre en cuenta es que todas las coordenadas que reciben estas funciones se toman siempre con respecto a la esquina superior izquierda de la imagen (0, 0). La mejor forma de conocer realmente estas funciones es, desde luego, crear un script que las use y nos muestre el resultado. El script se llama formas.php, y su listado es el siguiente:

Como ves, hemos creado una imagen nueva. Aunque todas las funciones que hemos visto pueden dibujar sobre imágenes ya existentes, de este modo veremos los resultados más claros. Prueba el script, para ver los resultados. No hemos usado todas las posibles formas geométricas, para no extendernos mucho. Sólo algunas, para que puedas comprobar su operatividad. Experimenta con éstas y con las restantes. Por cierto. Antes te mencioné que existía una forma de crear líneas de más de un píxel de ancho. Se puede usar la función imagefilledrectangle() para crear un rectángulo largo y estrecho que aparecerá como una línea gruesa de trazado ancho. Naturalmente, esto sólo vale si la línea es horizontal o vertical.

FILTROS

A una imagen se le pueden aplicar filtros para conseguir determinados efectos, similares a los que se logran con algunas aplicaciones de retoque de imágenes. Para ello contamos con la función imagefilter(), que recibe dos argumentos. El primero de ellos es, cómo no, el manejador de la imagen sobre la que vamos a trabajar. El segundo es una constante que determina el tipo de filtro que queremos aplicar. Algunos de estos filtros requieren, para su funcionamiento, hasta tres parámetros adicionales.

Vamos a ver, a modo de ejemplo, unos scripts muy sencillitos. Luego comentaremos los posibles filtros que ofrece la librería GD2. Empezaremos por uno que convierte una imagen en color a escala de grises. El script se llama grises.php, y su listado es el siguiente.

Observa, en la línea resaltada, cómo se ha usado la función, con la constante que establece que se transforme la imagen a escala de grises. Prueba el script para verificar su correcto funcionamiento. Vamos a ver otro ejemplo. El script coloreado.php toma una imagen y la cubre de un filtro de color verde, con lo que se tiñen con este tono los colores originales.

Pruébalo para ver el resultado. Mira, en la línea resaltada, cómo se usan los argumentos numéricos cuando son necesarios. En el caso de este filtro, son tres, pero en otros sólo será uno. Ves las descripciones más abajo.

Como último ejemplo, usaremos un filtro que elimina el suavizado de los detalles, dando un efecto de boceto. El listado de sketchy.php es similar a los anteriores, sólo que la línea de filtro es la siguiente:

imagefilter($imagen, IMG_FILTER_MEAN_REMOVAL);

Los filtros que podemos emplear aparecen en la tabla siguiente:

FILTROS PARA IMÁGENES
FILTRO EFECTO Y COMENTARIOS
IMG_FILTER_NEGATE Crea el negativo de una imagen.
IMG_FILTER_GRAYSCALE Convierte una imagen a escala de grises.
IMG_FILTER_BRIGHTNESS Cambia el brillo de una imagen. Utilice un argumento numérico, a continuación de la constante del filtro, para establecer el nivel de brillo.
IMG_FILTER_CONTRAST Cambia el contraste de una imagen. Utilice un argumento numérico, a continuación de la constante del filtro, para establecer el nivel de contraste.
IMG_FILTER_COLORIZE Crea un filtro de color para la imagen. Utilice tres argumentos numéricos para establecer los valores de rojo, verde y azul del filtro.
IMG_FILTER_EDGEDETECT Resalta los bordes de la imagen. Llamamos bordes a aquellas zonas donde se producen cambios de color.
IMG_FILTER_EMBOSS Crea un efecto de relieve.
IMG_FILTER_GAUSSIAN_BLUR Desenfoque gausiano de la imagen.
IMG_FILTER_SELECTIVE_BLUR Desenfoque de la imagen.
IMG_FILTER_MEAN_REMOVAL Efecto boceto.
IMG_FILTER_SMOOTH Suaviza la imagen. Utilice un argumento numérico para establecer el nivel de suavizado.

Prueba los distintos filtros, modificando alguno de los scripts que tienes aquí. Usa distintos argumentos numéricos en aquellos filtros que lo admitan, para ver los resultados.

TEXTO EN LAS IMÁGENES

Otro efecto interesante es incorporar texto en las imágenes, a modo de notas aclaratorias, o para cualquier fin publicitario, etc. PHP nos proporciona algunas funciones muy interesantes.

La función imagestring() permite insertar una cadena de texto en la posición deseada en una imagen. Los argumentos que recibe son los siguientes:

  • El manejador de la imagen a la que le vamos a añadir el texto.
  • El tamaño de la fuente a emplear, de 1 a 5, siendo el 1 el más pequeño y el 5 el más grande.
  • La coordenada x donde se inicia el texto.
  • La coordenada y donde se inicia el texto.
  • La cadena de texto que queremos incluir en la imagen.
  • El índice de la paleta de colores de la imagen que corresponde al color deseado.

Como complemento a esta función contamos con imagestringup(), que coloca una cadena de texto en vertical, en lugar de horizontalmente. La sintaxis es la misma que la de la anterior.

Para ver cómo podemos usar estas funciones, hemos creado un script que muestra la media mensual de temperaturas de un año en una ciudad cualquiera, que podría ser la tuya. Se llama grafica.php, y su listado es el siguiente:

Por supuesto, el script es, conceptualmente, muy simple. Lo que quiero decir es que, si esto fuera real, las coordenadas con las que se han trazado las líneas de la gráfica procederían de otras fuentes, tales como una base de datos, tema que veremos en un artçiculo posterior. También podríamos haber optimizado el dibujo de las temperaturas mediante un bucle. Pero esto no tiene relevancia ahora. He preferido que quedara muy claro lo que hemos hecho, con fines didácticos. Con el tiempo, cuando tengas soltura en escribir scripts para tsus páginas, irás descubriendo la forma de optimizar el código para lograr los mismos o mejores resultados con menos líneas, y de obtener los datos de forma adecuada.

PHP también permite incluir tipografías True Type (ttf) en las imágenes. Esto es lógico. La fuente que emplea por defecto el intérprete para escribir en las imágenes, y que hemos usado en el ejemplo anterior es bastante pobre para efectos publicitarios o decorativos. Para incluir otras tipografías en una imagen contamos con la función imagettftext(). Los argumentos que necesita esta función para trabajar son los siguientes:

  • El manejador de la imagen en la que se va a incluir un rótulo.
  • El tamaño de la fuente, en puntos.
  • El ángulo con el que deberá quedar el rótulo respecto a la horizontal. Si el ángulo es 0, el rótulo quedará totalmente horizontal. Valores positivos de este parámetro rotan el texto en sentido contrario a las agujas del reloj.
  • La coordenada x donde empieza el texto.
  • La coordenada y donde empieza el texto.
  • El índice de la paleta de colores de la imagen que corresponde al color en el que queremos el texto.
  • Una cadena con el nombre y, en su caso, la ruta del archivo que contiene la tipografía. Los archivos de tipografías deben ser accesibles para el script. Lo normal es que se coloquen en el servidor, junto con las páginas, o en una carpeta específica.
  • La cadena de texto que queremos incluir en la imagen.

Fíjate en la descripción de los argumentos. Es necesario que dispongas de los archivos .ttf con las fuentes que desees incorporar, pero no es preciso que el usuario que se conecte a su página los tenga, para visualizar correctamente la imagen. Basta con que estén en el servidor donde se alojan las páginas. Sin embargo, aquí se presenta un pequeño escollo. Muchos archivos .ttf tienen derechos de autor. En tus páginas deberás incluir tipografías libres de derechos, o bien contar con el permiso para usar las que incluyas.

Supongamos un script con una línea como la siguiente:

imagettftext ($imagen, 30, 15, 50, 100, $rojo, "stocky.ttf", "Texto en una imagen");

Puedes ver un ejemplo completo en letras.php:

Este script crea una imagen con fondo negro y un texto en rojo, cómo ves a continuación:

texto_en_una_imagen

Naturalmente, tendrás que tener la fuente en la ruta especificada. Y, por si te lo estás preguntando, puedes incluir estos rótulos en cualquier imagen que ya tengas, no sólo en las que crees nuevas. Para el script que has visto aquí te dejo la fuente stocky.ttf para descargar, que es de libre uso.

     

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 *