Изменение размеров изображений в режиме реального времени
Моментальное изменение размеров изображений в режиме реального времени
В качестве веб-архитектора одной из многих проблем является управление активами. И наиболее значительной проблемой с активами являются изображения. Наивным подходом будет установить изображение и позволить браузеру изменять размер изображения с помощью CSS:
Однако это означает, что вы загружаете оригинальное изображение. Это влечет две проблемы: размер оригинального изображения и субоптимальное изменение размера в браузере.
В этой статье будут рассмотрены два альтернативных решения: традиционные и совершенно новые.
Масштабирование наперед
Традиционным решением для одного источника изображения являлось масштабирование наперед. Перед выпуском дизайнеры тратят время на создание нескольких версий изображения разного разрешения. В этом блоге я использую эту технику. Я предоставляю три разрешения для отображения основного изображения записи в разных контекстах в качестве фоновых изображений:
- От интернета вещей до интернета всего слияние искусственного интеллекта и 6G для связанного интеллекта
- Миджорни V5 Последняя версия Миджорни
- CG Гик делает VFX выглядеть просто на этой неделе ‘В NVIDIA Studio
- Большое для публикации на ее странице
- VoAGI для публикации на главной странице
- Маленькое для связанных записей на странице записи
Я также удаляю метаданные JPEG для еще большего сокращения размера.
Тем не менее, традиционным подходом является использование тега HTML picture
:
HTML-элемент
<picture>
содержит ноль или более элементов<source>
и один элемент<img>
для предложения альтернативных версий изображения для разных сценариев отображения/устройств.Браузер рассмотрит каждый дочерний элемент
<source>
и выберет наилучшее соответствие среди них. Если совпадений не найдено или браузер не поддерживает элемент<picture>
, выбирается URL атрибута src элемента<img>
. Выбранное изображение затем отображается в месте, занимаемом элементом<img>
.
В свою очередь, можно использовать его следующим образом:
Этот способ работал веками, но у него есть две проблемы. Во-первых, использование нескольких разрешений для каждого изображения занимает много времени. Можно автоматизировать процесс и получить хорошие результаты с помощью искусственного интеллекта.
Однако объем необходимого хранилища может быть в два или три раза больше, чем у оригинального изображения, в зависимости от количества созданных дополнительных разрешений. В среде, богатой активами, например, в электронной коммерции, это значительно увеличивает затраты.
Масштабирование «на лету»
Я недавно наткнулся на imgproxy
, компонент для изменения размеров изображений на лету:
imgproxy делает веб-сайты и приложения быстрыми и экономит место и затраты на SaaS
Он предлагает точку входа, куда можно отправить закодированный URL, определяющий:
- Изображение для изменения размера и его расположение, например, локальное, HTTP-URL, корзина S3 и т. д.
- Различные параметры масштабирования, например, размеры, соответствие или заполнение и т. д.
- Формат.
imgproxy
поддерживает стандартные форматы, такие как JPEG и PNG, а также более современные, такие как WebP и AVIF. Он также может выбрать лучший формат в зависимости от заголовка «Прием». - Множество (множество!) других параметров, таких как водяные знаки, фильтрация, поворот и т. д.
imgproxy
предлагает как свободную версию с открытым исходным кодом, так и платную версию; все, что включено в эту статью, является частью первого.
Одним из решений было бы веб-разработчику кодировать каждый URL imgproxy
в HTML:
Это приводит к утечке связанных с топологией деталей на веб-странице. Это не поддерживаемое решение. Мы можем решить эту проблему с помощью обратного прокси или шлюза API. Я буду использовать Apache APISIX по очевидным причинам.
С таким подходом вышеуказанный HTML становится намного проще:
Apache APISIX перехватывает запросы, начинающиеся с /resize
, изменяет URL для imgproxy
и пересылает измененный URL в imgproxy
. Вот общий ход:
Соответствующая конфигурация Apache APISIX выглядит следующим образом:
- Сопоставляйте запросы с префиксом
/resize
- Переписывайте URL
- Отлавливайте ширину и изображение с помощью регулярного выражения
- Форматируйте URL для
imgproxy
.http://server:3000
– это сервер, на котором находится исходное изображение;@webp
указывает предпочтение формату WebP (если браузер его поддерживает)
С помощью указанного выше кода, /resize/200/ai-generated.jpg
на Apache APISIX переписывается как /rs:fill/w:200/plain/http://server:3000/ai-generated.jpg@webp
в imgproxy
.
Тестирование
Мы можем создать небольшой тестовый пример с помощью Docker Compose:
- Простой веб-сервер, на котором размещены HTML и основное изображение
Теперь мы можем протестировать указанную выше настройку с помощью инструментов разработчика браузера, эмулируя устройства с маленьким экраном, такие как iPhone SE. Результат следующий:
- Из-за разрешения экрана запрашивается изображение шириной 400 пикселей, а не оригинальное. Вы можете увидеть это в URL запроса
- Возвращаемое изображение имеет формат WebP, его размер составляет 14.4 КБ
- Оригинальное изображение в формате JPEG весит 154 КБ, более чем в десять раз больше. Это значительная экономия пропускной способности сети!
Обсуждение
Сокращение затрат на хранение в десять раз, конечно, является большим преимуществом. Однако, не все так радужно. Создание измененного изображения требует вычислительных ресурсов, и каждый запрос требует затрат процессорного времени. Более того, несмотря на эффективность imgproxy
, создание изображения занимает некоторое время. Мы поменяли затраты на хранение на затраты на процессорное время и теперь сталкиваемся с небольшим снижением производительности.
Чтобы исправить это, нам нужен прокси-кэш спереди, либо настраиваемый, либо, скорее всего, CDN. Вы можете возразить, что мы снова будем хранить ресурсы, и затраты на хранение снова вырастут. Однако существенное отличие состоит в том, что кэш работает только для используемых изображений, в то время как в предыдущем решении мы платили за хранение всех изображений. Также можно применять известные методы кэширования, такие как “предварительная загрузка” (pre-warming), когда известно, что группа изображений будет активно использоваться, например, перед событием.
Заключение
В этой статье мы описали, как использовать Apache APISIX с imgproxy
, чтобы снизить затраты на хранение изображений разных разрешений. С использованием кэширования, мы добавляем еще несколько компонентов в общую архитектуру, однако сокращаем затраты на хранение.
Эта статья была вдохновлена докладом Андреаса Лера на конференции StackConf.
Полный исходный код для этой статьи можно найти на GitHub.