Это сайт — моя персональная записная книжка. Интересна мне, по большей части, история, своя жизнь и немного программирование.

Оптимизация картинок поворотом

Есть такой старый трюк, который с развитием CSS получил новое прочтение. Дело в том, что при упаковке изображения в графические форматы, в основном, сканируют и упаковывают изображение, двигаясь по его линиям слева направо. Первом об этом на русском языке написал, думаю, Лебедев, вот что написано в книге «Реактивные вебсайты», соавтором которой я являюсь:

Изображения GIF хорошо поддаются оптимизации. В параграфе №8 «Ководства» Артемия Лебедева есть небольшое, но интересное исследование особенностей этого формата. Вывод из параграфа простой: чем больше на картинке горизонтальных линий одного цвета, тем лучше сжимается изображение. Алгоритм компрессии LZW, применяемый в GIF, вообще лучше сжимает регулярные горизонтальные структуры в пределах одной линии.

Соответственно, если есть возможность повернуть картинку, то, бывает, она сжимается лучше. Где-то была хорошая статья с колесом на эту тему, не могу найти. Смысл там в том, что изображение с колесом можно поверкнуть как угодно, разницы нет, у колеса, поставленного на попа, нет «верха» и «низа», а вращение даёт возможность упаковать картинку эффективнее.

Но не всегда так везёт, гораздо чаще, согласитесь, встречаются изображения, которые повернуть нельзя. Значит о способе забываем?

Вот тут нам и пригодятся нововведения в ЦСС. Берём свою картинку, сохраняем ещё три копии повёрнутые на 90°, 180° и 270°, а потом все четыре изображения оптимизируем, выбираем то, которое меньше занимает. А дальше просто поворачиваем его при помощи ЦСС (я ещё фильтр для старых ИЕ добавил и некоторые свойства для других браузеров):

.rotate90 {
    filter: progid:DXImageTransform.Microsoft.BasicImage(rotation=1); /* IE 5.5+ */
    -ms-filter: "progid:DXImageTransform.Microsoft.BasicImage(rotation=1)"; /* IE 8 */
    -ms-transform: rotate(90deg); /* IE 9 */
    -o-transform: rotate(90deg); /* Opera 10.5+ */
    -webkit-transform: rotate(90deg); /* Chrome, Opera 15+, Safari 3.1+, Android 2.1+, iOS 3.2+ */
    -moz-transform: rotate(90deg); /* FF 3.5+ */
    transform: rotate(90deg); /* FF 16+, IE 10+, Opera 12.1-14.99 */
}

Картинка поворачивается браузером и визуально остаётся как была.

Вообще, конечно, можно поворачивать на любой угол, если фон картинки прозрачный или совпадает с окружающим фоном, но в старых ИЕ для этого придётся использовать другой фильтр — Matrix, формула расчёта параметров такая:

progid:DXImageTransform.Microsoft.Matrix(
  M11 = cos(угол),
  M12 = -sin(угол),
  M21 = sin(угол),
  M22 = cos(угол),
  sizingMethod = 'auto expand'
);

Метод не лишён недостатков, конечно. Во-первых, всё это может сказаться на производительности, особенно в старых Эксплорерах (в последнем даже сомнений нет — скажется). Во-вторых, как видно из версий, которые я добавил в ЦСС, не все версии браузеров поддерживают поворот, правда их доля совсем невелика и продолжит снижаться.

15 комментариев
Юрий 2013

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

Влад 2013

Хоть и не по теме, но... наблюдаю забавный эффект у буквы «й» — съехавшую в сторону закорючку. В цитате она съехала почти на половину буквы, а в основном тексте гораздо меньше, но тоже.
WinXP, Firefox 22.0

Скриншот по ссылке: http://yadi.sk/d/s3eeiG3L6i3iC

SiMM (mr-simm.livejournal.com) 2013

Комментарий для Влад:

В цитате нет символа «й» ;) Там два — «и» и «кратка» http://ru.wikipedia.org/wiki/%D0%9A%D1%80%D0%B0%D1%82%D0%BA%D0%B0

Влад 2013

Комментарий для mr-simm.livejournal.com:

А-а-а. Ну тада да.

Евгений Степанищев (bolknote.ru) 2013

Комментарий для Влад:

Я из PDF это скопировал :) Видимо, там для чего-то не буква «й» сделана.

3 2013

Экономия будет копеечная, а затраты памяти и процессора, если, скажем на странице пара сотен картинок.. И в пнг картинка будет скорее всего меньше, чем минимальный из гифов.

Евгений Степанищев (bolknote.ru) 2013

Комментарий для 3:

Почему вы решили, что речь только о гифах? Читали по диагонали? Экономию в ПНГ можно оценить по ссылке в статье.

Кстати, поворот на градус кратный 90 плёвое дело, никак не медленнее вывода картинки без поворота.

Евгений Степанищев (bolknote.ru) 2013

Комментарий для Юрий:

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

+1, не подумали, видимо. Всё-таки форматы без потерь у нас довольно старые все (GIF, PNG), надо посмотреть как дела в WebP, у него есть вариант без потерь.

karudo (karudo.ya.ru) 2013

А почему ЦСС, а не КТС?

Евгений Степанищев (bolknote.ru) 2013

Комментарий для karudo.ya.ru:

Потому же почему БМВ, а не БМЗ и АЕГ, а не ВЭК.

Давид Мзареулян (david-m.livejournal.com) 2013

А потом придёт Гугл и проиндексирует положенную набок картинку:)

Хотя сама по себе идея, конечно, хорошая.

Евгений Степанищев (bolknote.ru) 2013

Комментарий для david-m.livejournal.com:

Это трудности Гугла :)

Глеб Арестов 2013

png умеет делать оптимизации и по горизонтали и по вертикали
http://www.artlebedev.ru/tools/technogrette/img/png-1/

Евгений Степанищев (bolknote.ru) 2013

Комментарий для Глеб Арестов:

Тем не менее у автора статьи, на которую я ссылаюсь, получили разные результаты. Он использовал pngcrush -brute и deflopt. Видимо какие-то особенности присутствуют, я с утра плохо соображаю, поэтому не могу понять какие.

Евгений Степанищев (bolknote.ru) 2013

Комментарий для Глеб Арестов:

Я сейчас прошёлся пакетом imgo по этим картинкам ( https://github.com/imgo/imgo ) с ключами «m» и «b», файл слева сжался ещё на 5,5 килобайт, файл слева остался того же размера. В итоге, разница только увеличилась.