我有几千个图像要处理,所以每毫秒计数。每张图片的大小约为2-3Mb。
源文件送到转换器:image.jpg
要从源生成的文件:
orig_image.jpg // original image
1024x768_image.jpg // large image
250x250_image.jpg // thumbnail 1
174x174_image.jpg // thumbnail 2
在浏览imagemagick转换性能的不同主题时,我感觉单个命令应该比每个图像大小的单个转换更快。此外,还提到了内存利用率作为性能提升。 (ImageMagick batch resizing performance)
多个命令转换(每个命令在循环中通过php的exec()运行):
convert "image.jpg" \
-coalesce -resize "1024x768>" +repage "1024x768_image.jpg"
convert "1024x768_image.jpg" \
-coalesce \
-resize "250x250>" \
+repage \
-gravity center \
-extent "250x250" "250x250_image.jpg"
convert "1024x768_image.jpg" \
-coalesce \
-resize "174x174>" \
+repage \
-gravity center \
-extent "174x174" "174x174_image.jpg"
mv image.jpg orig_image.jpg
包含ImageMagicks mpr的单一命令转换:
convert "image.jpg" -quality 85 -colorspace rgb -coalesce \
-resize "1024x768>" \'
-write "1024x768_image.jpg" \
-write mpr:myoriginal +delete \
mpr:myoriginal -coalesce \
-resize "250x250>" \
-gravity center \
-extent "250x250" \
-write "250x250_image.jpg" +delete \
mpr:myoriginal -coalesce \'
-resize "174x174>" \
-gravity center \
-extent "174x174" \
-write "174x174_image.jpg"
性能测试后,结果有些出乎意料。循环中的单个命令转换在62秒内完成,而多个命令转换仅在16秒内执行?
# convert -version
Version: ImageMagick 7.0.2-1 Q8 i686 2017-02-03 http://www.imagemagick.org
Copyright: Copyright (C) 1999-2016 ImageMagick Studio LLC
License: http://www.imagemagick.org/script/license.php
Features: Cipher DPC HDRI OpenMP
Delegates (built-in): bzlib freetype jng jpeg lzma png tiff wmf xml zlib
还安装了libjpeg-turbo jpg处理库,但我不知道(不知道如何检查)如果ImageMagic正在使用它或旧的libjpeg。
任何想法如何加快图像转换过程?
编辑:不知道如何在stackoverflow上正确格式化它,但我只是注意到单行命令有一个参数“-colorspace rgb”并且多行命令没有实际导致如此奇怪的结果,其中多个命令被更快地处理。
删除了“-colorspace rgb”参数,之后MPR转换版本运行最佳,并提供了额外的性能提升。
总而言之,我最终使用了这个命令:
// MPR
convert "orig_image.jpg" -quality 80 -coalesce \
-resize "1024x768>" \
-write 1024x768_image.jpg \
-write mpr:myoriginal +delete \
mpr:myoriginal -resize "250x250>" \
+repage -gravity center -extent "250x250" \
-write "250x250_image.jpg" \
-write mpr:myoriginal +delete \
mpr:myoriginal -coalesce -resize "174x174>" \
+repage -gravity center -extent "174x174" \
-write "174x174_image.jpg"
你没有使用jpeg收缩负载,这将提供一个简单的加速。
jpeg库有一个简洁的功能,它可以让你以全分辨率,1 / 2,1 / 4或1/8进行解压缩。由于jpg在内部工作的方式,1/8分辨率特别快。
要在convert
中利用它,你需要提示你需要一个特定大小的图像的jpeg加载器。为避免混叠,您应该要求至少比目标尺寸大200%的图像。
在这台机器上,我看到:
$ vipsheader image.jpg
image.jpg: 5112x3470 uchar, 3 bands, srgb, jpegload
$ time convert image.jpg -resize 1024x768 1024x768_image.jpg
real 0m0.405s
user 0m1.896s
sys 0m0.068s
如果我设置了收缩负载提示,它的速度提高了约2倍:
$ time convert -define jpeg:size=2048x1536 image.jpg -resize 1024x768 1024x768_image.jpg
real 0m0.195s
user 0m0.604s
sys 0m0.016s
对于非常大的jpg文件,你会看到一个惊人的加速。
你也可以考虑另一个缩略图。例如,vipsthumbnail
再次快一点:
$ time vipsthumbnail image.jpg -s 1024x768 -o 1024x768_image.jpg
real 0m0.111s
user 0m0.132s
sys 0m0.024s
虽然实时时间仅下降了2倍,但用户时间却下降了5倍左右。这使得与gnu并行运行很有用。例如:
parallel vipsthumbnail image.jpg -s {} -o {}_image.jpg ::: \
1024x768 250x250 174x174
埃里克和约翰的建议有很多智慧,可以和我的建议混在一起 - 这就是使用GNU Parallel。当你有成千上万的图像时,它真的会计算在内。
我创建了100个图像(实际上使用GNU Parallel,但这不是重点),通过image-0.jpg
称为image-99.jpg
。然后,我做了一个简单的调整大小操作,只是为了展示如何做到这一点,而不是太多挂在ImageMagick方面。首先,我按顺序执行,花了48秒来调整100张图像,然后我使用GNU Parallel做了完全相同的事情,并在10秒内完成 - 因此可以节省大量时间。
#!/bin/bash
# Create a function used by both sequential and parallel versions - it's only fair
doit(){
echo Converting $1 to $2
convert -define jpeg:size=2048x1536 "$1" -resize 1024x768 "$2"
}
export -f doit
# First do them all sequentially - 48 seconds on iMac
time for img in image*.jpg; do
doit $img "seq-$img"
done
# Now do them in parallel - 10 seconds on iMac
time parallel doit {} "par-{}" ::: image*.jpg
只是为了踢 - 观看CPU测量仪(在电影的右上角)和文件在电影的最后1/6中弹出GNU Parallel的速率。
这很有趣,因为我前一段时间做了一些转换,发现mpr也慢了。无论如何试试这个:
$cmd = " convert "image.jpg" -colorspace rgb -coalesce \( -clone 0 -resize 1024x768> -write 1024x768_image.jpg +delete \)".
" \( -clone 0 -resize 250x250> -gravity center -extent 250x250 -write 250_wide.jpg +delete \) ".
" -resize 174x174> -gravity center -extent 174x174 null: ";
exec("convert $cmd 174x174_image.jpg ");
我注意到你没有背景颜色。
您还可以在循环方法中添加-define,并在此列表中查看:https://www.imagemagick.org/script/command-line-options.php#define jpeg:size = geometry仅读取创建图像所需的数据量而不读取整个图像。您也可以将它添加到第一行。 -quality用于输出,并且在您放置它时不起作用。
$cmd = " convert "image.jpg" jpeg:size=1024x768 -colorspace rgb -coalesce \( -clone 0 -resize 1024x768> -write 1024x768_image.jpg +delete \)"..
我永远不会记得它是在文件名之前还是之后
在Magick Persistent Registry(.mpc
)上尝试Magick Persistent Cache图像文件格式(.mpr
)。
convert "image.jpg" -quality 85 -colorspace rgb myoriginal.mpc
convert myoriginal.mpc \
-resize "1024x768>" \
-write "1024x768_image.jpg" \
-resize "250x250>" \
-gravity center \
-extent "250x250" \
-write "250x250_image.jpg" \
-resize "174x174>" \
-gravity center \
-extent "174x174" \
"174x174_image.jpg"
当使用1.8mb jpeg进行测试时,会导致以下时间。
real 0m0.051s
user 0m0.133s
sys 0m0.013s
确实,这将需要两个命令(尽管可以简化为-write ... +delete
),但在将.mpc
加载回图像堆栈后,I / O成本非常低。
要么
你可以跳过.mpc
和...
convert "image.jpg" -quality 85 -colorspace rgb \
-resize "1024x768>" \
-write "1024x768_image.jpg" \
-resize "250x250>" \
-gravity center \
-extent "250x250" \
-write "250x250_image.jpg" \
-resize "174x174>" \
-gravity center \
-extent "174x174" \
"174x174_image.jpg"
结果......
real 0m0.061s
user 0m0.163s
sys 0m0.012s
ImageMagick有一个名为-thumbnail <geometry>
的特殊调整大小运算符变体,用于将非常大的图像转换为小缩略图。它在内部使用
-sample
将图像缩小到最终高度的5倍,如果缩略图比原始图像小得多,则比-resize
快得多。因为此运算符使用减少的滤波器集,所以忽略-filter
运算符!-strip
删除图像中通常不需要缩略图的所有配置文件。这还进一步减小了生成的图像文件的大小。-resize
最终创建所需的大小和比例在从JPEG图像创建缩略图时,可以使用特殊的JPEG缩放加载选项-define jpeg:size=<size>
,如user894763所述。请注意,必须在convert
之后立即指定此选项,例如:
convert -define jpeg:size=<size> input-image.jpg ...
无论如何,-thumbnail
运算符可以另外指定,因为它从缩略图图像中删除所有配置文件,从而减小文件大小。
详细信息可以在ImageMagick usage documentation找到。
我在ImageMagick 6.9.10.0 Q16 Mac OSX中使用一个命令行大约一半的时间从3 MB输入JPG图像开始。
list="image.jpg"
time for img in $list; do
convert "image.jpg" \
-coalesce -resize "1024x768>" +repage "1024x768_image.jpg"
convert "1024x768_image.jpg" \
-coalesce \
-resize "250x250>" \
+repage \
-gravity center \
-extent "250x250" "250x250_image.jpg"
convert "1024x768_image.jpg" \
-coalesce \
-resize "174x174>" \
+repage \
-gravity center \
-extent "174x174" "174x174_image.jpg"
done
时间:0分90秒
time convert "image.jpg" \
-resize "1024x768>" \
+write "1024x768_image.jpg" \
-resize "250x250>" \
-gravity center \
-extent "250x250" \
+write "250x250_image.jpg" \
-resize "174x174>" \
-gravity center \
-extent "174x174" \
"174x174_image.jpg"
时间:0m0.478s
由于JPG不支持虚拟画布,因此不需要在多个命令中合并。因此删除它会将乘法命令行时间减少到0m0.738s
由于您必须编写和读取中间图像,因此多个命令应该更长。由于您的中间图像是JPG,因此每次编写和读取中间图像时都会失去更多的视觉质量。因此,一条长命令行的质量也应该更好。