Сжатый несжатый GIF
Как многие знают, браузер нативно понимает сжатие gzip (алгоритм DEFLATE).
Графический файлы обычно так не сжимают — внутри у них свой алгоритм сжатия, например в ПНГ используется тот же DEFLATE. Но с ГИФом ситуация хуже — у него внутри более старый алгоритм LZW, к тому же нет никаких оптимизационных техник (например, ПНГ использует так называемые «фильтры», которые позволяют эффективно сжимать градиенты.
Вот я и подумал — нельзя ли
Смотрите, слева у вас на экране ГИФ, сжатый при помощи gzip (так и грузится с сервера), справа — ПНГ.
![]()
![]()
В каждом из них равное количество уникальных цветов, ПНГ пропущен через все оптимизаторы, которые я только нашёл. При этом ПНГ занимает 1374 байта, а гзипованный ГИФ — 1347, на 27 байт меньше. Дело тут конечно, не в паре десятков байт, а в принципе — если бы я выбрал картинку побольше, выигрыш, возможно, был бы существеннее.
Почему же LZW внутри ГИФа, плюс DEFLATE снаружи сделали файл меньше, чем оптимизирующие просто DEFLATE, плюс фильтры в случае ПНГ? Обычно наложение одного сжимающего алгоритма на другой делает файл больше сравнению с применением одного, более удачного алгоритам из двоих.
Дело в том, что в ГИФ я использовал несжатый, он подготовлен специальным образом, так, что его собственный алгоритм сжатия не работает, а gzip работает над несжатым потоком данных.
Самый простой, по моему мнению, способ получить такой файл — пропустить его через утилиту gifinter из набора libungif — библиотеки и набора утилит для работы с несжатыми файлами ГИФ.
Утилиты эти отлично скомпилировались под мой «Мак» и обрабатывал я ГИФ следующим образом: для начала оптимизировал его при помощи giflite (эта старая утилита под DOS, которую я запускаю
gifinter optimized.gif > non-compressed.gif
gzip -9n non-compressed.gifДальше я переименовал файл
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Если интересно как устроен несжатый ГИФ, об этом можно прочитать в Википедии, откуда я взял картинку, там интересная уличная магия, перепечатывать «Википедию»
Готовой разгадки почему сжатый несжатый ГИФ обогнал ПНГ у меня нет, но есть одно возможное соображение — ГИФ
Комментарии 14
In: 1374 bytes 2012.08.08.png /c3 /f0 /d8
Out: 1320 bytes 2012.08.08.png /c3 /f0 /d8, 102 colors
Chg: -54 bytes ( 96% of original)
Я пропускал через pngcrush, optipng, оптимизатор Yahoo и punypng. Значит надо было ещё и pngout использовать. Кошмар :)
В любом случае, ценность идеи совсем не в этом (см. последнее предложение в заметке).
Могу, кстати, этот ГИФ ещё на 18 байт уменьшить. Где бы ещё 11 байт найти? :)
Т.е. 9, конечно, а не 11.
Комментарий для alexeyten.ya.ru:
$ ./compressgif test.giftest.gif-def
Это утилита из следующей статьи: /all/3713