ICC-профили в GIF

Формат ГИФ почему-то окружён каким-то нереальным количеством мифов, хотя до недавнего времени он был очень популярен, а для анимации до сих пор остаётся единственным универсальным форматом.

Например, считается, что анимация появилась только в версии 89a (неправда, она была уже в версии 87a, в 89а её возможности были расширены), что ГИФ может использовать не более 256 цветов (не совсем так — не более 256 цветов на кадр, кадры могут накладываться друг на друга, давая любое отображаемое компьютером количество цветов).

Другое распространённое заблуждение — что ГИФ не поддерживает цветовые профили (ICC).

В самом деле, если посмотреть спецификацию формата, то слово «ICC» там не найдётся, но не найдётся там и слова «loop» (здесь: количество повторов), тем не менее, вы видели анимации, где указано определённое количество повторений и браузеры как-то это понимают.

Дело в том, что формат ГИФ поддерживает расширения. Расширения в спецификацию формата не входят.

Упомянутое количество повторов анимации задаётся в расширении, которое было когда-то предложено фирмой «Нетскейп» и потому имеет заголовок «NETSCAPE2.0», у расширения, которое содержит цветовой профиль заголовок другой — «ICCRGBG1012». ГИФ всегда разбит на блоки, и блок расширения (любого) помечен специальным флагом; заголовок расширения позволяет просмотрщику (в нашем случае — браузеру) решить с каким из расширений формата он имеет дело.

Вот начало файла ГИФ с внедрённым профилем:

00000000 47 49 46 38 39 61 01 00 01 00 f0 00 00 fe 00 02 |GIF89a..........|
00000010 00 00 00 21 f9 04 00 00 00 00 00 21 ff 0b 49 43 |...!.......!..IC|
00000020 43 52 47 42 47 31 30 31 32 ff 00 00 03 f0 55 43 |CRGBG1012.....UC|
00000030 43 4d 02 40 00 00 6d 6e 74 72 52 47 42 20 58 59 |CM.@..mntrRGB XY|


Пока не все браузеры умеют поддерживать цветовые профили ГИФ (как и профили любого другого формата), так ФФ не научился делать это до сих пор, а «Опера» научится это делать в новой версии 12.50.

Проверить поддерживает ли браузер цветовые профили можно и через Джаваскрипт. Принцип такой: я загружаю ГИФ-изображение 1×1 с цветовым профилем в тег CANVAS, потом проверяю цвет точки, он должен быть определённого цвета. Проверить поддерживает ли ваш браузер цветовой профиль четвёртой версии ГИФ можно у меня на сайте, в разделе «Храню».
7 комментариев
29 августа 2012 08:19

Сжатие GIF через gzip

Эксперимент мой сжатию несжатых ГИФ, по сути, провалился — если статические изображения иногда оказываются меньше (или сравнимы) с PNG, то с анимированными изображениями, ради которых всё и затевалось, всё плохо, я не сумел подобрать условия, при которых новоявленный метод обгоняет обычные соптимизированные ГИФы.

Зато я попутно выяснил, что ГИФ, вопреки моим ожиданиям, иногда жмётся gzip, на первой попавшейся анимации я получил выигрыш порядка 9%. Так что вот он метод ещё больше утоптать файлы ГИФ:
#!/bin/sh

which -s defluff
if [ $? -eq 0 ]; then
    gifsicle -O3 "$1" |  gzip -9nc | defluff 2>&- > "$2".temp
else
    gifsicle -O3 "$1" |  gzip -9nc > "$2".temp
fi

size=( $(ls -l "$2".temp) )

# срезаем заголовок gzip и контрольную сумму
let 'size=size[4]-10-8'

dd if="$2".temp of="$2" bs=1 skip=10 count=$size 2>&-
rm -f "$2".temp
В настройки Апача надо добавить новое расширение файла:
AddEncoding deflate .gif-def
AddType image/gif .gif-def
Для браузера вместо gzip я указываю метод deflate — по факту это тот же gzip, но без заголовка и контрольной суммы, что позволяет сэкономить 18 байт, не бог весть сколько, конечно, но почему бы их не убрать, спрашивается.

Утилита defluff , которая у меня упоминается — это оптимизатор кодов Хаффмана для gzip, PNG и zip, иногда даёт выигрыш в размере.
25 комментариев
11 августа 2012 12:47

Конвертор в несжатый GIF

