Escalar imágenes con PHP es una necesidad que se nos presenta a menudo. Bien sea que la imagen esté ya almacenda en el servidor, o que proceda de un fichero enviado por un usuario a través de un formulario, es muy habitual que tengamos que crear una miniatura de la imagen. Las miniaturas pueden estar en el mismo directorio que las imágenes originales, o en un directorio especifico. Esto se hace para, por ejemplo, poder mostrar al usuario una colección de miniaturas y, cuando pulse sobre alguna de ellas, se le mostrará la imagen origirnal.
![]() |
Sacar una copia reescalada de una imagen implica varios problemas que hay que resolver. Tenemos que determinar cuales serán las dimensiones máximas de la miniatura, cual será su peso máximo, y sacar una copia escalada que cumpla estos requisitos, manteniendo las proporciones de la imagen original y, en la medida de lo posible, la máxima calidad o, al menos, una calidad aceptable.
La clase class.reescalado.php
ha sido creada con esta finalidad. Su listado es el siguiente:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 |
<?php class reescalado{ // Definimos las propiedades necesarias. public $nombreArchivoOriginal = ""; // El nombre del archivo original y su ruta, // con respecto al script llamante, no a este, en su caso. private $nombreArchivoReescalado = ""; // El nombre del archivo reeacalado y su ruta, // con respecto al script llamante, no a este, en su caso. private $manejadorOriginal; // El manejador para el archivo original. private $manejadorReescalado; // El manejador para el archivo reescalado. private $anchuraOriginal; // La anchura original en píxeles. private $alturaOriginal; // La altura original en píxeles. private $pesoOriginal; // El peso de la imagen original en bytes. private $anchuraDeReescalado; // La anchura que queda a la imagen tras reescalar. private $anchuraMaximaDeReescalado; // La máxima anchura que podrá tener la imagen tras reescalar. private $alturaDeReescalado; // La altura que queda a la imagen tras reescalar. private $alturaMaximaDeReescalado; // La máxima altura que podrá tener la imagen tras reescalar. private $pesoDeReescalado; // El peso que queda a la imagen tras reescalar. private $orientacion; // Si la imagen es horizontal ("H"), vertical ("V") o neutra ("N"); public static $prefijoDeReescalados = "RESIZED_"; // El prefijo que se añadirá al nombre del archivo de la // imagen reescalada, si es el caso. private static $prefijoDeTemporales = "tmp_"; // El prefijo que se añadirá al nombre del archivo de la // imagen reescalada temporal, si es el caso. public static $rutaDeOriginales = ""; // La ruta donde se encuentra el archivo original, con respecto al // script llamante, no a este. // Si se especifica, debe terminar con "/". // Si no se especifica, se asumirá que está en la misma que el // script llamante. public static $rutaDeReescalados = ""; // La ruta donde se grabarán los reescalados, con respecto al // script llamante, no a este. // Si se especifica, debe terminar con "/". // Si no se especifica ruta, se grabarán en la ruta de origen // con el prefijo_de_reescalados. Si este se especifica como "" // (cadena vacía), se restaurará a "RESIZED_". // El objetivo es no "machacar" la imagen original. public static $anchuraMaxDeReescalados = 150; // En píxeles public static $alturaMaxDeReescalados = 100; // En píxeles public static $pesoMaxDeReescalados = 50000; /* EL CONSTRUCTOR */ public function __construct($nombreDeArchivoOriginal){ $this->nombreArchivoOriginal = reescalado::$rutaDeOriginales.$nombreDeArchivoOriginal; /* Se determina la anchura y altura de la imagen original. */ $this->anchuraOriginal = getimagesize($this->nombreArchivoOriginal)[0]; $this->alturaOriginal = getimagesize($this->nombreArchivoOriginal)[1]; /* Se determina si la imagen es vartical, apaisada o neutra. */ $this->orientacion = ($this->anchuraOriginal > $this->alturaOriginal)?"H":(($this->anchuraOriginal == $this->alturaOriginal)?"N":"V"); /* En base a la orientación de la imagen, se determina su anchura y altura máximas, según lo indicado en las propiedades de la clase. */ switch($this->orientacion){ case "H": $this->anchuraMaximaDeReescalado = reescalado::$anchuraMaxDeReescalados; $this->alturaMaximaDeReescalado = reescalado::$alturaMaxDeReescalados; break; case "N": $this->anchuraMaximaDeReescalado = reescalado::$anchuraMaxDeReescalados; $this->alturaMaximaDeReescalado = reescalado::$anchuraMaxDeReescalados; break; case "V": $this->anchuraMaximaDeReescalado = reescalado::$alturaMaxDeReescalados; $this->alturaMaximaDeReescalado = reescalado::$anchuraMaxDeReescalados; break; } /* Se determina el nombre (con la ruta, si procede) de la imagen reescalada. */ if (reescalado::$rutaDeReescalados == "" || reescalado::$rutaDeReescalados == reescalado::$rutaDeOriginales) reescalado::$rutaDeReescalados = reescalado::$rutaDeOriginales; if (reescalado::$rutaDeReescalados == reescalado::$rutaDeOriginales && reescalado::$prefijoDeReescalados == "") reescalado::$prefijoDeReescalados = "RESIZED_"; $this->nombreArchivoReescalado = reescalado::$rutaDeReescalados.reescalado::$prefijoDeReescalados.$nombreDeArchivoOriginal; /* Si la anchura y/o la altura exceden los máximos, se calcula la anchura y altura definitivas. */ if ($this->anchuraOriginal > $this->anchuraMaximaDeReescalado || $this->alturaOriginal > $this->alturaMaximaDeReescalado){ $coeficienteHorizontal = $this->anchuraOriginal / $this->anchuraMaximaDeReescalado; $coeficienteVertical = $this->alturaOriginal / $this->alturaMaximaDeReescalado; $coeficienteDeReescalado = max($coeficienteHorizontal, $coeficienteVertical); } else { $coeficienteDeReescalado = 1; } $this->anchuraDeReescalado = round($this->anchuraOriginal / $coeficienteDeReescalado); $this->alturaDeReescalado = round($this->alturaOriginal / $coeficienteDeReescalado); /* Ya tenemos las dimensiones finales. Ahora hay que grabar una imagen temporal con dichas dimensiones. A partir de ahi, se empezará la comprobación del peso. */ /* Se crea el manejador para una imagen sin contenido de las dimensiones temporales. */ $this->manejadorReescalado = imagecreatetruecolor($this->anchuraDeReescalado, $this->alturaDeReescalado); /* Segun el tipo de imagen, se crea un manejador a partir de la imagen original. */ switch(getimagesize($this->nombreArchivoOriginal)[2]){ // El tipo de imagen case "1": // gif $this->manejadorOriginal = imagecreatefromgif($this->nombreArchivoOriginal); break; case "2": // jpg $this->manejadorOriginal = imagecreatefromjpeg($this->nombreArchivoOriginal); break; case "3": // png $this->manejadorOriginal = imagecreatefrompng($this->nombreArchivoOriginal); break; } // Se copia la imagen original en la escalada, a través de sus manejadores. imagecopyresized($this->manejadorReescalado, $this->manejadorOriginal, 0, 0, 0, 0, $this->anchuraDeReescalado, $this->alturaDeReescalado, $this->anchuraOriginal, $this->alturaOriginal); // Se graba la imagen del manejador de reescalado en un archivo. $archivoTemporal = reescalado::$rutaDeReescalados.reescalado::$prefijoDeTemporales.$nombreDeArchivoOriginal; switch(getimagesize($this->nombreArchivoOriginal)[2]){ // El tipo de imagen case "1": // gif imagegif ($this->manejadorReescalado, $archivoTemporal); break; case "2": // jpg imagejpeg ($this->manejadorReescalado, $archivoTemporal); break; case "3": // png imagepng ($this->manejadorReescalado, $archivoTemporal); break; } /* Ahora se comprueba si el peso del archivo excede del límite. */ if (filesize($archivoTemporal) > reescalado::$pesoMaxDeReescalados) { $coeficiente = filesize($archivoTemporal) / reescalado::$pesoMaxDeReescalados; $anchuraDeTemporal = getimagesize($archivoTemporal)[0]; $alturaDeTemporal = getimagesize($archivoTemporal)[1]; $this->anchuraDeReescalado = round($anchuraDeTemporal / $coeficienteDeReescalado); $this->alturaDeReescalado = round($alturaDeTemporal / $coeficienteDeReescalado); /* Se crea el manejador para una imagen sin contenido de las dimensiones temporales. */ $this->manejadorReescalado = imagecreatetruecolor($this->anchuraDeReescalado, $this->alturaDeReescalado); /* Segun el tipo de imagen, se crea un manejador a partir de la imagen original. */ switch(getimagesize($this->nombreArchivoOriginal)[2]){ // El tipo de imagen case "1": // gif $this->manejadorOriginal = imagecreatefromgif($archivoTemporal); break; case "2": // jpg $this->manejadorOriginal = imagecreatefromjpeg($archivoTemporal); break; case "3": // png $this->manejadorOriginal = imagecreatefrompng($archivoTemporal); break; } // Se copia la imagen temporal en la escalada, a través de sus manejadores. imagecopyresized($this->manejadorReescalado, $this->manejadorOriginal, 0, 0, 0, 0, $this->anchuraDeReescalado, $this->alturaDeReescalado, $anchuraDeTemporal, $alturaDeTemporal); // Se graba la imagen del manejador de reescalado en un archivo definitivo. $archivoFinal = reescalado::$rutaDeReescalados.reescalado::$prefijoDeReescalados.$nombreDeArchivoOriginal; switch(getimagesize($this->nombreArchivoOriginal)[2]){ // El tipo de imagen case "1": // gif imagegif ($this->manejadorReescalado, $archivoFinal); break; case "2": // jpg imagejpeg ($this->manejadorReescalado, $archivoFinal); break; case "3": // png imagepng ($this->manejadorReescalado, $archivoFinal); break; } /* Se elimina el archivo temporal */ unlink($archivoTemporal); } else { $archivoDefinitivo = reescalado::$rutaDeReescalados.reescalado::$prefijoDeReescalados.$nombreDeArchivoOriginal; rename ($archivoTemporal, $archivoDefinitivo); } } } ?> |
Su uso es muy simple. En primer lugar tenemos que importarla en nuestro script, desde luego.
require ("class.reescalado.php");
Si estuviera en un directorio diferente, especificaremos el mismo en la importación, cómo es normal.
A continuación, estableceremos las propiedades de clase. En algunas, nos valdrá el valor por defecto. En otras, deberemos cambiarlo. Las propiedades de clase que se pueden establecer son las siguientes:
PROPIEDAD | USO | VALOR POR DEFECTO |
---|---|---|
reescalado::$prefijoDeReescalados |
Un prefijo que se antepondrá al nombre de la imagen en el reescalado. Así, si establecemos RESIZED_ y la imagen original se llama foto.jpg , la miniatura se llamará RESIZED_foto.jpg . Podemos poner una cadena en blanco, siempre que nos aseguremos de que las miniaturas se grabarán en una ruta diferente a los originales. |
RESIZED_ |
reescalado::$rutaDeOriginales |
La ruta en la que están las imágenes originales, relativa al script en el que estamos trabajando, no al directorio dónde esté la clase. | |
reescalado::$rutaDeReescalados |
La ruta dónde se grabarán las miniaturas, relativa al script en el que estamos trabajando, no al directorio dónde esté la clase. Si dejamos esto cómo una cadena vacía, las miniaturas se grabarán en la misma ruta que estén los originales, por lo que deberemos establecer la propiedad reescalado::$prefijoDeReescalados para evitar conflictos. |
|
reescalado::$anchuraMaxDeReescalados |
La anchura máxima que deberán tener las miniaturas, en píxeles (1). | 150 |
reescalado::$alturaMaxDeReescalados |
La altura máxima que deberán tener las miniaturas, en píxeles (1). | 100 |
reescalado::$pesoMaxDeReescalados |
El peso máximo, en bytes que deberán tener las miniaturas. | 50000 |
(1) Estos parámetros están pensados para una imagen apaisada, es decir, más ancha que alta. Si la imagen es vertical (más alta que ancha), la clase lo detecta automáticamente, manteniendo las proporciones y la orientación originales.
Una vez establecidas las variables de clase, llamamos al constructor, pasándole, cómo argumento, el nombre del fichero de la imagen que queremos miniaturizar, sin especificar la ruta, ya que esta ya la hemos establecido en las variables de clase. Sería algo así cómo esto:
$objetoImagen = new reescalado("imagen_grande.jpg");
CONSIDERACIONES IMPORTANTES
Debemos tener precaución con los siguientes detalles:
La imagen original debe existir en la ruta que hayamos especificado, y ser legible.
La ruta de las minituras debe existir y debemos tener permiso de escritura.
Las imágenes deben ser en formato .jpg
, .gif
o .png
, que son los que se emplean en la web. Otro formato producirá un error.
Normalmente, las variables de clase se establecen una sóla vez en el script que haga uso de esta herramienta. Despues sólo deberemos crear un objeto por cada imagen que queramos miniaturizar.
![]() |
Pingback: PHP-TUT-24 Configuración de PHP. Directivas y extensiones. » Recursos para programadores
No he podido implementar el cogido en una arquitectura MVC me podrias ayudar por favor. muchas gracias
La cuestión que me planteas es muy escueta. No sé si me hablas de una aplicación MVC que hayas creado “a mano” o estás usando algún framework PHP específico. Por otro lado el “no me funciona” es muy ambiguo. No dice nada del problema. No obstante, te voy a dar algunas sugerencias.
Lo primero, si usas MVC (lo que está muy bien; ojalá todo el mundo lo usara) debería ser una aplicación con un autoloader y con espacios de nombres.
Deberías invocar la clase con su espacio de nombres, y comprobar, en el proceso donde la llames, si se está cargando correctamente. Una forma simple de comprobar esto es crear un objeto de la clase y volcarlo a pantalla, mediante un var_dump(), por ejemplo.
También deberías, en la fase de desarrollo, tener activada la directiva display_errors. Mucha gente la omite, porque los mensajes de errores son molestos, pero en desarrollo son una gran ayuda.
Si quieres, puedes publicar la parte de tu código que intenta usar la clase, y detallar mejor el problema exacto que te surge, para que lo veamos.
Como sugerencia adicional, publica todo en stack overflow (https://es.stackoverflow.com/). Es el mejor sitio de preguntas y respuestas, y somos miles de desarrolladores. Alguno te daremos la respuesta, pero tu pregunta debe ser detallada y concreta respecto al problema que te surge.