Os estaréis preguntando cual es el problema en el escalado de imágenes con GD. Ninguno, el resultado era perfecto hasta que nos encontramos con gif’s transparentes. Al hacer el escalado se perdía la transparencia sin remedio. Dimos muchas vueltas y probamos distintos métodos que fuimos leyendo por cientos y cientos de foros y blogs, puesto que en la documentación de PHP no quedaba nada claro cómo hacerlo hasta que dimos con la solución.
He decidido separar este artículo en dos partes. En el segundo trataremos el escalado de gif’s animados, un proceso bastante más complejo que los estáticos.
En un GIF, la transparencia viene definida por un color, un solo color, que se define como transparente, de manera que cada pixel que tenga exactamente ese color será transparente, de ahí que, tradicionalmente, se comience por una imagen de fondo blanco o negro y sobre ella se dibuje, guardando ese color de fondo inicial como el de transparencia. La transparencia es una característica de la imagen, no del color en sí. No tiene por qué ser blanco o negro, cualquier color puede ser el transparente, pero una vez definido, cualquier pixel que tenga ese color será transparente. Por otro lado, en un GIF se guarda la paleta de colores que utiliza, de manera que se optimiza el tamaño de la imagen manteniendo la información únicamente de los colores disponibles y referenciándolos por un índice dentro de esa paleta. Esto que puede parecer un dato sin importancia es fundamental a la hora de tener claro el proceso a seguir desde PHP.
Hay varias funciones de PHP que hacen referencia a la transparencia y a los colores. En unas se utilizan los colores como tal en formato RGB, en otras se utiliza el índice de color en la paleta y en otras se necesita la representación del color. Aquí está uno de los problemas, ¿cómo se debe utilizar el resultado de cada una de las funciones disponibles?.
Lo primero que debemos calcular es el porcentaje de escalado que vamos a aplicar. Esto dependerá de nuestra aplicación y del destino de la misma. Si queremos fijar un determinado ancho habrá que calcular el porcentaje sobre el que debemos escalar el alto y viceversa. No entraremos en detalles sobre este aspecto puesto que se sale fuera del objeto de este artículo.
Una vez tenemos claro el nuevo tamaño, debemos, antes de nada, saber cual es el color transparente de la imagen original. Para ello usamos la función imagecolortransparent, si hay transparencia nos devolverá el identificador de ese color. A partir del índice del color transparente, obtenemos la representación RGB en la imagen original con imagecolorsforindex y ya podemos localizar ese color en la nueva imagen con imagecolorallocatealpha. Ya tenemos todo lo necesario. Ahora simplemente rellenamos la nueva imagen con ese color, le decimos que ese color será el transparente y copiamos la imagen original en la nueva escalando según necesitamos.
A la hora de copiar la imagen y escalarla no utilizamos imagecopyresampled ya que, a diferencia de imagecopyresized, hace una interpolazión para suavizar el resultado final. Esto, que en general es correcto, en el gif transparente provoca la deformación de pixeles propios de la interpolación, haciendo que se pierda parte de la trasparencia ya que estos pixeles no son del color exacto.
Este sería el código final.
Código PHP:
1.
$srcImage=imagecreatefromgif("demo.gif");
2.
$new_w=160;
3.
$new_h=114;
4.
$dst_img=imagecreatetruecolor($new_w,$new_h);
5.
$transcolor=imagecolortransparent($srcImage);
6.
if($transcolor!=-1){
7.
$trnprt_color = imagecolorsforindex($srcImage, $transcolor);
8.
$trnprt_indx = imagecolorallocatealpha($dst_img, $trnprt_color[‘red’], $trnprt_color[‘green’], $trnprt_color[‘blue’], $trnprt_color[‘alpha’]);
9.
imagefill($dst_img, 0, 0, $trnprt_indx);
10.
imagecolortransparent($dst_img, $trnprt_indx);
11.
}
12.
imagecopyresized($dst_img,$srcImage,0,0,0,0,$new_w,$new_h,ImageSX($srcImage),ImageSY($srcImage));

URL Autor
Parte 1
Parte 2
Parte 3