From be57c71c3cad9120cd24fc79e7cb46e2a94fe997 Mon Sep 17 00:00:00 2001 From: Ryan Oldenburg Date: Thu, 20 Jan 2022 20:04:13 -0600 Subject: [PATCH] ppm consistent style pass --- src/pixie/fileformats/ppm.nim | 81 +++++++++++++++++++++-------------- tests/test_ppm.nim | 4 +- 2 files changed, 50 insertions(+), 35 deletions(-) diff --git a/src/pixie/fileformats/ppm.nim b/src/pixie/fileformats/ppm.nim index 7562c18..87099fd 100644 --- a/src/pixie/fileformats/ppm.nim +++ b/src/pixie/fileformats/ppm.nim @@ -16,9 +16,10 @@ proc decodeHeader(data: string): PpmHeader {.raises: [PixieError].} = if data.len <= 10: # Each part + whitespace raise newException(PixieError, "Invalid PPM file header") - var commentMode, readWhitespace: bool - var i, readFields: int - var field: string + var + commentMode, readWhitespace: bool + i, readFields: int + field: string while readFields < 4: let c = readUint8(data, i).char if c == '#': @@ -41,7 +42,8 @@ proc decodeHeader(data: string): PpmHeader {.raises: [PixieError].} = result.maxVal = parseInt(field) else: discard - except ValueError: failInvalid() + except ValueError: + failInvalid() field = "" elif not (c in Whitespace): field.add(c) @@ -54,49 +56,64 @@ proc decodeP6Data(data: string, maxVal: int): seq[ColorRGBX] {.raises: [].} = let needsUint16 = maxVal > 0xFF result = newSeq[ColorRGBX]( - if needsUint16: data.len div 6 - else: data.len div 3 + if needsUint16: + data.len div 6 + else: + data.len div 3 ) # Let's calculate the real maximum value multiplier. - # rgbx() accepts a maximum value of 0xFF. Most of the time, - # maxVal is set to 0xFF as well, so in most cases it is 1 - let valueMultiplier = 0xFF / maxVal + # rgbx() accepts a maximum value of 255. Most of the time, + # maxVal is set to 255 as well, so in most cases it is 1 + let valueMultiplier = (255 / maxVal).float32 # if comparison in for loops is expensive, so let's unroll it if not needsUint16: for i in 0 ..< result.len: let - red = (readUint8(data, i + (i * 2)).float * valueMultiplier + 0.5).uint8 - green = (readUint8(data, i + 1 + (i * 2)).float * valueMultiplier + 0.5).uint8 - blue = (readUint8(data, i + 2 + (i * 2)).float * valueMultiplier + 0.5).uint8 - result[i] = rgbx(red, green, blue, 0xFF) + red = data.readUint8(i + (i * 2)).float32 + green = data.readUint8(i + 1 + (i * 2)).float32 + blue = data.readUint8(i + 2 + (i * 2)).float32 + result[i] = rgbx( + (red * valueMultiplier + 0.5).uint8, + (green * valueMultiplier + 0.5).uint8, + (blue * valueMultiplier + 0.5).uint8, + 255 + ) else: for i in 0 ..< result.len: let - red = (readUint16(data, i + (i * 5)).swap.float * valueMultiplier + 0.5).uint8 - green = (readUint16(data, i + 2 + (i * 5)).swap.float * valueMultiplier + 0.5).uint8 - blue = (readUint16(data, i + 4 + (i * 5)).swap.float * valueMultiplier + 0.5).uint8 - result[i] = rgbx(red, green, blue, 0xFF) + red = data.readUint16(i + (i * 5)).swap.float32 + green = data.readUint16(i + 2 + (i * 5)).swap.float32 + blue = data.readUint16(i + 4 + (i * 5)).swap.float32 + result[i] = rgbx( + (red * valueMultiplier + 0.5).uint8, + (green * valueMultiplier + 0.5).uint8, + (blue * valueMultiplier + 0.5).uint8, + 255 + ) proc decodeP3Data(data: string, maxVal: int): seq[ColorRGBX] {.raises: [PixieError].} = - let needsUint16 = maxVal > 0xFF - let maxLen = ( - if needsUint16: data.splitWhitespace.len * 2 - else: data.splitWhitespace.len - ) - var p6data = newStringOfCap(maxLen) + let + needsUint16 = maxVal > 0xFF + maxLen = + if needsUint16: + data.splitWhitespace.len * 2 + else: + data.splitWhitespace.len + var p6data = newStringOfCap(maxLen) try: if not needsUint16: for line in data.splitLines(): for sample in line.split('#', 1)[0].splitWhitespace(): - p6data.add(parseInt(sample).chr) + p6data.add(parseInt(sample).char) else: for line in data.splitLines(): for sample in line.split('#', 1)[0].splitWhitespace(): p6data.addUint16(parseInt(sample).uint16.swap) - except ValueError: failInvalid() + except ValueError: + failInvalid() result = decodeP6Data(p6data, maxVal) @@ -105,20 +122,20 @@ proc decodePpm*(data: string): Image {.raises: [PixieError].} = let header = decodeHeader(data) - if not (header.version in ppmSignatures): failInvalid() - if 0 > header.maxVal or header.maxVal > 0xFFFF: failInvalid() + if not (header.version in ppmSignatures): + failInvalid() + + if 0 > header.maxVal or header.maxVal > 0xFFFF: + failInvalid() result = newImage(header.width, header.height) result.data = ( if header.version == "P3": decodeP3Data(data[header.dataOffset .. ^1], header.maxVal) - else: decodeP6Data(data[header.dataOffset .. ^1], header.maxVal) + else: + decodeP6Data(data[header.dataOffset .. ^1], header.maxVal) ) -proc decodePpm*(data: seq[uint8]): Image {.inline, raises: [PixieError].} = - ## Decodes Portable Pixel Map data into an Image. - decodePpm(cast[string](data)) - proc encodePpm*(image: Image): string {.raises: [].} = ## Encodes an image into the PPM file format (version P6). diff --git a/tests/test_ppm.nim b/tests/test_ppm.nim index d041c12..578b85d 100644 --- a/tests/test_ppm.nim +++ b/tests/test_ppm.nim @@ -7,9 +7,7 @@ block: )) writeFile("tests/fileformats/ppm/feep." & $format & ".ppm", encodePpm(image)) - let image = decodePpm(readFile( - "tests/fileformats/ppm/feep.p3.hidepth.master.ppm" - )) + let image = decodePpm(readFile("tests/fileformats/ppm/feep.p3.hidepth.master.ppm")) writeFile("tests/fileformats/ppm/feep.p3.hidepth.ppm", encodePpm(image)) # produced output should be identical to P6 master