Давид Мзареулян (david_m) wrote,
Давид Мзареулян
david_m

Categories:

Немного о быстром создании превьюшек

Допустим, вы на сервере, и к вам приходит картинка. Большая картинка, с какой-нибудь современной полнокадровой зеркалки или даже с Хасселя, мегапикселей на 40. И вам нужно из неё сделать превьюшку. Скажем, 150×150 пикселей. Как быть?



UPD В комментарии пришёл lusever и объяснил, что всё ниженаписанное — ерунда, и надо пользоваться GraphicsMagick вместо IM. Я проверил — действительно, так и есть. GM отличается от IM (помимо прочего) наличием ключе “-size”. Этот ключ “gives a hint to the JPEG decoder that the image is going to be downscaled to this size, allowing it to run faster by avoiding returning full-resolution images to GraphicsMagick for the subsequent resizing operation”. То есть, он делает ровно то, о чём я писал в посте — сначала быстро ресайзит JPEG на основе блоков (об этом в цитате не написано, но это можно понять, если поиграть с ключами команды), а потом уже доводит до нужного размера.




Стандартный способ — ImageMagick. Запускаем:

convert src.jpg -resize 150x150 dst.jpg

На моём десктопе время исполнения для 40-мегапиксельной картинки — 5 секунд. Это МНОГО. 5 секунд программа грузит процессор на полную катушку, да ещё и файл в память разворачивает (а развёрнутые 40 мегапикселей — это мегабайт 160 минимум). Можно ли тут что-нибудь оптимизировать? Оказывается, можно.

Есть такая малоизвестная утилитка — jpegtran, она входит в пакет libjpeg. Для Windows она тоже есть, бинарник можно скачать с сайта http://jpegclub.org/.

Эта утилитка предназначена для loseless (беспотерьных) преобразований JPEG-файлов. Как известно, JPEG — формат сжатия с потерями. Работает он так: картинка разбивается на квадратики 8×8 пикселей (редко — 16×16), каждый квадратик кодируется с потерями независимо от других. Это значит, что можно _не перекодируя данные_ просто переставить квадратики и собрать новую картинку. Ну, на самом деле над квадратиками тоже возможны беспотерьные преобразования, например, отражение или поворот на 90°.

jpegtran именно этим и занимается. Он позволяет _без перекодирования данных_ (а значит, не внося в картинку новых искажений):
а) поворачивать картинку на 90°, 180° и 270°;
б) отражать её по вертикали и горизонтали;
в) кадрировать;
г) …и много чего ещё.

Но тут, конечно, есть ограничения. Поскольку все операции делаются над блоками 8×8, то, например, при кадрировании координаты начала кропа должны быть кратны 8 по обеим осям. Отражение и отдельные повороты тоже работают только для картинок, чьи размеры по обеим осям делятся на 8. Ну, в общем, естественные ограничения.

Самое интересное для нас — в последней версии в jpegtran появилась возможность масштабирования (уменьшения) избражений. Да, тоже «без потерь», хотя тут это понятие довольно условное. Изменять размер картинки можно в рациональное число раз, причём в знаменателе дроби должна стоять восьмёрка. То есть, можно сделать картинку размером в 1/8 исходной, 2/8, 3/8 и т. д. Поскольку оперции, как и раньше, производятся над блоками, а не над пикселями, то всё происходит очень быстро.

Итак, возьмём нашу картинку и уменьшим в 8 раз:

jpegtran -scale 1/8 src.jpg dst1.jpg

Время исполнения — 1 секунда. Но 1/8 от 40-мегапиксельной картинки — это всё равно много (у меня это примерно 900×700), поэтому снова используем ImageMagick:

convert dst1.jpg -resize 150x150 dst.jpg

Время исполнения — 0.3 секунды, итого — 1.3 секунды на весь процесс, в 4 раза быстрее чем при лобовом применении IM. Плюс существенная экономия памяти, потому что оригинал картинки не раскодируется.

Применение ImageMagick на последнем шаге — необходимо, даже если дальнейшего уменьшения не нужно. Дело в том, что результатом работы jpegtran при ресайзе (и только при ресайзе, на остальные операции это не распространяется) является немного нестандартный JPEG, так называемый SmartScale JPEG. Я не знаю точно, что он из себя представляет, но Фотошоп и прочие доступные мне редакторы и смотрелки его не открывают. Но IM его понимает, и позволяет конвертировать в обычный JPEG.
Subscribe
  • Post a new comment

    Error

    Anonymous comments are disabled in this journal

    default userpic

    Your reply will be screened

    Your IP address will be recorded 

  • 22 comments