Some notes on PPM files

PPM (Portable Pix Map) is a simple image file format to record RGB pixel data. You can write out PPM files using any C/C++/other program or even type pixel values directly into a text editor and save the result into a text file. This makes it an ideal format to use when you want to quickly create an image file to view/manipulate using Photoshop, etc. You don't need to include any headers or link with image libraries, instead you can simply use cout(), printf() etc. to output your "image". The downside is this: since the files contain raw (uncompressed) data in ASCII format, file sizes would be huge compared to TIFF or other better formats.

Here is a sample PPM image, with just 16 pixels (for ease of explanation):


P3
4 4
255

# the pixels below are:
# bwww
# wbww
# wwbw
# wwwb

# the scanlines below are going to be painted (by the viewer)
# TOP to BOTTOM, ie, in the order in which they appear below!

0 0 0 255 255 255 255 255 255 255 255 255

255 255 255 0 0 0 255 255 255 255 255 255

255 255 255 255 255 255 0 0 0 255 255 255

255 255 255 255 255 255 255 255 255 0 0 0
Notice that the image "header" is really simple: it is "P3", followed by <xres> <yres>, followed by the brightest R or G or B value among all the pixels about to follow. PPM files contain 8-bit data for R/G/B, meaning each channel (R/G/B) holds a 0 to 255 int value where 0 means 'black' and 255 means 'full intensity'. So a '0 0 0' pixel will be a black pixel, and a '255 255 255' pixel is pure white. '255 0 0' is pure red, '128 128 128' is 50% (mid-tone) gray, etc. If the above image is viewed using xv or Photoshop or Irfanview etc., you'd see this (magnified, since a 4x4 image is REALLY tiny :)):

The interesting thing is that the pixels appear in the order in which they are specified in the PPM file. So the very first pixel (with value 0 0 0 in our above sample) is at the top-left corner of the image.

If you want the black pixels to go diagonally from bottom-left to top-right instead (in other words, if you want them mirrored about the horizontal axis), you need to swap the rows (scanlines):


P3
4 4
255

# The foll. four rows of pixels are in reverse order compared to
# the previous version, to make the image appear correspondingly 
# reversed (scanline-wise)
255 255 255 255 255 255 255 255 255 0 0 0

255 255 255 255 255 255 0 0 0 255 255 255

255 255 255 0 0 0 255 255 255 255 255 255

0 0 0 255 255 255 255 255 255 255 255 255
The above image looks like this:

The reason why you need to note the origin location is this: if you store your image pixels in a two-dimensional array and write out the results to a file using a standard nested for() loop, you'll notice that your image is mirrored about the horiz. axis and therefore looks INCORRECT!

To fix this (to make the image be displayed corrected by the viewer programs), you can do one (NOT both!!) of the following:

To r/w PPM files, you can use: