如何使用ImageMagick的convert命令链接图像转换?

5
我有一张原始图片(比如说,1600x1200),我想创建一系列缩略图,分别具有以下不同的分辨率:
  • 900x0(即按比例缩放为900像素宽)
  • 700x0
  • 0x550(即按比例缩放为550像素高)
  • 0x400
  • 0x150
  • 200x200(即裁剪并居中)
单独处理每个转换都可以使用convert命令。问题在于,不断重新初始化convert会浪费大量资源,最好的方法是链接这些操作,以便convert可以重复使用其工作。
使用ImageMagick 6.7.0-10,我尝试了以下操作(使用+write选项,参见http://www.imagemagick.org/script/command-line-options.php#write),但它似乎无效,因为+write命令不能将图像恢复到其原始状态:
convert '/tmp/original.jpg'[0] -quality 95 -density 72x72 -resample 72x72 +profile '!xmp,*'\
-resize '900>' +write '/tmp/900.jpg'\
-resize '700>' +write '/tmp/700.jpg'\
-resize '200x' -crop '200x200+0+35' +repage +write '/tmp/200.jpg' \
-resize 'x550>' +write '/tmp/550.jpg'\
-resize 'x400>' +write '/tmp/400.jpg'\
-resize 'x150>' '/tmp/150.jpg'\

* 为了提高可读性,可以使用行末反斜杠(end-of-line backslashes)

另外,我尝试了以下方法(使用+clone-delete),它似乎有效,但可能可以更加高效(也许使用mpr:http://www.imagemagick.org/Usage/files/#mpr):

convert 'original.jpg'[0] -quality 95 -density 72x72 -resample 72x72 +profile '!xmp,*' \
    \(+clone -resize 'x150>' -write '150.jpg' \) \ 
-delete 1 \(+clone -resize 'x400>' -write '400.jpg' \) \ 
-delete 1 \(+clone -resize 'x550>' -write '550.jpg' \) \ 
-delete 1 \(+clone -resize '200x' -crop '200x200+0+35' +repage -write '200.jpg' \) \ 
-delete 1 \(+clone -resize '700>' -write '700.jpg' \) -delete 1 -resize '900>' '900.jpg' \

有人能解释一下我在第一个例子中(使用+write命令)做错了什么吗?另外,有人能提出任何改进来使CPU/内存更有效率吗?

回答后

我仍然很好奇为什么+write不起作用。


@D Camey:您的IM似乎非常更新。您考虑过尝试在一两个之前发布的版本中使用+write命令吗?您考虑过向ImageMagick开发人员提交关于+write的错误报告吗? - Kurt Pfeifle
是的,我考虑过了。我想我会先在这里检查一下,以防我误解了文档或其他人有相同的问题。 - David Carney
2个回答

5
原来,根据我在论坛和其他地方看到的内容,使用“mpr:”是正确的方法:
convert 'original.jpg'[0] -quality 95 -density 72x72 -resample 72x72 +profile '!xmp,*' \
-write mpr:orig +delete \
mpr:orig -resize 'x150>' -write '150.jpg' +delete \
mpr:orig -resize 'x400>' -write '400.jpg' +delete \
mpr:orig -resize 'x550>' -write '550.jpg' +delete \
mpr:orig -resize '200x' -crop '200x200+0+35' +repage -write '200.jpg' +delete \ 
mpr:orig -resize '700>' -write '700.jpg' +delete \ 
mpr:orig -resize '900>' '900.jpg' +delete 

注意:如果您错过了,最后一个图像不需要使用-write命令。
另外请注意:在输出文件时使用扩展名非常重要。如果省略它,convert不知道在写入它们时应该使用哪种格式(可能是因为将图像存储在mpr:中会破坏该信息)。

4
你误解了+write参数的含义。它不会撤消之前执行的任何图像处理,只会撤消写入操作本身所造成的任何处理。 例如,假设你有一张JPG图片并执行以下操作: convert original.jpg -scale 50% -write output1.gif output2.jpg 会发生什么?convert将把original.jpg读入内存并将其缩小到二分之一的分辨率。现在应该将其写入output1.gif,但由于GIF格式仅支持基于调色板的图像,因此它将转换图像为256种颜色并写入GIF文件。现在,将当前图像(减少到256种颜色)转换回真彩色(24位RGB),然后写入output2.jpg,因为JPG文件不支持基于调色板的图像。尽管如此,JPG看起来与将GIF文件转换为JPG相似(将限制为大约256种不同的颜色)。
现在让我们再试一次相同的操作,但这次我们执行以下操作: convert original.jpg -scale 50% +write output1.gif output2.jpg 会发生什么?convert将把original.jpg读入内存并将其缩小到二分之一的分辨率。现在应该将其写入output1.gif,但是不修改它,这就是+write所表示的,因此它首先克隆内存中的图像。它将克隆体转换为256种颜色并将结果写入output1.gif。然后再次丢弃克隆体,并继续处理它在克隆之前所具有的图像。现在,这个图像被写入output2.jpg,这意味着这次,output2.jpg将是original.jpg的缩小版本,而不是看起来像256种颜色调色板的图像。
在任何情况下,缩放操作都不会被撤消,因为它与写入操作完全无关。如果要撤消缩放操作,则需要保存图像,对其进行缩放,写入它,然后恢复它,或者克隆它,对其进行缩放,写入它,然后丢弃克隆体。两种方法的执行速度应该相同,因为内存中执行的副本数量相同,只是命令行语法不同。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接