Ver índice
Efectos en imágenes y CAPTCHA

        Ocultar índice  

   Índice de contenidos
   Instalación en Windows
   Instalación en Ubuntu
   Servidores seguros
   Páginas dinámicas
   Sintaxis básica
   Operaciones
   Arrays
   Formatos de presentación
   Operadores
   Bucles
   Extraer y ord. información
   Funciones
   Ficheros externos
   Imágenes dinámicas
   Gestión de directorios
   Cookies y sesiones
   Clases y objetos
   Ficheros en formato PDF
   Bases de datos MySQL
   PHP y XML
   PDO - Bases SQLite / MySQL
   MySQL a traves de misqli
   Algo de JavaScript y AJAX


Aplicando filtros a imágenes

A partir de PHP 5 se han incluido funciones que permiten aplicar a las imágenes filtros modificadores que producen muchos de los efectos que hasta ahora estaban reservados al software gráfico del tipo Gimp o PhotoShop por poner dos ejemplos.

Al incluir la función:

imagefilter ( $imagen , tipo_filtro, param1, param2, ... )

Dónde $imagen es el identificador de imagen, tipo_filtro es un valor numérico entero (o una constante, en cuyo caso no deber su nombre entre comillas) y los parámetros cuyo número y valores dependen del tipo de filtro utilizado. Aquí debajo tienes una tabla que contiene los diferentes tipos de filtros disponibles así como los parámetros utilizados por cada uno de ellos.

Imagen original Imagen transformada Código fuente
Pulsando en las opciones de la parte inferior podrás visualizar aquí el código fuente de los scripts que transforman la imagen original de acuerdo con los parámetros elegidos para cada opción

Nombre de la constante Valor
equivalente
ParámetrosFunción Aplicar
IMG_FILTER_NEGATE 0  Invierte los colores de la imagenAplicar
IMG_FILTER_GRAYSCALE1 Convertir a escala de grisesAplicar
IMG_FILTER_BRIGHTNESS2Aumenta o disminuye el brillo en el intervalo 255 a -255Aplicar
IMG_FILTER_CONTRAST3Aumenta o disminuye el contraste en el intervalo 255 a -255Aplicar
IMG_FILTER_COLORIZE4



ColorizaAplicar
IMG_FILTER_EDGEDETECT5 Detectar y resalta bordesAplicar
IMG_FILTER_EMBOSS6 Efecto relieveAplicar
IMG_FILTER_GAUSSIAN_BLUR7 Desenfoque gaussianoAplicar
IMG_FILTER_SELECTIVE_BLUR8 Desenfoque selectivoAplicar
IMG_FILTER_MEAN_REMOVAL9 Aplica efecto boceto a la imagenAplicar
IMG_FILTER_SMOOTH10Aplica suavizado la imagenAplicar
IMG_FILTER_PIXELATE11
Pixelación
avanzada Si
Pixela la imagen (Solo funciona en versiones PHP 5.3 y superiores)Aplicar
Los filtros requieren incluir los parámetros que aparecen en las respectivas cuadrículas. Su inclusión se realiza agregándolos (únicamente sus valores numéricos) a continuación del nombre o identificador del filtro y separados de este y entre ellos por una coma.

Aplicaciones sucesivas de efectos

Las diferentes opciones de filtrado pueden irse aplicando de forma sucesiva sobre una misma imagen. Un caso típico puede ser el que puedes verlo en la imagen de la parte superior si pulsas en este enlace. El efecto «sepia» se logra aplicando primero IMG_FILTER_GRAYSCALE para convertir a escala de grises y colorizando por medio de IMG_FILTER_COLORIZE. En este caso los valora aplicados a las componentes R,G,B han sido 210, 90, 30 respectivamente y el valor del cuarto parámetro (canal alfa) ha sido de 64

Obtención de valores de las componentes de color

PHP dispone de función:

$codigo_de_color=imagecolorat($imagen, x, y)

por medio de la cual la variable $codigo_de_color recogería un valor decimal resultante de convertir en decimal el color correspondiente (la cadena hexadecimal con el formato clásico RRGGBB) al pixel cuyas coordenadas horizontal y vertical, respecto a la esquina superior izquierda de la imagen son x e y de la imagen cuyo identificador es $imagen

Para la manipulación de imágenes puede resultar muy interesante conocer las componentes R,G y B de esos colores. En caso de la libreria GD cuando se trata de conocer el color de uno de los pixel de una imagen los valores R,G, B de sus componentes puede obtenerse por medio de la función:

$codigo_de_color=imagecolorat($imagen ,x,y)
$array_de_colores=imagecolorsforindex($imagen ,$codigo_de_color)

Ver ejemplo Ver código fuente

