Revista Tecnología

Redimensionando fotos en PHP evitando que se deformen nuestras imágenes

Publicado el 22 junio 2016 por Gaspar Fernández Moreno @gaspar_fm

Redimensionando fotos evitando deformen nuestras imágenesRedimensionando fotos en PHP evitando que se deformen nuestras imágenes
En las webs modernas se intenta que el usuario sea capaz de hacer casi de todo. Eso sí, siempre que de cara al servidor sea seguro. Por ejemplo, de nada vale que un usuario pueda generar a través de una web 1000000 de decimales del número PI si mientras tanto ningún usuario más es capaz de hacer nada.
Una de las tareas básicas de una web hoy e día es redimensionar un foto. Es decir, adaptar el tamaño de una foto para adecuarla a nuestras necesidades. Lo primero que tenemos que pensar es que a la hora de transmitir imágenes por la red, tenemos que evitar enviar archivos demasiado grandes. Por ejemplo, si tenemos que mostrar una imagen como máximo a 500×500, debemos evitar enviar la imagen a 4096×4096 ya que no vamos a mostrarla tan grande, vamos a desperdiciar ancho de banda nuestro enviando la foto y tiempo del usuario descargándola.
Todo eso sumado al auge de las webs dinámicas que deben permitir la subida de archivos de imagen al usuario (o al administrador) y de forma sencilla adaptarlas a la web. De forma que se pueda subir una foto directamente de la cámara digital y a la hora de visualizarla en la web quedarnos sólo con el tamaño o los tamaños que necesitemos.

Aunque, como siempre, tenemos varias formas de hacer las cosas, y, sobre todo, hay un factor que debemos tener en cuenta: el aspecto de la foto.

Aspecto de una imagen

El aspecto de una imagen no es más que la relación entre anchura y altura. Vamos, ancho partido por alto. Si os fijáis, es lo mismo que se utiliza en las pantallas. Ahora es común que las pantallas sean 16:9 (panorámicas, que son mucho más anchas que altas), antiguamente los monitores solían ser 4:3 (no eran cuadrados, pero casi). No obstante hay muchas relaciones de aspecto estándar para monitores, proyección, etc.
Cuando hablamos de imágenes, puede haber tantas relaciones de aspecto como imágenes, ya que las fotos podemos recortarlas de mil maneras, y tanto anchura como altura pueden tomar casi cualquier valor y su relación de aspecto se suele expresar como el resultado de la división entre ancho y algo. Si nuestra foto tiene una resolución de 320×240 su relación será 1,33 (¡ anda ! 4/3 da también 1,33 y es que esta imagen se podrá presentar a pantalla completa sin que se observe ninguna deformación), si nuestra foto tiene de dimensiones 600×500 la relación será de 1,2 y si la ponemos a pantalla completa en un monitor 4:3 la veremos deformada.

Dejo aquí la foto original con una resolución de 1280×792 y una relación de aspecto de 1,61:

Redimensionando fotos evitando deformen nuestras imágenes
Redimensionando fotos en PHP evitando que se deformen nuestras imágenes

Sobre PHP y Frameworks

Si estás trabajando con un framework o una biblioteca especializada en imágenes, seguramente dispongas de funciones o métodos para realizar estas operaciones de forma directa y con algunas opciones más. Pero si te gusta programar PHP a pelo, aquí encontrarás algunas guías que podrán ser útiles para tus proyectos. Aunque podemos utilizar otras bibliotecas para gráficos en PHP, como por ejemplo ImageMagick, estos ejemplos se han hecho utilizando GD.

Las funciones que utilizaré aquí serán sencillas, porque sobre todo el post va encaminado a la matemática de la transformación de las dimensiones y el recorte de la foto.

Redimensionado rápido y directo

Lo que hacemos aquí es cambiar el tamaño de la foto. Nos da igual la relación de aspecto, cogeremos una foto (baterias.jpg) y sean cuales sean sus dimensiones, las cambiaremos.
Para ello utilizaremos imagecopyresampled(), eso sí, si no tenemos cuidado con la resolución que pongamos, la imagen puede quedar deformada.
Si tomamos este código:

