使用ImageMagick高效生成缩略图并进行转换

时间:2012-08-30 22:03:38

标签: imagemagick thumbnails imagemagick-convert

我希望用Python中的ImageMagick转换实用程序有效地生成各种大小的缩略图。我的一些图像文件非常大(约15MB 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

这样做有什么缺点,或者更好的方法吗?看来这会更有效率。

作为必然结果,是否有任何标志或“技巧”转换用途来加速这一过程?

5 个答案:

答案 0 :(得分:17)

ImageMagick有一些技巧可以帮助您在处理大型图像时优化速度,并且当您想要从同一原始图像创建不同的输出时:

  1. 利用ImageMagick的mpr:{name}功能,使其暂时将输入图像保存到命名的内存程序寄存器中,以后可以使用该功能(处理)以比硬盘更快的速度读取数据。

  2. 单个进程中进行所有调整操作,并写出所需的不同输出大小。

  3. 更好的消息是,您可以将这两者合并为一个命令。

    因此,您不需要使用所有上下文切换开销来运行多个进程 - 一次完成所有操作。

    以下示例还会从原始图像中裁剪两个单独的区域,并从中创建重新调整大小的缩略图,以显示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:-
    

    这样每个变体都会转到stdout。那么你如何处理这一连续图像流,取决于你......

    注意 ,您可以使用-write filename +delete代替+write filename。它的效果相同。

答案 1 :(得分:1)

我尝试对{KurtPfeifle的优秀答案进行计时vipsthumbnail。我使用10k x 10k像素RGB JPG图像(大约15MB)运行它:

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 GHz,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

比ImageMagick快10倍以上。

答案 2 :(得分:0)

对于我的观点,并且在测试之后,将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

答案 3 :(得分:0)

15MB的JPG非常大。我会先用最快的“-sample”参数将其调整到合理的大小(例如2500x2500),然后将这个较小的图像调整为不同的缩略图。

您可以根据图像大小做出明智的决定,并选择正确的调整大小的方法。

我建议您专注于缩略图质量而非转换速度,因此请查看不同的过滤器(-filter),锐化(-unsharp)和recommended downsampling methods

答案 4 :(得分:0)

我正在缩略图~50MB的JPG文件。在输入文件名之前,最大差异(~5x加速)的一个选项是“-define jpeg:size 128x128”。这里给出的例子:

http://www.imagemagick.org/Usage/formats/#jpg_read

......产生了巨大的变化:

convert -define jpeg:size=128x128 jpeg_large.jpg -thumbnail 64x64  jpeg_thumbnail.jpg

-define jpeg:size允许ImageMagick只读取磁盘所需的数据,这大大减少了非常大的图像的加载时间。

如链接页面所示,使用jpeg:size =最终缩略图大小的两倍以避免别名。

-thumbnail选项,如下所述:

http://www.imagemagick.org/Usage/resize/#thumbnail

...对图像进行采样和剥离,从而进一步加快处理速度。