Combining multiple images in ImageMagick with relative (not absolute) offsets

Przemek Kujonewicz picture Przemek Kujonewicz · Sep 5, 2012 · Viewed 10.9k times · Source

I'm looking for the most efficient way to stitch multiple images together in ImageMagick, on top of a background image, such that the spacing / padding between the overlaid images is consistent?

I've investigated use of +append, convert -composite, and convert with -page and -layers merge.

The following command (convert -composite) works, but requires precalculation of image dimensions in order to specify absolute offsets. Really, I want a 10 pixel gap between the end of the FIRST layered image and the start of the second layered image, but the only way I can see to achieve that is by specifying the absolute offset from the top-left corner of the canvas.

convert \
  background.jpg \
  first.jpg -gravity Northwest -geometry  +10+10 -composite \
  second.jpg                   -geometry +300+10 -composite \
  third.jpg                    -geometry +590+10 -composite \
  output.jpg

I am looking for some sort of operator so that the horizontal offset can be interpreted relative to the "last" image in the layering, so instead of specifying +300+10 for the second image and +590+10 for the third, I can somehow specify a +10+10 offset.

I thought gravity would allow me to achieve that (-gravity Northwest), in the same way that float: left; works in CSS positioning, but that is not the case.

I have also had some success with the following:

convert \
  -page  +10+10 first.jpg  \
  -page +300+10 second.jpg \
  -page +590+10 third.jpg  \
  -background transparent  \
  -layers merge \
   layered.png

convert background.jpg layered.png -gravity Center -composite output.jpg

Both the techniques described require pre-calculation of absolute offsets, which is a bit of a pain. Is there a better way to do this?

Answer

Kurt Pfeifle picture Kurt Pfeifle · Sep 5, 2012

You've overlooked the montage command.

The most simple command to add the wanted spacing with it would be to set a -frame 5 option with -mattecolor none. This works with images of different width values and spaces them all apart with a distance of 10 pixels:

montage             \
  -alpha on         \
  -background none  \
  -mode concatenate \
  -tile x1          \
  -frame 5          \
  -mattecolor none  \
   *.jpg            \
   output1.png

You'll easily notice however, that the resulting image's border is only 5 pixels wide on top, right, bottom and left. To remove these 5 pixels all around use:

convert  output1.png  -shave 5  output2.png

To overlay this result on your background.jpg, use:

convert             \
  background.jpg    \
  output2.png       \
 -gravity Northwest \
 -geometry +10+10   \
 -composite         \
  final.jpg