четверг, 2 октября 2008 г.

Extreme PNG optimizing and compressing

На этот раз поговорим о такой затертой теме, как уменьшение размера PNG-файлов. Казалось бы — куча информации, множество утилит. Даже в техногрете тему достаточно подробно обсудили. Осталось только подвести внятный итог. Итак,

Задача
Найти лучшие бесплатные утилиты для сжатия PNG и научиться качественно ими пользоваться.

Теория

  1. PNG-файл состоит из нескольких информационных блоков. Многие из них содержит вспомогательную информацию о изображении и для отображения не нужны. Т.е можно просто выбросить необязательные блоки.
  2. Можно оптимизировать тип изображения, хранимого в файле. PNG понимает их аж пять штук: от ЧБ до полноцветного с прозрачностью.
  3. Можно оптимизировать палитру изображения или снизить количество бит на пиксель: даже в полноцветных изображениях цветов может оказаться немного.
  4. Можно поиграться с дельта-фильтрами сжатия. У PNG их опять-таки пять.
  5. Можно поиграться с алгоритмами сжатия. И тут есть, где разыграться.
Решение
Путем экспериментов было выяснено, что лучше всего использовать пару утилит - optipng и pngout. Optipng умеет понижать битность и перебирать дельта-фильтры. Pngout умеет удалять ненужные блоки и имеет непревзойденную степень сжатия. Правда чтобы добиться этого приходится перебирать её параметры, а работает pngout крайне медленно. Pngout имеет и более серьезную версию - PngoutWin. Эта умеет перебирать ключи автоматически, но стоит денег. Что не подходит.
Путем экспериментов определился достаточно быстрый алгоритм работы:
  1. Сначала запускаем optipng с ключами -o4 -full -force. Этим мы заставляем утилиту быстро перебрать самые оптимальные варианты сжатия и оптимизировать палитру/битность изображения.
  2. Потом мы запускаем pngout с ключами /k0 /fX. На место X нужно подставить значение параметра "f", выданное optipng. Такая подстановка сильно сэкономит нам время, почти избавив нас от необходимости перебирать ключи у pngout. Кстати, также имеет смысл поэкспериментировать с ключом /n.
Итог
Указанная комбинация проигрывает платному PngoutWin на считанные байты. А при использовании ключа /n даже неплохо выигрывает у него.
Ну и завершающий штрих - cmd-файл для автоматизации этого процесса:
@echo off
optipng -o4 -full -force %1 > optipng.log || exit 1
for /f "delims==,IDAT tokens=5" %%i in (optipng.log) do (
    set f=%%i
)
set f=%f:~1,1%
del optipng.log
pngout /k0 /n2 /f%f% %1 || exit 3
Как легко заметить, мне подошел параметр /n2. Не факт что на ваших файлах это будет оптимально, но у меня исключений не нашлось.

2 коммент.:

9 комментирует...

Спасибо, отличный пост. Добавлю в закладки.

Павел комментирует...

Реально время экономится.
Напустил батник на каталог с тысячей картинок - за десять минут отработал, ужав на 12%.
Команда такая:
for %i in (*.png) do call crunch %i