shikhalev.org
Исходный скриншот диалога изменения размеров в GIMP

Недавно мне задали такой вопрос:

Иван, как-то довелось делать resize png-картинки в Gimp. По сравнению с Photoshop качество хуже. Можешь тут подсказать?

Фотошопа у меня нет, сравнить не могу, поэтому попробую рассмотреть вопрос несколько по другому — какие способы ресайза мы имеем в Linux, пусть не «из коробки», но с минимальными трудозатратами. И что нам со всем этим богатством делать…

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

Для начала, чтобы много не писать о сути проблемы вообще, сошлюсь на хабрастатью «Ликбез: методы ресайза изображений». Она старая, но в плане основ и теории достаточно хорошо всё описывает. Более подробно, но на английском, можно почитать на сайте ImageMagick: «Resizing or Scaling», «Resampling Filters» и «Re­sam­p­ling by Nicolas Robidoux». Если Photoshop не использует новейшие достижения искусственного интеллекта (это не шутка, различные AI-методы сейчас активно применяются в обработке изображений), то правильный выбор фильтров и параметров, будем надеяться, позволит получить результат не хуже.

Что же касается формата PNG, то тут есть два соображения: во-первых, область применения — как правило, в PNG сохраняют не фотографии, а изображения с чистыми цветами и четкими границами, а во-вторых, применимость его к финальному результату — запросто можно при уменьшении картинки получить файл большего объема…

В общем, я взял два типичных, как мне кажется, случая, когда применяется именно этот формат: уменьшение скриншота (небольшое, чтобы можно было говорить о читаемости) и увеличение иконки (тут — в разы). Экспериментировать я буду с при­ме­не­ни­ем GIMP и ImageMagick.

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

Уменьшение скриншота

Вот такой скриншот диалогового окна собственно GIMP и собственно изменения размеров. В оригинальном разрешении:

Исходный скриншот диалога изменения размеров в GIMP

Ширина в оригинале — 415px. Ужимать будем до 320px, то есть, если очень грубо, на 20%. Точно такая же картинка вверху этого поста, но сделанная движком браузера автоматически, что там, какие алгоритмы использованы — то мне неведомо.

GIMP

GIMP предлагает пять вариантов интерполяции:

  • Нет
  • Линейная
  • Кубическая
  • Без гало
  • Мало гало

Обратившись к документации, мы узнаем, что «Нет» — означает то, что обычно в источниках называется «метод ближайшего соседа», а «линейная» и «кубическая» чаще называются «билинейной» и «бикубической» соответственно. Какой алгоритм используется в двух последних вариантах — непонятно, судя по всему, подавление гало работает уже поверх собственно интерполяции… Так же возможно, это какие-то модификации метода Lanczos, который был на их месте в старых версиях GIMP.

Пять вариантов достаточно мало, для того, чтобы все попробовать. Что же мы получим?

«Нет»
«Нет»
«Линейная»
«Линейная»
«Кубическая»
«Кубическая»

Разницу между линейной и кубической уловить трудно, а последние два варианта — с гало и без — вообще от кубической на глаз не отличаются, поэтому я их приводить не стал. Однако есть еще момент — размеры файлов. Для полноты картины я сравнил размеры не только файлов, которые мне сохранил GIMP, но и их же после оптимизации программой optipng, которая не меняет пиксели, только перепаковывает.

$ optipng -dir ./opt1/ -o7 source.png gimp-*.png

Получилось:

ФайлПикселиБайтыОпт.
source.png (исходный файл)415x36134K25K
gimp-none.png (интерполяции нет)320x27825K16K
gimp-linear.png320x27837K24K
gimp-cubic.png320x27843K28K
gimp-wo-galo.png (без гало)320x27840K27K
gimp-s-galo.png (мало гало)320x27843K28K

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

  • Метод ближайшего соседа для уменьшения скриншотов не годится совсем — надписи не читаемы.

  • Если качество линейной интерполяции нас устраивает, берем ее — она не только выполняется быстрее, но и дает результат меньшего объема.

  • Если нам нужно максимальное качество, в GIMP выбираем вариант «Без гало» — за счет более резкой картинки (а именно это и делает подавление гало) файл лучше сжимается.

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

ImageMagick

Хорошая новость заключается в том, что ImageMagick предоставляет больше вариантов ресайза. Плохая — в том, что их намного больше. Команда convert -list filter на моей системе выдает список из 31 пункта. Но это еще не все — помимо оператора -resize есть еще -distort Resize… Так что количество вариантов нужно умножать на два. А еще у многих фильтров есть настраиваемые параметры, а еще… В общем, при углублении в тему документация ImageMagick подбрасывает все новые и новые уровни. В рамках этого поста я пройдусь по верхам и параметры по умолчанию менять не буду.

Чтобы посмотреть все варианты, я воспользовался таким скриптом:

#!/bin/bash

filters=$(convert -list filter);

convert source.png -resize 320x ./im/0-resize-default.png
convert source.png -adaptive-resize 320x ./im/0-resize-adaptive.png
convert source.png -distort Resize 320x ./im/0-distort-default.png

for f in $filters; do
    convert source.png -filter $f -resize 320x ./im/1-resize-$f.png;
    convert source.png -filter $f -distort Resize 320x ./im/2-distort-$f.png
done;

На самом деле -resize без указания фильтра — это то же самое, что -filter Mitchell -resize, а -distort Resize — -filter Robidoux -distort Resize. А вот -adaptive-resize — это отдельный режим, где обработка должна базироваться на данных самой картинки (в документации тут не все ясно).

Итого у меня получилось 65(!) вариантов, все я, естественно, приводить не буду. Начнем с умолчательных:

-resize
-resize
-distort Resize
-distort Resize
-adaptive-resize
-adaptive-resize

Далее проверим алгоритмы, которые должны соответствовать GIMP’овским (на самом деле не совсем).

-filter Point -resize
-filter Point -resize
-filter Point -distort Resize
-filter Point -distort Resize

-filter Point — это метод ближайшего соседа, как из него -distort получил нечто приемлемое — мне не очень понятно.

-filter Triangle -resize
-filter Triangle -resize
-filter Triangle -distort Resize
-filter Triangle -distort Resize
-filter Cubic -resize
-filter Cubic -resize
-filter Cubic -distort Resize
-filter Cubic -distort Resize
-filter Lanczos2 -resize
-filter Lanczos2 -resize
-filter Lanczos2 -distort Resize
-filter Lanczos2 -distort Resize
-filter Lanczos2Sharp -resize
-filter Lanczos2Sharp -resize
-filter Lanczos2Sharp -distort Resize
-filter Lanczos2Sharp -distort Resize

Курьеза ради, и чтобы не создалось впечатления, что -distort всегда лучше, чем -resize, приведу варианты с фильтром Sinc:

-filter Sinc -resize
-filter Sinc -resize
-filter Sinc -distort Resize
-filter Sinc -distort Resize

Завершу этот парад почти одинаковых картинок еще двумя фильтрами, которые показали приемлемые результаты по размеру выходного файла.

-filter Box -resize
-filter Box -resize
-filter Box -distort Resize
-filter Box -distort Resize
-filter Hermite -resize
-filter Hermite -resize
-filter Hermite -distort Resize
-filter Hermite -distort Resize

Теперь о размерах выходных файлов подробно (напомню, что исходный файл был 34K/25K):

Фильтр-resize-distort
БайтыОпт.БайтыОпт.
-resize по умолчанию (Mitchell)43K29K
-distort по умолчанию (Robidoux)46K31K
-adaptive-resize36K23K
Point (ближайший сосед)25K17K37K24K
Triangle (линейная)39K26K42K28K
Cubic41K30K41K30K
Lanczos247K31K47K32K
Lanczos2Sharp46K31K47K32K
Sinc67K46K67K39K
Box30K19K38K24K
Hermite39K25K40K26K

Выводы:

  1. Если очень нужно уменьшать разрешение скриншота в PNG, то -adaptive-resize;
  2. Но лучше вообще без этого обойтись, например, в вебе просто задав размеры у тега IMG и отдав масштабирование на откуп браузеру — трафик так можно сэкономить заметно.
Исходная картинка
Исходная картинка, отмасштабированная браузером

Это все, конечно, оносится только к случаям, подобным рассмотренному — когда размеры картинки ужимаются процентов на 20, чтобы, скажем, вписаться в верстку. При сильном уменьшении про читаемость можно просто забыть и использовать простейшие методы, дающие минимальный выходной файл. Кстати, на этот случай в ImageMagick есть еще и оператор -thumbnail, который работает еще быстрее и грубее, чем -resize, а заодно выбрасывает всю метаинформацию.

