Эффективное изменение размера картинок при помощи ImageMagick

Эффективное изменение размера картинок при помощи ImageMagick

617
ПОДЕЛИТЬСЯ

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

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

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

Огромные рисунки == огромные трудности
Средняя интернет-страничка весит 2 Мб, из их 2/3 – рисунки. Работа интернет-дизайнеров и разрабов – упростить и сделать лучше жизнь юзера. 2Мб-веб-сайты в этих вариантах работают страшно. Миллионы людей прогуливаются в веб через 3G, либо ещё ужаснее. Даже на стремительном соединении такие веб-сайты могут израсходовать лимиты трафика.

Чрезвычайно мелкие веб-сайты могут просто сохранить несколько вариантов всех картинок. Но что, раз у вас их дофига? К примеру, в магазине может быть сотка тыщ картинок – не делать же их варианты вручную.

ImageMagick
На данный момент я объясню, в чём неувязка, и покажу, какие опции нужны для её решения. Но с опциями по умолчанию файлы нередко получаются лишне большими – время от времени по размеру больше оригинала, хотя в их и меньше пикселей. В ней большая куча функций, и посреди их – скорое и автоматическое изменение размера картинок. Утилита командной строчки с 25-летним стажем в то же время является редактором картинок с полным набором функций.

Как работает изменение размера картинок
Раз её наращивают, на выходе будет больше пикселей, чем на входе; при уменьшении – напротив. По определению, при изменении размера рисунки изменяется количество пикселей в ней. Задачка состоит в том, как лучше всего сохранить содержимое начальной рисунки при помощи другого количества пикселей.

Чтоб сделать дискретизацию рисунки 4х4 на 8х8, необходимо куда-то вставить 48 излишних пикселей. Повышение картинок изобразить проще, так что начнём с него. Разглядим картину с квадратиком 4х4 пикселя, который мы желаем удвоить до 8х8. У их должен быть какой-то цвет – процесс его подбора зовётся интерполяцией. При дискретизации метод, выбирающий, как работает интерполяция, именуется фильтром дискретизации. По сущности, мы берём эту картину и натягиваем на новейшую сетку – это именуется resampling (дискретизация).

Это будет фоновая интерполяция, когда на пустых местах возникает цвет фона (красноватый). Проще всего добавить четыре ряда и четыре столбца хоть какого цвета. В фотошопе это делается через “Image” → “Canvas Size” заместо “Image” → “Image Size”. Фильтров таковых есть множество. Ну, скажем, красноватого.

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

Для картинок, в особенности для нашего квадратика, итог будет еще лучше. Ещё одна обычная интерполяция – сделать цвет новейших пикселей таковой же, как у их соседей – это интерполяция по наиблежайшим соседям.

Для начала новенькая сетка применяется к уникальной картинке. Необходимо принять, что в математических целях можно оперировать дробными пикселями. Так как пикселей стало меньше, а размер их больше, некие из их содержат по нескольку цветов. При понижающей дискретизации, то есть, уменьшении рисунки, не так-то просто сделать интерполяцию по наиблежайшим соседям.

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

Он работает быстро, выдаёт маленькие файлы, но смотрится плохо. Но раз это что-то посложнее полосы и квадратов, таковой способ выдаёт зазубренные и квадратные рисунки.

В билинейной интерполяции считается взвешенное среднее цветов. Большая часть фильтров употребляют варианты интерполяции по наиблежайшим соседям – они делают точечную дискретизацию по нескольким точкам и как-то вычисляют некоторый средний цвет для их.

Но таковой фильтр влияет на размер файла, поэтому что он совместно с округлыми краями добавляет новейшие цвета. У уникальной рисунки было всего два цвета, сейчас же у нас их больше. А при иных равных, чем больше цветов, тем тяжелее файл.

И что же это значит для нас

Больше всего на это влияет выбор фильтра, но и остальные опции тоже могут. Нам необходимо как-то уменьшать количество цветов, не теряя в качестве.

Рациональные опции для ImageMagick
Базы ImageMagick
Нас интересуют две функции, convert и mogrify. У ImageMagick дофига опций и функций, и отыскать подходящую достаточно тяжело. Они выполняют идентичные деяния, но mogrify работает с несколькими файлами сходу, а convert – по одному.

