WebP — сравнительно новый формат от Google. Картинки в этом формате занимают на 30% меньше места на странице благодаря особому сжатию, построенному на кодировании ключевых кадров в видеокодеке VP8.

WebP поддерживает сжатие с потерями и без, разные степени прозрачности, метаданные и может содержать встроенный ICC-профиль. Но пока не все браузеры и приложения поддерживают формат.

image


Как устроено сжатие в WebP


Сжатие с потерями основано на утверждении, что яркость и цвет соседних пикселей мало отличаются друг от друга.

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

После математически обратимого преобразования (с помощью ДКП) результат подвергается квантованию и энтропийному кодированию.

image

Lossy WebP


В lossy WebP используется арифметическое кодирование — один из алгоритмов энтропийного сжатия. В WebP используется блочное квантование и биты распределяются адаптивно между различными фрагментами изображения: меньшее количество бит для фрагментов с низкой энтропией и большее — для фрагментов с высокой. Такое кодирование считается более гибким, чем код Хаффмана (который использует JPEG).

JPEG делит изображение на одинаковые блоки, а технологии кодирования WebP использует умное деление. В тех частях картинки, где есть много мелких и быстро изменяющихся деталей блоки имеют размер 4 х 4 пикселя, а в монотонных областях — 16 х 16.

image

Как происходит прогнозирование


Декодер VP8 имеет 2 класса прогнозирования:

  • Intra — внутрикадровое пространственное предсказание блока на основе значений пикселей из соседних, уже закодированных блоков, слева и сверху.
  • Inter — межкадровое временное предсказание (оценка векторов движения).

Intra имеет четыре алгоритма прогнозирования для блоков 16х16 и 8 для детализирующих блоков 4 х 4:

  • H_PRED горизонтальное прогнозирование. Заливает следующую колонку на основе той, что находится слева от нее.
  • V_PRED вертикальное прогнозирование. Заливает следующий ряд на основе предыдущего верхнего.
  • DC_PRED заполняет блок, используя усредненные значения цвета и яркости пикселей строки
  • TM_PRED заполняет блок, используя не только усредненные значения строки A и колонки L, но и пиксель P, который находится сверху и слева от блока. Каждая строка начинается с пикселя в колонке L и заполняется в соответствии с различиями пикселей в колонке, начиная от пикселя P.

Изображение разбивается на сегменты, которые имеют явно схожие характеристики. Для каждого такого сегмента параметры сжатия и способы прогнозирования настраиваются независимо. Таким образом биты перераспределяются туда, где они наиболее полезны.

image

Сжатие без потерь


При сжатии без потерь используется вариант алгоритма LZ77 — кода Хаффмана. А также пространственное прогнозирование и преобразование цветового пространства.

Не только прогнозирование


Сжатие с альфа-каналом

Формат WebP позволяет получить сжатую картинку с альфа-каналом без потерь. Раньше, чтобы получить прозрачность все изображение должно было быть lossless. А в WebP можно уменьшить вес картинки с прозрачными областями.

Цветовое преобразование

Также в WebP используется методы адаптивного квантования цветовой составляющей, чтобы предотвратить влияние цветовых каналов друг на друга. Изображение делится на блоки и для каждого блока применяется свой режим трансформации green_to_red, green_to_blue или red_to_blue. Цветовое преобразование сохраняет неизменным значение зеленого канала G, преобразует красный R в зависимости от зеленого, и синий В в зависимости от зеленого, а затем в зависимости от красного.

Цветовое кеширование

Сжатие lossless WebP использует уже обработанные фрагменты изображения для работы с новыми пикселями. В случае если подходящие совпадения не найдены, используется локально созданная палитра. Эта палитра постоянно обновляется цветами, найденными при сканировании картинки.

Индексирование палитры

Если в картинке используется менее 256 цветов, алгоритм создает отдельный массив индексов цветов и сохраняет его отдельно, чтобы подменить значение цвета на индекс для каждого пикселя.

Для картинок с небольшим количеством мелких деталей используется технология апскейлинга. Прежде чем кодироваться — изображение ресайзится.

Статья написана на основе этого материала. А попробовать webp сжатие можно тут.

Конспект


  1. В WebP картинка делится на макроблоки. Блоки размером 4х4 px для мелких деталей и 16х16 для монотонных областей.
  2. Внутри каждого макроблока декодер предсказывает яркость и цвет каждого следующего пикселя на основе ранее полученных.
  3. В lossy WebP используется арифметическое кодирование, а в lossless — код Хаффмана.
  4. WebP позволяет получить сжатую картинку с альфа-каналом без потерь.

Комментарии (23)


  1. mkarev
    04.07.2015 20:44
    +4

    Декодер VP8 имеет 2 класса прогнозирования:

    Intra — внутри одного макроблока
    Inter — прогнозирование на основе соседних макроблоков

    <зануда>
    Intra — внутрикадровое пространственное предсказание блока на основе значений пикселей из соседних, уже закодированных блоков, слева и сверху.
    Inter — межкадровое временное предсказание (оценка векторов движения).
    </зануда>


    1. moccachin Автор
      05.07.2015 14:13
      -1

      Спасибо) Я поправлю, так даже лучше!))))


  1. ooprizrakoo
    04.07.2015 20:53
    -1

    Мне кажется, что подобное изобретение имеет несколько двоякое значение: с одной стороны, появление формата с более эффективным сжатием это хорошо. Но…
    Изобретение сжатия на 30% более эффективного сжатия графики напоминает ситуацию с 2,5 дискетами: при стандарте 1.44 мегабайта был изобретен способ записи 2х мегабайт на ту же магнитную площадь. Но это была эпоха середины-конца 90х, и изобретение оказалось никому не нужным.
    Или — на смену компакт и двд-дискам пришли блюрей диски — но и для них момент оказался безнадежно упущенным — в эпоху широкополосного интернета практически все что угодно можно скачать.

    Если сейчас попробовать взвесить данную страницу, на ней 59 кб занимает хтмл, 327 килобайт — жаваскрипт, и всего 139 килобайт — графика.
    Имхо, не то место Гугл решил оптимизировать. Напрашиваются мысли, что нам хотят навязать ещё один формат, чтобы Гугл смог контролировать из под себя ещё одну область интернет-стандартов.


    1. iDennis
      04.07.2015 21:11
      +2

      А если на сервере?


      1. ooprizrakoo
        05.07.2015 09:47
        -3

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


        1. khim
          05.07.2015 16:58
          +1

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

          Картинки, конечно, удаляются — когда придёт пора. Пока у вас удалённых данных мало — их действительно проще пометить как удалённые и не трогать. Но, конечно, если удалённых данных станет достаточно, то данные копируются с одного сервера на другой — но, разумеется, копируются только неудалённые данные.

          Но все эти детали не важны. Краевые эффекты могут иметь значение когда у вас серверов мало, но когда их много, то всё проще: если у вас для хранения картинок нужны сервера стоимостью $1'000'000, то их уменьшение на 30% обозначает экономию ~$300'000, точка.


    1. x4fab
      04.07.2015 22:15
      +2

      Скрипты-то обычно одни и те же со странички на страничку и отлично кешируются, а вот картинки нет. К тому же на данной странице графики-то особо и нет.


      1. ooprizrakoo
        05.07.2015 09:54
        -3

        Забавно, что на этой странице есть графика (ну, более-менее в среднем количестве для обычной интернет-странички), однако формат файл используется неоптимальный — верхняя картинка с шестеренками представляет собой jpg-файл, занимающий 80 кб, вместо которого было бы выгоднее использовать gif-файл (двухцветный черно-белый), в этом случае файл весил бы в два раза меньше, а выглядел бы более четко, без размытых краев.


    1. kAIST
      05.07.2015 03:13
      +2

      Давайте уж сразу в bmp или в png фотографии хранить, чтоб без потерь. Чего уж там, терабайтные винты и стомегабитные каналы есть у многих. Выше правильно сказали — если у тебя пару сотен килобайт графики, то разницы нет. А вот если гигабайты или терабайты (взять к примеру соцсети), то выигрыш может быть приличным.


    1. erlyvideo
      05.07.2015 10:41

      именно так. Именно для этого же гугл устроил шумиху вокруг закрытого и ужасного vp8, назвав его «открытым» в отличие от открытого h264.


  1. XaLBa
    04.07.2015 21:07

    Предположу, что там ещё есть постфильтрация для подавления блочности. По крайней мере, в VP8 она есть, и странно было бы её не использовать в WebP.


  1. xvilka
    05.07.2015 00:02
    +4

    Тем временем какую только фигню не встраивает в свой браузер Mozilla, включая проприетарный Pocket, Hello на базе патентов Telefonica и DRM, а нежелание добавлять поддержку WebP объясняет его «нестабильностью». Была бы достойная независимая альтернатива (не форк) — давно уже бы перешёл. Остается только надеятся на лучшее.

    [1] bugzilla.mozilla.org/show_bug.cgi?id=600919

    [2] bugzilla.mozilla.org/show_bug.cgi?id=856375


  1. Nomad1
    05.07.2015 10:58
    +1

    Нужна ли подобная статья про формат текстур PVRTC, включая C++ Neon/SSE код для программной распаковки?


    1. Biga
      05.07.2015 22:35

      Статья будет весьма полезна.

      Заодно можно рассказать, как избавиться от артефактов в альфа-канале, переключая блоки на второй режим модуляции, в котором есть «прозрачная» модуляция. Сделал себе такую штуку, работает отлично.


  1. Alex222
    05.07.2015 14:35
    -3

    Есть ведь png, он как раз для хорошего сжатия, без потерь. Зачем тогда WebP.


    1. deNULL
      05.07.2015 19:17

      Второе предложение в статье.

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

      На 30% меньше места, чем именно PNG с «хорошим сжатием».


      1. PsyHaSTe
        06.07.2015 08:02

        Я думал, ключевые кадры могут быть только в видео. Или речь о формате движущихся картинок, как в gif? Так там вроде новый формат на основе mp4 замутили, если мне память не изменяет… Можно поподробнее?


        1. deNULL
          06.07.2015 20:03

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


        1. erlyvideo
          07.07.2015 09:50

          речь идет о том, что сегодня h264 энкодер свои опорные кадры сжимает лучше, чем jpeg


  1. tony2001
    05.07.2015 21:37
    +1

    Мы тестировали (тестируем) WebP на продакшене, по моим данным «в среднем по больнице» картинки WebP на 50% меньше по объёму, чем JPEG при неотличимом на глаз качестве. Для мобильных пользователей социальных сайтов, где картинки составляют основную часть трафика — это серьёзное улучшение.
    Единственная проблема — исходное изображение в JPEG, поэтому за трафик приходится платить CPU при перекодировании (ну или хранить и JPEG, и WebP рядом).


  1. Apetrus
    06.07.2015 10:12
    +1

    Я использую WebP формат в мобильных играх, что значительно сократило конечный размер билда — примерно в два раза. Раньше приходилось использовать libjpegturbo для непрозрачных картинок и libpng для прозрачных, теперь все что нужно есть в WebP. Собирается libwebp отлично и под iOS, и Android, 32bit и 64bit. Время кодирования и декодирования также вполне приемлемое. Приятным сюрпризом оказался скейлинг картинки на лету при декордировании, время декодирования при даунскейлинге сокращается. Есть еще интересный формат BPG. Размер картинки в BPG меньше примерно на 10-20% чем WebP и на картинках с градиентом результат лучше. Но есть и минусы:
    1) декодирование примерно в два раза дольше чем WebP, кодирование вообще раз в 10 дольше.
    2) на картинках с мелкими деталями BPG начинает их «смазывать».
    3) чтобы собрать под моб. платформы придется повозиться.
    Конечно в «узких» местах все равно необходимо использовать сжатые текстуры (pvrtc, etc1, s3tc), но для большинства арта, UI, заставок и прочего оформления WebP пока что остается лидером.


    1. Biga
      07.07.2015 22:41
      +1

      Может вы это уже сделали, но на всякий случай напишу. Если заглянуть в настройки кодирования WebP, то там есть параметр, отвечающий за степень сжатия. Можно установить этот параметр так, что сжимать будет дольше, но файл получится меньше размером. По умолчанию сжимает не на максимум, зато быстро. Ещё есть какой-то параметр про сжатие альфы, я его тоже установил на максимум на всякий случай, но не замерял, даёт ли это эффект.
      Как-то так:

      WebPConfig config;
      WebPConfigPreset(&config, WEBP_PRESET_DEFAULT, 100);

      config.lossless = 1;
      config.method = 6; // best quality, slow.
      config.alpha_filtering = 2; // best, slow.


      1. Apetrus
        08.07.2015 08:37

        Да да, именно так и делаю при сжатии на компе командой
        cwebp image.png -m 6 -alpha_filter best -o out.webp