P3 support

also fixes an issue with header decoder whitespace handling
This commit is contained in:
Rasmus Moorats 2022-01-07 14:06:43 +02:00
parent 0139af545f
commit b136e5b4e2
No known key found for this signature in database
GPG key ID: FE14255A6AE7241C

View file

@ -16,7 +16,7 @@ proc decodeHeader(data: string): PpmHeader {.raises: [PixieError].} =
if data.len <= 10: # Each part + whitespace if data.len <= 10: # Each part + whitespace
raise newException(PixieError, "Invalid PPM file header") raise newException(PixieError, "Invalid PPM file header")
var commentMode: bool var commentMode, readWhitespace: bool
var i, readFields: int var i, readFields: int
var field: string var field: string
while readFields < 4: while readFields < 4:
@ -26,8 +26,9 @@ proc decodeHeader(data: string): PpmHeader {.raises: [PixieError].} =
elif c == '\n': elif c == '\n':
commentMode = false commentMode = false
if not commentMode: if not commentMode:
if c in Whitespace: if c in Whitespace and not readWhitespace:
readFields += 1 readFields += 1
readWhitespace = true
try: try:
case readFields: case readFields:
of 1: of 1:
@ -42,8 +43,9 @@ proc decodeHeader(data: string): PpmHeader {.raises: [PixieError].} =
discard discard
except ValueError: failInvalid() except ValueError: failInvalid()
field = "" field = ""
else: elif not (c in Whitespace):
field.add(c) field.add(c)
readWhitespace = false
i += 1 i += 1
result.dataOffset = i result.dataOffset = i
@ -77,8 +79,16 @@ proc decodeP6Data(data: string, maxVal: int): seq[ColorRGBX] {.raises: [].} =
blue = readUint16(data, i + 4 + (i * 4)).uint8 * valueMultiplier blue = readUint16(data, i + 4 + (i * 4)).uint8 * valueMultiplier
result[i] = rgbx(red, green, blue, 0xFF) result[i] = rgbx(red, green, blue, 0xFF)
proc decodeP3Data(data: string, maxVal: int): seq[ColorRGBX] {.raises: [].} = proc decodeP3Data(data: string, maxVal: int): seq[ColorRGBX] {.raises: [PixieError].} =
result = newSeq[ColorRGBX](1) var p6data = newStringOfCap(data.splitWhitespace.len)
try:
for line in data.splitLines():
echo line
for sample in line.split('#', 1)[0].splitWhitespace():
p6data.add(parseInt(sample).chr)
except ValueError: failInvalid()
result = decodeP6Data(p6data, maxVal)
proc decodePpm*(data: string): Image {.raises: [PixieError].} = proc decodePpm*(data: string): Image {.raises: [PixieError].} =
## Decodes Portable Pixel Map data into an Image. ## Decodes Portable Pixel Map data into an Image.
@ -116,7 +126,7 @@ proc encodePpm*(image: Image): string {.raises: [].} =
for y in 0 ..< image.height: for y in 0 ..< image.height:
for x in 0 ..< image.width: for x in 0 ..< image.width:
let rgb = image[x, y].rgba() let rgb = image[x, y].rgba()
# alpha channel is ignored # Alpha channel is ignored
result.addUint8(rgb.r) result.addUint8(rgb.r)
result.addUint8(rgb.g) result.addUint8(rgb.g)
result.addUint8(rgb.b) result.addUint8(rgb.b)