Home / Alt manpages / ppmshadow(1)

  • ppmshadow(1)
  • User command
  • linux

Add a controlled drop shadow to a PPM image with ppmshadow

You will add a simulated drop shadow to a PPM image and write a new PPM file without changing the source. The command treats the top-left pixel as the background colour, so the result is predictable when the image has a clean border. Allow about 15 minutes for a first run, including a small test image and a visual check.

This guide uses Netpbm 11.5.2, provided here by package version netpbm 2:11.05.02-1.1build1. The installed manual is dated 24 June 2017. Options and behaviour below are therefore verified against this local installation.

1. Check the installation and make a safe output path

The operation is an ordinary user-level image conversion. It reads one PPM file, writes PPM to standard output, and does not need sudo. Choose a destination that does not contain a useful file, because shell redirection with > truncates an existing destination before ppmshadow starts.

$ command -v ppmshadow
/usr/bin/ppmshadow
$ ppmshadow --version
netpbm 2:11.05.02-1.1build1

If the destination already exists, use a temporary name in the same directory and replace the old file only after checking it:

$ ppmshadow /path/to/source.ppm > /path/to/shadow.ppm.new
$ test -s /path/to/shadow.ppm.new && mv /path/to/shadow.ppm.new /path/to/shadow.ppm

Checkpoint: the source remains untouched, and a failed run leaves the previous shadow.ppm in place. If the new file is incomplete, remove only shadow.ppm.new after inspecting the error; do not remove the original output as part of recovery.

2. Run the default black shadow

With no options, ppmshadow creates a black shadow. It identifies the background as every pixel whose RGB value exactly matches the top-left pixel, and treats all other pixels as foreground. The output has the same width, height and maxval as the input.

$ ppmshadow /path/to/source.ppm > /path/to/shadow.ppm
$ file /path/to/shadow.ppm
/path/to/shadow.ppm: Netpbm image data, size 800 x 600, rawbits, pixmap
$ test -s /path/to/shadow.ppm && echo 'non-empty PPM written'
non-empty PPM written

Your file description may differ. The useful checks are a non-empty file and unchanged dimensions. Open the result in an image viewer or pass it to another Netpbm converter. Standard output carries the image, so a progress message is not expected.

A black object and a pixel exactly equal to the background do not cast a shadow. If an object contains a black region that should count as foreground, change that region to a colour differing from black by one RGB value before processing. The visual change is normally imperceptible, but keep the edited input separate from the original.

3. Set the light direction and softness

The -x and -y values describe where the light is, not where the shadow is. A positive -x value puts the light to the left, so the shadow moves right. A positive -y value puts the light above the image, so the shadow moves down.

$ ppmshadow -x 24 -y 18 -b 9 /path/to/source.ppm > /path/to/shadow-right-down.ppm

-b controls the fringe around the shadow. The default is 11 pixels. A larger value makes the shadow more diffuse; a smaller value makes it sharper. It controls the blur fringe, not the physical growth or shrinkage of the shadow. Start with the default, then try a smaller value such as 5 for a crisp graphic or a larger value such as 18 for a softer result.

If you omit -x and -y, each offset defaults to half the blur size, with the light to the left and above. For a reproducible script, specify all three values instead of relying on that relationship.

Checkpoint: compare two output files with different names. If increasing -x moves the shadow left, recheck the sign: the documented convention is that a larger positive x offset moves the shadow to the right.

4. Use translucent shadows only when the image suits them

The default models opaque material and produces a black shadow. Add -t when the foreground should cast a shadow coloured by the object itself:

$ ppmshadow -b 11 -x 16 -y 16 -t /path/to/source.ppm > /path/to/translucent-shadow.ppm

This can look better for translucent artwork, but it can also resemble a blurred copy of the image and become difficult to read when foreground and background contrast is low. Treat it as a visual choice, not as a higher-quality default. The option does not make the source image physically translucent or change its dimensions.

5. Fix the two input conditions that cause most failures

First, make sure the top-left pixel really is background. If the image is tightly cropped, add a one-pixel border in the intended background colour, run ppmshadow, then remove the corresponding border from the output. This matters because the program does not have a separate background-colour option.

Second, leave enough empty space on the edges in the direction of the shadow. The output cannot grow beyond the input dimensions, so the shadow is clipped at the image boundary. With too little room, internal Netpbm stages can fail rather than producing a useful partial image. Use pnmmargin to expand a tight border before shadowing, and crop later if the final composition requires it.

Do not use a low maxval when you need a smooth fringe. The blur needs enough available shades to represent its gradient. For PBM or another low-depth source, raise the depth first:

$ pamdepth 255 /path/to/low-depth.ppm > /path/to/source-255.ppm
$ ppmshadow -b 11 /path/to/source-255.ppm > /path/to/shadow-255.ppm

The output keeps the input maxval, so raising it before the shadowing step is what preserves room for intermediate shades.

6. Diagnose a bad run without guessing

Check the input header and permissions first:

$ file /path/to/source.ppm
$ test -r /path/to/source.ppm && echo readable
$ test -s /path/to/shadow.ppm.new && echo output-present

If the output is empty, treat the run as failed even if a wrapper reports success. The manual warns that an internal Netpbm error can leave an empty output without a non-zero status. Re-run to a new temporary name and keep the source available.

For deeper debugging, -k preserves intermediate files in a directory under TMPDIR, or under /tmp when that variable is unset:

$ ppmshadow -k -b 11 /path/to/source.ppm > /path/to/debug-shadow.ppm
$ find "${TMPDIR:-/tmp}" -maxdepth 1 -type d -name 'ppmshadow*' -user "$(id -un)" -print

Use -k only while investigating. It leaves a directory named with the process ID and can fail if that name is already in use. The preserved files can contain copies of the input image, so review and remove the specific debug directory when finished. Do not delete a broad temporary directory or anything you do not own.

Done means

  • The source PPM has a deliberate background colour at its top-left pixel and enough border space for the chosen offset.
  • The output is non-empty and has the same dimensions and maxval as the source.
  • The chosen -b, -x and -y values produce the intended softness and direction.
  • -t is used only when a coloured, translucent-looking shadow is wanted.
  • Any temporary output or -k debug directory has been checked and cleaned up without touching the original source.