Imagemagick convert and groups

I was willing to make some combined images to show off Camille Dolls, but I wanted to have good alignement and spacing between the pictures. I gave a shot at doing it by hand with Gimp but making alignement and spacing by hand was kind of a hassle. I'm pretty sure I missed some features which may have made it easier, but I decided to search another solution. Scribus seems to be made for this kind of things, but tends to be restrictive toward the final output given its main purpose being to design final paper documents.i

In the end, I decided to play with convert and other Imagemagick tools, which proved quite efficient once I got the grasp of groups.

When issuing a convert command for example, you can group set of option and they will be treated like an image. This allows more flexibility in the order to achieve your final result in less command and without, or with less intermediate images.

To stack 2 pictures on top of each other with a 10 pixels separation and a 10 pixels border around the whole thing, the steps are:

  • take first image
  • extent it by its height + 10
  • take second image
  • stack them
  • add border to whole thing

A useful command is identify which can give you output information about an image, and allows calculations to be done, to get the height + 10:

identify -format 'x%[fx:H+10]' in.png

To group commands in convert you put them between parenthesis, that needs to be escaped so your shell don't interpret them:

convert \( \( command1 \) \( command2 \) \) command_on_result out.png

So for our example:

img1=A.png
img2=B.png
convert \
    \( \ # group for resulting images stacked
        \( $img1 -extent $(identify -format 'x%[fx:H+10]' $img1) \) \ # take first pic and add 10px
        $img2 \
    \) \
    -append # stack images
    -border 10x10 \ # add border around stacked images
    out.png

A more complete thing I did was stack 2 pictures on the left, for a total of 800px, and then add another picture of 800px on the right, so to achieve this:

  • resize first picture to 395px height
  • add 10px space
  • resize the second picture to 395px height
  • stack them
  • add 10px to width to the result, you need to know the width of the resized images
  • add last picture to the right
  • add border

In term of convert:

convert \( \
  \( \
    \( -geometry x395 img1.png -extent x405 \) \ # resize + add 10px margin
    img2.png  -append \
  \) -extent 405x \ # add 10px to width
  img3.png
  \) +append \
  -border 10x10 \
  out.png

I hope this can be of some help to someone, you can check out my results.