How to chain image conversions with ImageMagick's convert command?
I've got an original image (say, 1600x1200) for which I want to create a series of thumbnails with a variety of resolutions:
- 900x0 (i.e. means that the image is scaled proportionally to 900 px wide)
- 700x0
- 0x550 (i.e. means that the image is scaled proportionally to 550 px tall)
- 0x400
- 0x150
- 200x200 (i.e. cropped and centred)
Individually, I can process each of these conversions with a convert
command. The problem is that it's a huge waste of resources to continually rein开发者_开发技巧itialize convert
; it would be better to chain things so that convert
could reuse its work.
Using ImageMagick 6.7.0-10 I've tried the following (using the +write
option, see http://www.imagemagick.org/script/command-line-options.php#write), but it doesn't work as the +write
command appears to be ineffective in restoring the image to its original state:
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 for readability purposes
Alternatively, I tried the following (using +clone
and -delete
). It seems to work, but could probably be made more efficient (perhaps with 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' \
Can anyone explain what I'm doing wrong in the first example (with the +write
command)? Also, can anyone suggest any improvements to make things more CPU/memory efficient?
POST-ANSWER
I'm still curious why +write
doesn't work.
Turns out that using mpr:
is the way to go (from what I've seen on forums and whatnot):
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
NOTE: just in case you missed it, you don't need a -write
command for the last image in the chain.
ALSO NOTE: it's important that you use an extension on the files being output. If you omit it, convert
doesn't know which format it should use when writing them (presumably because storing the image in mpr:
destroys that information).
You misunderstood the meaning of the +write
argument. It will not undo any of your image processing performed previous to the write operation, it will only undo any processing caused by the write operation itself.
E.g. assume you have a JPG image and you do the following:
convert original.jpg -scale 50% -write output1.gif output2.jpg
What is going to happen? convert
reads original.jpg
to memory and shrinks it to half the resolution. Now it should write it to output1.gif
, but as the GIF format only supports images that are palette based, it will convert the image to 256 colors and write the GIF file. Now it will take the current image, which was reduced to 256 colors, convert it back to true color (24 Bit RGB) and write it to output2.jpg
, because JPG files don't support palette based images. Still, the JPG will look pretty much like if you had convert the GIF file to JPG (it will be limited to about 256 distinct colors).
Now let's try the same thing again, but this time we do the following:
convert original.jpg -scale 50% +write output1.gif output2.jpg
What is going to happen? convert
reads original.jpg
to memory and shrinks it to half the resolution. Now it should write it to output1.gif
, however, without modifying it, that's what the +write
is saying, so it first clones the image in memory. It converts the clone to 256 colors and writes the result to output1.gif
. Then it discards the clone again and continues processing with the image it had prior to cloning. This image is now written to output2.jpg
, which means this time, output2.jpg
will be a downscaled version of original.jpg
and not looking like a 256 color palette based image.
Under no circumstances the scale operation is undone, because it is completely unrelated to the write operation. If you want to undo the scale operation, you need to either save the image, scale it, write it and then restore it, or clone it, scale it, write it and then discard the clone. Either way should be equally fast because the number of copies performed in memory is identical in both cases, it's just the command line syntax that is different.
精彩评论