Dave switches gears this month and begins delving into the more functional topic of image manipulation.
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.
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 at www.imagemagick.org, 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 use 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 (www.macports.org), 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 convert -version 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.
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 its cousin mogrify:
mogrify -format jpg *.gif
Let's give it a whirl with a folder that contains a half-dozen GIF images, using 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 and 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!
Another useful feature of the ImageMagick suite is to be able to identify the dimensions of a graphic image. The latest version of the file command 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 identify 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.
Okay, ImageMagick is complicated. In fact, I didn't really get much into scripting this month. But, come back next month; I'll explain how to turn all this knowledge of convert, mogrify and identify into some pretty sick scripts. See you then!