One of the reasons for starting a blog was to be able to write down stuff for future reference. Even if there’s a better guide elsewhere on the web, at least I’ll have a place where I know I can find the solution I found a year later without having to search for it.
So here’s a brief introduction to ImageMagick, found mostly by some Googling and trial & error rather than structured reading of manuals.
I want to upload some audio clips to YouTube. Nothing pirated, but official concert recordings of the choir I sing in. For a few of those, we actually have videos, but the rest of them should have a static image, composed of a group photo from the concert where the clip was recorded, the choir’s logo and a label displaying the title of the piece. As I need this for several clips and don’t want to mess around manually with GIMP every time, I wrote a little ImageMagick script to perform the task.
I’m working with ImageMagick 6.6.9-7. I’m sure older versions will do, as I only used fairly standard functionality, but I didn’t do any research as to what the minimum required version is. ImageMagick is available for Windows, Apple and Unix systems, so the following should work pretty much everywhere. The final script is a Bash script, so Windows would require some tweaking.
To install ImageMagick in Ubuntu, if you don’t already have it, just do this:
sudo apt-get install imagemagick
As described above, I have two images and a text string and want to combine them into one stamped image. The base image is a group photo of the respective concert. That means that it different audio clips may use different base images. I’ve decided to stick to a 1280×720 resolution for all of them though, so all positioning numbers are based on this.
Here’s an example of a base image:
The name and path to the base image will be passed to the script as a parameter.
Next, the logo. To stay flexible, I’m using the full resolution version of our logo as the source and let ImageMagick scale it to my desired size. This’ll make it easier to change sizes later on if I want to.
Here’s the logo:
The logo file will be named logo-amerlingchor.png and placed in the same directory as the script.
Note that it’s a simple black text with transparent background. This’ll make it easy to stamp a white version of it with a black shadow on top of the base image.
Finally the label. We decided to use Century Gothic Italic as the font, based on our CD cover designs. The label should be stamped left aligned at the bottom of the base image, with a black background. After some experimenting I decided on a text size of 30, with height of 50 pixels for the background rectangle.
I installed the TTF file of the required font via KDE’s font installer to make it available to ImageMagick.
ImageMagick has a few command line tools to convert and compose images. My first version of the script used the convert tool to stamp the text on the base image and store the result in a temporary file. Then the composite tool was called stamp the logo on top of the temp image and store the result to the target file.
The final version uses convert‘s ability to handle a list of operations to create the entire image with just one call.
The script has three parameters:
- $source – The path and name of the source image.
- $text – The text to display in the label.
- $dest – The path and name of the image file that should be written by the script.
I start by calling convert and providing the base image:
convert -size 1280x720 $source
Next, I specify the font family and size. To figure out the name of the available fonts, I used the following command:
convert -list font
So the font setup parameters look like this:
-pointsize 30 -font "Century-Gothic-Italic"
The draw operation allows be to draw both the black background rectangle and the white text on top of it:
-draw "gravity southwest \ fill black rectangle 0,670,1280,720 \ fill white text 15,10 \"$text\""
gravity southwest specifies the bottom left corner as the origin for relative coordinates. rectangle seems to use absolute coordinates with 0/0 being the top left corner of the image (so 0/670 is the top left corner and 1280/720 the bottom right corner of a 50 pixel high rectangle spanning the full width), but the text operation uses the specified origin, so 15/10 offsets the label by 15 pixels from the left edge and by 10 pixels from the bottom edge.
Finally, the logo. I’ve decided on a width of 350 pixels and an offset of 20/10 from the top left corner. I could use the following line to simply stamp the logo image there with these parameters:
logo-amerlingchor.png -geometry 350x200+20+10 -composite
Note that the specified vertical size – 200 pixels – is ignored because the scaled image maintains its aspect ratio. 0 would result in an empty image though, so I just used a random number roughly (very roughly) in the correct range.
The above command would stamp the black logo on the base image. I want a white image with a black background, though. The logical way to do this would be to compose a logo stamp by placing a white version of the logo on top of the black version, offset by a few pixels, and then to stamp the result on the base image. To create a white version of the logo, the -negate option comes in handy, which simply inverts all colours and keeps the transparent pixels transparent. For logo using only the colour black, this results in a white image. With a coloured logo as the starting point, the correct approach would be to create a matching shadow by using an all-black version of the original image.
I’m lazy though, so I didn’t compose the shadowed logo in advance. Instead, I simply stamp the logo on top of the base image twice:
logo-amerlingchor.png -geometry 350x200+22+12 -negate -composite logo-amerlingchor.png -geometry 350x200+20+10 -negate -composite
The fact that the -negate operation is its own inverse operation is the key here. The first line stamps the black logo on the base image and then inverts the entire image, resulting in a negative version of the base image with a white logo. The second line stamps the original black version of the logo on top of this and again inverts the entire image – resulting in a real colour (twice inverted) version of the base image with a black (twice inverted) version of the logo and on top of that a white (once inverted) version of the logo.
The coordinates offset the shadow from the white logo by two pixels in both dimensions.
And this is what the result looks like:
#!/bin/sh source=$1 text=$2 dest=$3 convert -size 1280x720 $source \ -pointsize 30 \ -font "Century-Gothic-Italic" \ -draw "gravity southwest \ fill black rectangle 0,670,1280,720 \ fill white text 15,10 \"$text\"" \ logo-amerlingchor.png -geometry 350x200+22+12 -negate -composite \ logo-amerlingchor.png -geometry 350x200+20+10 -negate -composite \ $dest
For the above image, I call it like this:
./stamp.sh group_photo.jpg "Pierre Attaignant: Tourdion" tourdion.png