Обычная операция:

convert input.jpg -resize 300 output.jpg

Функция -resize 300 – пример одной из множества функций. У их у всех один формат: -functionName option. При этом IM берёт input.jpg и изменяет размер на пикселей в ширину, сохраняя итог в output.jpg.

Применять mogrify можно также, с маленьким дополнением:

mogrify -path output/ -resize 300 *.jpg

Здесь IM берёт все файлы JPEG из текущей директории (*.jpg), изменяет их размер до 300 пикселей в ширину и сохраняет их в директории output.

Функции можно сочетать:

convert input.jpg -resize 300 -quality 75 output.jpg

Это тоже изменяет размер input.jpg до 300 пискелей, но устанавливает качество JPEG в 75 перед сохранением в output.jpg.

Тестирование и результаты
Я добивался оценки DSSIM не наиболее 0,0075. Я употреблял для проверки как субъективное мировоззрение, так и объективное – измерял структурные различия (structural dissimilarity, DSSIM). Чем меньше оценка, тем больше они похожи. Тестируя разные опции IM, я стремился уменьшить размер файлов, не ухудшая их свойства – так, чтоб их не отличить было от функции фотошопа «Save for Web». DSSIM ассоциирует две рисунки и выдаёт оценку. А в одном из исследований в прошедшем году было установлено, что традиционно люди не могут на глаз отличить рисунки с DSSIM наименее 0,015. 0 значит идентичность.

Протестировав разные изображения различных размеров в форматах JPEG и PNG я пришёл к выводу, что последующие опции IM делают меньшие результаты, которые при этом фактически неотличимы от выдачи фотошопа:

mogrify -path OUTPUT_PATH -filter Triangle -define filter:support=2 -thumbnail OUTPUT_WIDTH -unsharp 0.25×0.25+8+0.065 -dither None -posterize 136 -quality 82 -define jpeg:fancy-upsampling=off -define png:compression-filter=5 -define png:compression-level=9 -define png:compression-strategy=1 -define png:exclude-chunk=all -interlace none -colorspace sRGB -strip INPUT_PATH

Разберём их подробнее.

Mogrify либо Convert
IM употребляет convert для обработки картинок по одной, а mogrify традиционно нужен для пакетной обработки. В безупречном мире результаты их работы должны совпадать. К огорчению, в convert есть ошибка, из-за которой он игнорирует некие из опций (-define jpeg:fancy-upsampling=off), потому пришлось применять mogrify.

Дискретизация (resampling)
Выбор фильтра дискретизации в IM почему-то запутан. Есть три метода это сделать:

выбрав функцию конфигурации размера
используя опцию -filter
либо опцию -interpolate

Примеры работы 12-ти разных функций конфигурации размера

Эта функция работает в три шага: Очевиднее всего применять –resize, но результаты получаются очень большими. Я проверил 11 различных функций и нашел, что лучше всего с уменьшением справляется –thumbnail, как по размеру, так и по качеству.

изменяет размер рисунки до размера, в 5 раз превосходящего нужный, используя функцию –sample, у которой есть собственный интегрированный фильтр
потом изменяет размер до нужного через –resize
удаляет мета-данные из рисунки

И в конце удалит мета-данные. То есть, раз мы уменьшаем картину до 500 пикселей в ширину, -thumbnail поначалу изменит её размер до 2500 при помощи –sample. Потом IM изменит размер с 2500 до 500 через –resize.

У неких функций есть интегрированные фильтры, а у остальных есть фильтры по умолчанию, которые можно поменять. На втором шаге работы –thumbnail употребляется –filter, поэтому что там употребляется функция –resize. 2-ой метод выбрать фильтр дискретизации – через –filter.

Я проверил 31 вариант опций для –filter и достигнул наилучших результатов, используя Triangle. Я отыскал, что лучше всего задавать область примыкающих пикселей как -define filter:support=2 setting. Он вычисляет взвешенный средний цвет из примыкающих пикселей. Этот фильтр также известен как билинейная интерполяция.

