Формат WebP

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

Алгоритм сжатия с потерями WebP основан на методе, который видеокодек VP8 использует для сжатия ключевых кадров в видео. На высоком уровне это похоже на кодирование JPEG: WebP работает в терминах «блоков», а не отдельных пикселей, и имеет аналогичное разделение на яркость и цветность. Блоки яркости в WebP имеют размер 16x16, а блоки цветности 8x8, и эти «макроблоки» дополнительно делятся на подблоки 4x4.

Радикальное отличие WebP от JPEG заключается в двух особенностях: «предсказание блоков» и «адаптивное квантование блоков».

Предсказание блоков

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

По правде говоря, и PNG, и JPEG тоже в той или иной степени выполняют подобное предсказание. Однако WebP уникален тем, что он берёт образцы данных из окружающих блоков, а затем пытается заполнить текущий блок с помощью нескольких различных «режимов предсказания», фактически пытаясь «нарисовать» недостающую часть изображения. Результаты, полученные в каждом режиме предсказания, сравниваются с реальными данными изображения и выбирается наиболее близкое к ним предсказание.

Конечно, даже самое близкое предсказание не будет полностью верным, поэтому различия между предсказанными и фактическими значениями блока кодируются в файле. При декодировании изображения механизм отображения использует те же данные для той же логики прогнозирования, что приводит к тем же прогнозируемым значениям для каждого блока. Разница между предсказанием и ожидаемым изображением, которое было закодировано в файле, затем применяется к предсказаниям. Это работает подобно записи изменений в репозиторий Git, который представляет собой патч, применяемый к локальному файлу, а не совершенно новую копию файла.

Для иллюстрации: вместо того чтобы вникать в сложную математику, связанную с настоящим алгоритмом предсказания, мы придумаем кодирование подобное WebP с одним режимом предсказания и будем использовать его для эффективной передачи сетки чисел так же, как мы это делали с устаревшими форматами. Наш алгоритм имеет единственный режим предсказания, который мы назовем «режим предсказания один»: значение каждого блока — это сумма значений блоков, расположенных над ним и слева от него, начиная с 1.

Теперь предположим, что мы начинаем со следующих реальных данных изображения:

111151111
122456389

Используя нашу прогнозирующую модель для определения содержимого сетки 2x9, мы получим следующий результат:

111111111
123456789

Наши данные хорошо подходят для изобретённого нами алгоритма: прогнозируемые данные очень близко соответствуют нашим реальным данным. Конечно, это не идеальное совпадение — фактические данные содержат несколько блоков, которые отличаются от прогнозируемых данных. Итак, отправляемая нами кодировка включает в себя не только используемый метод прогнозирования, но и разницу любых блоков, которые должны отличаться от их прогнозируемых значений:

_ _ _ _ +4 _ _ _ _
_ _ -1 _ _ _ -4 _ _

Выражаясь простым языком, как и некоторые кодировки старых форматов, которые мы обсуждали:

Сетка 2x9 использует режим предсказания один. +4 к 1x5, -1 к 2x3, -4 к 2x7.

В итоге получается невероятно эффективный закодированный файл.

Адаптивное квантование блоков

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

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

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

Размер файлов обоих изображений примерно одинаков. Когда мы смотрим на крылья монарха, качество примерно схожее — если присмотреться внимательно, можно заметить несколько крошечных различий в конечном результате, но реальной разницы в общем качестве нет. В WebP цветы молочая чуть более резкие — опять же, скорее всего, не настолько, чтобы это было заметно, если только вы не сравниваете два снимка рядом и не ищете разницу в качестве, как это делаем мы. С фоном совсем другая история: на нем почти нет следов очевидных артефактов JPEG. WebP даёт нам тот же размер файла, но гораздо более качественное изображение — плюс-минус несколько крошечных деталей, которые наши психовизуальные системы не смогли бы обнаружить, если бы мы не сравнивали их так внимательно.

Использование WebP

Внутреннее устройство WebP может быть значительно сложнее, чем кодирование JPEG, но столь же простым для целей нашей повседневной работы: вся сложность кодирования WebP стандартизирована вокруг одного значения «качество», выражаемого в пределах от 0 до 100, как и в JPEG. Опять же, это не значит, что вы ограничены единственным универсальным значением «качества». Вы можете и должны возиться со всеми тонкостями кодирования WebP, хотя бы для того, чтобы лучше понять, как эти обычно невидимые параметры могут влиять на размер и качество файла.

Google предлагает кодировщик cwebp для командной строки, который позволяет конвертировать или сжимать отдельные файлы или целые каталоги изображений.

$ cwebp -q 80 butterfly.jpg -o butterfly.webp

Saving file 'butterfly.webp'
File:   butterfly.jpg
Dimension: 1676 x 1418
Output: 208418 bytes Y-U-V-All-PSNR 41.00 43.99 44.95   41.87 dB
        (0.70 bpp)
block count:    intra4:     7644  (81.80%)
               Intra16:     1701  (18.20%)
               Skipped:       63  (0.67%)
bytes used:  header:            249  (0.1%)
              mode-partition:  36885  (17.7%)
Residuals bytes  |segment 1|segment 2|segment 3|segment 4|  total
macroblocks:     |       8%|      22%|      26%|      44%|   9345
quantizer:       |      27 |      25 |      21 |      13 |
filter level:    |       8 |       6 |      19 |      16 |

Если вы не тяготеете к командной строке, Squoosh также подойдёт для кодирования WebP. Это даёт возможность параллельного сравнения разных форматов, параметров, уровней качества и различий в размере файла по сравнению с JPEG.

Автор: Мэт Маркиз
Последнее изменение: 20.05.2024