Home / Alt manpages / rawtoppm(1)

  • rawtoppm(1)
  • User command
  • linux

Turn Raw RGB Bytes into a Verified PPM with rawtoppm

rawtoppm never learns your image's dimensions on its own, so a wrong width shifts every row and still produces a file that looks valid. This gets you a checked PPM from a stream of raw 8-bit RGB bytes in about fifteen minutes.

You need a shell, a readable raw image file, and the image width and height. This only reads the input and writes a new output file: no sudo needed.

Safety warning

Shell redirection with > truncates an existing destination before rawtoppm even starts. Use a new name while testing, or write a temporary file and rename it only after verification.

1. Check the installed command

Confirm the command is the Netpbm binary you expect and record its package version:

$ command -v rawtoppm
/usr/bin/rawtoppm
$ dpkg-query -W -f='${Package} ${Version}\n' netpbm
netpbm 2:11.05.02-1.1build1
$ rawtoppm --version 2>&1 | head -4
rawtoppm: Using libnetpbm from Netpbm Version: Netpbm 11.5.2
rawtoppm: Built from source dated 2024-03-31 09:09:47

The version output carries build details, so the date and extra lines can vary between installations. What matters is the Netpbm library version: 11.5.2 here, with the installed manual as the contract for the options below.

Checkpoint

If command -v finds nothing, stop and install Netpbm through your normal package management. Don't copy a binary from an unrelated host just to make the example run.

2. Confirm the input layout

rawtoppm can't discover image dimensions from a raw stream; you supply width and height yourself. By default each pixel is three bytes, red, green, blue, one byte per component, maximum value 255. The expected data size follows directly:

width * height * 3 bytes
  • Do the arithmetic first. A 2 by 2 RGB image needs 12 bytes. A camera header or end-of-row padding needs additional options, covered below.
  • Never infer size from the filename. A wrong width shifts the boundary between rows, and the converter can still produce a syntactically valid but visibly corrupted PPM.

Keep the original input untouched until the output has been checked.

3. Convert a normal interleaved stream

Pass the dimensions and input file, then redirect standard output to a new PPM file:

$ rawtoppm 1920 1080 /path/to/frame.rgb > frame.ppm

The input argument is optional. Leave it out and rawtoppm reads standard input, useful in a pipeline:

$ cat /path/to/frame.rgb | rawtoppm 1920 1080 > frame.ppm

There's normally no progress display, since the image goes straight to standard output. A successful exit status means the converter finished; it says nothing about whether your dimensions or colour order actually describe the source.

Checkpoint

Check the destination is non-empty and identified as a PPM before opening it in a viewer:

$ test -s frame.ppm && echo 'output is non-empty'
output is non-empty
$ file frame.ppm
frame.ppm: Netpbm image data, size = 1920 x 1080, rawbits, pixmap
$ head -c 11 frame.ppm
P6
1920 1080
255

file may word this slightly differently. What counts: the expected dimensions and the PPM magic number P6. The pixel data after the header is binary, so never edit the file in a text editor.

4. Account for a header or padded rows

Metadata before the pixel raster gets skipped with -headerskip:

$ rawtoppm -headerskip 128 640 480 /path/to/frame-with-header.rgb > frame.ppm

Padding after each row's pixels gets skipped with -rowskip:

$ rawtoppm -rowskip 4 640 480 /path/to/padded-frame.rgb > frame.ppm

Both values are bytes, not pixels. For a 640-pixel RGB row the image data itself is 640 * 3 bytes, so a four-byte alignment pad is extra and -rowskip 4 is correct. Combine both if you need to:

$ rawtoppm -headerskip 128 -rowskip 4 640 480 /path/to/input.rgb > frame.ppm

Never guess these counts from a damaged-looking output. Get them from the format specification or the producer that wrote the stream: a plausible-looking PPM can still hide shifted rows.

5. Correct component order and interleaving

The default is -rgb and -interpixel: red, green and blue sit next to each other for every pixel. Switch component order when the source stores each pixel differently:

$ rawtoppm -bgr 1920 1080 /path/to/frame.bgr > frame.ppm
$ rawtoppm -gbr 1920 1080 /path/to/frame.gbr > frame.ppm

The supported orders are -rgb, -rbg, -grb, -gbr, -brg and -bgr, each naming the three bytes belonging to a pixel. Swap red and blue and people often get an obvious colour cast, though a subtler mistake may need a known test image to expose it.

Some formats store a full row of one component, then a row of the next, rather than interleaving per pixel. Use -interrow for that:

$ rawtoppm -interrow 640 480 /path/to/planar-by-row.rgb > frame.ppm

-interplane is not implemented here. A file storing all red pixels, then all green, then all blue needs a different route: split the data into three parts, convert each with rawtopgm, and combine the results with rgb3toppm.

6. Handle bottom-first images

The input is assumed to start with the top row. If the source stores rows bottom to top, conversion still succeeds but the image lands upside down. Convert first, then flip:

$ rawtoppm 640 480 /path/to/bottom-first.rgb > upside-down.ppm
$ pamflip -tb upside-down.ppm > frame.ppm
$ file frame.ppm
frame.ppm: Netpbm image data, size = 640 x 480, rawbits, pixmap

The first command hasn't touched the source. If you're replacing an existing output, keep both names until the corrected image has been inspected.

7. Recover from a failed or unsafe write

A failed conversion can leave the redirected destination empty or incomplete. For an important existing output, write to a temporary name first and replace the old file only once the checks pass:

$ rawtoppm 1920 1080 /path/to/frame.rgb > frame.ppm.new
$ test -s frame.ppm.new && file frame.ppm.new
$ mv frame.ppm.new frame.ppm

Warning

mv replaces frame.ppm if it already exists. That's deliberate, and it can remove the only good copy, so back up first when the old output matters. If conversion fails, leave the original output alone and remove only the incomplete frame.ppm.new after checking its exact path.

Done means

  • Version recorded: the installed Netpbm version and command path confirmed.
  • Real dimensions used: taken from the actual input format, never guessed.
  • Header verified: the output begins with a P6 PPM header and reports the expected dimensions.
  • Layout matched: header bytes, row padding, component order and interleaving all match the source.
  • Orientation fixed: a bottom-first image was flipped with pamflip -tb where needed.
  • Output protected: an existing file stayed safe from truncation until the replacement was verified.