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.
Consts
pbmFileDescriptorP1 = "P1"
pgmFileDescriptorP2 = "P2"
ppmFileDescriptorP3 = "P3"
pbmFileDescriptorP4 = "P4"
pgmFileDescriptorP5 = "P5"
ppmFileDescriptorP6 = "P6"
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:
- It is P1 or P4 that 2 byte data at the head.
- 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:
- It is P2 or P5 that 2 byte data at the head.
- It is decimal number that data on 2 line.
- 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:
- It is P3 or P6 that 2 byte data at the head.
- It is decimal number that data on 2 line.
- 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: [].}