Manipulate Images with ImageMagick
In my last article, I had some fun looking at the children's game of rock, paper, scissors, writing a simple simulator and finding out that some strategies are better than others. Yes, I used "strategy" and "rock, paper, scissors" in the same sentence!
So for this article, I thought it would be interesting to delve into something more functional and pragmatic: image manipulation. Ordinary shell scripts don't tend to do much with images because you can't display anything from the command line.
But let's be honest here. The chance that you're running Linux or a similar command-line interface raw on a computer terminal is pretty darn low. More likely, you've got a terminal window open on your X11 system or, like I often have, you're running a command-line interface app within a modern OS like Mac OS X. And this means, yes, you do have the ability to display graphics, just not within the terminal app itself.
Get Yourself a Copy of ImageMagick
The first step is to download and install a copy of the ImageMagick
suite of graphics-related commands. You already might have it installed
if you're lucky: Just type
convert -version, and if you have it
installed, you'll see something similar to this:
$ convert -version Version: ImageMagick 6.9.6-6 Q16 x86_64 2016-12-31 ↪http://www.imagemagick.org Copyright: Copyright (C) 1999-2016 ImageMagick Studio LLC License: http://www.imagemagick.org/script/license.php Features: Cipher DPC Modules Delegates (built-in): bzlib djvu fftw fontconfig freetype gslib ↪jbig jng jp2 jpeg lcms ltdl lzma openexr png ps tiff ↪webp x xml zlib
If you don't have it installed, it can be quite a task to get it all up and running. Everything lives here, which is where you want to get started.
On a Linux system, you can use the package manager of choice for your
distro. You can grab a compressed tar image from the site, or you can
rpm, like this:
rpm -Uvh ImageMagick-7.0.4-1.x86_64.rpm
Of course, there's a bit more to it, but that'll get you started.
On a Mac, you'll want to start by installing MacPorts, which you can't do until you install Xcode (free from Apple, get it through the App Store). Once you've installed Xcode and MacPorts, you can install ImageMagick, and you're good to go.
You know you're good to go when the test command
returns something meaningful. As always, when you install new software,
you'll want to log out and log in again for the PATH changes and shell
command-line hash to include all the newest programs.
Converting Image Formats
One of the most useful tasks ImageMagick can help you with is converting image file formats. It's a remarkably well built suite of programs and can read or write more than 200 different formats. Don't believe me? Try this command:
convert -list format | more
Among the most common formats that you'll actually encounter in your day-to-day computer usage are the following:
BMP: MS Windows bitmapped image.
GIF: Graphics Interchange Format.
JPG: JPEG image format.
PNG: Progressive Network Graphic format.
TIFF: Tagged Image File Format.
ImageMagick knows oodles of other formats too, including all the major video formats (MKV, MP4, AVI, MOV). It also can convert things like EPSF (Encapsulated Postscript) and even PDF (Portable Document Format), which can be useful in specific instances.
Armed with that knowledge, conversion between image file formats is really ridiculously simple. Let's say you want to convert an image from JPEG to PNG. It's as simple as:
convert image.jpeg image.png
Since the ImageMagick utilities are glob-aware (that is, you can use
wild cards and specify multiple filenames), you also can convert a group
of GIF images to JPG with the
convert command or, more easily, with
mogrify -format jpg *.gif
Let's give it a whirl with a folder that contains a half-dozen GIF
ls to show the folder contents before and after the
mogrification (is that a word?):
$ ls -s total 272 8 add-to-google-reader.gif 24 blogger-1.gif 8 dave.gif 8 add-to-newsgator.gif 24 blogger-2.gif 176 manga.gif 16 aw-logo.gif 8 blogger-3.gif $ mogrify -format jpg *gif $ ls -s total 752 8 add-to-google-reader.gif 24 blogger-1.gif 8 dave.gif 8 add-to-google-reader.jpg 112 blogger-1.jpg 8 dave.jpg 8 add-to-newsgator.gif 24 blogger-2.gif 176 manga.gif 8 add-to-newsgator.jpg 128 blogger-2.jpg 168 manga.jpg 16 aw-logo.gif 8 blogger-3.gif 24 aw-logo.jpg 24 blogger-3.jpg
Simple enough. Use
convert for individual images
mogrify for bulk
conversions. It'd be an easy script to differentiate between these
two cases and invoke the correct command with the correct arguments
too. I'll leave that up to you!
Checking Image Sizes
Another useful feature of the ImageMagick suite is to be able to identify
the dimensions of a graphic image. The latest version of the
can offer this information on some systems:
$ file manga* manga.gif: GIF image data, version 89a, 358 x 313 manga.jpg: JPEG image data, JFIF standard 1.01, ↪aspect ratio, density 1x1, segment length 16, ↪baseline, precision 8, 358x313, frames 3 manga.png: PNG image data, 358 x 313, 8-bit/color RGB, ↪non-interlaced
But on most Linux systems, one or more of these would exclude the actual dimensions. Further, look closely at the above output, and you'll see it's quite inconsistent, making it difficult to parse out the dimensions if you don't encode specific rules for each format—which is, uh, lame.
Instead, you can glean image size with the
command, as shown here:
manga.gif GIF 358x313 358x313+0+0 8-bit sRGB 256c 88.5KB ↪0.000u 0:00.000 manga.jpg JPEG 358x313 358x313+0+0 8-bit sRGB 85.4KB 0.000u ↪0:00.000 manga.png PNG 358x313 358x313+0+0 8-bit sRGB 266KB 0.000u ↪0:00.000
That's better. It's consistently the third parameter, which means that a simple script can strip out everything but the image dimensions:
$ for image in manga*; do identify $image | cut -f1,3 -d\ ; done manga.gif 358x313 manga.jpg 358x313 manga.png 358x313
Easy enough, and notice that the
cut command is invoked both with a
space as the default field delimiter and specifying that you want field
1 and 3 but none of the others.
And Next Time...
Okay, ImageMagick is complicated. In fact, I didn't really get much
into scripting here, but in my next article, I'll explain how to turn all
this knowledge of
identify into some pretty sick
scripts. See you then!