liveBook · Manning

Portable graymap format

As explained in Learn Haskell by Example

A graymap is a PNM image format in which each pixel is represented by a single grayscale sample.

Portable Graymap Format (PGM) is a Portable Anymap Format (PNM) for grayscale images. Each pixel has one sample value, from 0 through the maximum value declared in the header. PGM keeps its header in ASCII and avoids superfluous metadata, making the format straightforward to inspect and parse. section 12.1.1

A PGM header identifies the encoding with a magic number, then gives image width, height, and maximum sample value. P2 denotes ASCII data; P5 denotes binary data. File extensions are not relied upon to determine the format, and comments beginning with # may appear in headers. section 12.1.1 section 12.2.3

Choose the pixel reader from the magic number and maximum value:

  • For P2, read one decimal value for each grayscale pixel. section 12.2.3
  • For P5, read one byte per pixel by default; when the header maximum exceeds 255, read two bytes per pixel. section 12.2.3
  • Keep raw parsing separate from validation: later checks can confirm pixel count, pixel shape, and that samples do not exceed the header maximum. section 13.1.1

An ASCII graymap

A P2 file can declare a 10×14 image with maximum value 9, followed by 140 whitespace-separated samples. In the shown image, 0 represents black and 9 represents white; intermediate values form the grayscale drawing. section 12.1.1

Listing 12.2 A simple PGM file with comments in its header
P2 10 14 # PGM in ASCII with 10x14 pixels
9        # Values from 0 (black) to 9 (white)
9 6 3 4 9 9 9 9 9 9
8 4 2 2 6 9 9 9 9 9
8 6 9 5 4 9 9 9 9 9
8 9 9 9 4 9 9 9 9 9
9 9 9 9 4 7 9 9 9 9
9 9 9 9 3 6 9 9 9 9
9 9 9 6 1 3 9 9 9 9
9 9 9 4 0 3 8 9 9 9
9 9 7 0 4 4 8 9 9 9
9 9 4 1 7 5 6 9 9 9
9 7 1 3 9 6 5 9 9 8
9 5 0 7 9 8 3 8 9 6
8 1 2 8 9 8 3 3 4 4
5 2 5 9 9 9 7 2 1 7

Inspect a complete P2 graymap: its magic number, dimensions, maximum value, comments, and one grayscale sample per pixel are all visible as text. section 12.1.1

PGM belongs beside PBM and PPM in the PNM family. PBM stores one black-or-white value per pixel, while PPM stores three values per pixel for RGB. PGM occupies the middle ground: one variable grayscale value per pixel. section 12.1.1

A parser can initially represent PGM samples as single raw numeric pixels, then convert validated images into 8-bit or 16-bit grayscale pixel types. This preserves the distinction required by binary data whose maximum value may require two-byte samples. section 12.2.3 section 13.1.1

How Learn Haskell by Example covers it

How deep it goes
Explains headers, ASCII and binary samples, 8-bit versus 16-bit reading, and subsequent validation checks.
Examples
Demonstrates a commented 10×14 P2 file with maximum value 9 and visible grayscale sample data.
What it assumes
Introduces PGM structure before using decimal parsing, byte reading, Word16 values, and validation representations.
What you can do after
Build from scratch parsers that select decimal, 8-bit, or 16-bit grayscale sample readers from PGM metadata.
How it connects
Connects PGM to PNM, PBM, PPM, magic numbers, ASCII and binary encoding, validation, and JuicyPixels.

Related concepts

This explainer was generated by Manning's knowledge graph from the text of Learn Haskell by Example. The section links point to the parts of the book it draws on.