Redimensionar imágenes sobre la marcha

Redimensionando imágenes en tiempo real

Como arquitecto web, uno de los muchos problemas es la gestión de activos. Y el problema más significativo en los activos son las imágenes. Un enfoque ingenuo sería configurar una imagen y permitir que el navegador redimensione la imagen a través de CSS:

Sin embargo, significa que descargas la imagen original. Conlleva dos problemas: el tamaño de la imagen original y la redimensión subóptima por parte del navegador.

Esta publicación cubrirá dos alternativas: soluciones tradicionales y nuevas.

Redimensionamiento por Adelantado

La solución tradicional para una sola fuente de imagen ha sido el redimensionamiento por adelantado. Antes de su lanzamiento, los diseñadores tomarían tiempo para proporcionar múltiples versiones de imágenes en diferentes resoluciones. En este blog, estoy utilizando esta técnica. Proporciono tres resoluciones para mostrar la imagen principal de la publicación en diferentes contextos como imágenes de fondo:

  • Grande para la publicación en su página
  • VoAGI para la publicación en la página de inicio
  • Pequeña para publicaciones relacionadas en una página de publicación

También elimino los metadatos JPEG para una reducción aún mayor del tamaño.

Aún así, el enfoque tradicional es aprovechar la etiqueta HTML picture:

El elemento HTML <picture> contiene cero o más elementos <source> y un elemento <img> para ofrecer versiones alternativas de una imagen para diferentes escenarios de visualización/dispositivos.

El navegador considerará cada elemento hijo <source> y elegirá la mejor coincidencia entre ellos. Si no se encuentran coincidencias o el navegador no admite el elemento <picture>, se selecciona la URL del atributo src del elemento <img>. La imagen seleccionada se presenta en el espacio ocupado por el elemento <img>.

El elemento Picture en la documentación web de MDN

A su vez, uno puede usarlo de la siguiente manera:

Esta forma ha funcionado durante años, pero tiene dos problemas. En primer lugar, proporcionar múltiples resoluciones para cada imagen lleva mucho tiempo. Se podría automatizar el proceso y obtener buenos resultados con la IA.

Sin embargo, el volumen de almacenamiento necesario podría ser el doble o el triple del tamaño de la imagen original, dependiendo del número de resoluciones adicionales creadas. En un entorno rico en activos, por ejemplo, un comercio electrónico, esto aumentaría significativamente los costos.

Redimensionamiento en el Momento

Recientemente me encontré con imgproxy, un componente para redimensionar imágenes en el momento:

imgproxy hace que los sitios web y aplicaciones sean extremadamente rápidos mientras se ahorra almacenamiento y costos de SaaS

Sitio web de imgproxy

Ofrece un punto final donde puedes enviar una URL codificada que define:

  • La imagen a redimensionar y su ubicación, por ejemplo, local, una URL HTTP, un cubo S3, etc.
  • Diferentes parámetros de tamaño, por ejemplo, las dimensiones, si ajustar o llenar, etc.
  • El formato. imgproxy admite formatos estándar como JPEG y PNG, pero también formatos más modernos como WebP y AVIF. También puede elegir el mejor formato según el encabezado ‘Accept’.
  • Muchas (¡muchas!) otras opciones, como marca de agua, filtrado, rotación, etc.

imgproxy ofrece tanto una versión gratuita de código abierto como una versión de pago; todo lo incluido en esta publicación es parte de la primera.

Una solución sería que el desarrollador web codifique cada URL de imgproxy en el HTML:

Esto filtra detalles relacionados con la topología de la página web. No es una solución mantenible. Podemos resolver el problema con un proxy inverso o una puerta de enlace de API. Utilizaré Apache APISIX por razones obvias.

Con este enfoque, el HTML anterior se vuelve mucho más sencillo:

Apache APISIX intercepta las solicitudes que comienzan con /resize, reescribe la URL para imgproxy y reenvía la URL reescrita a imgproxy. Aquí está el flujo general:

La configuración correspondiente de Apache APISIX se ve así:

  1. Corresponder las solicitudes con el prefijo /resize
  2. Reescribir la URL
  3. Capturar el ancho y la imagen en la expresión regular
  4. Formatear la URL para imgproxy. http://server:3000 es el servidor que aloja la imagen original; @webp indica una preferencia por el formato WebP (si el navegador lo admite)

Con lo anterior, /resize/200/ai-generated.jpg en Apache APISIX se reescribe como /rs:fill/w:200/plain/http://server:3000/ai-generated.jpg@webp en imgproxy.

Pruebas

Podemos configurar una pequeña muestra de prueba utilizando Docker Compose:

  1. Servidor web simple que aloje el HTML y la imagen principal

Ahora podemos probar la configuración anterior con las Herramientas de desarrollo del navegador, emulando dispositivos de pantalla pequeña, como el iPhone SE. El resultado es el siguiente:

  • Debido a la resolución de pantalla, la imagen solicitada tiene un ancho de 400px, no el original. Puedes verlo en la URL de la solicitud
  • La imagen devuelta está en formato WebP y su tamaño es de 14,4 kb
  • La imagen JPEG original pesa 154 kb, más de diez veces más. ¡Es un gran ahorro de ancho de banda de la red!

Discusión

Reducir los costos de almacenamiento a una décima parte es sin duda un gran beneficio. Sin embargo, no todo son unicornios y arcoíris. Calcular la imagen redimensionada es una operación intensiva en cuanto a CPU y requiere tiempo para crear la imagen, a pesar de lo eficiente que sea imgproxy. Hemos intercambiado costos de almacenamiento por costos de CPU y ahora incurrimos en una ligera disminución del rendimiento.

Para solucionarlo, necesitamos una capa de almacenamiento en caché, ya sea personalizada o, lo más probable, una CDN. Puede objetarse que volveremos a almacenar activos, por lo que los costos de almacenamiento volverán a subir. Sin embargo, la gran diferencia es que la caché solo funciona para imágenes utilizadas, mientras que en la solución anterior pagamos por almacenar todas las imágenes. También se pueden aplicar técnicas conocidas para almacenamiento en caché, como el precalentamiento, cuando se sabe que un grupo de imágenes será muy solicitado, por ejemplo, antes de un evento.

Conclusión

En este post, describimos cómo utilizar Apache APISIX con imgproxy para reducir el costo de almacenamiento de imágenes en múltiples resoluciones. Con la caché por encima, se agregan más componentes a la arquitectura general, pero se reducen los costos de almacenamiento.

Este post se inspiró en la charla de Andreas Lehr en StackConf.

El código fuente completo de este post se puede encontrar en GitHub.

Para ir más allá

We will continue to update Zepes; if you have any questions or suggestions, please contact us!

Share:

Was this article helpful?

93 out of 132 found this helpful

Discover more

Inteligencia Artificial

Un novedoso modelo de aprendizaje automático acelera la evaluación de catalizadores de descarbonización de meses a milisegundos

La biomasa se refiere a la materia orgánica, como plantas, madera, residuos agrícolas y otros materiales biológicos, ...

Ciencia de Datos

Aprendizaje Profundo en Sistemas de Recomendación Una introducción.

Los sistemas de recomendación se encuentran entre las aplicaciones de Aprendizaje Automático industrial de más rápido...

Inteligencia Artificial

Uso de Computadoras Analógicas en Inteligencia Artificial (IA)

Las Computadoras Analógicas son una clase de dispositivos en los cuales las cantidades físicas como el voltaje eléctr...