From be26fe5193d3559260ad727394c567df5e254be2 Mon Sep 17 00:00:00 2001 From: Rasmus Moorats Date: Mon, 10 Jan 2022 15:23:48 +0200 Subject: [PATCH] fix high-depth handling and add a test case --- src/pixie/fileformats/ppm.nim | 33 ++++++++++++------ .../ppm/feep.p3.hidepth.master.ppm | 8 +++++ tests/fileformats/ppm/feep.p3.hidepth.ppm | Bin 0 -> 59 bytes tests/test_ppm.nim | 5 +++ 4 files changed, 35 insertions(+), 11 deletions(-) create mode 100644 tests/fileformats/ppm/feep.p3.hidepth.master.ppm create mode 100644 tests/fileformats/ppm/feep.p3.hidepth.ppm diff --git a/src/pixie/fileformats/ppm.nim b/src/pixie/fileformats/ppm.nim index be9434b..7562c18 100644 --- a/src/pixie/fileformats/ppm.nim +++ b/src/pixie/fileformats/ppm.nim @@ -61,30 +61,41 @@ proc decodeP6Data(data: string, maxVal: int): seq[ColorRGBX] {.raises: [].} = # 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 div maxVal).uint8 + let valueMultiplier = 0xFF / maxVal # 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)) * valueMultiplier - green = readUint8(data, i + 1 + (i * 2)) * valueMultiplier - blue = readUint8(data, i + 2 + (i * 2)) * valueMultiplier + 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) else: for i in 0 ..< result.len: let - red = readUint16(data, i + (i * 4)).uint8 * valueMultiplier - green = readUint16(data, i + 2 + (i * 4)).uint8 * valueMultiplier - blue = readUint16(data, i + 4 + (i * 4)).uint8 * valueMultiplier + 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) proc decodeP3Data(data: string, maxVal: int): seq[ColorRGBX] {.raises: [PixieError].} = - var p6data = newStringOfCap(data.splitWhitespace.len) + let needsUint16 = maxVal > 0xFF + let maxLen = ( + if needsUint16: data.splitWhitespace.len * 2 + else: data.splitWhitespace.len + ) + var p6data = newStringOfCap(maxLen) + try: - for line in data.splitLines(): - for sample in line.split('#', 1)[0].splitWhitespace(): - p6data.add(parseInt(sample).chr) + if not needsUint16: + for line in data.splitLines(): + for sample in line.split('#', 1)[0].splitWhitespace(): + p6data.add(parseInt(sample).chr) + else: + for line in data.splitLines(): + for sample in line.split('#', 1)[0].splitWhitespace(): + p6data.addUint16(parseInt(sample).uint16.swap) except ValueError: failInvalid() result = decodeP6Data(p6data, maxVal) diff --git a/tests/fileformats/ppm/feep.p3.hidepth.master.ppm b/tests/fileformats/ppm/feep.p3.hidepth.master.ppm new file mode 100644 index 0000000..4678865 --- /dev/null +++ b/tests/fileformats/ppm/feep.p3.hidepth.master.ppm @@ -0,0 +1,8 @@ +P3 +# feep.p3.hidepth.master.ppm +4 4 +7919 # prime number chosen for test purposes + 0 0 0 0 0 0 0 0 0 7919 0 7919 + 0 0 0 0 7919 3695 0 0 0 0 0 0 + 0 0 0 0 0 0 0 7919 3695 0 0 0 +7919 0 7919 0 0 0 0 0 0 0 0 0 diff --git a/tests/fileformats/ppm/feep.p3.hidepth.ppm b/tests/fileformats/ppm/feep.p3.hidepth.ppm new file mode 100644 index 0000000000000000000000000000000000000000..d2cbd0db64dd5ee88994b66dcf3fb4ed43c9c209 GIT binary patch literal 59 kcmWGA<1$e&;W9EcU&u0Wb~bLZ!e0013MYu>b%7 literal 0 HcmV?d00001 diff --git a/tests/test_ppm.nim b/tests/test_ppm.nim index 06256dd..d84ec9a 100644 --- a/tests/test_ppm.nim +++ b/tests/test_ppm.nim @@ -6,3 +6,8 @@ block: "tests/fileformats/ppm/feep." & $format & ".master.ppm" )) writeFile("tests/fileformats/ppm/feep." & $format & ".ppm", encodePpm(image)) + + let image = decodePpm(readFile( + "tests/fileformats/ppm/feep.p3.hidepth.master.ppm" + )) + writeFile("tests/fileformats/ppm/feep.p3.hidepth.ppm", encodePpm(image))