3-ий метод выбора фильтра – это –interpolate, но он игнорируется при использовании -thumbnail.

Я решил, что она только наращивает размер картинок, а разница в качестве выходит пренебрежимо малой, потому рекомендую отключать её через -define jpeg:fancy-upsampling=off. Не считая всего остального, IM по умолчанию употребляет некоторую функцию под заглавием JPEG fancy upsampling, которая пробует выдать JPEG лучшего свойства.

Повышение чёткости (Sharpening)
Я рекомендую фильтр unsharp, который, невзирая на заглавие, наращивает чёткость рисунки: -unsharp 0.25×0.25+8+0.065. При изменении размера рисунки слегка размываются, потому тот же фотошоп применяет разные техники роста чёткости.

Фильтр работает так, что поначалу применяется гауссово размытие. 1-ые два числа – это радиус и сигма (в нашем случае, по 0,25 пикселя). Опосля размытия фильтр ассоциирует размытую версию с оригиналом, и там, где яркость различается наиболее, чем данный порог (0.065), применяется повышение чёткости данной силы (8).

Уменьшение цветности
Потому необходимо попробовать уменьшить их количество, но без утраты свойства. Как я говорил ранее, основная причина роста размера файлов при изменении размера картинок – добавление новейших цветов.

Один из методов – это постеризация (posterization), когда градиенты заменяются на наборы из точных цветов. Постеризация уменьшает количество уровней цвета – это то, сколько вариантов остаётся у красноватого, зеленоватого и голубого каналов. Общее количество цветов рисунки будет композицией цветов этих каналов.

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

Оригинал

Уменьшение количества цветов

В теории это отменная мысль. Дизеринг (Dithering) – процесс, который смягчает последствия уменьшения количества цветов, добавляя шума в цветовые наборы, чтоб сделать иллюзию большего количества цветов.

Опосля дизеринга

К счастью, и без него результаты постеризации смотрятся хорошо. Потому его лучше отключить через -dither None. К огорчению, в IM есть ошибка, которая портит рисунки с прозрачностью при дизериге.

Ошибка дизеринга в IM

Цветовое место
Это пространтсво описывает, какие цвета доступны. Цветовой место косвенно относится к количеству цветов на картинке. И все они содержат цветов меньше, чем лицезреет глаз. На картинке ниже показано, что место цветов ProPhoto RGB содержит больше цветов, чем Adobe RGB, которое, в свою очередь, содержит больше, чем sRGB.

В фотошопе это также это цветовое место по умолчанию. Короче, sRGB – наилучший выбор для интернета, и раз вы желаете, чтоб ваши рисунки верно показывались, лучше применять его. Его одобрили W3C и остальные организации. Он обязателен к поддержке в CSS Color Module Level 3 и в спецификациях SVG и WebP. На него ссылаются в спецификации PNG. sRGB сделали владыкой цветовых пространств веба.

Качество и сжатие
В форматах с потерей свойства вроде JPEG качество и сжатие соединены впрямую – чем больше сжатие, тем ниже качество и меньше размер файла. Потому необходимо отыскать баланс.

В моих тестах у контрольных картинок и фотошопа было выставлено качество high, либо 60. Почему? А в настройках IM я рекомендую применять 82.

В моих тестах я узнал, что фотошоповское 60 соответствует -quality 82 в ImageMagick. Качество 60 в фотошопе может оказаться таковым же, как качество 40 в одной програмке, качество B+ в иной либо качество «офигенское» в третьей. Оказывается, что количественно настройка свойства не определена в формате JPEG, и потому она не является эталоном.

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

Я достигнул наилучших результатов при использовании адаптивной фильтрации (-define png:compression-filter=5). Уровень сжатия я рекомендую ставить на максимум, 9 (-define png:compression-level=9). Фильтр сжатия – это доп шаг перед сжатием, который так сортирует данные, что сжатие становится наиболее действенным. Мне больше приглянулась стратегия по умолчанию (-define png:compression-strategy=1). Сжатие PNG в IM можно установить 3-мя опциями: -define png:compression-filter, -define png:compression-level и -define png:compression-strategy. А стратегия описывает сам метод.