Увеличение иконки

Здесь я решил поиздеваться над иконкой Darktable, в оригинале — 64x64px.

Иконка Darktable

Будем увеличивать ее в 5 раз по линейным размерам, т.е. в 25 по площади — до 320x320px. Вот так это может сделать браузер:

Иконка Darktable

GIMP

А вот что нам предлагает GIMP:

«Нет»
«Нет»
«Линейная»
«Линейная»
«Без гало»
«Без гало»

В режиме «Нет интерполяции» мы ожидаемо видим увеличение каждого пикселя, а в режиме «Линейная» — какое-то мыло. «Без гало» дает нам мыло немножко по краям подшарпленое, что, кстати, наиболее похоже на вариант от браузера. Что же до оставшихся «Кубической» и «Мало гало» — я не смог их отличить от «Линейной», даже быстро переключаясь с одной на другую.

ФайлПикселиБайтыОпт.
darktable.png (исходный файл)64x646.2K6.2K
gimp-none.png (интерполяции нет)320x3209.7K9.4K
gimp-linear.png320x32068K68K
gimp-cubic.png320x32075K75K
gimp-wo-galo.png (без гало)320x32072K72K
gimp-s-galo.png (мало гало)320x32076K75K

Выводы? Ну, для демонстрации пиксель-арта первый вариант может быть полезен. В остальных случаях браузер справляется не хуже, а объем меньше на порядок.

ImageMagick

Скриптом, аналогичным предыдущему, удалось получить множество вариантов. Но ничего прямо так принципиально отличающегося в лучшую сторону. Вероятно, без применения каких-нибудь AI-методов (т.е. распознавания и перерисовывания по сути) ничего принципиально улучшить и не получится. Поэтому ограничусь только тремя примерами:

-adaptive-resize
-adaptive-resize
-filter Parzen -distort Resize
-filter Parzen -distort Resize
-filter Sinc -distort Resize
-filter Sinc -distort Resize

Третий пример, если кто не догадался, вставлен забавы ради.

Как можно видеть, -adaptive-resize справляется, как минимум, не хуже GIMP’а… Что же по размерам файлов?

Фильтр-resize-distort
БайтыОпт.БайтыОпт.
-resize по умолчанию (Mitchell)74K70K
-distort по умолчанию (Robidoux)77K73K
-adaptive-resize67K61K
Point (ближайший сосед)11K9.6K69K66K
Parzen88K84K78K74K
Sinc111K107K131K130K

Я не стал вставлять картинку с -filter Point -resize, поскольку она ожидаемо неотличима от того, что делает GIMP без интерполяции. А еще такой же результат позволяют получить операторы -sample и -scale, только быстрее. Так же, как и -thumbnail — это максимально упрощенные и тупые варианты ресайза.

Итого

  • Во-первых, формат PNG применяется для тех случаев, когда нам важно сохранить каждый пиксель как он есть. Т.е. любое масштабирование для таких картинок противопоказано. Именно для картинок как таковых, а не для формата. Если мы храним в PNG что-то хорошо масштабируемое, возможно, мы что-то делаем не так.

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

  • Если всё же необходимо ресайзить PNG и именно в PNG, я бы, пожалуй, первым делом попробовал оператор -adaptive-resize пакета ImageMagick. А если результат не устраивает — прогнал бы скриптом прочие варианты фильтров. Можно, конечно, заморочиться и на подгонку их параметров, но боюсь, мои глаза не справятся с отловом тончайших отличий в огромном количестве файлов.

  • GIMP, честно говоря, удивил бедностью возможностей — уж с десяток алгоритмов могли бы и завезти…


PS. Для удобства оригиналы ссылкой: скрин и значок. Желающие могут попробовать поиграть с их размерами в разном другом софте, включая фотошоп.

Добавить комментарий

Будет добавлен комментарий верхнего уровня.

В тексте комментария можно использовать markdown-разметку, например, *курсив* или **полужирный**. HTML-разметку использовать нельзя.

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

В случае каких-то проблем с reCAPTCHA, пожалуйста, напишите мне на shikhalev@gmail.com.