Сделал я конвертор из обычного ГИФа в несжатый формат сжатый gzip, выложил на ГитХабе. Основное (разбор ГИФа) написано на Пайтоне, утилита, которая всё запускает — на Шеле. Для работы требуются ImageMagick (предпочтительнее) или gifsicle, gitinter (из libungif) и интерпретатор Пайтона.

Кажется, эксперимент провалился, я ещё буду вертеть различные ГИФы, но вряд ли что-то получится. По сравнению с анимированными ГИФами, где не используется оптимизация (не убираюся из следующих кадров статические куски, не используется фокусы с прозрачностью и наложением) выигрыш бывает, но по сравнению с оптимизированными, ещё не видел, чтобы испытываемый формат выигрывал.

Из плюсов для себя: детально для себя разобрал формат GIF, освежил знания Пайтона (которые уже начинают тускнеть), Шела, поработал над интересной идеей.
11 комментариев
11 августа 2012 12:32

Сжатый несжатый GIF

Как многие знают, браузер нативно понимает сжатие gzip (алгоритм DEFLATE). Наконец-то браузеры научились с ним правильно работать, после стольких лет мучений — сжимать можно что угодно, достаточно просто указать правильный заголовок.

Графический файлы обычно так не сжимают — внутри у них свой алгоритм сжатия, например в ПНГ используется тот же DEFLATE. Но с ГИФом ситуация хуже — у него внутри более старый алгоритм LZW, к тому же нет никаких оптимизационных техник (например, ПНГ использует так называемые «фильтры», которые позволяют эффективно сжимать градиенты.

Вот я и подумал — нельзя ли как-то заменить алгоримт сжатия ГИФа с внутреннего LZW на внешний gzip? Если было бы нельзя, я бы эту заметку не писал.

Смотрите, слева у вас на экране ГИФ, сжатый при помощи gzip (так и грузится с сервера), справа — ПНГ.



В каждом из них равное количество уникальных цветов, ПНГ пропущен через все оптимизаторы, которые я только нашёл. При этом ПНГ занимает 1374 байта, а гзипованный ГИФ — 1347, на 27 байт меньше. Дело тут конечно, не в паре десятков байт, а в принципе — если бы я выбрал картинку побольше, выигрыш, возможно, был бы существеннее.

Почему же LZW внутри ГИФа, плюс DEFLATE снаружи сделали файл меньше, чем оптимизирующие просто DEFLATE, плюс фильтры в случае ПНГ? Обычно наложение одного сжимающего алгоритма на другой делает файл больше сравнению с применением одного, более удачного алгоритам из двоих.

Дело в том, что в ГИФ я использовал несжатый, он подготовлен специальным образом, так, что его собственный алгоритм сжатия не работает, а gzip работает над несжатым потоком данных.

Самый простой, по моему мнению, способ получить такой файл — пропустить его через утилиту gifinter из набора libungif — библиотеки и набора утилит для работы с несжатыми файлами ГИФ.

Утилиты эти отлично скомпилировались под мой «Мак» и обрабатывал я ГИФ следующим образом: для начала оптимизировал его при помощи giflite (эта старая утилита под DOS, которую я запускаю из-под dosbox, творит с ГИФами чудеса), потом пропустил через утилиту, вырезающую из ГИФа комментарии (их туда вставил giflite), только после этого пропустил файл через gifinter и сжал при помощи gzip:
gifinter optimized.gif > non-compressed.gif
gzip -9n non-compressed.gif
Дальше я переименовал файл в 2012.08.08.gif-gz и добавил в конфигурацию своего «Апача» следующие строки:
AddEncoding gzip .gif-gz
AddType image/gif .gif-gz
Теперь при запросе сервер будет выдавать все необходимые заголовки:
bolk@Bolk ~  $ telnet bolknote.ru 80
Trying 91.230.61.15...
Connected to bolknote.ru.
Escape character is '^]'.
HEAD /imgs/2012.08.08.gif-gz HTTP/1.0
Host: bolknote.ru
Accept-encoding: gzip

HTTP/1.1 200 OK
Server: nginx
Date: Wed, 08 Aug 2012 06:12:14 GMT
Content-Type: image/gif
Content-Length: 1347
Connection: close
Accept-Ranges: bytes
Cache-Control: max-age=2592000
Expires: Fri, 07 Sep 2012 06:12:14 GMT
Content-Encoding: gzip
Если интересно как устроен несжатый ГИФ, об этом можно прочитать в Википедии, откуда я взял картинку, там интересная уличная магия, перепечатывать «Википедию» не очень-то интересно.

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

По-настоящему опыт ценен, если удасться сделать несжатую ГИФ-анимацию (этого я ещё не пробовал) и сжать её при помощи gzip. Если удасться, это будет очень полезно, буду держать вас в курсе.
14 комментариев
8 августа 2012 09:43

TrueColor GIF

TrueColor GIF (191.75КиБ) Была у меня такая задумка — попробовать сделать полноцветную GIF-анимацию. Сразу скажу, идея провалилась, к сожалению.

Мысль-то простая — каждый полноцветный кадр должен представлять из себя полноцветный GIF. Общеизвестно, что формат GIF поддерживает только 256 цветов. Не страшно, разбиваем картинку так, чтобы каждый кадр содержал в себе не более 256 цветов и ляпаем их каждый поверх другого без задержки, в конце получится полноцветное изображение. Несколько таких изображений с задержкой между ними — и готова анимация.

Разбиение для начала выбрал простое — исходя из площади покрытия, думал потом взяться за оптимизацию (выбирать площадь, потом брать все цвета, которые в ней содержатся), но этого не понадобилось, оказалось, что если поставить задержку между кадрами ноль, то каждый браузер всё равно будет отрисовывать анимацию с очень заметной на глаз задержкой. Кажется в спецификации вообще не определено что означает нулевая задержка:
Delay Time - If not 0, this field specifies the number of hundredths (1/100) of a second to wait before continuing with the processing of the Data Stream. The clock starts ticking immediately after the graphic is rendered. This field may be used in conjunction with the User Input Flag field.
Но и если поставить задержку в 1/100 секунды, браузеры всё так же неторопливо отрисовывают картинку. Нарезанные кадры я собирал через утилиту gifsicle, она ещё и оптимизирует изображение — ненужны мне области я заливал прозрачным цветом, gifsicle умеет такие области отбрасывать, что уменьшает размер изображения:
gifsicle --delay 0 --crop-transparency -O3 out/*.gif > out.gif
Жаль, что ничего не получилось. Всё-таки надо переходить на APNG.

Зато выяснились любопытные подробности. Не знаю как это выглядит в IE (негде попробовать), а вот FireFox и Chrome умеют, один раз отрисовав конечную анимацию, потом мгновенно доставать её из кеша на перезагрузке страницы. «Опера», как и следовало ожидать, постоянно перерисовает анимацию — стоит только вернуться на страницу с другого таба или прокрутить её обратно до анимированного изображения.
43 комментария
12 августа 2011 01:22

33000 и анимированный GIF

По всей видимости, «Опера» немного неправильно обрабатывает анимированные «гифы».

Анимированный GIF устроен очень просто — поверх первого кадра через заданное время лепится следующий. Задержка задаётся в сотых долях секунды и, согласно спецификации, поля для её хранения имеет размер беззнаковое слово (2 байт), то есть максимальное значение — 655,35 секунд или почти 11 минут.

Распространённая ошибка в Си и похожих языках — использовать вместо беззнакового число со знаком. Тогда максимальное значение по модулю сокращается в два раза.

Вот я и проверил — не содержат ли кодеки популярных браузеров эту ошибку. На картике — число «1», если оно через пять-шесть минут сменится на «2», значит ошибки нет. Я выставил задержку между кадрами в 33000 (330 секунд или 5,5 минут). Кодек с ошибкой будет трактовать это число как -233 (отрицательное), поэтому кадр не сменится.

У меня на ноуте на FF 5, Safari 5.0.5, Chrome 12.0.742.122 цифра меняется, а на «Опере» 11.50 — нет. Сейчас попробую найти ноут с Windows 7 и попробую там. Попробуйте тоже на своих браузерах.

Добавлено: меняются ещё цифры на Андроиде 2.3.4, на FF 4.0.1 (Windows), а так же под Internet Explorer 9.0 и 10PP2 (Windows 7).

Добавлено ещё позднее: всё в порядке у «Оперы», разъяснил один из читателей — «Опера» начинает анимацию заново, если GIF не было видно. Дожидаясь, я переключал табы, поэтом анимация стартовала всегда сначала и «2» не появлялась. Так что ложная тревога, но любопытый факт.
14 комментариев
13 июля 2011 20:11

Как сэкономить один байт в GIF

Trailer (7.79КиБ) Я понимаю, один байт — не бог весть что, но, возможно, кому-то и такая мелочь будет приятна. Например, полезно во всяких конкурсах, вроде JS1K и т.п.

Файл в формате GIF должен заканчиваться символом с кодом 0x3B («;»), который называется «trailer». На самом деле, этот символ чаще всего не требуется декодерами (хотя обязателен в стандарте). Я проверил на сервисе скриншотов, все браузеры, которые там перечислены, кроме Konqueror 4.2 и выше, поддерживают файлы GIF без этого байта.

Я так же вывесил такой GIF у себя на сайте, обнаружилось, что его так же не поняли агенты, которые подписываются как Java/1.6.0_xx (думаю, это какие-то браузеры на J2ME).

Вывод: если вас это не смущает, то можете сократить свои GIFы на один байт. Или, напротив, проверьте имеют ли ваши GIF этот байт, если для вас почему-то важны эти браузеры (основанные на J2ME и Konqueror 4.xx).
4 комментария
20 января 2011 23:03

Internet Explorer показывает не все GIF

IE, не покажи этот GIF! (1.21КБ)Нашёл в ЖЖ DiBR'а GIF, который не показывает Internet Explorer. Забавно, хотя в отличие от JPEG, который не показывает современная «Опера», этот GIF несколько некорректен.

Вот текст комментария из ЖЖ, который разъясняет принцип:
Согласно описанию формата, сразу за заголовком («GIF89a») идет Logical Screen Descriptor (в котором как раз и прописан размер 80x80), затем Global Color Table, а уж за ним — всякие Extensions и данные изображений. В обсуждаемом файле Global Color Table просто отсутствует (так что IE ведет себя вполне адекватно). Зато присутствует картинка размером 100×100, которую и видят менее привередливые рендереры.
Комментировать
16 января 2011 20:26

GIF plain text extension

В формате GIF89 есть забавное поле — «plain text extension», заброшенное и никем не используемое. Настолько заброшенное, что для него делали специальное соответствующее поле в формате PNG, для совместимости, но потом объявили его «deprecated».

Как будет в точности выглядеть GIF с этим полем мне неизвестно, думаю, зависит от программы. По идее, оно должно выводить моноширинный семибитный (никакого Unicode) текст.

Насилу нашёл редактор, который умеет создавать GIF с таким полем, но, увы, ни один из браузеров не умеет правильно показывать содержимое такого GIF. Некоторые браузеры не умеют показывать его даже неправильно — выводят пиктограмму ошибочно загруженной картинки (например, IE, Opera 8.xx/9.xx, Safari и другие).

Понятно, что extension совершенно бесполезный, но всё-таки мне было любопытно на его посмотреть.

P.S. Для тестирования браузеров я использовал сервис BrowserShots.

Добавлено 6 октября 2009 14:40: почти все браузеры показывают изображение в котором есть ещё хоть что-то, кроме такого текста. Если же изображение содержит только текст, то многие браузеры (как сказано выше) покажут ошибку загрузки.
7 комментариев
6 октября 2009 01:32

Сжатие картинок

Вчера попробовал натравить инструменты для оптимизации картинок на свой каталог с картинками этого блога. Результат следующий: выигрыш составил около 10 процентов (больше всего у меня JPEG-файлов). Немного, но и не мало в некоторых ситуациях. Я использовал только утилиты для командной строки.

PNG. Для сжатия PNG использовался известнейший pngcrush. Интересен в режиме «brute force» (перебора), где перебираются комбинации фильтров (фильтры — это специализированные методы сжатия, например, для градиента и т.д.). Я запускал сделующим образом: «pngcrush -brute -fix -e .png1 *.png». В итоге, все файлы png у меня в папке получают свою оптимизированную копию с расширением png1. Есть опасный момент — если у вас есть файлы APNG, pngcrush их превратит в файл без анимации. Экономия получилась порядка 7%.

JPEG. В JPEG'e особо оптимизировать нечего, формат сжатия с потерями, поэтому оптимизацию без участия человека не произвести — трудно просчитать насколько критично изменился рисунок. Оптимизировать тут нечего, но можно убрать мусор — многие программы записывают в файл комментарии, лишнюю информацию. Я использовал для чистки PureJPEG, после него прошёлся своим Photoshop Crap Remover, чтобы дочистить файл. Формат запуска PureJPEG следующий: «dir /B /S /A-D *.jpg | purejpeg», в итоге все файлы с расширением jpg будут вычищены. Моя утилита написана на PHP, так что я даже не буду упоминать как её запустить — кому надо разберётся, остальным объяснить очень трудно. Экономия — около 10%.

GIF. Несмотря на то, что утилите GIFLite уже около 12 лет, мне она кажется лидером по переупаковке GIF. Утилита написана White River Software, её разработка начата ещё в 1992 году и она рабоатет под DOS, т.е. должна запускаться даже в Linux из-под какого-нибудь DOSEmu. Утилита платная, но кому платить уже непонятно — никаких координат этой фирмы в сети нет. Поэтому ищем любой ключ, запускаем giflite с ключём /R и «регистрируемся».

Запускать её сложнее, чем предыдущие — в 1992-м году длинных имён не было, да и перебирать свои методы она не умеет. Поэтому я написал небольшую batch-программу. Она проходит по всем GIF-файлам в папке, применяет на каждый один из четырёх методов (видимо выбирается какая-то стратегия для выбора словаря в LZW-сжатии), после чего выбирает файл с наименьшим размером. Экономия составила около 8%.

giflite.cmd — внутри по ссылке
12 комментариев
30 ноября 2007 13:10

Анимация в вебе

Как известно, единственный формат анимированных картинок, который был доступен в вебе до недавнего времени — Animated GIF. Его недостатки общеизвестны — поддерживается только 256 цветов, нет полупрозрачности (альфа-канала). На смену GIF, теоритически, должен прийти более совершенный PNG, с выходом Internet Explorer 7, который стал поддерживать альфа-канал почти так же хорошо, как его младшие братья, ситуация всё улучшается, но…

В PNG, увы, нет анимации. Три новых формата, которые пока знакомы редкому веб-мастеру — APNG, MNG и SVG позволяют, в какой-то степени, исправить это досадное упущение.

MNG (Multiple-image Network Graphics) в данный момент поддерживается без плагинов в Konqueror и Netscape 6 и выше. Формат похож на PNG, но использует больше типов данных. Фрейм, используемый в анимации, может сохраняться в форматах PNG или JNG (JPEG Network Graphics, по сути — JPEG с прозрачностью).

Анимированный PNG (10.98КиБ)

APNG (Animated PNG) — формат расширяющий PNG и совместимый сверху вниз. Если ваш браузер не поддерживает APNG, вы увидите просто статичную картинку. В настоящее время формат поддерживают Opera 9.50 и далёкий пока от релиза FireFox 3. Картинка выше этого абзаца — тест, поддерживает ли ваш браузер APNG. Если вы видите «Your browser does support Animated PNG», значит поддержка есть.

SVG (Scalable Vector Graphics) — относительно молодой векторный формат, который поддерживают достаточно много браузеров: Opera с восьмой версии, Safari 3 и выше, FireFox с версии 1.5, а так же все браузеры на движке Gecko, начиная с версии 1.8. Это XML формат, который для меньшего размера можно сжать алгоритмом GZip (формат SVGZ). Обычно, анимацию в SVG делают при помощи внедрённого туда EMCAScript, сменяя кадры из картинок в любом другом формате. Не совсем то, но поддерживается почти любым современным браузером, хотя в стандарте SVG есть собственные методы анимации, по этой теме можно почитать статью на несложном английском «Advanced SVG Animation Techniques».
2 комментария
21 ноября 2007 22:17

Фокусы с GIF, прозрачность и hover

Самые внимательные, наверное, заметили, что в прошлых заметках у меня на картинке использовалась эмуляция эффекта наведения на ссылку — посмотрите, если навести на картинку мышку, «ссылка», выделенная синим, на картинке подчеркнётся. И это не JavaScript.

Объяснение очень простое — картинка сделана с прозрачностью, далее при помощи CSS под неё подставлен белый фон, а при наведении (селектор «:hover») фон меняется на голубой. Такой же эффект использован на картинке с пистолетом слева (наведите мышку). Ссылка на картинке обязательна — без неё в Internet Explorer (версии ниже 7-й) фон менять не будет, «:hover» просто не сработает. Таблица стилей для этой картинки выглядит вот так:
a.gun:hover img { background: black } /* стиль при наведении мышкой */
a.gun img { margin: 0px; background: white } /* убираем поля в Opera и подкладываем белый фон */
HTML, соотвественно:
<a href="#" class="gun"><img src="gun.gif" /></a>
Если вам не ясно, почему пистолетик «стреляет» (т.е. почему изображение движется, когда наводишь мышку), то тут всё просто — прозрачная область движется (это animated GIF), на белом фоне этого не видно, когда фон меняется, создаётся эффект движущейся пули.

Ещё интересные эффекты можно получить, если использовать альфа-канал (полупрозрачность) в формате PNG, но, к сожалению, об анимации тут придётся забыть.
Комментировать
1 ноября 2007 13:41