Home / Alt manpages / rawtoppm(1)

  • rawtoppm(1)
  • User command
  • linux

Turn Raw RGB Bytes into a Verified PPM with rawtoppm

You will finish with a PPM image made from a stream of raw, 8-bit RGB bytes, plus checks that its dimensions and header are correct. The examples use rawtoppm from Netpbm 11.5.2, installed here as package version 2:11.05.02-1.1build1.

Allow about fifteen minutes. You need a shell, a readable raw image file, and the image width and height. This workflow only reads the input and writes a new output file. It does not need sudo.

Safety warning

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

1. Check the installed command

Confirm that 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 includes build details, so the date and extra lines can differ between installations. The useful fact here is the Netpbm library version. The installed manual is the contract for the options used below.

Checkpoint

If command -v finds nothing, stop and install Netpbm through your normal package-management process. Do not copy a binary from an unrelated host merely to make the example run.

2. Confirm the input layout

rawtoppm does not discover image dimensions from a raw stream. You must supply width and height. By default, each pixel is three bytes in red, green, blue order, with one byte per component and a maximum value of 255. The expected data size is therefore:

width * height * 3 bytes

For example, a 2 by 2 RGB image needs 12 bytes. A file with a camera header or padding at the end of each row needs additional options, covered below. Keep the original input untouched until the output has been checked.

Do not infer the size from the file name. A wrong width shifts the boundary between rows, and the converter can still produce a syntactically valid but visibly corrupted PPM.

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. If you leave it out, rawtoppm reads standard input, which is useful in a pipeline:

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

There is normally no progress display because the image is written to standard output. A successful exit status means the converter completed; it does not prove that the supplied dimensions or colour order describe the source correctly.

Checkpoint

Check that the destination is non-empty and identified as a PPM before opening it in an image 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 use slightly different wording. The important checks are the expected dimensions and the PPM magic number P6. The pixel data after the header is binary, so do not edit the file in a text editor.

4. Account for a header or padded rows

If a file starts with metadata before the pixel raster, skip that byte count with -headerskip:

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

If every input row has padding after its pixels, skip that padding with -rowskip:

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

These values are bytes, not pixels. For a 640-pixel RGB row, the image data itself is 640 * 3 bytes. A four-byte alignment pad is extra, so -rowskip 4 is the right form. If both conditions apply, use both options:

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

Do not guess these counts from a damaged output. Obtain them from the format specification or the producer that wrote the stream. A plausible-looking PPM can still contain shifted rows.

5. Correct component order and interleaving

The default is -rgb and -interpixel: red, green and blue are adjacent for each pixel. Use one of the other component-order options 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. The option names describe the three bytes belonging to each pixel. If red and blue are swapped, people and objects often acquire an obvious colour cast, but a subtle source mistake may need a known test image to expose it.

Some formats store a complete row of one component, followed by a row of the next component, rather than placing components next to each pixel. Select -interrow for that layout:

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

-interplane is not implemented by this command. A file containing all red pixels, then all green pixels, then all blue pixels needs a different workflow, such as splitting the data into three parts, converting each part with rawtopgm, and combining the results with rgb3toppm.

6. Handle bottom-first images

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

$ 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 has not changed the source. If you are replacing an existing output, keep both names until you have inspected the corrected image.

7. Recover from a failed or unsafe write

If a conversion fails, the redirected destination may be empty or incomplete. With an important existing output, write to a temporary name in the same directory and replace the old file only after 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

mv replaces frame.ppm if it already exists. That replacement is deliberate and can remove the only good copy, so make a backup first when the old output matters. If the conversion fails, leave the original output in place and remove only the incomplete frame.ppm.new after checking its exact path.

Done means

  • You recorded the installed Netpbm version and confirmed the command path.
  • You supplied dimensions from the real input format, not from a guess.
  • The output begins with a P6 PPM header and reports the expected dimensions.
  • Header bytes, row padding, component order and row interleaving match the source layout.
  • A bottom-first image was flipped with pamflip -tb when required.
  • An existing output was protected from truncation until the replacement was verified.