Cambiar tamaño y peso de imágenes

Para trabajar con imágenes en PHP se suele usar la biblioteca GD. Esta biblioteca se puede descargar desde su página web http://www.boutell.com/gd/.

Para saber si tenemos instalado las librerías GD y que versión, lo podemos ver con phpinfo() buscando "GD".

Esta función de ejemplo no funcionará sin la biblioteca GD. Esta función ha sido probada con la versión 2.0, por lo que alguna función puede (debe) devolver error en versiones anteriores, estas funciones susceptibles de ser problemáticas son las de tipo "imagexxxx". Si tuviéramos una versión anterior o nos dieran problemas estas funciones, podríamos reemplazar el "switch" que verifica el tipo de imagen y la asignación de cabecera previa, o sea este código:

:

/*
Se envía la cabecera de los datos de la imagen.
Cuando llegue aquí no debe de haber sido enviado NADA.
Si se ha enviado algo, aunque fuera un "intro" o espacio daría error
*/
header("Content-type: ".$sTipo);

// Se pinta la imagen según el tipo
switch($vDatosImg[2]){
case IMAGETYPE_GIF:
imagegif($imgDestino);
break;
case IMAGETYPE_JPEG:
imagejpeg($imgDestino);
break;
case IMAGETYPE_PNG:
imagepng($imgDestino);
break;
case IMAGETYPE_SWF:
case IMAGETYPE_PSD:
case IMAGETYPE_BMP:
case IMAGETYPE_TIFF_II:
case IMAGETYPE_TIFF_MM:
case IMAGETYPE_JPC:
case IMAGETYPE_JP2:
case IMAGETYPE_JPX:
case IMAGETYPE_JB2:
case IMAGETYPE_SWC:
case IMAGETYPE_IFF:
return -12;
break;
case IMAGETYPE_WBMP:
imagewbmp($imgDestino);
break;
case IMAGETYPE_XBM:
imagexbm($imgDestino);
break;
default:
return -13;
break;
}


Por este otro:

/*
Se envía la cabecera de los datos de la imagen.
Cuando llegue aquí no debe de haber sido enviado NADA.
Si se ha enviado algo, aunque fuera un "intro" o espacio daría error
*/
header("Content-type: image/png");

// Se pinta la imagen según el tipo
imagepng($imgDestino);


La función "iPintaImagenRedimensionada" recibe 5 parámetros:

$sDirImagen: Cadena que debe contener la dirección de la imagen que queremos cambiar el tamaño, esta dirección puede ser relativa, absoluta, de archivo ó URL, ejemplos:

Relativa:imagen.gif
Absoluta de archivo:c:\imagenes\imagen.gif
Absoluta de URL:http://www.tuweb.com/imagenes/imagen.gif


$bEscalable: Booleano, si esta activado (1 ó TRUE) la imagen cambiara de forma porcentual al valor pasado por alto y ancho, así por ejemplo si lo establecemos a TRUE y le pasamos como ancho y alto 0.5, la imagen será reducida a la mitad de su tamaño, con 0.25 a un cuarto de su tamaño, 2 al doble de su tamaño, 1 se quedaría en su tamaño ...
Mientras que si este valor es FALSE (0) lo que hará será dar a la imagen resultante el tamaño pasado por alto y ancho directamente.

$ancho y $alto: Pasan el ancho y alto de la imagen con las características que hemos comentado anteriormente con la variable $bEscalable. Si una de estas variables recibe un valor negativo, cogerá la medida proporcional correspondiente al otro valor, así por ejemplo si una imagen de 600px de ancho por 300px de alto recibe como valores $bEscalable 0, $ancho 300 y $alto -1; La imagen resultante tendrá 150px de alto, ya que el ancho se ha reducido a la mitad, el alto también se reduce.

$iTipo: Entero que pasa el tipo del contenido MIME de la imagen, este valor no suele ser usado por la función, ya que antes de coger el tipo MIME por esta variable, lo intenta coger de las propias cabeceras de la imagen. Por lo que no es imprescindible que este parámetro sea pasado correctamente. Los tipo mime pueden ser:

ValorDefinesalida cabecera MimeDescripción
1IMAGETYPE_GIFimage/gifImagen GIF (Dibujo)
2IMAGETYPE_JPEGimage/jpegImagen JPEG (Foto)
3IMAGETYPE_PNGimage/pngImagen PNG (muy usada en PHP)
4IMAGETYPE_SWFapplication/x-shockwave-flashAnimación flash
5IMAGETYPE_PSDimage/psdFormato digital de Photoshop
6IMAGETYPE_BMPimage/bmpImagen de mapa de Bits
7IMAGETYPE_TIFF_IIimage/tiffImagen Tiff con orden de bytes Intel
8IMAGETYPE_TIFF_MMimage/tiffImagen Tiff con orden de bytes Motorola
9IMAGETYPE_JPCapplication/octet-streamGráfico
10IMAGETYPE_JP2image/jp2Imagen JP2 (jpeg 2000)
11IMAGETYPE_JPXapplication/octet-streamImagen JPX (JPEG extendido)
12IMAGETYPE_JB2application/octet-streamImagen JB2, imágenes bitonales
13IMAGETYPE_SWCapplication/x-shockwave-flashComponente de shockwave flash
14IMAGETYPE_IFFimage/iffImagen IFF
15IMAGETYPE_WBMPimage/vnd.wap.wbmpImagen wap
16IMAGETYPE_XBMimage/xbmImagen xbm (pequeños iconos)

$iTipo podría recibir o bien el valor (1, 2, 3, 4) o el define (IMAGETYPE_XXX).

Esta función pintará una imagen redimensionada si no ocurre ningún error. Si todo ha funcionada correctamente, devolverá 1, en caso contrario un número negativo. Debido a que puede devolver diferentes errores, hemos añadido una función que los gestiona y presenta una imagen describiendo el error. Esta función recibe un parametro que debería ser lo que devuelve la función de "iPintaImagenRedimensionada" (como se ve en el ejemplo).
Esta función crea las imágenes con un tamaño fijo (400 x 40), para cambiar este tamaño modificar la línea:
$imagen = imagecreate (400, 40);

Y los colores que usa son los colores "McAnam" de fondo y el marrón oscuro para el texto. Para cambiar esto colores, modificar las líneas:
$cFondo = imagecolorallocate ($imagen, 255, 226, 169);
$cTexto = imagecolorallocate ($imagen, 153, 102, 0);

"imagecolorallocate" recibe la imagen donde se va a definir el color y los tres colores rojo, verde y azul (rgb) de 0 a 255.


Código:
//Copyright © McAnam.com
function iPintaImagenRedimensionada ($sDirImagen, $bEscalable, $ancho, $alto, $iTipo){

// Cogemos los datos de la imagen
$vDatosImg = @getimagesize($sDirImagen);

if (!$vDatosImg) return -8;

// Recogemos el Tipo Mime
if (isset($vDatosImg['mime']))
$sTipo = $vDatosImg['mime'];
else if(isset($vDatosImg[2]))
$sTipo = image_type_to_mime_type($vDatosImg[2]);
else if (isset($iTipo))
$sTipo = image_type_to_mime_type($iTipo);
else
return -10;

// Recogemos la imagen a partir de la dirección dada ($sDirImagen)
switch($vDatosImg[2]){
case IMAGETYPE_GIF:
$imgOrigen = imagecreatefromgif($sDirImagen);
break;
case IMAGETYPE_JPEG:
$imgOrigen = imagecreatefromjpeg($sDirImagen);
break;
case IMAGETYPE_PNG:
$imgOrigen = imagecreatefrompng($sDirImagen);
break;
case IMAGETYPE_SWF:
case IMAGETYPE_PSD:
case IMAGETYPE_BMP:
case IMAGETYPE_TIFF_II:
case IMAGETYPE_TIFF_MM:
case IMAGETYPE_JPC:
case IMAGETYPE_JP2:
case IMAGETYPE_JPX:
case IMAGETYPE_JB2:
case IMAGETYPE_SWC:
case IMAGETYPE_IFF:
return -11;
break;
case IMAGETYPE_WBMP:
$imgOrigen = imagecreatefromwbmp($sDirImagen);
break;
case IMAGETYPE_XBM:
$imgOrigen = imagecreatefromxbm($sDirImagen);
break;
default:
return -13;
break;
}

/*
Establecemos los tamaños:
- Si bEscalable viene como true.
Se multiplican los valores recibidos para ancho y alto
por el ancho y alto de la imagen,
así 0.5 sería la mitad de la imagen y 2 sería el doble
- Si bEscalable viene como false.
Los tamaños serán los pasados por ancho y alto directamente
- Si ancho o alto vienen como 0 o numero negativo,
el valor de esta propiedad será asignada proporcionalmente con
el valor de la otra.
- Si ancho y alto vienen como 0 o numero negativo, Error
*/

if (!(is_numeric($ancho)) || !(is_numeric($alto))) return -20;

if ($bEscalable){
if ($ancho > 0){
$ancho *= $vDatosImg[0];
if ($alto > 0) $alto *= $vDatosImg[1];
else $alto = $vDatosImg[1] * ($ancho / $vDatosImg[0]);
}else if ($alto > 0){
$alto *= $vDatosImg[1];
$ancho = $vDatosImg[0] * ($alto / $vDatosImg[1]);
}else{
return -21;
}
}else{
if (($ancho > 0) && ($alto < 1))
$alto = $vDatosImg[1] * ($ancho / $vDatosImg[0]);
else if (($alto > 0) && ($ancho < 1))
$ancho = $vDatosImg[0] * ($alto / $vDatosImg[1]);
else if (($alto < 1) && ($ancho < 1))
return -21;

}

// Se crea la nueva imagen redimensionada
if (function_exists("ImageCreateTrueColor"))
$imgDestino = ImageCreateTrueColor($ancho,$alto);
else
$imgDestino = ImageCreate($ancho,$alto);

ImageCopyResized ($imgDestino, $imgOrigen, 0, 0, 0, 0, $ancho, $alto, $vDatosImg[0], $vDatosImg[1]);

/*
Se envía la cabecera de los datos de la imagen.
Cuando llegue aquí no debe de haber sido enviado NADA.
Si se ha enviado algo, aunque fuera un "intro" o espacio daría error
*/
header("Content-type: ".$sTipo);

// Se pinta la imagen según el tipo
switch($vDatosImg[2]){
case IMAGETYPE_GIF:
imagegif($imgDestino);
break;
case IMAGETYPE_JPEG:
imagejpeg($imgDestino);
break;
case IMAGETYPE_PNG:
imagepng($imgDestino);
break;
case IMAGETYPE_SWF:
case IMAGETYPE_PSD:
case IMAGETYPE_BMP:
case IMAGETYPE_TIFF_II:
case IMAGETYPE_TIFF_MM:
case IMAGETYPE_JPC:
case IMAGETYPE_JP2:
case IMAGETYPE_JPX:
case IMAGETYPE_JB2:
case IMAGETYPE_SWC:
case IMAGETYPE_IFF:
return -12;
break;
case IMAGETYPE_WBMP:
imagewbmp($imgDestino);
break;
case IMAGETYPE_XBM:
imagexbm($imgDestino);
break;
default:
return -13;
break;
}

imagedestroy($imgOrigen);
imagedestroy($imgDestino);

return 1;

}

function ErrorPintaImagenRedimensionada($iRetorno){

$sTexto1 = "";
$sTexto2 = "";

switch($iRetorno){
case -8:
$sTexto1 = "La dirección de la imagen dada no es válida";
break;
case -10:
$sTexto1 = "No se ha encontrado el tipo mime de la imagen";
$sTexto2 = "ni en sus cabeceras ni pasadas por parámetro";
break;
case -11:
$sTexto1 = "El tipo de la imagen dado no se puede redimensionar";
$sTexto2 = "Se recomiendan los tipos jpg, gif ó png";
break;
case -12:
$sTexto1 = "No es posible crear una imagen con el tipo dado";
$sTexto2 = "Se recomiendan los tipos jpg, gif ó png";
break;
case -13:
$sTexto1 = "El tipo mime no esta implementado";
$sTexto2 = "Se recomiendan los tipos jpg, gif ó png";
break;
case -20:
$sTexto1 = "Error en los parámetros pasados ancho (3º) ó alto(4º)";
$sTexto2 = "Los valores deben ser numéricos enteros o decimales";
break;
case -21:
$sTexto1 = "Error en los parámetros pasados ancho (3º) y alto(4º)";
$sTexto2 = "al menos uno de estos parámetros deben de ser positivos";
break;
default:
if ($iRetorno < 0) $sTexto1 = "Error desconocido";
break;
}

if ($sTexto1 != ""){
$imagen = imagecreate (400, 40);
$cFondo = imagecolorallocate ($imagen, 255, 226, 169);
$cTexto = imagecolorallocate ($imagen, 153, 102, 0);
imagefilledrectangle ($imagen, 0, 0, 150, 30, $cFondo);
if ($sTexto2 == ""){
imagestring ($imagen, 3, 5, 15, $sTexto1, $cTexto);
}else{
imagestring ($imagen, 3, 5, 5, $sTexto1, $cTexto);
imagestring ($imagen, 3, 5, 20, $sTexto2, $cTexto);
}

header("Content-type: image/png");
imagepng($imagen);
imagedestroy($imagen);
}

}


$iError = iPintaImagenRedimensionada("imagen.jpg", TRUE, 0.5, -1, IMAGETYPE_JPEG);
ErrorPintaImagenRedimensionada ($iError)

?>

3 comentarios:

Unknown dijo...

Hola amigo, muy interesante la función...

Juliana, Sole y Martin dijo...

Hola, muy buena la función. Estoy usando una versión simplificada para tratar de cargar fotos desde un form, cambiarles el tamaño y guardarlas en una base de datos MySQL.
Después te cuento como anduvo!

Saludos

Chinea Habana dijo...

Hola, la verdad que es muy Buena función y se muestra la imagen muy bien, he analizado función tras función pero en ningún momento se hace una copia al servidor o se guarda en algún directorio.
Según la función imagejpeg(image, filename, quality ) esta función como las otras para diferentes tipos de imágenes, me referiré a esta que es la que me interesa, estos tres paramentos son la imagen destino como primero, segundo el lugar donde se copiará o se guardaré y el tercero que es la calidad de 0 a 100.
En fin traté de poner esto [ imagejpeg($imgDestino,"../i_casas",100);] en el código donde debe ser pero no me copia la imagen y el resultado que me da es que me muestra todo el código en html como página, puse como comentario esto //header("Content-type: ".$sTipo); y //header("Content-type: image/jpg"); y el resultado fue que me sale un error diciendo que tengo permiso denegado.
Este es el error.:
Warning: imagejpeg() [function.imagejpeg]: Unable to open '../i_casas' for writing: Permission denied in C:\xampp\htdocs\plantilla.php on line 123
¿Que hago?