Como crear vistas previas escaladas y recortadas en PHP
En la publicación anterior, creamos vistas previas escaladas de imágenes que mantenían la relación de aspecto. En esta publicación veremos como recortar y escalar la imagen para que el area de la vista previa quede llena.
Temas
Objetivo, requerimientos y
uso
Creando la función
Notas
finales
Descarga la función
Objetivo, requerimientos y uso
Nuestro objetivo aquí es que, dado el tamaño de la vista previa, escalemos la imagen original de tal manera que se ajuste al tamaño de la vista previa sin dejar espacio vacío, y todo lo que no entre en el área rectangular de la vista previa sea cortado.
Usualmente, al subir una imagen al servidor de manera dinámica,
guardamos el nombre de la misma en una base de datos, o le asignamos un
nombre con el que podamos relacionarla a un registro; el siguiente
ejemplo asume que obtenemos los datos del registro en una variable
llamada $row["imagen"] y usamos esta para llamar
la imagen:
<img src="/direccion/<?=$row["imagen"];?>"
width="100" height="100" alt="" />
La idea es que en vez de llamar a la imágen de la manera anterior, podamos llamarla como a continuación, asumiendo que "mini" sea el prefijo que deseamos utilizar; también podemos utilizar algo como "mini100x100" si queremos, podría ser útil si generamos más de un tamaño, dándole a cada tamaño su propio prefijo:
<img src="/direccion/mini_<?=$row["imagen"];?>"
alt="" />
Requerimos cuatro valores para esto:
- La dirección de la imagen: Esta imagen necesita estar ya guardada en una carpeta dentro de nuestro servidor, por lo tanto, esta función debe ser llama tras procesar la transferencia de la imagen al servidor.
- El ancho deseado de la vista previa.
- El alto deseado de la vista previa.
- Un prefijo (o podría utilizarse un sufijo si se desea) que será añadido al nombre de la imagen original.
Y será llamada de la siguiente manera, una vez que la imagen ya se encuentra en el servidor, ajustando la dirección relativa de la imagen, el tamaño, y el prefijo de la manera que deseamos:
crear_previo_cortado("../imagenes/".$nombre_imagen,
100, 100, "mini");
Creando la función
Necesitamos crear un búfer de imagen con la imagen original, calcular si necesitamos cortar un área de la imagen y que tanto, crear un segundo búfer de imagen donde guardaremos la imagen escalada, realizar la operación de corte y escalado, guardar la nueva imagen y finalmente destruir los búfers de las imágenes.
function crear_previo_cortado($direccion_imagen,
$previo_ancho, $previo_alto, $prefijo) {
Antes que nada revisamos que los parámetros son números enteros positivos.
if (!(is_integer($previo_ancho) && $previo_ancho >
0)) {
echo "El ancho es inválido";
exit(1);
}
if
(!(is_integer($previo_alto) && $previo_alto > 0)) {
echo
"El alto es inválido";
exit(1);
}
A continuación averiguamos con que tipo de imagen estamos lidiando, una
gif, una jpg o una png, usando pathinfo(), y creamos el
primer búfer con la imagen original.
$extension = pathinfo($direccion_imagen,
PATHINFO_EXTENSION);
switch ($extension) {
case "jpg":
case
"jpeg":
$imagen_original =
imagecreatefromjpeg($direccion_imagen);
break;
case
"gif":
$imagen_original =
imagecreatefromgif($direccion_imagen);
break;
case
"png":
$imagen_original =
imagecreatefrompng($direccion_imagen);
break;
default:
exit(1);
echo "Tipo de archivo invalido";
break;
}
Tras cargar el búfer con la imagen original, obtenemos su ancho y su alto:
$original_ancho = imageSX($imagen_original);
$original_alto
= imageSY($imagen_original);
Ahora necesitamos calcular los parámetros faltantes para poder general la vista previa, reglas de tres son usadas aquí para calcular el ancho o el alto de el área que vamos a utilizar para general la vista previa, y entonces utilizamos una resta para encontrar las coordinadas desde donde vamos a cortar la imagen original para crear la vista previa. Podemos encontrarnos con tres diferentes situaciones:
La imagen original y la vista previa tienen la misma relación de aspecto.
En este caso simplemente asumimos que las coordenadas comienzan en 0, 0 y no realizamos ningún calculo, al escalar la imagen ajustará perfectamente en la vista previa.
if ((($original_ancho / $original_alto) -
($previo_ancho / $previo_alto)) == 0) {
$original_x = 0;
$original_y
= 0;
}
La imagen original es más ancha que la vista previa.
En este caso nos quedamos con la altura de la imagen original, y
recalculamos con una regla de tres el ancho con base en la relación de
aspecto de la vista previa. Además, tomamos la coordenada y como 0, y
calculamos la coordenada x. Si queremos que la vista previa comience
desde la izquierda, podemos ajustar la coordenada x en 0, o si queremos
que comience desde la derecha, podemos ajustar la formula como $original_x
= $original_ancho - $temporal_ancho;
if (($original_ancho / $original_alto) >
($previo_ancho / $previo_alto)) {
$original_y = 0;
$temporal_ancho
= ceil($original_alto * $previo_ancho / $previo_alto);
$original_x
= ceil(($original_ancho - $temporal_ancho) / 2);
$original_ancho
= $temporal_ancho;
}
La imagen original es más angosta que la vista previa.
En este caso mantenemos el ancho de la imagen original, y recalculamos
la altura con una regla de tres, basados en la relación de aspecto de la
vista previa. Tomamos la coordinada x como 0, y calculamos la coordinada
y. Si queremos que la vista previa comience desde la parte de arriba,
podemos poner la coordinada y como 0, o si queremos que comience desde
abajo, podemos ajustar la formula a $original_y = $original_alto -
$temporal_alto;
if (($original_ancho / $original_alto) <
($previo_ancho / $previo_alto)) {
$original_x = 0;
$temporal_alto
= ceil($original_ancho * $previo_alto / $previo_ancho);
$original_y
= ceil(($original_alto - $temporal_alto) / 2);
$original_alto =
$temporal_alto;
}
Una vez que calculamos los valores necesarios, creamos el búfer para la
vista previa con ImageCreateTrueColor():
$imagen_destino =
ImageCreateTrueColor($previo_ancho, $previo_alto);
Y creamos la vista previa con toda la información que calculamos, para
esto utilizamos imagecopyresampled():
imagecopyresampled($imagen_destino,
$imagen_original, 0, 0, $original_x, $original_y, $previo_ancho,
$previo_alto, $original_ancho, $original_alto);
Una vez hecho esto, guardamos la imagen. Utilizamos la extensión que extrajimos previamente para generar la nueva imagen:
$archivo_destino = pathinfo($direccion_imagen,
PATHINFO_DIRNAME) . "/";
$archivo_destino .= $prefijo . "_"
. pathinfo($direccion_imagen, PATHINFO_FILENAME);
switch ($extension)
{
case "jpg":
case "jpeg":
imagejpeg($imagen_destino, $archivo_destino);
break;
case "gif":
imagegif($imagen_destino, $archivo_destino);
break;
case "png":
imagepng($imagen_destino, $archivo_destino);
break;
}
Y finalmente, destruimos los búfer de las imágenes con imagedestroy()
y cerramos la función:
imagedestroy($imagen_destino);
imagedestroy($imagen_original);
}
Notas finales
Si queremos usar un sufijo en lugar de un prefijo, solo necesitamos reemplazar $prefijo con $sufijo en la declaración de la función, y cambiar la linea:
$archivo_destino .= $prefijo . "_" .
pathinfo($direccion_imagen, PATHINFO_FILENAME);
por las lineas:
$archivo_destino .= pathinfo($direccion_imagen,
PATHINFO_BASENAME);
$archivo_destino .= "_" . $sufijo . "." .
$extension;
Descarga la función
Solo recuerda llamarla una vez que la imagen fue subida al servidor, y agregarle el prefijo (o sufijo) al nombre de la imagen para mostrar la vista previa.
previo_recortado.tar.gz
md5sum:
a377dcb1dec64b77267ffe7109dc44de
Categorías: PHP, Programación
