Open Source Software Technical Articles

Want the Best of the Wazi Blogs Delivered Directly to your Inbox?

Subscribe to Wazi by Email

Your email:

Connect with Us!

Current Articles | RSS Feed RSS Feed

Become an ImageMagick Ninja: Doing Things in Batches


Last month we introduced ImageMagick, a software suite that lets you manipulate images in several interesting ways. In that article we learned a lot of ways to resize images, make thumbnails, and convert image file formats. Today we're going to unleash more of the mighty ImageMagick power and learn to make drop shadows, raised buttons, and proof sheets, and generate different sizes of the same image.

As always, before you manipulate irreplaceable photos, back up your originals first!

Before we start talking about more ImageMagick functionality, here's a tip that can help you with all ImageMagick commands. Using ImageMagick commands in single-line bash shell scripts lets you quickly modify multiple images in one batch. Even if you prefer using a different programming or scripting language, bash one-liners are useful for testing whether your ImageMagick commands are doing what you want. Consider this command:

$ for file in *.jpg; do convert $file -resize 640x480 640x480-$file; done

This resizes all the JPG images in the current directory to 640x480, preserves the originals, and creates new files with 640x480- prepended to the filenames. It is easy to customize this for different file types, different convert command options, and different conventions for naming the new files. Tweak it just a little and you can create thumbnails:

$ for file in *.jpg; do convert $file -thumbnail 125x -quality 85 tn-$file; done

This creates 125-pixel-wide thumbnails out of all the JPGs in the current directory, at 85 JPG quality level, and prepends the filenames with tn. As before, the originals are preserved.

By the way, even though it's not an ImageMagick command, here's a way to handle the common annoyance of mixed upper- and lower-case file extensions. Windows applications and a lot of digital cameras like to shout at you by putting file extensions in all caps. Windows is not case-sensitive, but Linux and Unix are. Mac OS X is extra fun because the HFS filesystem is not case-sensitive, but HFS+ is. One way to handle this is to list both cases in your bash invocation; for example, for file in * .jpg *.JPG;. But this doesn't really solve the problem. Why not change all the extensions to lowercase instead:

$ for file in *.JPG; do mv $file ${file%%.JPG}.jpg; done

Drop Shadows

You can apply bash one-liners to any ImageMagick command, so let's learn a few more. Suppose you want to add a drop shadow border to an image. Adding the shadow option to the convert command is not enough by itself; you need to string several options together correctly. The incantation below works for any image format that supports transparency, such as PNG, BMP, and TIFF:

$ convert image1.png \( +clone -background black -shadow 60x5+30+40 \) +swap -background none -layers merge +repage image2.png

This command adds a drop shadow on the right and bottom of image1.png and renames it image2.png, so the original is unchanged. It is not solid black but 60% opacity; higher values are more opaque. The 5 value creates a soft rounded edge; 0 is a hard edge with square corners, and the higher the value, the softer the edge. +30 is the x or horizontal axis value in pixels. + places the shadow on the right and - places it on the left. +40 is the y, or vertical axis value. + places the shadow at the bottom and - places it at the top. You don't have to have shadows on two sides; you can use zero, like +0+30, to create a shadow on a single border.

Image formats that do not support transparency, like GIF and JPG, must swap in a white background:

$ convert deer1.jpg \( +clone -background black -shadow 60x5+30+40 \) +swap -background white -layers merge +repage deer2.png

Figure 1 shows the result.

[caption id="attachment_87607" align="alignnone" width="590" caption="Fig. 1: The little buck that ate my tomatoes and beans, with a stylish drop shadow."][/caption]

The +clone -background color can be any color. Use the color names or codes on the ImageMagick Color Names page.

What if you want to add nice drop shadows to a whole batch of images?

$ for file in *.jpg; do convert $file \( +clone -background black -shadow 60x5+30+40 \) +swap -background white -layers merge +repage shadow-$file; done


Making Raised Buttons

Another thing you might want to do with images is turn your thumbnails into raised buttons:

$ convert thumbnail.jpg -raise 10 raised-thumbnail.jpg

This creates a 10-pixel-wide border with shadows on the right and bottom (Figure 2). If you use +raise then ImageMagick puts the shadows on the other sides, which is supposed to make it look sunken.

[caption id="attachment_87608" align="alignnone" width="200" caption="Fig. 2: Thumbnail of the garden-eating little buck as a raised button."][/caption]

How do you make a batch of these? I think you know by now!

Proof Sheet

Old geezers like me have happy memories from the olden days of image proof sheets, such as contact prints of photographic negatives, which are the ancestors to thumbnails on web pages. Proof sheets are still useful, because they let you print pages of reduced-size images for quick review. ImageMagick's montage command creates proof sheets with ease:

$ montage '*.jpg' -geometry 200x+15+5 proof-sheet.jpg

This command takes all the JPG files in the current directory, creates thumbnails 200 pixels wide, spaces them in rows 15 pixels apart and columns 5 pixels apart, and outputs a single JPG file. Your output file can be any image format you want.

Generating Different Sizes of the Same Image

In addition to smaller copies of multiple images, you might sometimes want to have different sizes of the same image. This example makes three different sizes of a flower picture to make wallpaper for different screen resolutions:

$ convert flower.png \
\( +clone -resize 1280x -write flower-1280.png +delete \) \
\( +clone -resize 1024x -write flower-1024.png +delete \) \
-resize 800x flower-800.png

For each resizing operation a new clone is made of the original, then deleted when the resized file is created, so each copy is made from the original, rather than from increasingly degraded copies of reduced-size copies.

Scripting and APIs

All of this bash goodness is useful and fun, but what if you prefer to use a different programming or scripting language? Visit the ImageMagick project page Convert, Edit, or Compose Images From Your Favorite Programming Language to learn about ImageMagick's ready-made interfaces for a large number of languages. There are special helpers for C, C++, Ruby, Perl, Python, PHP, and many more.

Fred's ImageMagick Scripts is a treasure trove of bash scripts for dozens of different effects, such as pagecurl emboss, fisheye2pano, stainedglass, rotate3d, and many more. These are useful even when you're not scripting in bash because Fred Weinhaus, the generous author of these scripts, has documented the ImageMagick commands and options in each script thoroughly, with an abundance of before and after images to illustrate. It's one of the best ImageMagick references anywhere.

This work is licensed under a Creative Commons Attribution 3.0 Unported License
Creative Commons License.

This work is licensed under a Creative Commons Attribution 3.0 Unported License
Creative Commons License.


Thanks now I'm a Ninja!
Posted @ Thursday, March 13, 2014 4:08 PM by Feamarth
I used to following but it doesn't work: 
$ for file in *.jpg; do convert $file -thumbnail 125x -quality 85 tn-$file; done 
I tried to modify it to do 120 wide and prefix the filename with tn_
Posted @ Friday, June 06, 2014 4:51 PM by Mike
Here is what worked but I can't get it to work in a batch file. 
for $f in (*.jpg) do convert $f -thumbnail 120x tn_$f 
I have to cd (change directory) first into the folder I want the images to resize and rename. 
Posted @ Friday, June 06, 2014 6:40 PM by Mike
Post Comment
Website (optional)

Allowed tags: <a> link, <b> bold, <i> italics