Binary data encodes values as bits and bytes instead of textual characters. In PNM images, binary formats P4, P5, and P6 store bitmap, graymap, and pixmap data compactly, requiring parsers to read bytes and interpret their bits or numeric values. section 12.2.3
Parsing binary PNM data requires these decisions:
- Read bitmap bytes from the most-significant bit to the least-significant bit; ignore unused trailing bits when the pixel count is not divisible by eight. section 12.2.3
- Read graymap and pixmap values as one byte by default, or two bytes when the maximum value exceeds 255. section 12.2.3
- Combine two bytes into a 16-bit value by shifting the first byte eight places and applying bitwise OR to the second. section 12.2.3
Listing 12.26 Parsers for binary encoded PNM files in 8-bit and 16-bit variants
p5PixelWord8P :: Parser RawPixel
p5PixelWord8P = Single <$> (fromIntegral <$> anyWord8) #1
p5PixelWord16P :: Parser RawPixel
p5PixelWord16P = Single <$> anyWord16 #2
p6PixelWord8P :: Parser RawPixel
p6PixelWord8P = RGB <$> p <*> p <*> p #3
where
p = fromIntegral <$> anyWord8
p6PixelWord16P :: Parser RawPixel
p6PixelWord16P = RGB <$> anyWord16 <*>
anyWord16 <*> anyWord16 #4
Use the parser definitions to distinguish eight-bit and sixteen-bit graymap and pixmap values. section 12.2.3
Listing 12.27 A parser for binary-encoded bitmaps
p4PixelP ::
Parser
( RawPixel,
RawPixel,
RawPixel,
RawPixel,
RawPixel,
RawPixel,
RawPixel,
RawPixel
)
p4PixelP = do
w <- anyWord8 #1
let parseBitAtIndex n =
Single $ if testBit w n then 1 else 0 #2
return
( parseBitAtIndex 7, #3
parseBitAtIndex 6, #3
parseBitAtIndex 5, #3
parseBitAtIndex 4, #3
parseBitAtIndex 3, #3
parseBitAtIndex 2, #3
parseBitAtIndex 1, #3
parseBitAtIndex 0 #3
) #3
Use the bitmap parser to see how one byte becomes eight pixels through explicit bit tests. section 12.2.3



