pstopnm renders a PostScript or Encapsulated PostScript file to PPM, PGM or PBM through Ghostscript, no separate viewer required. This guide builds a repeatable version of that render: useful pixel dimensions, a result you check before it overwrites anything, and a rescue path when Ghostscript chokes on the input. The examples match Netpbm 11.5.2, installed here as Debian package netpbm 2:11.05.02-1.1build1.
Allow about fifteen minutes. You need a readable PostScript file, pstopnm, Ghostscript, and a shell. The conversion normally needs no elevated privileges. Do not use sudo merely because the input is PostScript: render it in a working directory you control.
Confirm the executable and package version before building a script around them:
$ command -v pstopnm
/usr/bin/pstopnm
$ pstopnm --version
pstopnm: Using libnetpbm from Netpbm Version: Netpbm 11.5.2
pstopnm: Built from source dated 2024-03-31 09:09:47
$ command -v gs
/usr/bin/gs
$ gs --version
10.02.1
The exact build line can differ. What matters is that both commands exist. pstopnm delegates rendering to Ghostscript, so a missing Ghostscript binary or a build without the relevant PNM devices causes conversion to fail. Check the available device list if you are diagnosing that failure:
$ gs --help | grep -E 'pbm(raw)?|pgm(raw)?|pnm(raw)?|ppm(raw)?'
You need at least one of the listed PBM, PGM, PNM or PPM devices. This is a read-only check.
Use -stdout when you want a pipeline or an explicitly named destination. Add -ppm to make the output format unambiguous, and -dpi to choose the rendering resolution:
$ pstopnm -stdout -ppm -dpi 72 /path/to/document.ps > /tmp/document.ppm
$ file /tmp/document.ppm
/tmp/document.ppm: Netpbm image data, size = 612 x 792, rawbits, pixmap
The dimensions in the example are illustrative. They depend on the input bounding box and the selected resolution. The redirection target is a deliberate temporary name; shell > truncates an existing target before pstopnm starts, so do not point it at a valuable image unless replacement is intended.
Checkpoint: a successful conversion should produce a non-empty PNM file and a zero exit status. Check both without opening or modifying the input:
$ test -s /tmp/document.ppm && echo 'output exists and is non-empty'
output exists and is non-empty
$ printf 'exit status: %s\n' "$?"
exit status: 0
Without -stdout, the command writes one file per page beside the input. For document.ps, the usual names are document001.ppm, document002.ppm, and so on. PPM is the default format. Use -pgm or -pbm when a greyscale or bitmap result is specifically required:
$ mkdir -p /tmp/pstopnm-pages
$ cp /path/to/document.ps /tmp/pstopnm-pages/document.ps
$ cd /tmp/pstopnm-pages
$ pstopnm -ppm document.ps
$ file document001.ppm
document001.ppm: Netpbm image data, size = ..., rawbits, pixmap
Copying the input into a scratch directory keeps generated page files away from your source tree. If the input name does not end in .ps, pstopnm uses the whole name when constructing the output name. If an exact input name does not exist but the same name with .ps appended does, pstopnm tries that spelling.
For a multi-page PostScript file, standard output is usually easier to control. It produces a multi-image PNM stream; use pnmsplit later if you need separate page files. A named file is treated differently for Encapsulated PostScript: a file containing concatenated EPS documents is not processed like a standard-input stream.
-dpi sets the same output device resolution horizontally and vertically. For a fixed pixel size, use -xsize and -ysize:
$ pstopnm -stdout -ppm -xsize 1200 -ysize 1800 \
-portrait /path/to/document.ps > /tmp/document-1200x1800.ppm
$ file /tmp/document-1200x1800.ppm
/tmp/document-1200x1800.ppm: Netpbm image data, size = 1200 x 1800, rawbits, pixmap
If you provide only one of those size options, pstopnm chooses the other to keep the same resolution in both directions. The dimensions describe the rendered image, not necessarily the physical page. -portrait and -landscape force orientation; if neither is present, pstopnm chooses the orientation it considers the best fit.
By default, pstopnm may add borders. Set both border fractions to zero when the image must match the selected subject area:
$ pstopnm -stdout -ppm -xborder 0 -yborder 0 \
-xsize 1200 -ysize 1800 -portrait /path/to/document.ps \
> /tmp/document-cropped.ppm
-nocrop changes the output to the dimensions of the bordered subject image. If no size or resolution is specified, pstopnm uses historical calculations involving -xmax and -ymax, whose defaults are 612 by 792 pixels. Do not rely on that implicit sizing for a reproducible batch job.
For a normal PostScript file, pstopnm reads the %%BoundingBox comment when it is available. Standard input cannot use that information in the same way, so specify the subject rectangle with -llx, -lly, -urx and -ury if the default area is wrong:
$ pstopnm -stdout -ppm -llx 0 -lly 0 -urx 612 -ury 792 \
-xborder 0 -yborder 0 /path/to/document.ps > /tmp/document-page.ppm
Those coordinates are in PostScript page units, not pixels. Inspect the input first if you need its bounding box:
$ grep '%%BoundingBox' /path/to/document.ps
Do not treat a successful exit status as proof that the crop is visually correct. Check the dimensions with file and inspect the image with a trusted viewer or a later Netpbm conversion.
Use -verbose for processing details, including the selected bounding box, output dimensions and Ghostscript invocation. If the file is an older PostScript Level 1 document and no image is produced, convert a copy to PostScript Level 3 with ps2ps, then retry. Keep the original file untouched.
Some PostScript files initialise the current transformation matrix in a way pstopnm cannot handle correctly. The manual's suggested starting point is:
$ pstopnm -stdout -ppm -xborder 0 -yborder 0 \
-portrait -nocrop /path/to/document.ps > /tmp/document-retry.ppm
If Ghostscript reports an invalid document or a required device is unavailable, fix that environment or input problem rather than relaxing system protections. The installed command invokes Ghostscript with a safer execution mode, but PostScript is still input data that deserves ordinary file-handling care.
pstopnm and Ghostscript are installed and their versions are known.file confirms a non-empty PBM, PGM or PPM result.