• punypng

    Хоть и зарекался я не рекомендовать инструменты для пакетной оптимизации графики, но тут все-таки придется.

    Встречайте нового игрока — punypng. Новый сервис, очень похожий (но пока не такой удобный) на известный smush.it.

    После публикации на SM первой части статьи про оптимизацию PNG со мной связались ребята из проекта Ask.com — довольно известного на Западе поисковика. Они как раз начали разрабатывать очередной оптимизатор картинок для веба. Немного проконсультировавшись, они добавили чистку прозрачных пикселей, что в большинстве случаев дает довольно ощутимое сжатие. Так что я теперь являюсь консультантом проекта punypng, а этот пост — наглый пиар 🙂

    А теперь немного конкретики. Я прогнал несколько тестовых изображений через этот сервис и могу сказать, что результат был действительно впечатляющим. Практически на всех изображениях удавалось достичь дополнительного сжатия. Даже на изображениях, которые я оптимизировал вручную и прогнал через OptiPNG.

    Чтобы сравнить результаты, я дополнительно прогнал несколько изображений (наиболее показательным оказалось вот это) через smush.it и ImageOptim.

    smush.it использует утилиту pngcrush, которая по всем меркам является устаревшей. Она пытается перепаковать изображения, не меняя их тип (например, черно-белая RGB-картинка не будет преобразована в Grayscale). Утилита OptiPNG, которая является ответвлением от pngcrush, делает такие преобразования автоматически, но при этом работает гораздо медленнее (поэтому на smush.it используется pngcrush). Так что от этого сервиса ждать каких-то выдающихся результатов пока не приходится. Однако на выходе мы получаем «безопасное» преобразование, которое гарантирует, например, что полноцветный полупрозрачный PNG не будет преобразован в полупрозрачный PNG с палитрой (разница в отображении в IE6).

    ImageOptim, в свою очередь, пытается прогнать изображение через несколько библиотек, выбирая наилучший результат. Среди этих библиотек — PNGOUT Кена Сильвермана, которая априори должа выдавать лучший результат, так как использует собственный алгоритм упаковки данных. Даже она не смогла сжать лучше, чем punypng. Не говоря уже о том, что punypng отработал горазо быстрее, чем ImageOptim.

    Так что от всей души советую попробовать этот сервис. Я, в свою очередь, постараюсь описать больше алгоритмов оптимизации изображений, чтобы сделать сервис еще лучше.

    UPD: Окей, значит, расклад такой.

    PNGOUT сам не умеет перебирать фильтры. Как правильно заметил Павел у себя в блоге, с этим успешно справляется OptiPNG, выдавая в консоль статистику обработки файла. Соответственно, правильный способ максимального сжатия файла такой: сначала пропускаем через OptiPNG, получаем от него номер N примененного фильтра и отдаем его в качестве параметра -fN для PNGOUT.

    По поводу ImageOptim. Судя по исходнику, там PNGOUT используется без указания правильного фильтра, и, более того, применяет библиотеки не друг за другом на одном и том же файле, а независимо, выбирая наименьший результат (поправьте меня если не прав, так как Objective-C не знаю). Поэтому и результат сжатия у меня получился не самый лучший.

    PNGSquash, напротив, применяет библиотеки в цепочке, поэтому получается так сильно сжать файлы. Так что эта программка работает лучше, чем ImageOptim.

    Сейчас узнаю, как работает punypng.

    UPD2: punypng не использует PNGOUT из-за лицензионных ограничений. Есть вероятность того, что ребята сделают офлайновую версию punypng: для этого нужно всей толпой проголосовать за это предложение.

  • 51 комментарий

    1. iSergey
      22 июля 2009

      Действительно впечатляет.

    2. Сергей
      22 июля 2009

      Спасибо вам! Сначала ручками, при помощи методов, про которые вы пишите, а потом уже через утилиту. Правда иногда хочется, чтобы такие утилиты стояли локально…

    3. 22 июля 2009

      Ну почему они не проставляют ручками цвет фона для сайта… Почему все думают, что у меня по умолчанию белый фон, а?

    4. 22 июля 2009

      Круто! Хотелось бы иметь command-line.

    5. Мохов Олег
      22 июля 2009

      Замечательный сервис. Спасибо.
      Порадовал комент к новой фиче (http://www.gracepointafterfive.com/punypng-now-supports-dirty-transparency):
      ?????????? ?????? ?????? — punypng. ????? ??????, ????? ??????? (?? ???? ?? ????? ???????) ?? ????????? smush.it. =)

    6. 22 июля 2009

      Прогнал PNG с одного из проектов (графика была только порезана в фотошопе, без последующей оптимизации другими инструментами), результат приятно удивил. Некоторые картинки потеряли до 20-22% веса. Беру punypng на вооружение ))

    7. Сергей Чикуенок
      22 июля 2009

      Круто! Хотелось бы иметь command-line

      Я тоже хочу. Насколько я понял, там тоже картинка прогоняется через несколько библиотек.

    8. 22 июля 2009

      Главный плюс ImageOptim в том, что это софт 😉
      Лучше бы ребятам собрать их супер-алгоритмы в простую GUI-оболочку, иначе популярности им не видать.

    9. Алексей
      22 июля 2009

      «Зарекаюсь не рекомендовать» — это значит
      «обещаю не не рекомендовать».

    10. 22 июля 2009

      > Лучше бы ребятам собрать их супер-алгоритмы в простую GUI-оболочку, иначе популярности им не видать.

      Уже есть. http://github.com/msanders/PNGSquash
      «PNGSquash combines the top PNG compressors (that is, PNGCrush, OptiPNG, AdvPNG, and PNGOut*) into a streamlined interface for quick and effective compression.»

      Я взял пару картинок, сжатых с помощью PNGSquash. Punypng не смог сжать их лучше ни на байт.

    11. 22 июля 2009

      Что, продался вавилону? 🙂
      Вот ничто так не ограничивает свободу, как напутствие «иди на все четыре». Так и ты — не могу я, глядя на «наглый пиар», не зайти-поглазеть.

    12. Сергей Чикуенок
      22 июля 2009

      Проверл PNGSquash — действительно сжал лучше. По сути, это тот же ImageOptim, только, как я понял, с более агрессивными параметрами сжатия.

      Но в любом случае, у punypng есть чистка прозрачных пикселей, чего нет ни у ImageOptim, ни у PNGSquash. А это может дать дополнительную экономию тем, кто не хочет чистить вручную. И скоро может появится еще несколько методов оптимизации, но с потерями качества.

    13. GreLI
      22 июля 2009

      PunyPNG тоже без спроса преобразует 32-битный цвет в палитру с альфой, гордо показывая проценты сжатия, когда этого не надо делать из-за IE6.

      На моих тестах в других картинках по сравнению с PNGOut (использую консольную линукс версию с перебором параметров вручную) улучшений нет.

    14. Сергей Чикуенок
      22 июля 2009

      А с какими параметрами вызывали pngout? У меня со стандартными настройками на тестовой картинке он выдавал больший размер, чем оригинальная картинка.

    15. Eugéne
      22 июля 2009

      Заметил интересную вещь, к посту, впрочем, слабо относится.

      Сделал диагональный градиент от серого к белому в шопе. В ргб, вызвал окно save for web, png 24 — показывает около 90 кб, отменил, поменял режим в grayscale, кажет 47 кб, отменил, перевёл в RGB и обратно в Grayscale, уже показывает 52 кб, и так далее, с каждой итерацией перевода туда-сюда растёт объем.

      Кажется, что шоп добавляет дифузию и с каждым разом всё больше и больше… стрянно. Я ещё понимаю в первый раз он смешал, из-за перехода в цветовое пространство с меньшим диапазоном (да и то сомнительно, ведь цвета-то были от серого к белому), но зачем смешивать каждый раз?! Ведь не то чтобы добавилось информации при конвертировании из Grayscale в RGB.

    16. 22 июля 2009

      Если кому интересно про ускорение работы pngout, то посмотрите
      http://blog.ad.by/2008/10/extreme-png-optimizing-and-compressing.html

      Там приведен тупой батник, который выжимает много из optipng+ pngout за короткое время.

    17. 23 июля 2009

      афтар, пеши исцо!

    18. GreLI
      23 июля 2009

      Обычно начинаю пускать с pngout -n1 -f0. На тестовой картинке сразу же дало 83588 байт (94% от 88443). Иногда помогает включение фильтра, потом увеличиваю n, на больших картинках это даёт эффект. В этом примере n2 дало 82271. n3 — 82163. n4 — 81880 (93% от оригинала), дальше эффекта не было. Иногда несколько байт даёт ещё b512 или аналогичная.

      Интересно, что линуксовая версия от 2007 года, может быть, свежие виндовые экзешники ещё больше дадут (кажется, были небольшие улучшения алгоритма). PunyPNG на этой картинке сэкономил ещё 125 байт. Возможно, от эффекта «грязной прозрачности», возможно, как раз более новая версия всё того же pngout.

      P.S. Это ж надо называть домены типа «*.ad.*» или «*/adv.»…

    19. GreLI
      23 июля 2009

      Нет, свежескаченный экзешник pngout дал тот же результат.

    20. Сергей Чикуенок
      23 июля 2009

      Написал UPD к посту.

    21. Георгий
      23 июля 2009

      прийдется => придется

    22. GreLI
      23 июля 2009

      Насколько мне известно, pngout пытаётся угадать фильтр, но ему это не всегда удаётся. Это весьма интересный вопрос, сами создатели PNG думают над этим.
      OptiPNG перебирает, но из-за стандартной libpng, результат хуже чем у, применённого с умом, pngout.
      Интересно как сделали в PunyPNG: перебором или сами что-то придумали?

    23. GreLI
      23 июля 2009

      Вдогонку: помнится у меня был случай, когда OptiPNG выдал результат с фильтром (+использовался AdvPNG), а pngout обогнал его в варианте без фильтра.

    24. 24 июля 2009

      У меня есть скрипт для макоси который применяет сначала pngcrush+optipng, потом optipng+pngcrush (с максимальным перебором вариантов, но без изменения битности картинки), сравнивает полученные размеры и оставляет наилучший результат.

      Пока не нашёл у себя картинки, где punypng сделал бы лучше.

    25. Сергей Чикуенок
      24 июля 2009

      А вот эту картинку пробовал?

    26. Дмитрий Чаплинский
      27 июля 2009

      Сергей, а какие–то подвижки в плане оффлайновой версии будут? У нас в проекте большой объем png–графики (около шести миллионов изображений), который бы желательно обработать батчем.

    27. Сергей Чикуенок
      27 июля 2009

      Смотрите второй апдэйт, нужно проголосовать за это предложение.

    28. Дмитрий Чаплинский
      27 июля 2009

      Готово.
      Ну я еще погоняю существующие решения на тестовой выборке в пару сотен картинок, чтобы оценить эффект/скорость, а то ведь всех можно и не дождаться :))

    29. Алексей
      4 августа 2009

      Сергей, не мог бы ты записать скринкаст или статью по работе с SVN в Linux/Mac? Исполььзуя тот же Eclipse например.

    30. Сергей Чикуенок
      4 августа 2009

      Я скоро разгребусь с делами и напишу полноценную статью по командной работе в Eclipse

    31. Алексей
      4 августа 2009

      Ок, жду:)

    32. Дмитрий Чаплинский
      5 августа 2009

      Запустил тестирование на выборке из 1000 картинок. О результатах и таймингах отпишусь.

    33. Алексей
      6 августа 2009

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

      SC: спасибо, исправил

    34. Дмитрий Чаплинский
      6 августа 2009

      Сергей, я тут у вас обнаружил забавную штуку в старом посте — малозаметную ссылку в футере на http://www.asbafo.net/.

      Сам пост вот — http://chikuyonok.ru/2009/04/dont-use-import/#comments

      Скриншот вот — http://img.skitch.com/20090806-89cxsx93siiy153y9627wg2gyg.png

      Я так понимаю, что вы не торгуете линками, а вас скорее поломали?

    35. Сергей Чикуенок
      6 августа 2009

      Нет, меня не поломали 🙂 Это пока эксперимент моего друга, посмотрим, что с этого получится.

    36. Дмитрий Чаплинский
      6 августа 2009

      Ох, дружба с СЕОшниками опасна и трудна 🙂

      Я тут заканчиваю с экспериментами по оптимизации, кстати, есть пара забавных результатов.

    37. Сергей Чикуенок
      6 августа 2009

      Не, тут не СЕО (по крайней мере СЕО не в моих интересах). Просто на правах эксперимента: могу ли я на своем блоге своими же статьями заработать.

    38. Дмитрий Чаплинский
      6 августа 2009

      Ну не таким же варварским методом.

      Блог работает на признание и популярность, что вы не просто«Сергей, который там у самизнаетекого работает», а человек, который заинтересован в продвижении направления, в котором он работает. Подобное уже по необходимости конвертируется в другую работу, какие–то связи и прочая–прочая. С моей точки зрения, естественно.

      Можно и кнопочку донейшна повесить 🙂

    39. 7 августа 2009

      а как насчёт http://psydk.org/PngOptimizer ?

    40. Сергей Чикуенок
      7 августа 2009

      Про PNGOptimizer ничего сказать не могу, так как сижу на Маке. Но мне кажется, что все эти утилиты работают по одному и тому же принципу: используют всем известные библиотеки типа OptiPNG для оптимизации изображений.

    41. Дмитрий Чаплинский
      7 августа 2009

      У PngOptimizer есть еще CLI версия (что, я надеюсь, предполагает свой алгоритм). Надо будет попробовать на виртуалке.

    42. Дмитрий Чаплинский
      7 августа 2009

      Как и обещал небольшой отчет по моим изысканиям:

      Задача:
      Найти наиболее оптимальный способ оптимизировать большое количество однотипных png изображений при помощи бесплатных утилит. Под оптимальным подразумевается хорошая эффективность сжатия + скорость работы.

      Инструменты:
      * pngOUT, последние доступная бинарная сборка под Mac OS (Apr 30 2007).
      * optipng 0.6.3, собраная из последних исходников.
      * pngcrush 1.7.0, собранная из последних исходников.

      Исходный материал — 991 png изображение с прозрачностью, используемое mydeco.com для работы Moodboard App (http://mydeco.com/rooms/moodboard/). Сами изображения — уменьшенные фотографии товаров с обрезанным (прозрачным) фоном.
      Взять можно, например, отсюда:
      http://mydeco.com/ws/search/search?db=product&display=thumbnail_nobkg_270&count=1000

      Скачать себе можно при помощи простого скрипта на python + wget:
      import os
      import sys
      import urllib2
      import simplejson

      response = urllib2.urlopen(«http://mydeco.com/ws/search/search?db=product&display=thumbnail_nobkg_270&count=1000»).read()
      data = simplejson.loads(response)

      print «n».join([item[1][‘thumbnail_nobkg_270’] for item in data[‘results’][‘product’][‘items’]])

      Изначально изображений планировалось тысяча, но часть из них в выдаче дублировалась, поэтому после чистки осталось 991 общим весом в 72268kb.

      Методика тестирования:
      Сначала каждая утилита запускалась с максимальными настройками перебора на указаном наборе изображений, с замером времени исполнения и объемом картинок после обработки. После этого логи optipng были пропарсены небольшим скриптом на пайтоне:
      import os
      import sys
      import re
      from operator import itemgetter

      params = re.compile(‘Selecting parameters:s*(.*)IDAT’, re.MULTILINE)

      content = open(‘optipng.log’).read()

      mydict = {}
      for match in params.finditer(content):
      line = match.group(1)
      mydict[line] = mydict.setdefault(line, 0) + 1

      gen = mydict.iteritems()
      test = sorted(gen, key=itemgetter(1), reverse=True)
      for tup in test:
      print tup

      чтобы получить наиболее частоиспользуемые параметры оптимизации из лога. После этого была проведена оптимизация при помощи optipng с использованием самого удачного набора параметров, комбинации двух самых удачных наборов и четырех самых удачных.

      Потом была проверена совместная работа optipng (комбинация двух параметров) + pngout по алгоритму указаному Павлом выше. Под конец, для очистки совести, был запущен брутфорс pngout поверх брутфорса optipng (что предсказуемо дало наилучший результат с наибольшими затратами времени).

      Результаты ниже:
      Original files:
      Weight
      72268kb

      OptiPNG bruteforce:
      find source/ -name «*.png» -print | xargs optipng -o7 —dir optipng —quiet -l optipng.log
      Weight
      57700kb
      Decrease
      20.15%
      Time
      real 113m45.249s
      user 104m32.803s
      sys 5m28.420s

      PNGCrush bruteforce:
      find source/ -name «*.png» -print | xargs pngcrush -rem alla -reduce -brute -d pngcrush > pngcrush.log
      Weight
      62464kb
      Decrease
      13.56%
      Time
      real 86m16.769s
      user 70m50.347s
      sys 7m29.228s

      PNGOut bruteforce:
      for i in `find ./ -name «*.png» -print`; do pngout -y $i; done > ../pngout.log
      Weight
      55368kb
      Decrease
      23.38%
      Time
      real 57m14.420s
      user 53m58.410s
      sys 2m17.734s

      OptiPNG one param:
      find source/ -name «*.png» -print | xargs optipng -zc=9 -zm=8 -zs=0 -f=5 —dir optipng_1 —quiet -l optipng_1.log
      Weight
      58368kb
      Decrease
      19.23%
      Time
      real 3m47.360s
      user 2m59.876s
      sys 0m10.289s

      OptiPNG two params:
      find source/ -name «*.png» -print | xargs optipng -zc=9 -zm=8 -zs=0-1 -f=5 —dir optipng_2 —quiet -l optipng_2.log
      Weight
      57852kb
      Decrease
      19.94%
      Time
      real 5m29.486s
      user 4m30.160s
      sys 0m13.699s

      OptiPNG four params:
      find source/ -name «*.png» -print | xargs optipng -zc=9 -zm=8-9 -zs=0-1 -f=5 —dir optipng_3 —quiet -l optipng_3.log
      Weight
      57840kb
      Decrease
      19.95%
      Time
      real 8m56.324s
      user 7m27.380s
      sys 0m22.028s

      OptiPNG two params + PNGOut:
      for i in `find ./ -name «*.png» -print`; do pngout -y -k0 -n2 -f5 $i; done > ../opti-out1.log
      Weight
      55500kb
      Decrease
      23.20%
      Time (+ to OptiPNG two params)
      real 52m32.620s
      user 47m36.084s
      sys 2m0.568s

      OptiPNG bruteforce + PNGOut bruteforce:
      for i in `find ./ -name «*.png» -print`; do pngout -y $i; done > ../opti_out2.log
      Weight
      55312kb
      Decrease
      23.46%

      Выводы:
      В конкретно моем случае лидером выглядит оптимизация при помощи optipng используя комбинацию двух наиболее удачных наборов параметров сжатия, поскольку она дает вразумительный выигрыш при сжатии + справляется за короткое время. Таким образом, полученные параметры можно экстраполировать на все остальные изображения (несколько миллионов).

      Наиболее качественно в плане сжатия отработала спарка optipng + pngout в «брутфорс» режиме. pngcrush предсказуемо оказался неинтересен. Вариант, предложенный Павлом, заметного выигрыша не дал.

      Сорри за большой объем и корявый пайтон 🙂

    43. Дмитрий Чаплинский
      7 августа 2009

      И за инлайновый python тоже пардон, что–то pastebin.ca не работает.

    44. Сергей Чикуенок
      7 августа 2009

      Круто, спасибо 🙂

    45. Дмитрий Чаплинский
      7 августа 2009

      Ждем оффлайновой punypng 🙂

    46. pJ
      11 августа 2009

      BTW, этот самый «CQ», о котором я писал, содержит внутри: линейный алгоритм сжатия png, pngcrush и pngout. При записи выбирается лучший результат. Причем картинка пред-обрабатывается при передаче упаковщику, а pngout вызывается с кустомными ключами, которые CQ подобирает, анализируя картинку. У x128 есть мысль сделать из этого безобразия пакетную сжималку, но пока руки не дошли.

    47. 12 августа 2009

      нас на выставке тоже это больше всего заинтересовало. Жалко что народ на выставке был мало связан с технологами и поэтому многие не заметили ) ну или не поняли в чем моменты

    48. Стас
      15 августа 2009

      Я понимаю что это не ваша проблеа, но с казахстана (казахтелеком) негрузится http://www.punypng.com/ 🙁

    49. 22 августа 2009

      da, imet’ konsolnuyu versiyu bilo zamechatel’no, ya bi prikrutil k optimizatoru Data URI CSS Sprites http://duris.ru

    50. Arris
      3 сентября 2009

      Почему-то этот великолепный http://pornel.net/imageoptim/en настоятельно указывает мне обновить ФФ2 на нелюбимый ФФ3.5 прямым редиректом на сайт мозиллы.

      В ИЕ он почему-то этого не делает.

    51. Майк
      17 октября 2009

      Ни одно из сохранённых в Fireworks CS4 png ни улучшилось ни на чуть ))
      Использую комбинацию optipng+advancecomp