rawtopgm has no idea what shape your raw file is, so a guessed width will still produce a plausible-looking image that is quietly wrong. This turns a raw grayscale raster into a PGM that Netpbm and other tools can actually read, in about ten minutes once you know the dimensions and sample format.
You need a shell, the netpbm package, and a raw input file. This guide only reads the input and writes new output files: no elevated privileges required unless the input or destination directory is itself restricted. Keep the source file until you've checked the converted image.
Start by confirming which executable your shell will actually use:
$ command -v rawtopgm
/usr/bin/rawtopgm
$ rawtopgm -version
rawtopgm: Using libnetpbm from Netpbm Version: 11.5.2
Rawtopgm has no self-describing input format to inspect. You have to already know: the raster width and height, the bytes per grayscale sample, the byte order for two-byte samples, and whether rows carry padding. A file may also have a fixed header before the pixels start. All of that gets handed to the command as options and arguments.
Checkpoint: write down the dimensions and sample layout before running a conversion. Guess the width and the command will still happily produce a plausible-looking but incorrect image.
The usual case is one byte per pixel, ordered left to right, rows top to bottom. Output goes to standard output, so redirect it:
$ rawtopgm 640 480 /path/to/input.raw > image.pgm
Those two numbers are the input dimensions, not a resize request. The default is one byte per sample and a maximum value of 255. Standard input works too:
$ cat /path/to/input.raw | rawtopgm 640 480 - > image.pgm
Verify the result without opening binary pixel data in a text editor:
$ file image.pgm
image.pgm: Netpbm image data, size 640 x 480, rawbits, greymap
$ head -n 3 image.pgm
P5
640 480
255
The wording from file can vary. What matters: a non-empty file, the dimensions you expected, and a PGM header starting P5. A successful exit status only means rawtopgm completed; it proves nothing about whether your format assumptions were right.
If the file starts with metadata rather than pixels, skip its exact byte length:
$ rawtopgm -headerskip 128 640 480 /path/to/headered.raw > image.pgm
-headerskip defaults to zero. It doesn't parse or validate the header, and it can't discover its length for you: count from the start of the file to the first pixel yourself, using the format documentation.
Some rasters pad after each row. Pass that with -rowskip:
$ rawtopgm -rowskip 2 640 480 /path/to/padded.raw > image.pgm
Rowskip is padding bytes per row and can be fractional; rawtopgm spreads a fractional skip across multiple rows. Don't reach for -headerskip to handle row padding: the former applies once at the start, the latter after every row.
Checkpoint: compare the expected input size against the actual file size. For one-byte samples, expected size is header bytes plus height times the sum of pixel bytes per row and row padding. A mismatch means stop and check the format spec before trying more options.
Use -bpp 2 when each grayscale value takes two bytes. Without another flag, rawtopgm reads each pair most-significant byte first and writes a PGM with maximum value 65535:
$ rawtopgm -bpp 2 1024 768 /path/to/16bit.raw > image-16bit.pgm
$ head -n 3 image-16bit.pgm
P5
1024 768
65535
For little-endian input, add -littleendian:
$ rawtopgm -bpp 2 -littleendian 1024 768 /path/to/little-endian.raw > image-16bit.pgm
-littleendian has no effect with the one-byte default. If the source uses a smaller meaningful range, set the maximum explicitly with -maxval:
$ rawtopgm -bpp 2 -maxval 1023 640 480 /path/to/10bit-in-16bit.raw > image-10bit.pgm
The value after -maxval isn't a brightness adjustment. It tells rawtopgm the range the samples actually represent, and becomes the PGM header's maximum value. Use the range the source format defines, not a number that just looks right.
Rawtopgm expects rows top to bottom by default. If the file stores rows bottom-up, use -bt or the longer -bottomfirst:
$ rawtopgm -bt 640 480 /path/to/bottom-first.raw > image.pgm
The older -tb and -topbottom spellings still work for backwards compatibility, but -bt describes the input layout more clearly. This mode reads the whole input stream into memory rather than row-at-a-time, so avoid it on very large rasters unless you have the memory to spare.
If the converted picture comes out upside down, check this option and the source documentation first. Don't reverse the file in place: use a separate output and a tool like pamflip, already installed on this system, for a later correction.
Shell redirection with > truncates its destination before rawtopgm even starts. Write to a temporary name and replace the old result only after checking it:
$ rawtopgm 640 480 /path/to/input.raw > image.pgm.new
$ file image.pgm.new
image.pgm.new: Netpbm image data, size 640 x 480, rawbits, greymap
$ mv image.pgm.new image.pgm
mv just changes the directory entry, so check the new file first. If conversion fails, leave the existing image.pgm alone and remove only the incomplete image.pgm.new once you've checked its contents. Never delete the original raw file as part of this.
An error opening the input is usually a wrong path or missing read permission. Check without changing anything:
$ ls -l /path/to/input.raw
$ test -r /path/to/input.raw && echo readable
mv.