Оптимизируем графику с помощью WebP

Блог разработчика интерфейсовКакая сейчас неделя? Какая сейчас учебная неделя? Четная или нечетная?

По данным сайта Web Perfomance Today, средний вес страницы в 2015 году 1109 КБ. По прогнозам, к 2018 будет около 2 МБ. Загрузка изображений занимает в среднем 64% (711 КБ) всего времени загрузки страницы. Поэтому начинать оптимизацию скорости загрузки страницы нужно именно с графики.

Графика оптимизируется в двух направлениях:
  • уменьшение количества запросов
  • уменьшение веса графики

Для уменьшения запросов используются спрайты и вставка графики в через base64. Для уменьшения веса графика сжимается (с и без потерей качества).
К сожалению, сжатие часто приводит к плохому качеству и небольшому выигрышу в размере. Возможно поэтому Google в 2010 году создал свой формат сжатия изображений — WebP.

Поддержка


Поверим Can I Use, который говорит что WebP поддерживается на 64,77% в мире и 56,22% в России, что дает нам основание использовать его. Из браузеров это Chrome, Opera, Opera Mini, Android Browser, Chrome for Android.

Тестируем сжатие


Перед использованием WebP, проверим насколько это эффективно. Я скачал по 12 изображений png и jpg. И сравнил размеры до и после оптимизации:

  • Оригинальные файлы — 6,7 МБ
  • После сжатия — 5,4 МБ
  • Оригинальные в формате WebP — 1,6 МБ
  • После сжатия в формате WebP — 1,8 МБ


Выигрыш в размере получился 3.8 МБ, т.е 70.3%. Поскольку изображения в среднем это 64%, то выигрыш в скорости загрузки страницы составит ~44.8% для пользователей, чьи браузеры поддерживают WebP!

Используем WebP


Использовать новый формат можно через тег img и через css свойство background. Конечно не забудем про пользователей без поддержки этого формата.

Чтобы определить поддержку WebP, можно воспользоваться Modernizr или снипетом. После этого написать fallback:

.no-webp .logo { background-image: url(logo.png); }
.webp .logo { background-image: url(logo.webp); }

Через img казалось бы можно тоже сделать два изображения, и скрывать одно из них. Но проблема в том, что браузер все равно запросит и PNG и WebP, что наоборот увеличит время загрузки страницы.

Еще один способ — запрашивать изображение в формате WebP, если оно не загрузится, то показывать PNG.

<img src="image.webp" onerror="this.onerror=null; this.src='image.png'">

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

Другой вариант


Не найдя нативного решения, я написал небольшую библиотеку simple-webp, которая решает проблему двух запросов.

Пример использования:
  • Добавить в шапку
    <script async src="simple-webp.min.js">
  • Вместо стандартных изображений, написать по шаблону
    <noscript data-webp><img src="example.png" alt=""></noscript>


Библиотека проверяет поддержку формата WebP, после этого добавляет/убирает класс webp/no-webp к html и если браузер поддерживает WebP, то библиотека заменит расширение вашего изображения на .webp и загрузит его. Иначе браузер загрузит изображение в оригинальном формате.

К примеру если браузер поддерживает WebP, то вместо example.png загрузится example.webp, если нет — example.png.

Noscript необходим для предотвращения загрузки изображений, и если JavaScript будет отключен, пользователь все равно увидит изображение.

Библиотека находится в публичном доступе на Github, занимает 2 КБ в несжатом виде.

P.S. В примерах для оптимизации я использовал приложение под OS X — ImageOptim. Для конвертации в WebP — WebPonoize.

P.S.S. Скачать архив с изображениями, на которых я производил сравнение можно по ссылке.


UPD #1 В комментариях VEG указал на некорректно проведенный тест, и предоставил ссылки тесты от Mozilla 2013 и 2014 года. В них видно что уровень сжатия у WebP и других форматов примерно на одном уровне. Профит от WebP в том, что при сильном сжатии изображения выглядят лучше.

UPD #2 Способ через NOSCRIPT имеет большой недостаток в SEO, т.к. картинки не проиндексируются. pepelsbey в комментариях предложил использовать .
Поделиться публикацией

