There is probably no need for me to introduce a great library for processing images: imagemagick. In this mini how-to I will show how I’ve used imagemagick to build an image from few different pieces of media (images and text).

Problem

I wanted to build simple screensaver using public domain images and information. For this, I needed to create a lot of static .gif images with flags of the countries and some basic information about them. For  each image I wanted to use:

  • Country name – I had that as a string somewhere (it’s not relevant for this how-to how was I storing each piece of information – we’ll focus on imagemagick itself)
  • Country flag as .gif file. Each file was slightly different size.
  • Short description of the flag and country.

Solution

Well.. imagemagick and some commandline hackery is the solution of course.
First, I had to create and image from country name. As it turned out, some of the country names can get pretty long and they won’t fit into one line on the image. I have used simple fold utility to wrap longer lines. Imagine that we have name of the country in the variable $name. We process it like this:

echo $name | fold -s -w 30 | sed -n '1h;2,$H;${g;s/\n/\\n/g;p}'

fold -s -w 30 folds our $name without breaking the words (-s) and leaves at most 30 characters per line (-w 30). The scary looking sed command is probably an idea for another whole blog entry – but basically it simply changes newline into two characters: \n. imagemagick will use these to create the newlines when generating an image.
We are ready to generate GIF image that contains the name of the country:

convert -font /usr/share/fonts/truetype/thai/Purisa-BoldOblique.ttf -pointsize 58 -background $BACKGROUND label:"$(echo $name | fold -s -w 30 | sed -n '1h;2,$H;${g;s/\n/\\n/g;p}')" country-name.gif

In a similar fashion I’ve created an image out of a long text:

convert -font /usr/share/fonts/truetype/thai/Purisa-Oblique.ttf -background $BACKGROUND label:"$(fold -w 60 -s texts/long-text.txt | sed -n '1h;2,$H;${g;s/\n/\\n/g;p}')" flag-long-text.gif
  • -fontpoints to a font file I’ve found on my system
  • -pointsize 58 makes for rather big font size
  • -background $BACKGROUND sets the background color to whatever I’ve previously defined in $BACKGROUND, see imagemagick colors
  • label:”….” this is where we are putting our pre-processed text
  • finally, country-name.gif is simply an output filename

Next step: it turned out that the flags I’ve downloaded look much better with the frame around each of them. Also, some of the flags were too wide: I wanted to make them no bigger than 570 pixels. Flags that were smaller than 570 should stay as they are – only bigger ones should be resized. Easy:

convert flag.gif -bordercolor white  -border 6 -bordercolor grey60  -border 1 -resize 570\> flag-with-border.gif
  • options -bordercolor white -border 6 -bordercolor grey60 -border 1 create a 6 pixels wide white border and then 1 pixel wide grey line.
  • -resize 570\> will conditionally resize an image to 570 pixels – if an image is wider than 570 pixels – that is the meaning of the > sign at the end. I had to escape it as \> to prevent bash from interpreting it as redirection
  • like last time, the last argument is the name of the new file: flag-with-border.gif

Now let’s build an empty image. I will overlay other images on top of this one:

convert  -size 1024x768 xc:none -background $BACKGROUND -flatten empty.gif
  • -size 1024x768 is exactly what you think it is
  • xc:none – normally convert takes two arguments: source file and target file. Since we want to create new file, we don’t have any source yet, instead we use this pseudo-image
  • -flatten will remove the transparency

With all the elements ready, all that is left is to put all the images together. composite command will do just that:

#Add country name to empty image
composite -geometry +20+300 country-name.gif empty.gif flag-stage1.gif
#Add long text
composite -geometry +600+300 flag-long-text.gif flag-stage1.gif flag-stage2.gif
#Add flag image
composite -geometry +10+50 flag-with-border.gif flag-stage2.gif flag-full.gif

composite -geometry +X+Y will put an image that is given as a first argument on top of the second image at position (X,Y) and create (third argument) new file. I used it to create final image flag-full.gif step by step.

Here is the final effect:

Saint_Helena_flag

Of course, he next thing you want to do is to wrap those commands in some kind of script – and generate all images automatically.