Sunday, March 22, 2009

Tip #4: Manipulating images at the command line

The popular ImageMagick package provides a rich set of tools for performing image manipulations at the command line. While a full description of all features is well beyond the scope of this tip series, a quick introduction is in order.

Users will likely find themselves primarily using the convert utility that comes with ImageMagick. Another utility, mogrify is similar to convert, with the exception that it overwrites input images rather than outputting to a new file. As such, convert is probably a safer choice, particularly when a user is new to ImageMagick.

The following command rotates an image clockwise by 90 degrees and scales it down by 85% in both dimensions:

linux@devbox:~/tip4> convert -rotate 90 -scale 85%x85% infile.png outfile.png


Here, the file infile.png is used as input, and the modified image is written to outfile.png. convert does not modify the input file.

We can also do file type conversions using convert. Here, a PostScript file is converted to a PNG file. Notice that the output filename is prefixed with png:. This explicitly instructs convert to convert the file to PNG format. In fact, this is generally unnecessary, as convert should infer this from the file extension specified for the output file.

linux@devbox:~/tip4> convert infile.ps png:outfile.png


We can also use convert as a filter by specifying - for either the input file or output file. In the former case, the input image is read from standard input. As you might expect, in the latter case, the output image is passed to standard output. The following demonstrates the use of convert as a filter by taking a PostScript file (infile.ps), converting it to a PNM file using pstopnm, converting the PNM file to a PNG file using pnmtopng, and passing the result to convert to be rotated and scaled. The resulting image is then saved to outfile.png. Of course, this example is contrived since we can directly use convert to convert an image from one format to another, but it helps to illustrate the use of convert as a filter.

linux@devbox:~/tip4>pstopnm -stdout infile.ps | pnmtopng | convert -rotate 90 -scale 85%x85% - outfile.png

Sunday, March 15, 2009

Tip #3: Referencing the last argument to the last command in Bash

This command is no secret to intermediate and advanced Bash users, but it is one that all users should know since it comes in handy all the time.

It is often useful to reference the last argument to the most recently executed command in Bash. For instance, if one were to copy a file to a given directory, and then want to copy another file to the same directory, one might not want to type the entire path to the directory again. Fortunately, with the !$ operator, this is unnecessary.

linux@devbox:~/tip3> cp test1.png /root/Desktop/images/tip3
linux@devbox:~/tip3> cp test2.png !$


In the example above, instead of having to retype /root/Desktop/images/tip3 when performing the second copy, the !$ operator was used instead, which is replaced with the last argument of the last command executed.

Sunday, March 8, 2009

Tip #2: Displaying ASCII Codes

While a developer is working — particularly on a program that includes some sort of text-based interface — it is common to need to know the ASCII codes of one or more characters. Fortunately, most distributions ship with the showkey command:

linux@devbox:~/tip2> showkey -a

Press any keys - Ctrl-D will terminate this program
A 65 0101 0x41
b 98 0142 0x62
C 67 0103 0x43
^D 4 0004 0x04


As you can see, when you type a character, its ASCII code is displayed in decimal, octal, and hexadecimal. When finished entering characters, press Ctrl+D to exit.

ASCII codes are displayed by the showkey command when the -a option is specified. There are also modes to display scancodes (-s) and keycodes (-k or no argument), but most users will likely find themselves working in ASCII mode most frequently.

Sunday, March 1, 2009

Tip #1: Renaming Multiple Files in Bash

Sometimes you want to rename a set of files, applying some sort of common replacement to each filename. For example, suppose we have a set of files with the extension jpeg that we wish to rename to the more concise jpg. Our set of files is shown below:

linux@devbox:~/tip1> ls -la
total 1
drwxr-xr-x 2 linux users 168 2008-05-05 01:24 .
drwxr-xr-x 9 linux users 640 2008-05-05 01:24 ..
-rw-r--r-- 1 linux users 0 2008-05-05 01:24 l1.jpeg
-rw-r--r-- 1 linux users 0 2008-05-05 01:24 l2.jpeg
-rw-r--r-- 1 linux users 0 2008-05-05 01:24 l3.jpeg
-rw-r--r-- 1 linux users 0 2008-05-05 01:24 l4.jpeg
-rw-r--r-- 1 linux users 0 2008-05-05 01:24 l5.jpeg


All you need is one simple line:

linux@devbox:~/tip1> for file in `ls *.jpeg`; do mv $file ${file/jpeg/jpg}; done


Voilà!

linux@devbox:~/tip1> ls -la
total 1
drwxr-xr-x 2 linux users 168 2008-05-05 01:52 .
drwxr-xr-x 9 linux users 640 2008-05-05 01:24 ..
-rw-r--r-- 1 linux users 0 2008-05-05 01:24 l1.jpg
-rw-r--r-- 1 linux users 0 2008-05-05 01:24 l2.jpg
-rw-r--r-- 1 linux users 0 2008-05-05 01:24 l3.jpg
-rw-r--r-- 1 linux users 0 2008-05-05 01:24 l4.jpg
-rw-r--r-- 1 linux users 0 2008-05-05 01:24 l5.jpg