Вторая часть перевода статьи наших зарубежных коллег-марсиан, в которой мы продолжаем разбираться в веб-графике и оптимизации
Чёткость до последнего байта: как делать веб-графику хорошо. Часть 2
Сибирикс
Чёткость до последнего байта: как делать веб-графику хорошо
По-серьезному о графике в интернетах: основы форматов изображений, инструменты для оптимизации и то, как люди воспринимают веб-графику

Перевод. Часть 2
В предыдущем посте вы узнали, почему не все пиксели равны, критерии качества изображений и почему те иногда «шакалятся», а еще познакомились с SVG-форматом поближе. Сегодня продолжаем тему — расскажем о растровых форматах графики в интернете и поговорим о сжатии изображений. Оригинал статьи авторства Полины Гуртовой, Риты Клубочкиной и Энди Барнова ищите в блоге Evil Martians.
~
Что такое сжатие изображений?
У нас есть изображение размером 1000×1000 пикселей. Мы можем представить каждый пиксель четырьмя числами: три для цвета и одно для прозрачности. Каждое число — это один байт. Итого: 4 * 1000 * 1000 * 1байт — это 4 МБ необработанных данных изображения (довольно много). Нам нужно сжать изображение перед отправкой в браузер, а браузер должен декодировать его обратно.

Алгоритмы сжатия бывают «без потерь» и «с потерями»: первый способ гарантирует, что пиксели, из которых состоит изображение, будут точно соответствовать оригиналу, а второй будет ухудшать качество изображения для экономии места.

Сжатие обрабатывается кодировщиками — программами, которые используют набор алгоритмов, работающих с исходными данными изображения на разных этапах сжатия. На некоторых из этих этапов исходные данные могут быть отброшены, что приведет к сжатию с потерями (кстати, описанное выше уменьшение масштаба также приводит к потерям).

Создавая цифровой продукт, вам необязательно знать математику алгоритмов сжатия. Все, что нужно знать, — что выбор энкодера, его настройки и количество его запусков приведут к изменению визуального качества. А уж насколько это будет приемлемое изменение, зависит от вашего контекста.

Идеальной компрессии не бывает — есть только та, которая подходит для вашего случая.

Разные энкодеры в действии:
Кекс, экспортированный из Sketch. Кекс с кодировкой OptiPNG, весит на 21% меньше предыдущего
Поваренная книга сжатия

Авторы статьи потратили недели на эксперименты со сжатием растровых изображений — все приведенные ниже советы не претендуют на стандарты, но с визуальной точки зрения дают оптимальные результаты.

Вот инструменты в вашем распоряжении:

  • Любой графический редактор (Adobe Photoshop, GIMP, Figma, Sketch) имеет просто космическую панель параметров для сжатия. Но если у вас много изображений, обработка каждого из них отдельно в (чаще всего) дорогостоящем ПО не слишком оптимальна.

  • Если вы пользователь Mac, преспокойно остановитесь на ImageOptim (бесплатно, с открытым исходным кодом), который также доступен онлайн (платно). Он имеет простой интерфейс drag-n-drop, не перегружает вас кнопками и ползунками и идет вместе с плагином Sketch. К сожалению, ImageOptim вообще не поддерживает прогрессивный JPEG.

  • ImageMagick может не только оптимизировать, но и обрезать, изменять размеры, вращать, корректировать цвета, применять специальные эффекты к изображениям всех возможных форматов, создавать прогрессивные JPEG-файлы и многое другое.

  • Squoosh от Google имеет расширенные параметры сжатия (с потерями и без) для изображений различных форматов, позволяет изменять их размер или регулировать цветовую палитру (больше-меньше цветов). Одно из лучших веб-приложений. Но работает только с одним файлом за раз.

  • Если вы — разработчик веб-интерфейса, работаете в экосистеме Node. js и используете упаковщики ресурсов вроде Webpack, проверьте эти библиотеки: sharp (использует молниеносную libvips-библиотеку обработки изображений) и imagemin.

  • imgproxy — это быстрый и безопасный автономный сервер, написанный на Go, который позаботится о размерах, качестве, прогрессивности и даже автоматически определит, когда вы можете использовать формат WebP. Трансформирует изображения на лету, бесплатный и с открытым исходным кодом.

  • Некоторые CDN автоматически оптимизируют изображения, распознают современные форматы изображений и конвертируют между поддерживаемыми браузерами: Cloudinary, Cloudflare, Cloudimage.
JPEG

Формат JPEG существует с 1992 года — тогда отображение 16 миллионов цветов было большой проблемой. Он использует алгоритм сжатия с потерями и хранит метаданные: размеры, цветовой профиль, EXIF (информацию о настройках камеры) и данные геолокации.

И хотя формат старый, он по-прежнему крут в прогрессивной загрузке. С ним UX не страдает даже в 2019 году (GPRS по-прежнему широко распространена в половине мира) — достаточно секунды, чтобы заметить, как Instagram или Twitter загружают ваши изображения при медленных соединениях. Чтобы проверить, прогрессивно ли JPEG-изображение, попробуйте этот супер-простой веб-инструмент.

Одна проблема: JPEG так и не научился обращаться с прозрачностью. Артефакты сжатия JPEG настолько заметны, что практически породили новую форму искусства (глитч).
Эти артефакты потери качества выглядят не очень стильно. Они могут появляться, даже если вы повторно сохраняете свое изображение много раз или просто используете JPEG для карт или схем.
Например, у вас есть картинка:
Нужно быстро прояснить контекст: это баннер, предназначенный для привлечения внимания пользователя, где изображение лимонадов является основным визуальным контентом, который должен оставаться на переднем плане. Первоначально это была фотография, сделанная цифровой камерой, поэтому JPEG выглядит идеально подходящим: нам не нужна прозрачность, и мы не слишком заботимся о резкости или деталях. Но нам все еще нужно сжать его (примерно до 80%), чтобы избежать потери качества. Нам также нужна прогрессивность для улучшения UX. Оценим варианты:
Сжатие JPEG до 80% с помощью различных инструментов
Но если подобное изображение используется в качестве фона, можно сжать качество до 25% — внимание пользователя всё равно будет на тексте переднего плана.
Фото на фоне — можно сжать сильнее
Сжатие JPEG до 80% с помощью различных инструментов
Squoosh и ImageMin имеют схожие отличные результаты (потому что они оба используют MozJPEG для сжатия и ImageMagick для квантования). ImageOptim действительно полезен, если вы не хотите добавлять прогрессивности своему изображению, но мы не видим причин, чтобы этого не делать.

Подводя итог, JPEG хорош для использования:
  • фона;
  • больших фото с профессиональной камеры: аватары, баннеры и т. д.;
  • изображений, когда сверхточное качество не нужно.


PNG

PNG, сокращение от Portable Network Graphics, — это формат без потерь, разработанный в 1996 году как превосходная замена GIF без лицензии (тогда использование GIF не было бесплатным). Формат более гибкий, чем JPEG или GIF, и поддерживает значительно больше параметров сжатия, эффективно сохраняя изображения в зависимости от количества используемых ими цветов. основные преимущества перед JPEG — поддержка прозрачности и гораздо более высокая четкость, что делает PNG идеальным для отображения компьютерной графики вроде диаграмм и схем. Растрированный текст в PNG тоже выглядит лучше.

Побочный эффект — файлы PNG обычно весят больше, чем JPEG. В реальной веб-разработке PNG часто используются, когда нужна прозрачность. Овощи на картинке ниже будут хорошо смотреться на фоне любого цвета (кроме красного и зеленого, наверное). PNG также помогает сохранить невероятно чёткими листья шпината. Посмотрим, как разные инструменты справятся со сжатием до 80%.
Сжатие JPEG до 80% с помощью различных инструментов
Чересстрочная развертка здесь не улучшает UX, так как изображение становится больше (и, следовательно, загрузка занимает больше времени). Явный победитель — ImageOptim. Так что PNG идеально подходит для:

  • изображений, которые должны быть прозрачными;
  • диаграмм, схем, очень подробных карт, где детали имеют значение;
  • изображений, содержащих текст.


WebP

WebP — самый молодой статический формат, который поддерживается большинством веб-браузеров (в 2010 году его представил Google). Возможно, единственная причина не переходить на него прямо сейчас — Safari его не поддерживает, поэтому всё ещё нужны запасные варианты PNG или JPEG для такого случая. Ну и где-то за пределами сети этот формат почти не встречается.

Но преимущества перевешивают проблемы совместимости. Результаты сжатия WebP без потерь превосходят PNG — сохраняется четкость и прозрачность изображений, а сжатый с потерями формат заставляет JPEG курить в сторонке, поддерживая прозрачность.

Если вам нужно лучшее от обоих способов, формат WebP может обрабатывать цвета с потерями, обеспечивая при этом альфа-канал без потерь. Он также поддерживает анимацию, но не слишком впечатляйтесь по этому поводу — позже расскажем, почему.

Момент триумфа WebP — это сжатие с минимально возможным качеством. WebP с качеством 0% все еще воспринимается вашими глазами намного лучше, чем JPEG с качеством 10%.
JPEG со сжатием до 10% весь в артефактах и весит 128 КБ, а сжатый до 0% WebP выглядит более плавным и весит 107 КБ
С качеством 80% изображения визуально неразличимы, но WebP значительно выигрывает в размерах на фоне JPEG. Конвертировать изображение в WebP можно всеми инструментами, кроме ImageOptim.

