Imagemagick

Imagemagick is a set of command-line utilities for manipulating and viewing images, the most useful of which is probably convert. convert will convert images between different formats and will apply any of a number of image transformations upon request.

Why would you use convert instead of the GIMP or Photoshop? If you're doing something as simple as changing the format of an image, you can avoid the trouble of firing up an image editor. If you're applying the same transformation to many different images (e.g. generating thumbnails), you can script Imagemagick instead of opening up all the files in an image editor. And, of course, if you need to do image manipulation on-the-fly (e.g. for an interactive web site), you'll need something scriptable.

Here's how to convert an image to a different format, say, from a JPEG to a PNG:

convert boston.jpg boston.png
To do image transformations, specify some number of transformations between the input and the output file names. Here are some of my favorites:

convert boston.jpg -resize 640x480 boston-small.jpg
Resizes the image to fit in a 640x480 box while preserving the aspect ratio.
convert boston.jpg -quality 80 boston-lowres.jpg
Changes the quality of an image (for JPEG, you can specify any number from 0 [lowest image quality, least space] to 100 [highest image quality, most space]).
convert logo.png -rotate 10 logo2.png
Rotates an image by 10 degrees.
convert logo.png -negate logo2.png
Negates the colors in an image.
convert boston.jpg -fx 'luminosity' boston-grayscale.jpg
Desaturates an image (converts it to grayscale).

You can compound operations by stringing them together:

convert in.jpg -emboss 5 -fx 'luminosity' -rotate 10 out.png

convert has more options than you can shake a stick at: everything from color transformations to special effects and commands to let you draw arbitrary shapes or text on an image. And Imagemagick also provides bindings so you can use it as a library from any of a number of languages.

How to rescue a dying hard drive

If you suspect your hard drive is dying (unusually large amounts of disk thrashing, long access times, frequent file corruption, refuses to boot), and you have a spare disk, it's not hard to clone the disk. It will be easier to recover data from the clone, since continued use of the bad disk can make things worse.

  1. If the disk is your boot disk, move it to another computer. Otherwise, be sure to unmount it first.
  2. Determine what device and partition the disk appears on, perhaps using mount or fdisk.
  3. Use ddrescue to make an image of the disk:
    $ ddrescue /dev/sdb1 IMAGEFILE LOGFILE
    where sdb1 is the node for your source disk. ddrescue is like dd (which writes a copy of all the disk's raw data to a file), but works better for damaged disks: it fills in zeros for parts of the disk it can't read; you can run ddrescue as many times as you want, and if you provide the same LOGFILE it will attempt to fill in the gaps in the image that it didn't get before.
  4. Write the image to a new disk:
    $ dd if=IMAGEFILE of=/dev/sdc1
    where sdc1 is the node for your target disk.
  5. Mount the filesystem and run fsck or an equivalent. For NTFS volumes, moving the drive to a Windows computer and running chkdsk /F works wonders.

Makefiles

You may know make as a tool for building software, but it's actually a general utility for performing tasks based on a dependency graph, even if those tasks have nothing to do with compiling software. In many situations, files are processed in some way to create other files or perform certain tasks. For example:

  • A .c file is compiled to make a .o file, which is then linked to other object files to make an executable.
  • A .tex file is processed by LaTeX to make a PDF file.
  • A file containing data is processed by a script to generate graphs.
  • A web page needs to be uploaded to a remote server after it is modified.
  • A piece of software needs to be installed after it is compiled.
In each case, the modification of a source file demands that some task be performed to ensure that the corresponding resource is up-to-date (i.e., it reflects the changes made to the source file).

make automates the process of keeping resources up-to-date: you tell it about what resources depend on what source files, and what needs to be done to those source files to make the resources. It then runs only those tasks that actually need to be run. No more obsessive-compulsive internal dialogues that go like this: "Did I remember to compile that program again after I was done changing it?" "Well, I don't remember, so I might as well do it again." Running a properly-configured make will compile your program if it's necessary, and do nothing if your program is up-to-date. This can save you seconds, minutes, or hours, depending on what you're doing.

make determines what to do by comparing the modification times of the resources and the source files. For example, if thesis.pdf (a resource) is created from thesis.tex (a source file), then pdflatex needs to be run if thesis.pdf doesn't exist or if it's older than thesis.tex, but nothing needs to be done if thesis.pdf is newer than thesis.tex.

To use make to manage some files in a directory, create a file called Makefile in that directory. The syntax for the Makefile is refreshingly simple. For each resource to generate (these are called targets), type:

TARGET-FILE: DEPENDENCY-FILE-1 DEPENDENCY-FILE-2 ...
       COMMAND-TO-RUN
       ANOTHER-COMMAND

Each command to be run should be indented with a single tab. Here's an example Makefile, for a system where two files are to be compiled, then linked to make an executable:

helloworld: hello1.o hello2.o
       gcc -o helloworld hello1.o hello2.o
hello1.o: hello1.c
       gcc -c hello1.c
hello2.o: hello2.c
       gcc -c hello2.c

Running $ make helloworld tells make to resolve the dependencies necessary to generate the file helloworld: make first compiles the two source files, then links them. If I were to subsequently change hello1.c and run $ make helloworld again, make would recompile that file and relink the program, but it would not recompile hello2.c.

By default, $ make (without a target name) does whatever is necessary to make the first target that appears in your Makefile (in this case, helloworld).

In fact, your make targets do not have to refer to files. You can use make to define groups of commands to be run together under an (arbitrary) easy-to-remember target name. For example, I could define a publish target which would upload my web pages:

.PHONY: publish
publish: index.html stuff.html
       scp index.html stuff.html phil@remoteserver:~/www/

(The .PHONY directive tells make to not worry that a file named publish is not being generated.) Now publishing my web page is as easy as running $ make publish.

Here are some common applications of phony targets:

  • After you compile a piece of software, you can frequently install it with $ make install.
  • $ make clean usually has the job of removing compiled files from a directory (so you are left with the "clean" source files). It can often be defined similarly to this:
    .PHONY: clean
    clean:
           rm -f helloworld *.o
  • If a source directory contains multiple independent targets, an all target is usually created to force building the individual parts, and placed first so that $ make invokes $ make all:
    .PHONY: all
    all: part1 part2 part3

As you can see, you can use make to automate any well-defined process you're going to want to do repeatedly.