I'm trying to get ImageMagick to perform multiple operations (in this case, crops) in a single invocation, but it doesn't seem to be possible. For example, I can do a crop, rotate, and then another crop as two separate commands:
$ convert test.jpg -crop 223x187+588+757 -rotate 330 crop2.jpg
$ convert crop2.jpg -crop 200x100+43+87 crop3.jpg
But if I try to combine them into a single command, I get an error:
$ convert test.jpg -crop 223x187+588+757 -rotate 330 -crop
200x100+43+87 crop3.jpg
convert: geometry does not contain image `test.jpg' @ warning/transform.c/CropImage/666.
Obviously I could just create a pipe, but if possible I want to avoid the extra overhead of multiple processes. Is there a way to do this?
Update:
Also, a pipe seems problematic: I don't want an extra compress/decompress stage so I try piping it as RGB, but I can't seem to get the parameters right:
convert test.jpg -crop 223x187+588+757 -rotate 330 rgb:- | convert -size 287x273 -depth 8 rgb:- -crop 200x100+43+87 crop3.jpg
convert: unexpected end-of-file `-': No such file or directory @ error/rgb.c/ReadRGBImage/231.
Ok, so it turns out the above error is because my calculated size for the image differs from ImageMagick's calculations by two pixels. So obviously having to try to get the image size calculation exactly the same as IM is an extra problem introduced by the need to pipeline the two commands.
Here is a more generic approach to the question.
ImageMagick provides a few clever tricks which can help to optimize processing speed when...
- ...you want to process large images and
- ...when you want to create different output from the same original.
There are different methods which can even be combined:
- Take advantage of ImageMagick's special
mpr:{label}
format and syntax.
This tells ImageMagick to temporarily save the input image into a named magick program register label.
(I've also seen it explained as magick persistent (memory) register or memory program register.)
The command pipeline can then later (while processing) read the image data much faster from there than it could read from harddisk.
And the command can read it as often as you want, multiple times.
- Take advantage of ImageMagick's special
mpc:{name}
format and syntax.
This works similar to mpr:
.
Its long name is magick pixel cache.
I've also seen it as magick persistent (disk) cache.
MPC is the native in-memory uncompressed file format of ImageMagick, but dumped to disk.
Once written to disk, it can be re-read faster into memory again than a JPEG, TIFF or PNG could, because no conversion is needed.
- Construct a clever command sequence.
Make use of "sideway" processing, using the
\( ... \)
syntax in escaped parentheses where appropriate.
MPC
When the convert
command reads input image (JPEG, TIFF, GIF, PNG... whatever format it may currently be), it first processes this format into an MPC.
This processed result is kept in RAM as an uncompressed raster format.
From there the further conversions and image manipulations happen.
When you want write an MPC to disk as MPC you can use +write mpc:myfilename
.
This basically is simply a direct memory dump to disk.
ImageMagick then writes two, not one, (and larger than usual) binary files: myfilename.mpc
and myfilename.cache
.
The .mpc
file holds the metadata of the image, .cache
holds the actual pixel cache data.
A read from this disk file(s) is a fast memory map from disk to memory as needed (similar to memory page swapping).
But since the initial +write
operation did store the native uncompressed internal, IM-native raster format, now no image decoding is needed.
So this can be faster (especially for large images) to use, IF you cannot avoid writing temporary files out which you need to read in again.
However, be careful with your disk space.
Remember to clean up, once you no longer need the MPC file on disk.
IM will not automatically track your +write
commands for you.
(More technical details: MPC as a disk file format is not portable.
It also isn't suitable as a long-term archive format.
Its only suitability is as an intermediate format for high-performance image processing.
It requires two files to support one image.
It is not guaranteed to be 'stable' in between ImageMagick releases.
It may not work on a different machine from the one where you created it.)
If you still want to save this format to disk, remember this:
- Image attributes are written to a file with the extension .mpc.
- Image pixels are written to a file with the extension .cache.
MPC's main advantages lay in...
- ...processing very large images, or when
- ...applying several operations on one and the same image in "operation pipelines".
MPC was designed especially for workflow patterns which match the criteria "read many times, write once".
MPR
The MPR format (memory persistent register) does something similar as MPC.
It makes the image available via a named memory register.
You can use whatever name you want (even numbers).
Your process pipeline can also read the image again from that register -- multiple times even, should it need to do so.
The image mpr:label
persists in the register until the current command pipeline exits. (This is the difference to a to-disk-written mpc:filename
. This persists the completion of the current pipeline; it even survives system reboots.)
Clever command pipeline
(My use of the word 'pipeline' here is not to be confused with the pipelines in a shell, where multiple commands and processes are started and chained.
Here I talk only about a single invocation of convert
which chains multiple image manipulations and operations into one process.)
So it is possible to accomplish all resize, crop, append, thumbnailing, color-manipulating, blurring, ... what-have-you operations in one single process writing out the different intermediate outputs you require.
Practical example...
...hmm, I'm not so sure if it is soooo practical. I haven't tested it, I just used my phantasy to construct an example which shows the principles about the usage of the different concepts.
Note: +write someimage
is the same as -write someimage +delete
.
convert \
very-very-large.jpg \
-write mpr:XY \
+delete \
-respect-parentheses \
\( mpr:XY -crop '3000x2001+0+491' -resize '170x116!>' +write pic1.png \) \
\( mpr:XY -crop '2981x2883+8+0' -resize '75x75!>' +write pic2.png \) \
\( mpr:XY -crop '1100x1983+0+0' -resize '160x160!>' +write pic3.png \) \
\( mpr:XY -crop '2000x2883+0+0' -resize '1024x960!>' +write pic4.png \) \
\( mpr:XY -crop '1000x2883+0+0' -resize '190x188!>' +write mpr:pic5 \) \
\( mpr:pic5 +write pic5.png \) \
\( mpr:XY -crop '3000x2000+0+0' -resize '2048x2047!>' +write pic6.png \) \
\( mpr:XY -crop '3000x2883+0+0' -resize '595x421!>' +write pic7.png \) \
\( mpr:XY -crop '3000x2883+0+0' -resize '3000x2883!>' +write mpr:AB \) \
\( mpr:AB +write pic8.tiff \) \
\( mpr:AB -blur 0x8 +write blur1.gif \) \
\( mpr:pic5 mpr:AB +append mpr:pic5 -append +write append.jpg \) \
\( mpr:pic5 -rotate -130 mpr:AB -gravity center \
-compose difference -composite +write final.png \) \
null:
After the first operation, -write mpr:XY
, there are two images in the stack:
- the input file,
very-very-large.png
, and
- a copy of it which can be read from memory using its label
XY
.
We do not need the first of these two any more.
Hence we use +delete
to remove it from the stack.
So this command used one single command pipeline which carried out multiple commands and manipulations creating 11 different output images in one go:
pic{1,2,3,4,5,6,7}.png
, blur1.gif
, pic8.tiff
, append.jpg
and final.png
.
Quick'n'dirty answer: Insert a +repage
into your first single command:
convert test.jpg \
-crop 223x187+588+757 \
-rotate 330 \
+repage \
-crop 200x100+43+87 \
crop3.jpg
Long and comprehensive answer: Will follow later. I have to complete another task first. The long answer will give you a more generic approach, how you can crop multiple sections in one single command, while keeping up performance.