Для теста с потерями мы проверим картинку с лимонадами JPEG в WebP и проверим:
Конвертирование JPEG в WebP
Для теста без потерь исходным изображением будет изображение PNG с зелеными овощами выше:
Конвертирование PNG в WebP
Цифры говорят сами за себя: экономия за счет преобразования в WebP достигает 90% от исходного размера файла. Но несмотря на все технические достижения WebP, JPEG и PNG никуда не уходят, так как WebP работает только в браузерных средах: если вы сохраните такое изображение на диск, то, скорее всего, не сможете открыть его с помощью ПО для просмотра изображений по умолчанию в вашей системе.
Хаки с видео
Если все, что вас беспокоит, — это производительность, а поддерживаемостью браузера можно принебречь, используйте мощные эффективные алгоритмы сжатия видео для покадрового сжатия. Изображение на веб-странице тогда будет в виде крошечного зацикленного видеофайла, как этот:
<video src="path_to_your_one_frame_video" autoplay="true" muted>
Обратите внимание на атрибут muted — в противном случае некоторые браузеры откажутся показывать видео без дополнительной команды пользователя. Если этот экстравагантный подход для вас, взгляните на кодек AV1. Но сначала проверьте, а точно ли можете его использовать.
Анимации в сети
GIF — пожалуй, единственный широко используемый веб-форматом для анимаций: его создали в 1987 году, задолго до того, как кошачьи мемы стали мейнстримом. И поскольку он такой олдскульный, то поддерживает всего лишь 256 цветов, и его сжатие даже без потерь выглядит не очень. Причина мирового господства GIF — у мира, честно говоря, не было выбора: интернет-браузеры поддерживали GIF с первого дня. Но использование гифок для анимации на странице в 2019 году — невероятно плохая идея.

GIF действительно плохо справляется с межкадровым сжатием, которое поддерживают все современные форматы движущихся изображений. Альтернативой для GIF может быть APNG (анимированная версия PNG, разработанная в 2008 году) или анимированный WebP, созданный в 2010-м. APNG показывает лучшие результаты как по сжатию, так и по качеству, а WebP все еще может выглядеть немного размытым.

APNG имеет поддерживают почти все браузеры (кроме Microsoft Edge), поэтому это изображение, вероятно, вы увидите:
Salt Bae за делом
APNG и WebP, хотя и технически более продвинуты, имеют ту же проблему, что и GIF, когда речь идет о межкадровом сжатии. Даже GIPHY, любимый сервис анимированных мемов, обычно предлагает альтернативу — видео HTML5. Так что лучше публиковать анимационный контент в виде видеофайлов: либо MP4, либо WebM.

HTML5, MP4 и WebM видеофайлы на самом деле — просто контейнеры, в которых хранятся видеоданные, сжатые с помощью множества различных кодеков, таких как H.264 / AVC, H.265 / HEVC или AV1. В отличие от анимированных «статических» форматов, в которых хранится информация о каждом конкретном кадре, в видеоформатах хранится ряд так называемых ключевых кадров и информация об изменениях между этими кадрами — за счет этого файлы можно отлично сжимать.

Проведем тест — конвертируем GIF-картинку в WebP, APNG, AV1 в MP4, H.264 в MP4 и WebM, чтобы определить победителя. Мы будем использовать gif2webp и gif2apng, а также ffmpeg, а GIMP — в качестве альтернативного способа преобразования GIF в WebP.
Исходная гифка
Трансформирование гифки в другие форматы
Размер GIF уменьшается на 90% при использовании видеокодеков и на 67% при использовании сжатого WebP от GIMP. Поэтому, если вы хотите сделать интернет быстрее (и лучше), подумайте о том, чтобы всегда использовать MP4 в качестве анимированного изображения вместо GIF. Ведь вам не нужно быть инженером, чтобы уменьшить размер картинок в 10 раз!
Как использовать растровые изображения в вашей разметке?
Поскольку Safari не поддерживает WebP, нам нужно добавить дополнительный HTML-код, чтобы обеспечить откат к другим форматам.

Просто используйте тег <picture> вместе с атрибутом srcset:
<picture>
    <source srcset="cupcake.webp 1x, cupcake@2x.webp 2x" type="image/webp">
    <img src="cupcake.jpg" srcset="cupcake.jpg 1x, cupcake@2x.jpg 2x" alt="a yummy cupcake">
</picture>
Добавьте медиа-атрибут, чтобы добавить динамические условия, основанные на размере окна браузера:
<picture>
    <source
     media="(max-width: 799px)"
     srcset="cupcake.webp 1x, cupcake@2x.webp 2x"
     type="image/webp"
    >
    <source
     media="(min-width: 800px)"
     srcset="huge-cupcake.webp 1x, huge-cupcake@2x.webp 2x"
     type="image/webp"
    >
    ...
    <img src="cupcake.jpg" srcset="cupcake.jpg 1x, cupcake@2x.jpg 2x" alt="a yummy cupcake">
</picture>
Если вы хотите, чтобы ваше изображение выступало в качестве фона, просто используйте object-fit и object-position стили для тега <img> внутри тега <picture>.
Ну вот, теперь вы гуру по веб-графике в интернете и можете играючи выбирать разные форматы с полным пониманием дела. Поделитесь материалом с коллегами, чтобы они стали такими же умными, как вы (ну ладно, с вами-то всё равно никто не сравнится).