Read a pgm file in python

After reading the header as you've shown, you've got the width (1024) the height (the next 1024) and the depth (255). To get the pixel data it is easiest to read them byte-by-byte:

def read_pgm(pgmf):
    """Return a raster of integers from a PGM as a list of lists."""
    assert pgmf.readline() == 'P5\n'
    (width, height) = [int(i) for i in pgmf.readline().split()]
    depth = int(pgmf.readline())
    assert depth <= 255

    raster = []
    for y in range(height):
        row = []
        for y in range(width):
            row.append(ord(pgmf.read(1)))
        raster.append(row)
    return raster

This code will only work for 8-bit depth images which is why the assert statement is present.

It is legal for a PGM file to have the header information on one line as in:

P5 1024 1024 15

If you do encounter such a file, read_pgm will fail noisily; the code to handle such cases is left as an exercise for the reader.


msw's answer guided me to write the following function to read 16-bits .pmg images with the kind of header he described :

def read_pgm(pgmf):
"""Return a raster of integers from a PGM as a list of lists."""
   header = pgmf.readline()
   assert header[:2] == b'P5'
   (width, height) = [int(i) for i in header.split()[1:3]]
   depth = int(header.split()[3])
   assert depth <= 65535

   raster = []
   for y in range(height):
       row = []
       for y in range(width):
           low_bits = ord(pgmf.read(1))
           row.append(low_bits+255*ord(pgmf.read(1)))
       raster.append(row)
   return raster

f = open(pgm_path, 'rb')
im = read_pgm(f)
f.close()
im = np.array(im)

I hope this helps clarify how to use the previously given answer