Мета данные
На качество это не влияет. И хотя я указал, что –thumbnail удаляет мета данные, всё-таки она удаляет их не все. Не считая самой рисунки, файлы могут содержать мета данные – информацию о картинке, когда она была сотворена, о устройстве, которое её сделало. Есть возможность удалить все, используя -strip и -define png:exclude-chunk=all. Эта информация занимает место, но не улучшает восприятие рисунки, и её лучше удалить.

Прогрессивный рендер
Прогрессивный значит, что картина передаётся и выводится равномерно. По умолчанию выполняется 2-ой, когда пиксели грузятся по рядам, сверху вниз. JPEGs и PNGs можно сохранять при помощи прогрессивного (progressive) либо поочередно (sequential) рендера.

У JPEG прогрессивный рендер может произойти в хоть какое количество шагов – это определяется при сохранении файла. 1-ый шаг – версия низкого разрешения полной рисунки; на каждом следующем возникает версия наиболее высочайшего разрешения, пока не будет выдана вся картина в высшем разрешении.

У PNG есть вид прогрессивного рендера под заглавием Adam7 interlacing, когда пиксели выводятся в семь шагов на базе сетки 8х8.

Но необходимо ли? Оба вида рендера можно настроить в IM через –interlace.

Даже раз безупречная картина не загрузится сходу, он что-нибудь распознает, и это будет лучше, чем ничего. Длительное время числилось, что его необходимо включать, так как он улучшает пользовательское восприятие. Таковой рендер наращивает размер файлов.

В прошедшем году по результатам исследования стало видно, что юзеры предпочитают поочередный рендер. Так что я решил советовать применять поочередный рендер через "-interlace none". Это лишь одно исследование, но всё равно увлекательное.

Оптимизация картинок
Я упоминал оптимизацию. Все описанные до этого опции я рекомендую, раз вы не оптимизируете свои рисунки. Раз их можно улучшить, то я их поменяю: маленькие конфигурации в настройках -unsharp лучше работают (-unsharp 0.25×0.08+8.3+0.045 супротив -unsharp 0.25×0.25+8+0.065 без оптимизации) и не необходимо применять -strip.

mogrify -path OUTPUT_PATH -filter Triangle -define filter:support=2 -thumbnail OUTPUT_WIDTH -unsharp 0.25×0.08+8.3+0.045 -dither None -posterize 136 -quality 82 -define jpeg:fancy-upsampling=off -define png:compression-filter=5 -define png:compression-level=9 -define png:compression-strategy=1 -define png:exclude-chunk=all -interlace none -colorspace sRGB INPUT_PATH

Оптимизаторов есть множество. Раз у вас нет излишнего времени и процессорной мощности, то внедрение наиболее одной оптимизации будет чрезмерным. Я тестировал image_optim, picopt и ImageOptim, и они все прогоняют рисунки через серию различных шагов. Правда, опосля использования image_optim выгода от picopt и ImageOptim становится малой. Я инспектировал их по очереди и пришёл к выводу, что лучше изгнать файлы через все три в том порядке, в каком они приведены.

Результаты (и что, стоило так страдать?)
С радостью сообщаю, что потратив время на испытания, я смог кардинально уменьшить объёмы файлов, не проиграв в качестве. Естественно, опции мои сложны, но для улучшения пользовательского восприятия они необходимы.

В среднем размер файлов уменьшился на 35% по сопоставлению с опцией фотошопа “Save for Web”.

Сопоставление с Photoshop Creative Cloud

Мои опции без оптимизации оказались даже лучше, чем у фотошопа с оптимизацией!

По сопоставлению с опциями по умолчанию при изменении размера картинок у IM, мои советы выиграли в среднем 82%.

По сопоставлению с опциями по умолчанию в WordPress, который «под капотом» употребляет ImageMagick, мои опции в среднем выиграли 77%.

По сопоставлению с иными CMS и инструментами, которые употребляют ImageMagick, мои опции выигрывали аж до 144%.

Припоминаю, что все рисунки вышли неотличимыми от вывода фотошопа.

Как воплотить это в собственных проектах
bash shell
Тут можно добавить функцию-макрос в файл .bash_aliases (либо .bashrc), которая будет подменять мою рекомендуемую команду:

smartresize() {
mogrify -path $3 -filter Triangle -define filter:support=2 -thumbnail $2 -unsharp 0.25×0.08+8.3+0.045 -dither None -posterize 136 -quality 82 -define jpeg:fancy-upsampling=off -define png:compression-filter=5 -define png:compression-level=9 -define png:compression-strategy=1 -define png:exclude-chunk=all -interlace none -colorspace sRGB $1
}

А вызывать её необходимо так:

smartresize inputfile.png 300 outputdir/

Node.js
У npm package под заглавием imagemagick дозволяет применять ImageMagick. При его использовании можно добавить функцию конфигурации размера последующим образом:

var im = require(‘imagemagick’);

var inputPath = ‘path/to/input’;
var outputPath = ‘path/to/output’;
var width = 300; // output width in pixels

var args = [
inputPath,
‘-filter’,
‘Triangle’,
‘-define’,
‘filter:support=2’,
‘-thumbnail’,
width,
‘-unsharp 0.25×0.25+8+0.065’,
‘-dither None’,
‘-posterize 136’,
‘-quality 82’,
‘-define jpeg:fancy-upsampling=off’,
‘-define png:compression-filter=5’,
‘-define png:compression-level=9’,
‘-define png:compression-strategy=1’,
‘-define png:exclude-chunk=all’,
‘-interlace none’,
‘-colorspace sRGB’,
‘-strip’,
outputPath
];

im.convert(args, function(err, stdout, stderr) {
// do stuff
});

Grunt
В свои проекты её можно включать вот так: Раз вы используете Grunt для пуска задач, то специально для вас я сделал задачку по имени grunt-respimg (npm), которая делает всё, что я обрисовал.

npm install grunt-respimg —save-dev

А потом её можно выполнить в файле Grunt:

grunt.initConfig({
respimg: {
default: {
options: {
widths: [200, 400]
},
files: [{
expand: true,
cwd: ‘src/img/’,
src: [‘**.{gif,jpg,png,svg}’],
dest: ‘build/img/’
}]
}
},
});
grunt.loadNpmTasks(‘grunt-respimg’);

PHP
В PHP ImageMagick интегрирован под именованием Imagick. К огорчению, там он ограничен и не умеет делать всё то, что я рекомендовал – в частности, настраивать фильтр дискретизации на внедрение функции thumbnail.

Но для вас подфартило – я сделал модуль php-respimg (packagist), который делает всё необходимое. Его можно включить в проект при помощи Composer:

composer require nwtn/php-respimg

А потом изменять размер картинок вот так:

require_once(‘vendor/autoload.php’);
use nwtnRespimg as Respimg;
$image = new Respimg($input_filename);
$image->smartResize($output_width, 0, false);
$image->writeImage($output_filename);

Content Management Systems
Раз ваша CMS работает на PHP, берите секцию «PHP» и делайте из неё плагин. Раз вы используете WordPress, то вы сможете применять плагин RICG Responsive Images. Опосля его установки для активации нужно будет добавить последующее в файл functions.php:

function custom_theme_setup() {
add_theme_support( ‘advanced-image-compression’ );
}
add_action( ‘after_setup_theme’, ‘custom_theme_setup’ );

Остальные CMS так либо по другому дают доступ к функциям по работе с картинами – обратитесь к их документации.

Быстродействие
В собственных тестах я нашел, что по сопоставлению с –resize по умолчанию IM занимал в 2.25 раз больше времени на обработку картинок.

Заключение
Мы можем сделать веб-сайты наиболее шустрыми, сделать лучше их восприятие юзерами, и даже вывести наш контент на новейшие рынки. Дизайнеры и создатели чрезвычайно сильно влияют на то, как работает интернет. Урезание размера картинок делается достаточно просто и сильно влияет на повышение быстродействия веб-сайта – надеюсь, что вся эта информация окажется полезной для вас и дозволит для вас сделать лучше ваш веб-сайт для ваших юзеров.

Ссылки
grunt-respimg
php-respimg
RICG Responsive Images plugin habrahabr.ru