Netpbm and the PGM Format – Part 1

In this series of articles I’ll introduce the Netpbm suite of tools and its simple and versatile PGM image file format, and demonstrate how PGM can be used for image processing and arbitrary data storage in Python.

In this part we meet Netpbm and its PGM file format. In the next installment I’ll present some Python code to read and write a PGM file. Later on I’ll present a simple image viewer to display the data, and lastly, I’ll present some unconventional techniques for storing things other than actual images in the PGM format, along with some reasons for why one might want to do that.


Netpbm is a collection of utilities for the manipulation of graphic images. The toolkit includes something like 300 separate tools, and provides support for conversions, sizing, scaling and other operations. The tools are designed to be incorporated into shell scripts and pipelined with each other and with other utilities in a Unix/Linux type environment. You can find out more about Netpbm and its component parts here:

Its Unix-ish roots notwithstanding, Netpbm has ported to a number of platforms, including:

Along with its support for the standard image formats such as JPEG, BMP and PNG, among many others, it incorporates four “native” image formats: PBM, PGM, PPM, and PAM.

The PGM Image File Format

The documentation for the PGM format states: “The PGM format is a lowest common denominator grayscale file format. It is designed to be extremely easy to learn and write programs for. (It’s so simple that most people will simply reverse engineer it because it’s easier than reading this specification). ”

You can find the PGM format specification here:

As stated, one of the main attractions of PGM is its simplicity. It can, of course, be used to store grayscale (luminance map) image data, but it can also be used to store just about any other kind of data as well. The data doesn’t even have to be a 2-D array. Also, as the format specification points out, it can be used to create “synthetic images” from data that was not originally an image. The Netpbm tools can then convert that data into something readily viewable, such as a JPEG image. There are some interesting data visualization tricks lurking in that bag (imagine dumping code metrics values from a set of modules into a unique file every time testing occurs, and then converting the data in each file into an “image”, colorizing it, and stringing them all end-to-end to watch how defects shift, shrink, or grow over time).

Although originally intended for use with 8-bit data, the most recent version of PGM supports a maxval parameter of greater than 255, allowing for up to 16-bits per data element or pixel. For most imaging applications this is more than adequate, but for arbitrary data storage it might be a limitation. It can, however, be worked around without too much agony.

PGM File Structure

The PGM format is extremely simple. It’s very easy to create PGM files and also relatively easy to read them. A PGM file consists of a header section with optional comments and a data section. Here’s a graphic illustrating the sections in a PGM file:

PGM image data structure

The format specification also states that there may be more than one image in a file, although I have not yet found a compelling reason to do this. In any case, here’s an illustration of multiple PGM images in a single file:

Multiple PGM images in a file

As stated in the format specification: “A PGM file consists of a sequence of one or more PGM images. There are no data, delimiters, or padding before, after, or between images.” It is worthwhile to note that the optional comments in a PGM may be considered to be “whitespace”.

One of the things I like about the PGM format is that everything in the “header” section is in printable ASCII. On one past project PGM was used to capture raw image data from remote imaging instruments. When the data was written to a file (one image per file) the comments were used to hold things like a timestamp value, the full image name, the name of the instrument, and the values of various settings (exposure time, filters used, and the camera’s X and Y pointing orientation, to name just a few things). This allowed us to scan through a directory of images using grep and pull out all the lines beginning with the # comment marker. A simple shell script was then used to create a nicely formatted list of images.

Until Next Time

That’s it for now. In the upcoming installments I’ll present some simple Python routines to write and read a PGM image data file. In the meantime you might want to check out the Netpbm documentation. Downloading the Netpbm package and fiddling with the various tools would be a useful (and perhaps entertaining) activity as well.

0 Responses to “Netpbm and the PGM Format – Part 1”

  1. Leave a Comment

Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

Follow Crankycode on

Little Buddy

An awesome little friend

Jordi the Sheltie passed away in 2008 at the ripe old age of 14. He was the most awesome dog I've ever known.


%d bloggers like this: