Эффективное создание эскизов с помощью ImageMagick и конвертирование
Я хочу эффективно генерировать миниатюры различных размеров с помощью утилиты ImageMagick convert в Python. Некоторые из моих файлов изображений довольно большие (~ 15 МБ JPG).
Одним из способов сделать это было бы взятие полноразмерного изображения и создание различных миниатюр из полноразмерного изображения следующим образом:
convert sample_image.jpg -resize 1024x768 sample_image-1024x768.jpg
convert sample_image.jpg -resize 800x600 sample_image-800x600.jpg
convert sample_image.jpg -resize 400x300 sample_image-400x300.jpg
convert sample_image.jpg -resize 200x150 sample_image-200x150.jpg
Но другим способом было бы изменить размеры изображений друг от друга:
convert sample_image.jpg -resize 1024x768 sample_image-1024x768.jpg
convert sample_image-1024x768.jpg -resize 800x600 sample_image-800x600.jpg
convert sample_image-800x600.jpg -resize 400x300 sample_image-400x300.jpg
convert sample_image-400x300.jpg -resize 200x150 sample_image-200x150.jpg
Есть ли недостаток в этом, или, может быть, лучший способ? Похоже, это было бы намного более эффективно.
Как следствие, существуют ли какие-либо флаги или "трюки" для конвертирования, чтобы ускорить процесс?
Ответы
Ответ 1
У ImageMagick есть несколько трюков с рукавами, которые помогут вам оптимизировать скорость, когда вы хотите обрабатывать большие изображения, и когда вы хотите создать другой вывод из того же оригинала:
-
Используйте функцию ImageMagick mpr:{name}
, которая позволяет временно сохранить входное изображение в регистр mpr:{name}
именованной памяти, из которого вы можете позже (во время обработки) читать данные намного быстрее, чем вы могли бы сделать с жесткого диска.
-
Выполняйте все операции изменения размера в одном процессе, выписывая различные требуемые размеры вывода.
И еще лучшая новость заключается в том, что вы можете объединить оба эти метода в одну команду.
Таким образом, вам не нужно запускать несколько процессов со всеми их накладными расходами на контекст - сделайте все за один раз.
Следующий пример также отображает две отдельные области из исходного изображения и создает из них уменьшенные эскизы, чтобы показать, сколько разных операций IM может выполнять в одной командной строке. Он также, конечно, выводит требуемые размеры. (Конечно, вам понадобится действительно крупноформатное входное изображение для работы параметров обрезки).
convert \
huge-original.jpg \
-quality 80 \
-colorspace rgb \
+profile '*' \
-filter Lanczos \
-write mpr:copy-of-huge-original \
+delete \
mpr:copy-of-huge-original -crop '3000x2000+0+480' -resize '200x125!>' -write thumb1-extract.jpg +delete \
mpr:copy-of-huge-original -crop '2000x1500+280+220' -resize '75x75!>' -write thumb2-extract.jpg +delete \
mpr:copy-of-huge-original -resize '1024x768' -write sample-1024x768.jpg +delete \
mpr:copy-of-huge-original -resize '800x600' -write sample-800x600.jpg +delete \
mpr:copy-of-huge-original -resize '400x300' -write sample-400x300.jpg +delete \
mpr:copy-of-huge-original -resize '200x150' -write sample-200x150.jpg +delete \
mpr:copy-of-huge-original -resize '163x163!>' -write sample-163x163.jpg
Обновить
Я только сейчас увидел вопрос, заданный @JonathanOng: Как передать поток на <stdout>
?
Предположим, вы хотите, чтобы формат, идущий в stdout, также был JPEG, вы можете попробовать следующее:
convert \
huge-original.jpg \
-quality 80 \
-colorspace rgb \
+profile '*' \
-filter Lanczos \
+write mpr:copy-of-huge-original \
mpr:copy-of-huge-original -crop '3000x2000+0+480' -resize '200x125!>' +write thumb1-extract.jpg \
mpr:copy-of-huge-original -crop '2000x1500+280+220' -resize '75x75!>' +write thumb2-extract.jpg \
mpr:copy-of-huge-original -resize '1024x768' +write jpeg:- \
mpr:copy-of-huge-original -resize '800x600' +write jpeg:- \
mpr:copy-of-huge-original -resize '400x300' +write jpeg:- \
mpr:copy-of-huge-original -resize '200x150' +write jpeg:- \
mpr:copy-of-huge-original -resize '163x163!>' +write jpeg:-
Таким образом, каждый вариант будет идти в стандартный вывод. Как вы справляетесь с этим потоком последовательных изображений тогда, зависит от вас...
Обратите внимание, что вместо имени -write filename +delete
вы можете использовать имя +write filename
. Это эквивалентно такому же эффекту.
Ответ 2
Я пробовал время vipsthumbnail
против @KurtPfeifle отличный ответ. Я запустил это с изображением RGB JPG размером 10k x 10k (около 15 МБ):
convert \
/data/john/pics/wtc.jpg \
-quality 80 \
-colorspace rgb \
+profile '*' \
-filter Lanczos \
-write mpr:copy-of-huge-original \
+delete \
mpr:copy-of-huge-original -resize '1024x768' -write sample-1024x768.jpg +delete \
mpr:copy-of-huge-original -resize '800x600' -write sample-800x600.jpg +delete \
mpr:copy-of-huge-original -resize '400x300' -write sample-400x300.jpg +delete \
mpr:copy-of-huge-original -resize '200x150' -write sample-200x150.jpg +delete \
mpr:copy-of-huge-original -resize '163x163!>' -write sample-163x163.jpg x.jpg
Я обнаружил, что мне нужно дополнительное x.jpg
в конце, я не знаю, почему. На этой машине (E5-1650 3,2 ГГц, IM 6.8.9-9) Я вижу:
$ time ./m.sh
real 0m6.560s
user 0m31.908s
sys 0m0.264s
peak RES 711MB
Это (я думаю) эквивалент с vipsthumbnail
:
img=/data/john/pics/wtc.jpg
icc=/usr/share/color/argyll/ref/sRGB.icm
for size in 1024x768 800x600 400x300 200x150 163x163; do
vipsthumbnail $img --size $size --eprofile $icc -o vips-sample-$size.jpg[Q=80]
done
vipsthumbnail
умолчанию Lanczos3. Сроки с vips-8.4.4 Я вижу:
$ time ./n.sh
real 0m2.376s
user 0m2.412s
sys 0m0.108s
peak RES 70MB
Таким образом, полезное ускорение и значительное снижение использования памяти.
Поскольку использование памяти низкое, вы можете запускать много vipsthumbnail
параллельно, не убивая ваш сервер. Если я изменю сценарий:
img=/data/john/pics/wtc.jpg
icc=/usr/share/color/argyll/ref/sRGB.icm
parallel vipsthumbnail $img \
--size {} --eprofile $icc -o vips-sample-{}.jpg[Q=80] ::: \
1024x768 800x600 400x300 200x150 163x163
Теперь я вижу:
$ time ./n.sh
real 0m0.593s
user 0m1.960s
sys 0m0.100s
peak RES 280MB
Более 10 раз быстрее, чем ImageMagick.
Ответ 3
Для моей точки зрения, и после тестирования, изменение размера с 1024x768 до 800x600 плохо для алгоритма масштабирования. Следующий размер более прост, из-за кратного целого числа (2).
Итак, по качественной причине, я лично делаю это, это лучше:
convert sample_image.jpg -resize 1024x768 sample_image-1024x768.jpg
convert sample_image.jpg -resize 800x600 sample_image-800x600.jpg
convert sample_image-800x600.jpg -resize 400x300 sample_image-400x300.jpg
convert sample_image-400x300.jpg -resize 200x150 sample_image-200x150.jpg
Ответ 4
15MB JPG действительно большие. Я бы сначала изменил его размер до разумного размера (скажем 2500x2500) с самым быстрым параметром -sample, и это уменьшенное изображение затем изменит размер на разные миниатюры.
Вы можете сделать разумное решение на основе размера изображения и выбрать правильный способ изменения размера.
Я бы рекомендовал сосредоточиться на качестве эскизов вместо скорости преобразования, поэтому, пожалуйста, посмотрите на различные фильтры (-filter), резкость (-unsharp) и рекомендуемые методы понижающей дискретизации
Ответ 5
Я thumbnailing ~ 50MB JPG файлы. Единственный вариант, который сделал наибольшую разницу (~ 5x speedup), был "-define jpeg: размер 128x128" перед входным именем файла. Пример, приведенный здесь:
http://www.imagemagick.org/Usage/formats/#jpg_read
... сделал огромную разницу:
convert -define jpeg:size=128x128 jpeg_large.jpg -thumbnail 64x64 jpeg_thumbnail.jpg
-define jpeg: размер позволяет ImageMagick считывать только столько данных, сколько нужно с диска, что значительно сокращает время загрузки для очень больших изображений.
Как показывает связанная страница, используйте jpeg: size = дважды ваш окончательный размер эскиза, чтобы избежать наложения псевдонимов.
Опция -thumbnail, описанная здесь:
http://www.imagemagick.org/Usage/resize/#thumbnail
... образцы и полоски изображения, ускоряя процесс.