Search code examples
bashcommand-lineimagemagickwindows-subsystem-for-linuximage-manipulation

Can ImageMagick generate multiple outputs from one input?


I'm running this from the command line:

magick.exe input.png -shave '1x0' output_%d.png
magick.exe input.png -shave '2x0' output_%d.png
magick.exe input.png -shave '3x0' output_%d.png
magick.exe input.png -shave '4x0' output_%d.png
magick.exe input.png -shave '5x0' output_%d.png
magick.exe input.png -shave '0x1' output_%d.png
magick.exe input.png -shave '0x2' output_%d.png
magick.exe input.png -shave '0x3' output_%d.png
magick.exe input.png -shave '0x4' output_%d.png
magick.exe input.png -shave '0x5' output_%d.png

The first command creates output_0.png but the following commands overwrite the same file. Is there a single command that could generate output_0.png to output_9.png instead?

The ImageMagick documentation says:

Filename References

Optionally, use an embedded formatting character to write a sequential image list. Suppose our output filename is image-%d.jpg and our image list includes 3 images. You can expect these images files to be written:

image-0.jpg 
image-1.jpg
image-2.jpg

That's the closest evidence I found it's possible to do what I'm looking for in ImageMagick. It's not clear to me if I need to leverage shell scripting to do this or if ImageMagick provides a command line feature.


Solution

  • With ImageMagick you can run multiple operations on separate instances of the input image in a single command by cloning the input and isolating the operations inside parentheses like this...

    magick input.png \
       \( -clone 0 -shave '1x0' \) \
       \( -clone 0 -shave '2x0' \) \
       \( -clone 0 -shave '3x0' \) \
       \( -clone 0 -shave '4x0' \) \
       \( -clone 0 -shave '5x0' \) \
       \( -clone 0 -shave '0x1' \) \
       \( -clone 0 -shave '0x2' \) \
       \( -clone 0 -shave '0x3' \) \
       \( -clone 0 -shave '0x4' \) \
       \( -clone 0 -shave '0x5' \) \
       -delete 0 output_%02d.png
    

    That will create 10 output images, each with a sequential filename with the number padded to two places, like "output_00.png ... output_10.png".

    To convert this to Windows CMD syntax you can remove all the backslashes that escape the parentheses, and replace the continued-line backslashes "\" with carets "^".

    EDITED TO ADD: There are many ways to accomplish this task with ImageMagick. Here is another example command that would produce the same results, but it uses FX expressions so it will only work in IMv7. (The above command should work with IMv6 by changing "magick" to "convert".)

    magick input.png -duplicate 9 -shave "%[fx:t<5?t+1:0]x%[fx:t>4?t-4:0]" output_%02d.png
    

    This reads the input and duplicates it 9 times, then uses FX expressions as arguments to the -shave operation so it can step through all 10 images, shaving each according to the formula in the FX expression.