Si ejecutas el ejemplo anterior podrás ver que imagecolorsforindex es un array asociativo cuyos indices son: red, green,blue y alfa que corresponden los tres primeros a las componentes de los colores primarios y el cuarto –alfa– que indicaría el grado de transparencia de ese color (en caso de que la imagen la tuviera asignada). Por lo general la información de color de un pixel de una imagen estaría conformado por 24 bits de los cuales corresponden 8 a cada uno de ellos. Cuando se agrega un canal alfa para incluir una determinada transparencia se agregan otros 8 bits para recoger este valor. En ese caso, como resulta obvio, se requieren 32 bits por cada pixel. El valor cero asignado en el ejemplo anterior al índice alfa significa que no está asignada ninguna transparencia al pixel estudiado.

Cuando se trata de extraer, sin disponer de una imagen de referencia, las componentes de color de un código de color uno los procedimientos para hacerlo requiere el uso de los operadores bit a bit de la forma que hemos tratado de desglosar paso a paso en la tabla que tienes aquí debajo.

Valor inicial Función Valor decimal Valor hexadecimal Valor binario Resultado
$a="#ABCDEF" $b=str_replace('#','',$a));   ABCDEF   Elimina el carácter # de la cadena que contiene el color y determina sus valores hexadecimal, decimal y binario. Observa que el valor binario tiene 24 caracteres. Los 8 primeros son los dos dígitos hexadecimales del color rojo, los siguientes los del verde y los últimos los del azul.
$b=ABCDEF $c=hexdec($b); 11259375    
$c=11259375 decbin($c);     101010111100110111101111
101010111100110111101111
$c=11259375 ($c >> 16); 171     Elimina 16 caracteres por la derecha en la cadena que contiene el valor binario. Transformamos el resultado a las distintas bases.
Es la componente rojo del color
$c=11259375 base_convert(($c>>16),10,16);   AB  
$c=11259375 base_convert(($c >>16),10,2);     10101011
$c=11259375 $h=($c >> 8); 43981     Elimina 8 caracteres por la derecha en la cadena que contiene el valor binario. Transformamos el resultado a las distintas bases.
Son las componente rojo y verde del color
$c=11259375 base_convert(($c >> 8),10,16);   abcd  
$c=11259375 base_convert(($c >> 8),10,2);     1010101111001101
1010101111001101
$c=11259375 ($c >> 8 & 0xFF); 205     Por medio del operador & extraemos 8 caracteres por la derecha.
La razón es que el valor binario de 0xFF (sería lo mismo poner el decimal 255) es 11111111 y operar & con esta cadena daría los 8 carácteres (observa que estos son 8 unos) de la derecha de la otra cadena operada.
El resultado será la componente verde del color.
$c=11259375 base_convert(($c>>8 & 0xFF),10,16);   CD  
0xFF base_convert((0xFF),10,2);     1111111111111111
$c=11259375 base_convert(($c>>8 & 0xFF),10,2);     1111111111001101
$c=11259375 $c; 11259375     Estos son los valores iniciales. Los repetimos únicamente con el fin de facilitar la visualización de las cadenas binarias e ilustrar los procesos bit a bit
$c=11259375 base_convert($c,10,16);   abcdef  
$c=11259375 base_convert($c,10,2);     101010111100110111101111
$c=11259375 ($c & 0xFF); 239     El operador & compara cadenas de bits (por la derecha). Si ambos bits tienen valor 1 devuelve 1 en caso contrario devuelve cero. Por esa razón al comparar con 0xFF estamos comparando con unos y en consecuencia el resultado coincide con el valor de bit comparado.
El resultado de esta comparación es la componente azul del color.
$c=11259375 base_convert(($c & 0xFF),10,16);   EF  
0xFF base_convert((0xFF),10,2);     11111111
$c=11259375 base_convert(($c & 0xFF),10,2);     11101111

El cálculo utilizando los operadores bit a bit de la tabla anterior no es el único posible. Es el más rápido pero es equivalente a este otro realizado por medio de la aritmética clásica.

En un sistema de numeración hexadecimal (por su condición de ordenado y por ser su base igual a 16) siempre puede convertirse el número en una forma polinómica del tipo: A*165+B*164+C*163+D*162+E*161+F*160, o también (utilizando números de dos cifras) AB*164+CD*162+EF*160. Si dividimos el polinomio anterior entre 164 obtendremos AB como cociente entero y CD*162+EF*160 como resto.

Si el resto anterior, CD*162+EF*160 lo dividimos entre 162 obtendremos como cociente entero CD y como resto EF (160=1). Los resultados de estas operaciones resultan ser las componentes de los tres colores.

Por tanto, si partimos del valor $c=11259375 del ejemplo de la tabla anterior, tendríamos que la componente roja (expresada en valor decimal) del color se obtendría mediante: (int)($c/pow(16,4))=171 sería el valor de la componente roja del color.

El valor de (int)($c%pow(16,4)/pow(16,2))=205 nos daría la componente verde y, por último, por medio de (($c%pow(16,4)) % pow(16,2))=239 sería el valor de la componente azul.

Filtros personalizados

Cualquiera de los efectos que puedan provocarse en una imagen es el fruto de modificar los valores de color de sus pixels. Este tipo de modificaciones individuales para un solo pixel pueden realizarse por medio de las funciones:

$color=imagecolorAllocate($imagen,R,G,B)
o
$color=imagecolorallocatealpha($imagen,R,G,B,alfa)
y
imagesetpixel($imagen, $x, $y, $color)

Por medio de la primera de las funciones, ya comentada en páginas anteriores, se crea un índice de color($color) para la imagen identificada por $imagen al que se asignan como valores de R, G y B valores enteros comprendidos entre 0 y 255. En el segundo de los supuestos, el parámetro alfa es un indicador de transparecia que puede tomar valores entre 0 (opaco) y 127 (transparente).

El paso siguiente es aplicar la función imagesetpixel para asignar al pixel de la imagen$imagen cuyas coordenadas son x e y el color establecido en el índice $color.

Aquí tienes un ejemplo de como utilizar esas funciones para efectuar la transformación Umbral que no es otra cosa que transformar a escala de grises y posteriormente modificar el color de los mismos asignando color rojo a aquellos cuyas componentes de color sean superiores a un valor umbral (por ejemplo 110) y color negro a aquellos que lo tengan inferior a ese valor.

<?php
Header("Content-type: image/jpeg");
$im = imagecreatefromjpeg('./images/aviones4.jpg');
/* utilizamos imagesx e imagesy para calcular las dimensiones de la
   imagen actual. También podríamos haber utilizado los valores del array
   obtenido por medio de la funcion getimagesize que nos daría información
   de la imagen original. En este caso ambas son iguales */
$ancho=imagesx($im);
$alto=imagesy($im);
/* asignamos un valor entre 0 y 255 a la variable umbral
   dependiendo de este valor aumentarán o se reducirán
   las zonas blancas de la imagen */
$umbral=110;
/* convierto a escala de grise grises */
imagefilter($im,IMG_FILTER_GRAYSCALE);
/* creamos dos indices de color. Negro y rojo */
$color[0]=imagecolorAllocate($im,0,0,0);
$color[1]=imagecolorAllocate($im,255,0,0);

/* este doble bucle nos permite recorrer cada uno de los pixels de la imagen */
for ($i=0;$i<$ancho;$i++){
      for ($j=0;$j<$alto;$j++){
        /* leemos el color actual. Como se trata de grises las componentes
           R,G y B de cada uno de los pixels van a ser iguales, nos bastará
           por tanto conocer uno cualquiera. en este caso extraemos el
           valor correspondiente al azul */
        $color_actual =imagecolorat($im,$i,$j) & 0xFF;
        /* si la componente gris es mayor que el umbral pinto en negro
           en caso contrario en blanco */
        if($color_actual>$umbral){
                imagesetPixel($im,$i,$j,$color[1]);
        }else{
                imagesetPixel($im,$i,$j,$color[0]);
        }

 }
}
/* visualizamos la imagen */
imagejpeg($im);
imagedestroy($im);
?>
Ver ejemplo Ver código fuente

Creación de una imagen CAPTCHA

CAPTCHA es el acrónimo de Completely Automated Public Turing test to tell Computers and Humans Apart que podría ser traducido como Prueba de Turing pública y automática para diferenciar a máquinas y humanos. Desde el punto de vista gráfico ha de ser una imagen el la que se visualizarán carácteres alfanuméricos con elementos de distorsión y deformación que impidan (o al menos dificulten) la lectura por dispositivos electrónicos OCR.

Para dificultar ese proceso existen multitud de aplicaciones, clases PHP y recursos de toda índoles. Nosotros vamos a intentar crear una imagen con poca nitidez, con caracteres aleatorios de diferentes tamaños, posiciones, tranparencias y ángulos de rotación y posteriormente le añadiremos una deformación vertical desplazando los pixeles en esta dirección por medio de funciones sinusoidales y, posteriormente haremos lo mismo en sentido horizontal. Veamos paso a paso el proceso.

Fondo con ruido añadido


Ver código fuente

Inserción de caracteres aleatorios


Ver código fuente

Deformación vertical


Ver código fuente

Deformación horizontal


Ver código fuente

Detectar bordes


Ver código fuente