Комментарии 28

    0
    А ещё можно взять и настроить веб-сервер (через тот же .htaccess) и выдавать по возможности webp-изображение при его существовании и поддержке браузером пользователя. Беглый поиск по интернетам выдал что-то такое
      0
      Хотел именно это и написать, но в контексте Nginx.
      Браузер отправляет в заголовке информацию о том, что он поддерживает WebP и простой проверкой существования файла можно вернуть WebP изображение, если оно есть на сервере, при этом не меняя сами views сайта.
    • НЛО прилетело и опубликовало эту надпись здесь
        +8
        > Выигрыш в размере получился 3.8 МБ, т.е 70.3%.

        Ох, опять эти сравнения по методологии «пальцем в небо». А вы оптимизировали оригинальные изображения? Если да, то как? Для PNG хорошо подходят ImageOptim (Mac), ScriptPNG (Win). Для JPEG есть mozjpeg. Даже jpegtran может дать несколько процентов выигрыша.

        Судя по огромному выигрышу, сжатие производилось с потерями. Как оценивалась приемлемость этих потерь? Например, у JPEG это всем известные квадратики. При сжатии в WebP у меня появлялось размытие («замыливание») и искажение цветов.

        Даже PNG зачастую может получить хороший выигрыш с помощью пастеризации. При этом на глаз потеря качества будет неотличима. Или иметь незначительные отличия, но выглядеть вполне приемлемо, пользователи же не знают как должно быть :). Например, уменшив количество цветов с нескольких десятков тысяч до одной-двух тысяч для больших картинок или вообще до 256 цветов для простой графики/маленьких картинок, что позволить сохранить с палитрой а ля гифка. Это может сделать программа Color Quantizer.

        Есть хорошая статья на тему корректного сравнения методов сжатия картинок: pornel.net/faircomparison

        А как у вас дела с серверами? У вас есть в два раза больше места для картинок, и в два раза больше памяти, чтобы тот же набор картинок уместился в кеше? Или вы можете себе позволить уменьшение эффективного размера кеша в два раза? Вам ведь надо хранить две версии картинки: WebP и оригинальную.
          –2
          При переводе в WebP через командную строку есть множество настроек. Приемлемость потерь можно посмотреть в архиве. На картинках я не смог заметить разницу, возможно на длинных градиентах будет заметно. Замыливание в WebP в любом случае выглядит куда лучше квадратиков.

          На счет серверов, все такие не в 2 раза больше, а не более полутора. На счет кеша я не силен, но по моему мнению, увеличить размер сервера, чтобы увеличить скорость загрузки сайта вполне хорошая идея. Особенно для сервисов в которых доля изображений еще больше.
            +13
            Тест проведён неправильно:

            — Вы включили в набор фотографии в формате PNG (5165 килобайт, сжатие без потерь) и сравниваете их с WebP (686 килобайт, но это сжатие с потерями!).
            — Вы не оптимизировали исходные изображения в формате JPEG. В интернете большинство изображений никак не оптимизированы, и их часто можно уменьшить даже в разы без ощутимых потерь, с использованием стандартных форматов (JPEG для фотографий, PNG для схем и т.д.).
            — Вы банально даже не заметили, что часть изображений, исходники которых были в формате JPEG, стали весить больше после конвертации в WebP (j_cat1 и j_cat3).

            Ни о каких 70% выигрыша тут не может быть и речи, это обман. Хорошо, если при честном слепом тестировании WebP покажет хотя бы на 20% меньший объём при равном визуальном качестве.

            Для примера, я взял пару ваших оригинальных фотографий, сжал их в JPEG до того же объёма, что у вас получился в WebP.

            — Пример номер 1. Оригинал: j_girl3_orig.jpg (380 килобайт); JPEG: j_girl3.jpg (97 килобайт); WebP: j_girl3.webp (94 килобайт).
            — Пример номер 2. Оригинал: p_dog1_orig.png (1609 килобайт); JPEG: p_dog1.jpg (91 килобайт); WebP: p_dog1.webp (91 килобайт).

            Качество получилось сравнимым. Что в случае с вашими WebP, что в случае с моими оптимизированными JPEG, я вижу небольшие отличия в равном количестве, если буду присматриваться. То есть что JPEG, что WebP дали примерно одинаковый результат.
              –1
              Вы сейчас спорите, пытаясь определить уровень потерь «на глаз».
              Но сейчас уже есть множество алгоритмов, показывающих меру субъективного сходства между изображениями, отлично коррелирующих с субъективными оценками.
              Один из самых простых приёмов — использование SSIM метрики.
              Также могу посоветовать использовать такую программу, как MSU Quality Measurement Tool, если нужно больше метрик, хороших и разных (рекомендую 3-Component SSIM).
                +8
                Где вы здесь увидели спор? Тест проведён отвратительно, и я указал в каких именно моментах он проведён неправильно, и почему заявление про выигрыш 70% — чистой воды обман и подтасовка фактов. Также я показал, что JPEG при том же объёме выглядит примерно так же, как и WebP. Это сравнение не претендует на роль «ответного тестирования», это просто демонстрация того, что и обычный JPEG есть куда оптимизировать, чего автор даже не попытался сделать.

                Если вам интересен более-менее серьёзный тест форматов сжатия с потерями, можете изучить соответствующие тесты, проведённые Mozilla: октябрь 2013 года и июль 2014 года. Как видно, JPEG держится достойно и часто показывает результат даже лучше, чем WebP. А вот HEVC-MSP выглядит действительно перспективным. Жалко, что он запатентован по самое не хочу, и скорее всего мы не увидим его в браузерах.
                  +2
                  Спасибо за проведенную проверку, я понадеялся на ImageOptim, чего не надо было делать. Отдельное спасибо за ссылки на тесты. А как вам формат BPG? При сильном сжатии очень хорошие результаты показывает.
                    0
                    Это по сути и есть HEVC-MSP, просто со своим заголовком.
                      +1
                      А JPEG я сохранял через Save for Web без различной мета-информации в Photoshop CS2 (эту устаревшую, но рабочую версию программы плюс ключи к ней можно скачать прямо на сайте Adobe после регистрации). Такое сжатие хорошо тем, что можно сразу увидеть результирующее визуальное качество и примерный объём файла после сжатия. После Photoshop файл можно ещё дожать (без дополнительных потерь в качестве) при помощи jpegtran из набора mozjpeg командой:

                      jpegtran -copy none -optimize -outfile output.jpg input.jpg

                      В принципе, это можно и автоматизировать при желании.
              +3
              Вы пастеризацию и постеризацию сейчас перепутали.
                0
                Ну на счёт качества — это субъективно.
                На счёт места — не так и много то выходит. Если у Вас даже 500 гигов графики (ого подумал я) и Вы таки решили оптимизировать и хранить ещё WebP, то вы потратите не ещё 500 гигов, а, скажем, +300/+400.
                Да, это затраты, но если это решение поможет вашему ресурсу грузиться на 20-30% быстрее, что скажем принесёт Вам увеличение Вашей аудитории сайта на 8% и эти 8% с головой покрывают Ваши расходы на доп. дисковое пространство. То почему бы и нет? Лично мне приятно делать людям хорошо и уменьшать их время ожидания загрузки сайта.
                  0
                  Обычно еще и -x2/x3/x4 (retina), если не использовать zoom:
                  Добавим превью в 2-х вариантах (минимум).
                  Добавим кэш с водяными знаками.
                  Добавим разъяренных («продвинутых») пользователей, дядь Валер с Урюпинска, не понимающих, как сохранить картинку себе в каталог на excel.
                  И получим 100500 охренебайт картинок, БЭКАПОВ картинок, зоопарк mime-type и вот это всё выше.
                  Нет. Спасибо. Я уж как-нибудь с жипег поживу и content-encoding: gzip на png.
                  0
                  Оригинальные в формате WebP — 1,6 МБ
                  После сжатия в формате WebP — 1,8 МБ

                  То есть больше стало? Или ошибка?
                    0
                    Именно так, не ошибка.
                    Когда-то читал почему так происходит, но сейчас ссылку не могу найти.
                      +1
                      артефакты жпег весят много. вот и все.
                    +5
                    Если сопоставить браузеры, поддерживающие WebP и браузеры, подерживающие <picture>, то получится хорошее пересечение. Почему бы вместо скрипта не воспользоваться возможностями HTML? Фолбечится это на «ура»: не знаешь <picture> — берёшь <img>

                    <picture>
                    	<source srcset="opera.webp" type="image/webp">
                    	<img src="opera.jpg" alt="The Oslo Opera House">
                    </picture>


                    WebP и Picture:



                    Вот вам пара статей про <picture> на Dev.Opera для изучения:

                    Native Responsive Images
                    Responsive Images: Use Cases and Documented Code Snippets to Get You Started
                      0
                      Мне очень нравится эта идея, нужно обязательно протестировать.
                      Спасибо большое.
                      • НЛО прилетело и опубликовало эту надпись здесь
                        +1
                        Фолбек через srcset не cработает разве?
                        Зачем тащить лишние скрипты?
                          +1
                          Очень грамотно написано «Поэтому начинать оптимизацию скорости загрузки страницы нужно именно с графики.», почему то многие про это забывают когда делается оптимизацию «для галочки». Я использую ImageOptim на Mac, FileOptimizer для Windows и svgo-gui для векторной графики(можно запускать и как задачу в grunt, но надо следить за каждым файлом). На одном блоге который я администрировал, запустив ImageOptim на ночь, утром получил суммарную оптимизацию на 70 мегабайт.
                          0
                          И опять я напомню про довольно странную позицию Mozilla, по сути ограничивающую прогресс — webp это не только сжатие данных, но еще и современный формат анимации, на замену древнему GIF. Однако, ввиду каких-то своих непонятных целей Mozilla встала в позу и излагает позицию «только через мой труп», что выглядит очень плохо с их стороны. Вот два бага по подержке WebP в Firefox. Первому багу уже 5 лет, они его закрыли, чтобы люди не читали неудобные для Mozilla комметарии, и ограничили комментирование во второй. Просьба всем сочувствующим поддержке WebP пинать Mozilla по другим каналам.

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

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

                          P.S. Напомню, что из-за этой глупой позиции Mozilla некоторые крупные сайты были вынуждены добавить поддержку анимации в виде коротких MP4 и WebM роликов.
                            0
                            А я напомню про странную позицию Google. Почему они не поддержит APNG? Который, к тому же, имеет отличный fallback в виде статичной картинки в браузерах без поддержки этого формата. Причём, судя по этому тесту, APNG часто справляется с задачей лучше, чем анимированный WebP.

                            Разработчиков Chromium с 2008 года просят об этом, то есть уже 7 лет как. Но эти 5 лет назад закрыли обсуждение этого бага. Энтузиасты даже предлагали готовые рабочие патчи. Поскольку это лишь небольшое обновление поддержки уже существующего формата, лишнего кода это добавляло немного.
                              0
                              Кстати вот, Max Stepin совсем недавно в очередной раз актуализировал свой патч под текущий код движка. Как видите, изменений в коде не очень много. Разработчики Chromium пока что не реагируют.

                              Складывается впечатление, что там имеют место быть какие-то детские обиды. Поддержка APNG незначительно увеличивает существующий код, зато элегантно решает существующую проблему. Почему Google с 2008 года игнорирует его — не ясно. Даже Apple сдалась и APNG поддерживается в Safari, ну и в Webkit тоже. Было бы хорошо, чтобы Google поддержала APNG, а Mozilla в ответ — WebP. Тут дополнительного кода, конечно, будет на порядок больше, ибо это совершенно отдельный формат, но часть нужного кода в Firefox уже имеется, ведь WebP имеет много общего с WebM/VP8.
                              0
                              Думаю, не всё так просто как кажется.
                              Анимация в виде MP4 ролика — что в это плохого? А кодек так какой?)
                                0
                                Таки да, h264 или VP8 справятся с короткими видео лучше, чем WebP или APNG. И здесь тоже победителем вышел h264. Сама Google этому способствовала.

                                Проследите сами:
                                — Январь 2011, Google обещает удалить поддержку h264 в Chromium.
                                — Mozilla последовательно игнорирует существование h264 в пользу свободных форматов и ждёт обещанного от Google. Но Google и не думает совершать обещанное.
                                — В результате Mozilla вынуждена также поддержать h264, что и сделала спустя 2 года, в 2013 году.

                                Итого WebM/VP8 проиграл, а MP4/h264 выиграл, поскольку именно последний поддерживается всеми. И мне совершенно не ясно, зачем Google было устраивать всю эту показуху с WebM/VP8, тратить на это столько денег, если они сами не были настроены на его решительное продвижение.

                              Только полноправные пользователи могут оставлять комментарии. Войдите, пожалуйста.

                              Самое читаемое