ImageMagick单转换命令性能

时间:2017-02-03 11:17:48

标签: php imagemagick imagemagick-convert

我有几千个要处理的图像,因此每毫秒都很重要。每张图片的大小约为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&#s; 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"

6 个答案:

答案 0 :(得分:3)

你没有使用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

答案 1 :(得分:3)

埃里克和约翰的建议分享了很多智慧,可以和我的建议混在一起 - 即使用 GNU Parallel 。当你有数千张图片时,它真的会计算在内。

我创建了100个图像(实际上使用GNU Parallel,但这不是重点),称为image-0.jpgimage-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 的速率。

enter image description here

答案 2 :(得分:2)

很有趣,因为我前一段时间做了一些转换,发现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 \)"..

我永远不会记得它是在文件名之前还是之后

答案 3 :(得分:2)

在Magick Persistent Registry(.mpc)上尝试Magick持久缓存图像文件格式(.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

答案 4 :(得分:0)

ImageMagick有一个名为-thumbnail <geometry>的特殊调整大小运算符变体,用于将非常大的图像转换为小缩略图。在内部,它使用

  1. -sample将图像缩小到最终高度的5倍,如果缩略图比原始图像小得多,则比-resize快得多。 由于此运算符使用简化的滤镜集,因此忽略-filter运算符!
  2. -strip从图片中删除缩略图通常不需要的所有配置文件。这也进一步减小了生成的图像文件的大小。
  3. -resize最终创建所需的尺寸和比率
  4. 当谈到从JPEG图像创建缩略图时,可以使用特殊的JPEG缩放加载选项-define jpeg:size=<size>,如user894763所述。 请注意,必须在convert之后立即指定此选项,例如:

    convert -define jpeg:size=<size> input-image.jpg ...
    

    无论如何,-thumbnail运算符可以另外指定,因为它会从缩略图图像中删除所有配置文件,从而减小文件大小。

    详细信息可在ImageMagick usage documentation

    中找到

答案 5 :(得分:0)

我在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

时间:0m0.952s

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,因此每次编写和读取中间图像时都会失去更多的视觉质量。因此,一条长命令行的质量也应该更好。