Warp Image Corners with pamhomography
A photo shot at an angle turns a rectangle into a trapezoid, and pamhomography maps four corner points to four new ones to fix it. The same trick does perspective correction, skew, crop, flip or any other quadrilateral warp, and the output stays in Netpbm format. Give it about fifteen minutes for a first transformation, plus extra time to pick and check your coordinates. The examples use Netpbm 11.5.2 from the installed netpbm package.
The route
Jump straight to the step you need, or tick off Done means at the end.
This is an ordinary user-level workflow. You need a readable PAM-compatible image, a writable output directory and the pamhomography command. Nothing here needs sudo, and the original image is never touched until you have checked the result yourself.
1. Check the installed command
Confirm the binary and package version before you trust any example against your install. These commands only read local metadata:
$ command -v pamhomography
/usr/bin/pamhomography
$ dpkg-query -W -f='${Package} ${Version}\n' netpbm
netpbm 2:11.05.02-1.1build1
$ pamhomography --version 2>&1 | head -n 2
pamhomography: Using libnetpbm from Netpbm Version: Netpbm 11.5.2
pamhomography: Built from source dated 2024-03-31 09:09:47
Option names can be shortened to any unique prefix, with one or two hyphens, and a value can follow = or a space. The examples below spell everything out in full so the mapping stays easy to audit later.
2. Understand the four-point mapping
pamhomography maps a source quadrilateral to a target quadrilateral. Each list holds four integer coordinate pairs, in corresponding order, and normally runs clockwise starting at the upper-left corner. The origin is the image's upper-left pixel, and coordinates are allowed to fall outside the image boundary.
Leave out -from and the source defaults to the whole input image. Leave out -to and the target does too, which means a command using only -view can crop or add a border without touching the mapping at all.
Checkpoint
Write down the four source points and four target points before you type the command. A swapped pair still produces an image and a zero exit status, so a clean run proves nothing about whether the geometry is actually right.
3. Correct a photographed rectangle
Say the rectangular panel in photo.ppm has corners measured at (147,51), (316,105), (402,595) and (92,560). Map those to a clean 441 by 640 rectangle and write the result to a new file with shell redirection:
$ cat > panel.map <<'EOF'
(147, 51) (316, 105) (402, 595) (92, 560)
(0, 0) (440, 0) (440, 639) (0, 639)
EOF
$ pamhomography -mapfile panel.map photo.ppm > panel-rectified.ppm
The map file holds eight pairs: the first four are the source, the next four are the matching targets. Parentheses and commas are optional, since every character other than digits, plus and minus signs is treated as a separator. The output keeps the same Netpbm format as the input.
Verify the file before you open it in an editor or overwrite anything:
$ file panel-rectified.ppm
panel-rectified.ppm: Netpbm image data, size 441 x 640, rawbits, pixmap
$ head -n 3 panel-rectified.ppm
P6
441 640
255
Your file wording can read slightly differently. What matters is that the output exists, has the intended dimensions and is not empty, then a look at the image itself.
4. Use direct coordinates for a simple warp
For a whole-image transformation, -to is shorter than writing a map file. This stretches a 441 by 640 image into a trapezoid, with the target view fitted to the quadrilateral:
$ pamhomography -to '50,0 390,0 440,200 0,200' photo.ppm > photo-trapezoid.ppm
$ file photo-trapezoid.ppm
photo-trapezoid.ppm: Netpbm image data, size 440 x 200, rawbits, pixmap
Flip left to right by swapping the corresponding top and bottom points:
$ pamhomography -to '440,0 0,0 0,639 440,639' photo.ppm > photo-flipped.ppm
Worth remembering: point order describes correspondence, not just the shape's outline direction. A counterclockwise target is not a mistake when it is meant to be a reflection.
5. Control the visible output and fill colour
-view sets the upper-left and lower-right boundaries of what actually shows up in the output. -fill sets the colour used outside the target quadrilateral; left unset, that is black, or transparent when the input carries a transparency plane.
Scale a 441 by 640 image down to 341 by 540 and add a tan border by choosing a wider view:
$ pamhomography \
-to '0,0 340,0 340,539 0,539' \
-view '-100,-100 440,639' \
-fill tan \
photo.ppm > photo-small-border.ppm
$ file photo-small-border.ppm
photo-small-border.ppm: Netpbm image data, size 541 x 740, rawbits, pixmap
Combine matching -from and -to coordinates to pull out a non-rectangular quadrilateral. For a plain rectangular crop, -view on its own is enough:
$ pamhomography -view '130,10 205,80' photo.ppm > photo-crop.ppm
A negative coordinate is not automatically a mistake: it is genuinely useful for borders and rotated shapes. It can also produce a surprisingly large output, so check the dimensions every time.
6. Replace outputs without losing the old file
> truncates an existing destination the moment the shell opens it, before pamhomography has run at all. While you are experimenting, write to a temporary name and only promote it once you have checked it:
$ pamhomography -mapfile panel.map photo.ppm > panel-rectified.ppm.new
$ file panel-rectified.ppm.new
panel-rectified.ppm.new: Netpbm image data, size 441 x 640, rawbits, pixmap
$ mv panel-rectified.ppm.new panel-rectified.ppm
The final mv replaces the old output in place. If the conversion fails partway through, delete the incomplete .new file and rerun the command; the previous output is still sitting there untouched. Do not delete the source image or the old output until the new one has passed both the file check and a visual look.
7. Diagnose the common failures
A malformed coordinate list gets rejected before any image is produced. Each quadrilateral needs eight integers, and -view needs four. Seeing an error like failed to parse ... as a list of eight integers means: count your x and y values, check the quotes, and rule out accidental shell expansion.
Wrong output size: check -view first. Right size but a distorted subject: check the correspondence between each source point and target point, and whether the points went in clockwise as intended. A normal exit status only confirms the transformation was calculated and written, nothing about whether it is correct.
If an image viewer refuses to open the result, run file and check the first three header lines. The program keeps the input's Netpbm format, so feed the output through a Netpbm converter if your viewer does not speak that format natively. Keep the intermediate PPM files around until the final conversion is confirmed good.
Done means
- Checked the install. The
pamhomographybinary and Netpbm version match what you expect. - Recorded the points. Source and target coordinates are written down in matching order.
- Verified the output. Dimensions and Netpbm header confirmed with
fileandhead. - Used a temporary file. Any replacement went through a separate temporary output first.
- Kept the original. The source image is untouched and the transformed image has been inspected.