Anonymous user
Bitmap/Read a PPM file: Difference between revisions
Updated to work with Nim version 1.4; changed header parsing to conform to PPM specs; added integrity checks.
MaiconSoft (talk | contribs) |
(Updated to work with Nim version 1.4; changed header parsing to conform to PPM specs; added integrity checks.) |
||
Line 1,355:
=={{header|Nim}}==
<lang nim>import strutils
import bitmap
type FormatError = object of CatchableError
proc readPPM(f: TFile): Image =▼
if f.readLine != "P6":▼
raise newException(E_base, "Invalid file format")▼
# States used to parse the header.
var line = ""▼
type State = enum waitingMagic, waitingWidth, waitingHeight, waitingColors
if line[0] != '#':▼
#---------------------------------------------------------------------------------------------------
iterator tokens(f: File): tuple[value: string, lastInLine: bool] =
## Yield the tokens in the header.
let fields = line.splitWhitespace()
for i, t in fields:
yield (t, i == fields.high)
#---------------------------------------------------------------------------------------------------
proc getInt(s: string): int {.inline.} =
## Try to parse an int. Raise an exception if not an integer.
try:
result = s.parseInt()
except ValueError:
raise newException(FormatError, "Invalid value")
#---------------------------------------------------------------------------------------------------
proc header(f: File): tuple[width, height: Index] =
## Read the header and retrun the image width and height.
var state = waitingMagic
for (token, lastInLine) in f.tokens:
case state
of waitingMagic:
of waitingWidth:
result.width = token.getInt()
of waitingHeight:
result.height = token.getInt()
of waitingColors:
if not lastInLine:
raise newException(FormatError, "Invalid data after number of colors")
break
state = succ(state)
#---------------------------------------------------------------------------------------------------
▲ if f.readLine != "255":
## Read a PPM file into an image.
▲ raise newException(E_base, "Invalid file format")
let header = f.header()
result = initImage(header.width, header.height)
var
Line 1,377 ⟶ 1,417:
while read != 0:
for i in 0 ..
case pos mod 3
of 0: result.pixels[pos div 3].r = arr[i].uint8
Line 1,383 ⟶ 1,423:
of 2: result.pixels[pos div 3].b = arr[i].uint8
else: discard
inc pos
read = f.readBytes(arr, 0, 256)
if pos != 3 * result.w * result.h:
raise newException(FormatError, "Truncated file")
#---------------------------------------------------------------------------------------------------
proc readPPM*(filename: string): Image =
## Load a PPM file into an image.
var file = open(filename, fmRead)
result = file.readPPM()
file.close()</lang>
=={{header|OCaml}}==
|