Deskew a scanned PGM with pamtilt and pnmrotate
You will measure the skew in a scanned PGM image, inspect the angle that pamtilt reports, and use that value to create a straightened copy with pnmrotate. Allow about fifteen minutes. You need the Netpbm package, a readable scan, and enough free space for a second image.
The route
Jump straight to the step you need, or tick off Done means at the end.
This guide describes Netpbm 11.5.2, installed here as package version 2:11.05.02-1.1build1. The pamtilt manual page was written for an older Netpbm release, so check the installed command before putting the workflow into a batch job.
1. Check the installed command and input
Confirm that the executable and its package are the ones you expect. These are ordinary read-only commands and do not need elevated privileges:
$ command -v pamtilt
/usr/bin/pamtilt
$ pamtilt --help
pamtilt: Use 'man pamtilt' for help.
$ pamtilt --version
pamtilt: Using libnetpbm from Netpbm Version: Netpbm 11.5.2
$ dpkg-query -W -f='${Package} ${Version}\n' netpbm
netpbm 2:11.05.02-1.1build1
The --help response is a pointer to the manual rather than a list of options. The documented options use one leading hyphen, for example -angle=10 and -fast. Use the exact syntax shown by man pamtilt when you write scripts.
Checkpoint: make sure the source image is readable and is a PGM, PBM, or a compatible PNM or PAM image whose first plane contains the document:
$ test -r /path/to/crooked.pgm && echo readable
readable
$ file /path/to/crooked.pgm
/path/to/crooked.pgm: Netpbm image data, size 2480 x 3508, graymap
Your file description may differ. If it cannot identify the image, stop and inspect the file before passing it to pamtilt. Do not use sudo to compensate for a wrong path or an invalid image format.
2. Measure the document tilt
Run pamtilt with the image path as its optional final argument:
$ pamtilt /path/to/crooked.pgm
0.00
The output is one floating-point number in degrees. The example output is from a synthetic image with horizontal lines, not a promise about your scan. Save the value in a shell variable if you intend to use it immediately:
$ input=/path/to/crooked.pgm
$ angle=$(pamtilt "$input")
$ printf 'measured angle: %s degrees\n' "$angle"
measured angle: 0.00 degrees
There is no persistent state to undo. pamtilt only reads the input and writes its result to standard output. A non-zero exit status or an error message means that you do not have a trustworthy angle yet.
3. Treat an uncertain result as a checkpoint
pamtilt is designed for scanned text with strong horizontal lines. It performs three searches at increasingly fine increments, but it is not a general photo-orientation tool. The manual says it may report the special value 00.00 when it lacks confidence. On this installed build, the same kind of result is printed as 0.00.
Do not silently rotate a large archive when the result is uncertain. First inspect the scan and compare the measured value with what you can see. For a useful diagnostic, ask for the measurements on standard error:
$ pamtilt -verbose "$input" > /tmp/pamtilt-angle.txt 2> /tmp/pamtilt-measurements.txt
$ cat /tmp/pamtilt-angle.txt
0.00
$ sed -n '1,5p' /tmp/pamtilt-measurements.txt
21 angles from -10.00 to 10.00 by 1.00: best = 0.00, S:N = 10.36
-10.00: 2418.29 00000
The diagnostic is intentionally short here; the number of tested angles and the measurements depend on the image and options. The files under /tmp are disposable working data. If the result does not match the page, keep the original scan and investigate rather than forcing a rotation.
4. Widen or tune the search only when the scan needs it
The default maximum angle is 10.0 degrees. If you know the page was scanned outside that range, set a larger maximum explicitly:
$ angle=$(pamtilt -angle=15 "$input")
$ printf 'measured angle: %s degrees\n' "$angle"
The search still depends on visible document structure. -fast skips the third iteration, trading accuracy for speed, so leave it out for a first measurement. -quality=q raises the signal-to-noise threshold; a larger value can reject dubious results instead of producing a plausible-looking angle.
The sampling controls are -hstep, -vstep, -dstep, and -astep. They affect run time, memory, sampling, or the first angle increment. Leave their documented defaults alone unless you have measured a repeatable problem and can verify the result on representative scans.
5. Rotate to a new file
Once the angle looks sensible, pass it to pnmrotate. The command below writes a new PNM file and leaves the source unchanged:
$ output=/path/to/straight.pgm
$ pnmrotate -background white "$angle" "$input" > "$output"
$ file "$output"
/path/to/straight.pgm: Netpbm image data, size 2480 x 3508, graymap
pnmrotate measures its angle counter-clockwise and writes the rotated image to standard output. Its output rectangle can be larger than the input, and the background colour is selected automatically unless you provide one. Supplying -background white makes the intended page background explicit.
Warning: shell redirection truncates an existing destination before pnmrotate starts. Do not point this command at the only copy of the scan. If you must replace an existing derived image, use a temporary name, verify it, then move it into place:
$ temporary=/path/to/straight.pgm.new
$ pnmrotate -background white "$angle" "$input" > "$temporary"
$ file "$temporary"
$ mv -- "$temporary" "$output"
If conversion fails, remove only the incomplete .new file after checking that it is the temporary output. The original input and previous output remain available. The final mv is the state-changing step; it normally needs no elevated privileges when the directory belongs to you.
6. Diagnose the common wrong turns
- A photo or a page with weak horizontal structure can produce an unhelpful angle. Crop or inspect a representative document, but do not assume that a numerical result is correct.
- A result outside the default range needs an explicit
-anglevalue. The default is not inferred from the filename or scanner metadata. - Reducing
-hstepor-vstepcan increase work and memory use. Increasing sampling steps can make a run quicker while increasing the risk of a wrong result. - If
pnmrotatecannot open the image, check the path and permissions first. If it cannot write the destination, choose a writable directory; do not run the whole conversion as root.
Done means
pamtiltis the expected Netpbm 11.5.2 executable and the source image is readable.- You captured one floating-point angle and checked it against the document.
- You used
-verboseor adjusted-angleonly when the scan justified it. pnmrotatewrote a verified new image with the intended background.- The original scan remains untouched, and any replacement was staged through a temporary file.