Ускоряем обработку изображений

Всем привет! Сегодняшний пост посвящен производительности при обработке изображений. Почти в каждом проекте требуется обработка изображений, например, ресайзинг, поворот, обесцвечивание и т.д. Для этих целей я использовал широко известное решение, написанное на php и работающее с расширением GD - class.upload.php. До тех пор пока в проектах в основном изображения загружались через админку меня это решение полностью устраивало. Но в одном из последних проектов изображения являются одним из главных видов контента и загружаются пользователями в больших объемах. При профилировании я заметил что процесс ресайзинга и обработки изображений занимает очень много времени. Особенно это бросалось в глаза при использовании функции "повернуть изображение", которая должна делать ajax-запрос и отображать повернутое изображение пользователю. При достаточно большом разрешении изображения скрипт падал по timeout не успев вложиться в 30 с в других случаях была очень большая задержка. Далее я опишу каким образом была решена данная проблема и предоставлю несколько результатов тестов для сравнения.

Выбор инструмента

Очевидным решением было перенести данный функционал на консольную утилиту. Мой выбор пал на GraphicsMagick, т.к. данная утилита реализует все необходимые мне функции и при этом достаточно проста в использовании и хорошо документирована. Для установки в debian необходимо выполнить:

apt-get install graphicsmagick

Запуск выполняется при помощи команды gm. Рассмотрим несколько примеров использования.

Конвертирование изображений.

gm convert -quality 80 input.png output.jpg

Утилита выполнит конвертирование файла input.png в формат jpeg и сохранит как output.jpg. При помощи опции -quality выставляем качество выходного изображения в стандартной для jpeg форме.

Ресайзинг

Ресайзинг с установленной шириной (300px) и автоматически выбранной высотой с сохранением соотношения сторон:

gm convert -resize 300 input.jpg output.jpg

Ресайзинг с установленной высотой (200px) и автоматически выбранной шириной:

gm convert -resize x200 input.jpg output.jpg

Ресайзинг без сохранения пропорций:

gm convert -resize 300x200! input.jpg output.jpg

Ресайзинг с сохранением пропорций и вписыванием в заданный размер по большей стороне:

gm convert -resize 300x200 input.jpg output.jpg

Ресайзинг с сохранением пропорций и вписыванием в заданный размер по меньшей стороне:

gm convert -resize 300x200^ input.jpg output.jpg

Ресайзинг с сохранением пропорций, вписыванием по меньшей стороне и обрезкой лишнего с центированием:

gm convert -resize 200x300^ -gravity center -crop 200x300+0+0 input.jpg output.jpg

Поворот

gm convert -rotate 90 input.jpg output.jpg

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

Параметры можно комбинировать, что значительно упрощает выполнение сложных операций

Бенчмарк

Теперь, как и обещал, немного цифр. Сравним производительность php решения (class.upload.php) и утилиты GraphicsMagick.

Конвертирование изображений

Конвертируем 40 Mb изображение из png в jpeg.

  Время (с)
upload.class.php 97.150
GraphicsMagick 3.304

Ротация изображений

Поворачиваем изображение (jpeg файл 6.4 Mb) на 90 градусов.

  Время (с)
upload.class.php 162.750
GraphicsMagick 2.6597

Нарезка thumbnails

Нарезка 5 thumbnails различной конфигурации из jpeg файла 6.4 Mb.

  Время (с)
upload.class.php 12.010
GraphicsMagick 4.594

Выводы

Результаты теста вполне ожидаемы и из них можно сделать выводы, что обрабатывать изображения средствами php следуют только в крайних случая. Например, если вы используете shared hosting или если изображения добавляются не часто и только через админку. Также к плюсам upload.class.php можно отнести простоту в использовании, т.к. он предоставляет удобный класс со всеми необходимыми методами, но написать небольшую объектную обертку для GraphicsMagick я думаю не составит труда.