pnm

    Dark Mode
Search:
Group by:

pnm is parser/generator of PNM (Portable Anymap).

Basic usage

PBM (Portable bitmap)

Reading PBM file

readPBMFile proc can read PBM (P1 and P4).

import pnm

block:
  # P1
  let p = readPBMFile("tests/out/p1.pbm")
  echo p

block:
  # P4
  let p = readPBMFile("tests/out/p4.pbm")
  echo p

Writing PBM file

writePBMFile proc can write PBM (P1 and P4).

import pnm

let col = 32 # 8 (bit) x 4 (column) == 32
let row = 12
let data = @[
  0b11111111'u8, 0b00000000, 0b11111111, 0b00000000,
  0b11111111, 0b00000000, 0b11111111, 0b00000000,
  0b11111111, 0b00000000, 0b11111111, 0b00000000,
  0b11111111, 0b00000000, 0b11111111, 0b00000000,
  0b11111111, 0b11111111, 0b11111111, 0b11111111,
  0b11111111, 0b11111111, 0b11111111, 0b11111111,
  0b11111111, 0b11111111, 0b11111111, 0b11111111,
  0b11111111, 0b11111111, 0b11111111, 0b11111111,
  0b00000000, 0b00000000, 0b00000000, 0b00000000,
  0b00000000, 0b00000000, 0b00000000, 0b00000000,
  0b00000000, 0b00000000, 0b00000000, 0b00000000,
  0b00000000, 0b00000000, 0b00000000, 0b00000000,
]

block:
  # P1
  let p = newPBM(pbmFileDescriptorP1, col, row, data)
  writePBMFile("tests/out/p1.pbm", p)

block:
  # P4
  let p = newPBM(pbmFileDescriptorP4, col, row, data)
  writePBMFile("tests/out/p4.pbm", p)

PGM (Portable graymap)

Reading PGM file

readPGMFile proc can read PGM (P2 and P5).

import pnm

block:
  # P2
  let p = readPGMFile("tests/out/p2.pgm")
  echo p

block:
  # P5
  let p = readPGMFile("tests/out/p5.pgm")
  echo p

Writing PGM file

writePGMFile proc can write PGM (P2 and P5).

import pnm

let col = 6
let row = 12
let max = 2
let data = @[
  0'u8, 0, 0, 0, 0, 0,
  0'u8, 0, 0, 0, 0, 0,
  0'u8, 0, 0, 0, 0, 0,
  0'u8, 0, 0, 0, 0, 0,
  1, 1, 1, 1, 1, 1,
  1, 1, 1, 1, 1, 1,
  1, 1, 1, 1, 1, 1,
  1, 1, 1, 1, 1, 1,
  2, 2, 2, 2, 2, 2,
  2, 2, 2, 2, 2, 2,
  2, 2, 2, 2, 2, 2,
  2, 2, 2, 2, 2, 2,
]

block:
  # P2
  let p = newPGM(pgmFileDescriptorP2, col, row, data)
  writePGMFile("tests/out/p2.pgm", p)

block:
  # P5
  let p = newPGM(pgmFileDescriptorP5, col, row, data)
  writePGMFile("tests/out/p5.pgm", p)

PPM (Portable pixmap)

Reading PPM file

readPPMFile proc can read PPM (P3 and P6).

import pnm

block:
  # P3
  let p = readPPMFile("tests/out/p3.ppm")
  echo p

block:
  # P6
  let p = readPPMFile("tests/out/p6.ppm")
  echo p

Writing PPM file

writePPMFile proc can write PPM (P3 and P6).

import pnm

let col = 6
let row = 12
let max = 2
let data = @[
  0'u8, 0, 0, 0, 0, 0,
  0'u8, 0, 0, 0, 0, 0,
  0'u8, 0, 0, 0, 0, 0,
  0'u8, 0, 0, 0, 0, 0,
  1, 1, 1, 1, 1, 1,
  1, 1, 1, 1, 1, 1,
  1, 1, 1, 1, 1, 1,
  1, 1, 1, 1, 1, 1,
  2, 2, 2, 2, 2, 2,
  2, 2, 2, 2, 2, 2,
  2, 2, 2, 2, 2, 2,
  2, 2, 2, 2, 2, 2,
]

block:
  # P3
  let p = newPPM(ppmFileDescriptorP3, col, row, data)
  writePPMFile("tests/out/p3.ppm", p)

block:
  # P6
  let p = newPPM(ppmFileDescriptorP6, col, row, data)
  writePPMFile("tests/out/p6.ppm", p)

PNM format examples

PBM

P1
# comment
5 6
0 0 1 0 0
0 1 1 0 0
0 0 1 0 0
0 0 1 0 0
0 0 1 0 0
1 1 1 1 1

PGM

P2
# Shows the word "FEEP" (example from Netpgm man page on PGM)
24 7
15
0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0
0  3  3  3  3  0  0  7  7  7  7  0  0 11 11 11 11  0  0 15 15 15 15  0
0  3  0  0  0  0  0  7  0  0  0  0  0 11  0  0  0  0  0 15  0  0 15  0
0  3  3  3  0  0  0  7  7  7  0  0  0 11 11 11  0  0  0 15 15 15 15  0
0  3  0  0  0  0  0  7  0  0  0  0  0 11  0  0  0  0  0 15  0  0  0  0
0  3  0  0  0  0  0  7  7  7  7  0  0 11 11 11 11  0  0 15  0  0  0  0
0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0

PPM

P3
# The P3 means colors are in ASCII, then 3 columns and 2 rows, then 255 for max color, then RGB triplets
3 2
255
255 0 0
0 255 0
0 0 255
255 255 0
255 255 255
0 0 0

See also

Types

PBMObj = object
  fileDescriptor*: string    ## File descriptor (P1 or P4)
  col*, row*: int            ## Column count
  data*: seq[uint8]          ## Byte (pixel) data
  
PBM object. Don't directly use this type.
PBM = ref PBMObj
PBM ref object. Procedures use this type. Not PBMobj.
PGMObj = object
  fileDescriptor*: string    ## File descriptor (P2 or P5)
  col*, row*: int            ## Column count
  max*: uint8                ## Max value
  data*: seq[uint8]          ## Byte (pixel) data
  
PGM object. Don't directly use this type.
PGM = ref PGMObj
PGM ref object. Procedures use this type. Not PGMObj.
PPMObj = object
  fileDescriptor*: string    ## File descriptor (P3 or P6)
  col*, row*: int            ## Column count
  max*: uint8                ## Max value
  data*: seq[uint8]          ## Byte (pixel) data
  
PPM object. Don't directly use this type.
PPM = ref PPMObj
PPM ref object. Procedures use this type. Not PPMObj.
IllegalFileDescriptorError = object of Defect
  
Return this when file descriptor is wrong. filedescriptors are P1 or P2 or P3 or P4 or P5 or P6.
IllegalColumnRowError = object of Defect
  
Return this when column or row value is wrong.
IllegalMaxValueError = object of Defect
  
Return this when max value is wrong.

Procs

proc newPBM(fileDescriptor: string; col, row: int; data: seq[uint8]): PBM {...}{.
    raises: [], tags: [].}
Return new PBM.

Example:

let p1 = newPBM(pbmFileDescriptorP1, 1, 1, @[1'u8])
let p4 = newPBM(pbmFileDescriptorP4, 1, 1, @[1'u8])
proc newPGM(fileDescriptor: string; col, row: int; max: uint8; data: seq[uint8]): PGM {...}{.
    raises: [], tags: [].}
Return new PGM.

Example:

let p2 = newPGM(pgmFileDescriptorP2, 1, 1, 255'u8, @[1'u8])
let p5 = newPGM(pgmFileDescriptorP5, 1, 1, 255'u8, @[1'u8])
proc newPGM(fileDescriptor: string; col, row: int; data: seq[uint8]): PGM {...}{.
    raises: [], tags: [].}
Return a new PGM with the maximum brightness of the data as the maximum brightness of the image.

Example:

let p2 = newPGM(pgmFileDescriptorP2, 1, 1, @[1'u8])
let p5 = newPGM(pgmFileDescriptorP5, 1, 1, @[1'u8])
proc newPPM(fileDescriptor: string; col, row: int; max: uint8; data: seq[uint8]): PPM {...}{.
    raises: [], tags: [].}
Return new PPM.

Example:

let p3 = newPPM(ppmFileDescriptorP3, 1, 1, 255'u8, @[255'u8, 255, 255])
let p6 = newPPM(ppmFileDescriptorP6, 1, 1, 255'u8, @[255'u8, 255, 255])
proc newPPM(fileDescriptor: string; col, row: int; data: seq[uint8]): PPM {...}{.
    raises: [], tags: [].}
Return a new PPM with the maximum brightness of the data as the maximum brightness of the image.

Example:

let p3 = newPPM(ppmFileDescriptorP3, 1, 1, @[255'u8, 255, 255])
let p6 = newPPM(ppmFileDescriptorP6, 1, 1, @[255'u8, 255, 255])
proc formatP1(self: PBM): string {...}{.raises: [ValueError], tags: [].}
Return formatted string for PBM P1.

Example:

let p1 = newPBM(pbmFileDescriptorP1, 1, 1, @[0b1000_0000'u8])
doAssert p1.formatP1 == "P1\n1 1\n1"
proc formatP2(self: PGM): string {...}{.raises: [ValueError], tags: [].}
Return formatted string for PGM P2.

Example:

let p = newPGM(pgmFileDescriptorP2, 1, 1, 255'u8, @[2'u8])
doAssert p.formatP2 == "P2\n1 1\n255\n2"
proc formatP3(self: PPM): string {...}{.raises: [ValueError], tags: [].}
Return formatted string for PPM P3.

Example:

let p = newPPM(ppmFileDescriptorP3, 1, 1, 255'u8, @[255'u8, 255, 255])
doAssert p.formatP3 == "P3\n1 1\n255\n255 255 255"
proc formatP4(self: PBM): seq[uint8] {...}{.raises: [], tags: [].}
Return formatted byte data for PBM P4.

Example:

let p4 = newPBM(pbmFileDescriptorP4, 1, 1, @[0b1000_0000'u8])
doAssert p4.formatP4 == @[
  'P'.uint8, '4'.uint8, '\n'.uint8,
  '1'.uint8, ' '.uint8, '1'.uint8, '\n'.uint8,
  0b10000000'u8,
]
proc formatP5(self: PGM): seq[uint8] {...}{.raises: [], tags: [].}
Return formatted byte data for PGM P5.

Example:

let p = newPGM(pgmFileDescriptorP5, 1, 1, 255'u8, @[2'u8])
doAssert p.formatP5 == @[
  'P'.uint8, '5'.uint8, '\n'.uint8,
  '1'.uint8, ' '.uint8, '1'.uint8, '\n'.uint8,
  '2'.uint8, '5'.uint8, '5'.uint8, '\n'.uint8,
  2'u8,
]
proc formatP6(self: PPM): seq[uint8] {...}{.raises: [], tags: [].}
Return formatted byte data for PPM P6.

Example:

let p = newPPM(ppmFileDescriptorP6, 1, 1, 255'u8, @[255'u8, 255, 255])
doAssert p.formatP6 == @[
  'P'.uint8, '6'.uint8, '\n'.uint8,
  '1'.uint8, ' '.uint8, '1'.uint8, '\n'.uint8,
  '2'.uint8, '5'.uint8, '5'.uint8, '\n'.uint8,
  255'u8, 255, 255,
]
proc parsePBM(s: string): PBM {...}{.raises: [ValueError], tags: [].}
Return PBM that is parsed from string. This proc is function for PBM P1. You should validate string to use this proc with validatePBM proc .

Example:

doAssert "P1\n1 1\n1".parsePBM[] == newPBM(pbmFileDescriptorP1, 1, 1, @[0b1000_0000'u8])[]
P1用
proc parsePBM(s: openArray[uint8]): PBM {...}{.raises: [ValueError], tags: [].}
Return PBM that is parsed from uint8 sequence. This proc is function for PBM P4. You should validate string to use this proc with validatePBM proc .

Example:

doAssert @[
  'P'.uint8, '4'.uint8, '\n'.uint8,
  '1'.uint8, ' '.uint8, '1'.uint8, '\n'.uint8,
  0b1000_0000'u8,
].parsePBM[] == newPBM(pbmFileDescriptorP4, 1, 1, @[0b1000_0000'u8])[]
proc parsePGM(s: string): PGM {...}{.raises: [ValueError], tags: [].}
Return PGM that is parsed from string. This proc is function for PGM P2. You should validate string to use this proc with validatePGM proc .

Example:

doAssert "P2\n1 1\n255\n2".parsePGM[] == newPGM(pgmFileDescriptorP2, 1, 1, 255'u8, @[2'u8])[]
doAssert "P5\n1 1\n255\n2".parsePGM[] == newPGM(pgmFileDescriptorP5, 1, 1, 255'u8, @[2'u8])[]
proc parsePGM(s: openArray[uint8]): PGM {...}{.raises: [ValueError], tags: [].}
Return PGM that is parsed from string. This proc is function for PGM P2. You should validate string to use this proc with validatePGM proc .

Example:

doAssert @['P'.uint8, '2'.uint8, '\n'.uint8,
           '1'.uint8, ' '.uint8, '1'.uint8, '\n'.uint8,
           '2'.uint8, '5'.uint8, '5'.uint8, '\n'.uint8,
           2'u8,
].parsePGM[] == newPGM(pgmFileDescriptorP2, 1, 1, 255'u8, @[2'u8])[]
proc parsePPM(s: string): PPM {...}{.raises: [ValueError], tags: [].}
Return PPM that is parsed from string. This proc is function for PPM P3. You should validate string to use this proc with validatePPM proc .

Example:

doAssert "P3\n1 1\n255\n255 255 255".parsePPM[] == newPPM(ppmFileDescriptorP3, 1, 1, 255'u8, @[255'u8, 255, 255])[]
proc parsePPM(s: openArray[uint8]): PPM {...}{.raises: [ValueError], tags: [].}
Return PPM that is parsed from string. This proc is function for PPM P3. You should validate string to use this proc with validatePPM proc .

Example:

doAssert @['P'.uint8, '6'.uint8, '\n'.uint8,
           '1'.uint8, ' '.uint8, '1'.uint8, '\n'.uint8,
           '2'.uint8, '5'.uint8, '5'.uint8, '\n'.uint8,
           255'u8, 255, 255
].parsePPM[] == newPPM(ppmFileDescriptorP6, 1, 1, 255'u8, @[255'u8, 255, 255])[]
proc validatePBM(s: openArray[uint8]) {...}{.raises: [ValueError], tags: [].}

Validate PBM data format.

Validating contents are:

  1. It is P1 or P4 that 2 byte data at the head.
  2. It is decimal number that data on 2 line.

Raise IllegalFileDescriptorError or IllegalColumnRowError when illegal was found.

Example:

## No error
validatePBM(@['P'.uint8, '1'.uint8, '\n'.uint8,
              '1'.uint8, ' '.uint8, '1'.uint8, '\n'.uint8,
              '1'.uint8])
validatePBM(@['P'.uint8, '4'.uint8, '\n'.uint8,
              '1'.uint8, ' '.uint8, '1'.uint8, '\n'.uint8,
              '1'.uint8])
proc validatePGM(s: openArray[uint8]) {...}{.raises: [ValueError], tags: [].}

Validate PGM data format.

Validating contents are:

  1. It is P2 or P5 that 2 byte data at the head.
  2. It is decimal number that data on 2 line.
  3. It is max value of data that data on 3 line.

Raise IllegalFileDescriptorError or IllegalColumnRowError when illegal was found.

Example:

## No error
validatePGM(@['P'.uint8, '2'.uint8, '\n'.uint8,
              '1'.uint8, ' '.uint8, '1'.uint8, '\n'.uint8,
              '1'.uint8])
validatePGM(@['P'.uint8, '5'.uint8, '\n'.uint8,
              '1'.uint8, ' '.uint8, '1'.uint8, '\n'.uint8,
              '1'.uint8])
proc validatePPM(s: openArray[uint8]) {...}{.raises: [ValueError], tags: [].}

Validate PPM data format.

Validating contents are:

  1. It is P3 or P6 that 2 byte data at the head.
  2. It is decimal number that data on 2 line.
  3. It is max value of data that data on 3 line.

Raise IllegalFileDescriptorError or IllegalColumnRowError when illegal was found.

Example:

## No error
validatePPM(@['P'.uint8, '3'.uint8, '\n'.uint8,
              '1'.uint8, ' '.uint8, '1'.uint8, '\n'.uint8,
              '1'.uint8, '\n'.uint8,
              '1'.uint8])
validatePPM(@['P'.uint8, '6'.uint8, '\n'.uint8,
              '1'.uint8, ' '.uint8, '1'.uint8, '\n'.uint8,
              '1'.uint8, '\n'.uint8,
              '1'.uint8])
proc readPBM(f: File): PBM {...}{.raises: [IOError, ValueError, EOFError],
                             tags: [ReadIOEffect].}
Return PBM (P1 or P4) from file. This proc validates data before reading data. Raise errors when illegal was found. At seeing description of erros, see validatePBM proc

Example:

try:
  var f = open("p1.pbm")
  let p = f.readPBM
  ## do something...
  f.close
except:
  stderr.writeLine getCurrentExceptionMsg()
proc readPGM(f: File): PGM {...}{.raises: [IOError, ValueError, EOFError],
                             tags: [ReadIOEffect].}
Return PGM (P2 or P5) from file. This proc validates data before reading data. Raise errors when illegal was found. At seeing description of erros, see validatePGM proc

Example:

try:
  var f = open("p2.pgm")
  let p = f.readPGM
  ## do something...
  f.close
except:
  stderr.writeLine getCurrentExceptionMsg()
proc readPPM(f: File): PPM {...}{.raises: [IOError, ValueError, EOFError],
                             tags: [ReadIOEffect].}
Return PPM (P3 or P6) from file. This proc validates data before reading data. Raise errors when illegal was found. At seeing description of erros, see validatePPM proc

Example:

try:
  var f = open("p3.ppm")
  let p = f.readPPM
  ## do something...
  f.close
except:
  stderr.writeLine getCurrentExceptionMsg()
proc readPBMFile(fn: string): PBM {...}{.raises: [IOError, ValueError, EOFError],
                                    tags: [ReadIOEffect].}
Return PBM (P1 or P4) from file. This proc validates data before reading data. Raise errors when illegal was found. At seeing description of erros, see validatePBM proc

Example:

try:
  let p = readPBMFile("p1.pbm")
  ## do something...
except:
  stderr.writeLine getCurrentExceptionMsg()
proc readPGMFile(fn: string): PGM {...}{.raises: [IOError, ValueError, EOFError],
                                    tags: [ReadIOEffect].}
Return PGM (P2 or P5) from file. This proc validates data before reading data. Raise errors when illegal was found. At seeing description of erros, see validatePGM proc

Example:

try:
  let p = readPGMFile("p2.pgm")
  ## do something...
except:
  stderr.writeLine getCurrentExceptionMsg()
proc readPPMFile(fn: string): PPM {...}{.raises: [IOError, ValueError, EOFError],
                                    tags: [ReadIOEffect].}
Return PPM (P3 or P6) from file. This proc validates data before reading data. Raise errors when illegal was found. At seeing description of erros, see validatePPM proc

Example:

try:
  let p = readPPMFile("p3.ppm")
  ## do something...
except:
  stderr.writeLine getCurrentExceptionMsg()
proc writePBM(f: File; data: PBM) {...}{.raises: [IOError, ValueError],
                                    tags: [WriteIOEffect].}
Write PBM (P1 or P4) to file. Raise IllegalFileDescriptorError when illegal was found from file descriptor.

Example:

from os import removeFile
try:
  let p1 = newPBM(pbmFileDescriptorP1, 1, 1, @[1'u8])
  var f = open("p1.pbm", fmWrite)
  f.writePBM p1
  f.close
  removeFile "p1.pbm"
except:
  stderr.writeLine getCurrentExceptionMsg()
proc writePGM(f: File; data: PGM) {...}{.raises: [IOError, ValueError],
                                    tags: [WriteIOEffect].}
Write PGM (P2 or P5) to file. Raise IllegalFileDescriptorError when illegal was found from file descriptor.

Example:

from os import removeFile
try:
  let p1 = newPGM(pgmFileDescriptorP2, 1, 1, 255'u8, @[1'u8])
  var f = open("p2.pgm", fmWrite)
  f.writePGM p1
  f.close
  removeFile "p2.pgm"
except:
  stderr.writeLine getCurrentExceptionMsg()
proc writePPM(f: File; data: PPM) {...}{.raises: [IOError, ValueError],
                                    tags: [WriteIOEffect].}
Write PPM (P3 or P6) to file. Raise IllegalFileDescriptorError when illegal was found from file descriptor.

Example:

from os import removeFile
try:
  let p1 = newPPM(ppmFileDescriptorP3, 1, 1, 255'u8, @[1'u8])
  var f = open("p3.ppm", fmWrite)
  f.writePPM p1
  f.close
  removeFile "p3.ppm"
except:
  stderr.writeLine getCurrentExceptionMsg()
proc writePBMFile(fn: string; data: PBM) {...}{.raises: [IOError, ValueError],
    tags: [WriteIOEffect].}
Write PBM (P1 or P4) to file. Raise IllegalFileDescriptorError when illegal was found from file descriptor.

Example:

from os import removeFile
try:
  let p1 = newPBM(pbmFileDescriptorP1, 1, 1, @[1'u8])
  writePBMFile "p1.pbm", p1
  removeFile "p1.pbm"
except:
  stderr.writeLine getCurrentExceptionMsg()
proc writePGMFile(fn: string; data: PGM) {...}{.raises: [IOError, ValueError],
    tags: [WriteIOEffect].}
Write PGM (P2 or P5) to file. Raise IllegalFileDescriptorError when illegal was found from file descriptor.

Example:

from os import removeFile
try:
  let p1 = newPGM(pgmFileDescriptorP2, 1, 1, 255'u8, @[1'u8])
  writePGMFile "p2.pgm", p1
  removeFile "p2.pgm"
except:
  stderr.writeLine getCurrentExceptionMsg()
proc writePPMFile(fn: string; data: PPM) {...}{.raises: [IOError, ValueError],
    tags: [WriteIOEffect].}
Write PPM (P3 or P6) to file. Raise IllegalFileDescriptorError when illegal was found from file descriptor.

Example:

from os import removeFile
try:
  let p1 = newPPM(ppmFileDescriptorP3, 1, 1, 255'u8, @[1'u8])
  writePPMFile "p3.ppm", p1
  removeFile "p3.ppm"
except:
  stderr.writeLine getCurrentExceptionMsg()
proc `$`(self: PBM): string {...}{.raises: [], tags: [].}
proc `$`(self: PGM): string {...}{.raises: [], tags: [].}
proc `$`(self: PPM): string {...}{.raises: [], tags: [].}