Home / Alt manpages / ppmtoarbtxt(1)

  • ppmtoarbtxt(1)
  • User command
  • linux

Turn PPM Pixels into Plain Text with Netpbm ppmtoarbtxt

By the end of this guide, you will have converted a PPM image into a text stream whose format you control. Netpbm's ppmtoarbtxt is useful when the output is not a standard image format: terminal art, a small data file, or a scene description for another program.

Allow about 10 minutes. You need Netpbm, a PPM input image, and a text editor or shell that can create two small template files. The examples use Netpbm 11.5.2 from Debian package netpbm 2:11.05.02-1.1build1. The command reads an image and writes standard output; it does not need elevated privileges.

1. Check the installed command

Confirm that the executable and its local version are the ones you intend to use:

command -v ppmtoarbtxt
ppmtoarbtxt --version

On the version used for these examples, the second command reports Netpbm Version 11.5.2 and a Debian build date. The version matters because template behaviour belongs to the installed Netpbm implementation, not to a shell wrapper.

Checkpoint: input and output

ppmtoarbtxt accepts one body-template filename, optional head and tail templates, and an optional PPM filename. If the image filename is omitted, it reads PPM from standard input. The generated text always goes to standard output, so redirect it deliberately.

2. Make a small body template

A body template is applied once for every pixel, in image order. Text is copied literally except for substitutions written as #(...). This template prints each pixel's luminance as an integer from 0 to 9:

#(ilum %d 0 9)

Save that line as body.txt. The ilum value is calculated from red, green and blue using the luminance weights documented by the command. The last two arguments map black and white: here, black becomes 0 and white becomes 9. The shorter #(ilum) form instead uses the default integer range 0 to 255.

Run it against an existing PPM file:

ppmtoarbtxt body.txt input.ppm > output.txt

Safety boundary

The shell's > overwrites an existing output.txt before the program starts. Use a new filename when the previous output matters. The input is only read, so recovery from this operation is to restore the overwritten output from your backup or regenerate it from the same input and template.

3. Add dimensions with a head template

Body output has no automatic separators or newline. Put the format header in a separate file when the target format needs image dimensions. For a plain PGM-style stream, create head.txt with:

P2
#(width) #(height)
255

The final newline in a template file is ignored. The other whitespace is significant, so keep the line breaks shown above. Combine the templates like this:

ppmtoarbtxt body.txt -hd head.txt input.ppm > inverted.pgm

To make that output a usable plain grayscale image, the body must map the luminance in the direction required by the target. For inversion, use #(ilum %d 255 0) instead of the 0-to-9 template. Check the result without changing it:

head -n 4 inverted.pgm

You should see P2, the input width and height, 255, and then the generated pixel values. Do not assume the body adds a row break: add a newline or another separator to the body template when the consumer requires one.

4. Use pixel positions and colour channels

Pixel substitutions can include horizontal and vertical positions. The first pixel is at position 0,0. The floating-point channel substitutions use values from 0.0 to 1.0 when their references are 0 and 1:

#(posx),#(posy),#(fred %.1f 0 1),#(fgreen %.1f 0 1),#(fblue %.1f 0 1)

Save it as colour.txt, then run:

ppmtoarbtxt colour.txt input.ppm > pixels.txt
head -n 5 pixels.txt

fred, fgreen and fblue represent the red, green and blue channels. Integer alternatives are ired, igreen and iblue; posx and posy use unsigned integer positions. The command does not insert commas, spaces or newlines for you. Put literal separators outside the substitution, as in the example.

5. Add a tail or pipe the input

A tail template works like a head template but is appended after every body expansion. For example, a format that needs a closing marker can use tail.txt containing:

END

Run all three parts explicitly:

ppmtoarbtxt body.txt -hd head.txt -tl tail.txt input.ppm > rendered.txt

Head and tail templates may use width and height. Pixel substitutions such as posx and ilum are for the body template; the manual says their result is undefined in a head or tail template.

For a pipeline, leave off the input filename:

pnmfile input.ppm
cat input.ppm | ppmtoarbtxt body.txt > output.txt

The first command is a separate inspection step. If the input is not actually PPM, convert it before calling ppmtoarbtxt; a malformed or wrong-format stream is a likely cause of an early failure.

Common traps and failure checks

  • An unrecognised-looking #(...) is often copied literally, but text close to a valid substitution can make the program fail. Check spelling and parentheses first.
  • Keep format strings simple and fixed, such as %d or %.1f. They are passed to a C formatted-output function. Do not put a percent sign or newline into a format string, and do not build one from untrusted image data.
  • A missing newline is normally intentional according to the template rules. Add one explicitly when each pixel or row must be separated.
  • Head and tail templates are whole-image templates. Width and height are meaningful there; per-pixel values are not.

Done means

  • ppmtoarbtxt --version identifies the Netpbm build you tested.
  • Your body template contains only verified substitutions and deliberate separators.
  • The output file begins and ends as the target format requires, with head and tail templates where needed.
  • You inspected the generated output and did not overwrite a valuable file accidentally.