La imagen resultante será:

Redimensionando fotos evitando deformen nuestras imágenes
Redimensionando fotos en PHP evitando que se deformen nuestras imágenes

Y, como no hemos respetado la relación de aspecto de la pantalla, la imagen sale deformada, las baterías salen como aplastadas. Esto nos puede servir para imágenes muy pequeñas, o para cuando sepamos (o no nos importe) que la imagen no va a sufrir una deformación.

Una dimensión fija

Si no queremos que la imagen sufra ninguna deformación, lo que podemos hacer es dejar una dimensión fija. Si dejamos el ancho fijo, con la relación de aspecto de la imagen original podemos calcular la nueva altura, y si dejamos la altura fija, podemos calcular la anchura. Siguiendo las siguientes ecuaciones:

Redimensionando fotos evitando deformen nuestras imágenes
Redimensionando fotos en PHP evitando que se deformen nuestras imágenes

El código sería el siguiente:

Donde podemos cambiar la llamada a resizeAspectW() por resizeAspectH() dándonos como resultado las siguientes imágenes:

Mantener aspecto sin pasarse de dimensiones

El problema con el algoritmo anterior es que las dimensiones pueden crecer mucho. Sobre todo si permitimos que el usuario nos suba fotografías, pueden subir una foto alargada de dimensiones 1×10000 (aspecto 0,0001) si queremos fijar el ancho a 200 la altura saldría a 2000000 lo que es inviable. Por tanto, debemos controlar cuánto crece la imagen. Podemos seguir este código que fijará las dimensiones máximas a las que vamos a tener la imagen resultante. La relación de aspecto se mantendrá y no se superarán las dimensiones fijadas:

La imagen resultante ahora será (323×200):

Redimensionando fotos evitando deformen nuestras imágenes
Redimensionando fotos en PHP evitando que se deformen nuestras imágenes

Os invito a probar este algoritmo con otras dimensiones de imagen para ver cómo se comporta.

Redimensiona y recorta (resizeCrop)

En el caso anterior, una dimensión sí que quedará fija (se elegirá en función de la relación de aspecto), pero, si queremos que las dos dimensiones queden fijas sin que se pierda la relación de aspecto, lo que debemos hacer es recortar la imagen. De esta forma perderemos información, pero la foto se seguirá viendo bien, aunque deberíamos decidir de dónde perdemos información, ya que si la imagen resultante es más alta que la deseada, debemos perder información vertical y si es más ancha horizontal.
Podemos seguir el siguiente algoritmo:

La imagen resultante será (520×500):

Redimensionando fotos evitando deformen nuestras imágenes
Redimensionando fotos en PHP evitando que se deformen nuestras imágenes

El cuarto argumento, $displ podrá tener uno de los siguientes valores:

  • 'min': recortará la imagen arriba o a la izquierda
  • 'center': se quedará con la parte central de la imagen
  • 'max': recortará la imagen abajo o a la derecha
  • 0>=x>=1 (cualquier valor entre 0 y 1): desplazará la ventana de recorte hacia la derecha o abajo. Podemos interpretarlo como un porcentaje.

Rotar y recortar

Si queremos aplicar un efecto chulo a nuestras fotos, podemos rotarlas unos grados. El problema es que se crearán unos bordes negros (también podemos hacerlos transparentes), pero nos incomodarán. Así que, vamos a proceder a buscar la región cuadrada más grande de imagen sin bordes y recortar la imagen con esas dimensiones en esa posición (primero redimensiono la imagen para hacerla más cómoda para trabajar):

El resultado sería algo como esto:

Redimensionando fotos evitando deformen nuestras imágenes
Redimensionando fotos en PHP evitando que se deformen nuestras imágenes

Foto principal: Tony Webster


Volver a la Portada de Logo Paperblog