diff --git a/pixie.nimble b/pixie.nimble index 6ba1661..3604207 100644 --- a/pixie.nimble +++ b/pixie.nimble @@ -1,3 +1,4 @@ +packageName = "pixie" version = "0.0.1" author = "Andre von Houck and Ryan Oldenburg" description = "Full-featured 2d graphics library for Nim." @@ -9,4 +10,4 @@ requires "nim >= 1.2.6" requires "vmath >= 0.3.2" requires "chroma >= 0.1.5" requires "zippy >= 0.3.5" -requires "flatty >= 0.1.1" +requires "flatty >= 0.1.2" diff --git a/src/pixie.nim b/src/pixie.nim index 7d71504..9cf7e6a 100644 --- a/src/pixie.nim +++ b/src/pixie.nim @@ -1,7 +1,7 @@ ## Public interface to you library. -import pixie/images, pixie/masks, pixie/paths -export images, masks, paths +import pixie/images, pixie/masks, pixie/paths, pixie/common +export images, masks, paths, PixieError proc toMask*(image: Image): Mask = ## Converts an Image to a Mask. diff --git a/src/pixie/fileformats/png.nim b/src/pixie/fileformats/png.nim new file mode 100644 index 0000000..3a75136 --- /dev/null +++ b/src/pixie/fileformats/png.nim @@ -0,0 +1,443 @@ +import chroma, pixie/images, pixie/common, math, zippy, zippy/crc, flatty/binny + +# See http://www.libpng.org/pub/png/spec/1.2/PNG-Contents.html + +type + ChunkCounts = object + PLTE, IDAT: uint8 + + PngHeader = object + width, height: int + bitDepth, colorType, compressionMethod, filterMethod, interlaceMethod: uint8 + +template failInvalid() = + raise newException(PixieError, "Invalid PNG buffer, unable to load") + +# template failCRC() = +# raise newException(PixieError, "CRC check failed") + +when defined(release): + {.push checks: off.} + +proc parseHeader(data: seq[uint8]): PngHeader = + result.width = data.readUint32(0).swap().int + result.height = data.readUint32(4).swap().int + result.bitDepth = data[8] + result.colorType = data[9] + result.compressionMethod = data[10] + result.filterMethod = data[11] + result.interlaceMethod = data[12] + + if result.width == 0 or result.width > int32.high.int: + raise newException(PixieError, "Invalid PNG width") + + if result.height == 0 or result.height > int32.high.int: + raise newException(PixieError, "Invalid PNG height") + + template failInvalidCombo() = + raise newException( + PixieError, "Invalid PNG color type and bit depth combination" + ) + + case result.colorType: + of 0: + if result.bitDepth notin [1.uint8, 2, 4, 8, 16]: + failInvalidCombo() + of 2: + if result.bitDepth notin [8.uint8, 16]: + failInvalidCombo() + of 3: # PLTE chunk is required, sample depth is always 8 bits + if result.bitDepth notin [1.uint8, 2, 4, 8]: + failInvalidCombo() + of 4: + if result.bitDepth notin [8.uint8, 16]: + failInvalidCombo() + of 6: + if result.bitDepth notin [8.uint8, 16]: + failInvalidCombo() + else: + failInvalidCombo() + + if result.compressionMethod != 0: + raise newException(PixieError, "Invalid PNG compression method") + + if result.filterMethod != 0: + raise newException(PixieError, "Invalid PNG filter method") + + if result.interlaceMethod notin [0.uint8, 1]: + raise newException(PixieError, "Invalid PNG interlace method") + + # Not yet supported: + + if result.bitDepth == 16: + raise newException(PixieError, "PNG 16 bit depth not yet supported") + + if result.interlaceMethod != 0: + raise newException(PixieError, "Interlaced PNG not yet supported") + +proc parsePalette(data: seq[uint8]): seq[array[3, uint8]] = + if data.len == 0 or data.len mod 3 != 0: + failInvalid() + + result.setLen(data.len div 3) + + for i in 0 ..< data.len div 3: + result[i] = cast[ptr array[3, uint8]](data[i * 3].unsafeAddr)[] + +proc unfilter( + uncompressed: seq[uint8], height, rowBytes, bpp: int +): seq[uint8] = + result.setLen(uncompressed.len - height) + + template uncompressedIdx(x, y: int): int = + x + y * (rowBytes + 1) + + template unfiteredIdx(x, y: int): int = + x + y * rowBytes + + # Unfilter the image data + for y in 0 ..< height: + let filterType = uncompressed[uncompressedIdx(0, y)] + for x in 0 ..< rowBytes: + var value = uncompressed[uncompressedIdx(x + 1, y)] + case filterType: + of 0: # None + discard + of 1: # Sub + if x - bpp >= 0: + value += result[unfiteredIdx(x - bpp, y)] + of 2: # Up + if y - 1 >= 0: + value += result[unfiteredIdx(x, y - 1)] + of 3: # Average + var left, up: int + if x - bpp >= 0: + left = result[unfiteredIdx(x - bpp, y)].int + if y - 1 >= 0: + up = result[unfiteredIdx(x, y - 1)].int + value += ((left + up) div 2).uint8 + of 4: # Paeth + var left, up, upLeft: int + if x - bpp >= 0: + left = result[unfiteredIdx(x - bpp, y)].int + if y - 1 >= 0: + up = result[unfiteredIdx(x, y - 1)].int + if x - bpp >= 0 and y - 1 >= 0: + upLeft = result[unfiteredIdx(x - bpp, y - 1)].int + proc paethPredictor(a, b, c: int): int {.inline.} = + let + p = a + b - c + pa = abs(p - a) + pb = abs(p - b) + pc = abs(p - c) + if pa <= pb and pa <= pc: + a + elif pb <= pc: + b + else: + c + value += paethPredictor(up, left, upLeft).uint8 + else: + discard # Not possible, parseHeader validates + + result[unfiteredIdx(x, y)] = value + +proc parseImageData( + header: PngHeader, palette: seq[array[3, uint8]], data: seq[uint8] +): seq[ColorRGBA] = + result.setLen(header.width * header.height) + + let + uncompressed = try: uncompress(data) except ZippyError: failInvalid() + valuesPerPixel = + case header.colorType: + of 0: + 1 + of 2: + 3 + of 3: + 1 + of 4: + 2 + of 6: + 4 + else: + 0 # Not possible, parseHeader validates + valuesPerByte = 8 div header.bitDepth.int + rowBytes = ceil((header.width.int * valuesPerPixel) / valuesPerByte).int + totalBytes = rowBytes * header.height.int + + # Uncompressed image data should be the total bytes of pixel data plus + # a filter byte for each row. + if uncompressed.len != totalBytes + header.height.int: + failInvalid() + + let unfiltered = unfilter( + uncompressed, + header.height, + rowBytes, + max(valuesPerPixel div valuesPerByte, 1) + ) + + var bytePos, bitPos: int + for y in 0 ..< header.height: + for x in 0 ..< header.width: + var rgba: array[4, uint8] + case header.colorType: + of 0: + var value = unfiltered[bytePos] + case header.bitDepth: + of 1: + value = (value shr (7 - bitPos)) and 1 + value *= 255 + inc bitPos + of 2: + value = (value shr (6 - bitPos)) and 3 + value *= 85 + inc(bitPos, 2) + of 4: + value = (value shr (4 - bitPos)) and 15 + value *= 17 + inc(bitPos, 4) + of 8: + inc bytePos + else: + discard # Not possible, parseHeader validates + + if bitPos == 8: + inc bytePos + bitPos = 0 + rgba = [value, value, value, 255] + of 2: + let rgb = cast[ptr array[3, uint8]](unfiltered[bytePos].unsafeAddr)[] + rgba = [rgb[0], rgb[1], rgb[2], 255] + inc(bytePos, 3) + of 3: + var value = unfiltered[bytePos] + case header.bitDepth: + of 1: + value = (value shr (7 - bitPos)) and 1 + inc bitPos + of 2: + value = (value shr (6 - bitPos)) and 3 + inc(bitPos, 2) + of 4: + value = (value shr (4 - bitPos)) and 15 + inc(bitPos, 4) + of 8: + inc bytePos + else: + discard # Not possible, parseHeader validates + + if bitPos == 8: + inc bytePos + bitPos = 0 + if value.int >= palette.len: + failInvalid() + let rgb = palette[value] + rgba = [rgb[0], rgb[1], rgb[2], 255] + of 4: + rgba = [ + unfiltered[bytePos], + unfiltered[bytePos], + unfiltered[bytePos], + unfiltered[bytePos + 1] + ] + inc(bytePos, 2) + of 6: + rgba = cast[array[4, uint8]](unfiltered.readUint32(bytePos)) + inc(bytePos, 4) + else: + discard # Not possible, parseHeader validates + + result[x + y * header.width] = cast[ColorRGBA](rgba) + + # If we move to a new row, skip to the next full byte + if bitPos > 0: + inc bytePos + bitPos = 0 + +proc decodePng*(data: seq[uint8]): Image = + ## Decodes the PNG from the parameter buffer. Check png.channels and + ## png.bitDepth to see how the png.data is formatted. + ## The returned png.data is currently always RGBA (4 channels) + ## with bitDepth of 8. + + if data.len < (8 + (8 + 13 + 4) + 4): # Magic bytes + IHDR + IEND + failInvalid() + + # PNG file signature + let signature = cast[array[8, uint8]](data.readUint64(0)) + if signature != [137.uint8, 80, 78, 71, 13, 10, 26, 10]: + failInvalid() + + var + pos = 8 # After signature + counts = ChunkCounts() + header: PngHeader + palette: seq[array[3, uint8]] + imageData: seq[uint8] + prevChunkType: string + + # First chunk must be IHDR + if data.readUint32(pos).swap() != 13 or + data.readStr(pos + 4, 4) != "IHDR": + failInvalid() + inc(pos, 8) + header = parseHeader(data[pos ..< pos + 13]) + prevChunkType = "IHDR" + inc(pos, 13) + + # if crc32(data[pos - 17 ..< pos]) != read32be(data, pos): + # failCRC() + inc(pos, 4) # CRC + + while true: + if pos + 8 > data.len: + failInvalid() + + let + chunkLen = data.readUint32(pos).swap().int + chunkType = data.readStr(pos + 4, 4) + inc(pos, 8) + + if chunkLen > high(int32).int: + failInvalid() + + if pos + chunkLen + 4 > data.len: + failInvalid() + + case chunkType: + of "IHDR": + failInvalid() + of "PLTE": + inc counts.PLTE + if counts.PLTE > 1 or counts.IDAT > 0: + failInvalid() + palette = parsePalette(data[pos ..< pos + chunkLen]) + of "IDAT": + inc counts.IDAT + if counts.IDAT > 1 and prevChunkType != "IDAT": + failInvalid() + if header.colorType == 3 and counts.PLTE == 0: + failInvalid() + let op = imageData.len + imageData.setLen(imageData.len + chunkLen) + copyMem(imageData[op].addr, data[pos].unsafeAddr, chunkLen) + of "IEND": + if chunkLen != 0: + failInvalid() + else: + let bytes = cast[seq[uint8]](chunkType) + if (bytes[0] and 0b00100000) == 0: + raise newException( + PixieError, "Unrecognized PNG critical chunk " & chunkType + ) + + inc(pos, chunkLen) + + # if crc32(data[pos - chunkLen - 4 ..< pos]) != read32be(data, pos): + # failCRC() + inc(pos, 4) # CRC + + prevChunkType = chunkType + + if pos == data.len: + break + + if prevChunkType != "IEND": + failInvalid() + + result = Image() + result.width = header.width + result.height = header.height + result.data = parseImageData(header, palette, imageData) + +proc encodePng*( + width, height, channels: int, data: pointer, len: int +): seq[uint8] = + ## Encodes the image data into the PNG file format. + + if width <= 0 or width > int32.high.int: + raise newException(PixieError, "Invalid PNG width") + + if height <= 0 or height > int32.high.int: + raise newException(PixieError, "Invalid PNG height") + + if len != width * height * channels: + raise newException(PixieError, "Invalid PNG data size") + + let colorType = block: + case channels: + of 1: + 0.uint8 + of 2: + 4 + of 3: + 2 + of 4: + 6 + else: + raise newException(PixieError, "Invalid PNG number of channels") + + # Add the PNG file signature + result.add([137.uint8, 80, 78, 71, 13, 10, 26, 10]) + + # Add IHDR + result.addUint32(13.uint32.swap()) + result.addStr("IHDR") + result.addUint32(width.uint32.swap()) + result.addUint32(height.uint32.swap()) + result.add(8.uint8) + result.add([colorType, 0, 0, 0]) + result.addUint32(crc32(result[result.len - 17 ..< result.len]).swap()) + + # Add IDAT + # Add room for 1 byte before each row for the filter type. + var filtered = newSeq[uint8](width * height * channels + height) + for y in 0 ..< height: + filtered[y * width * channels + y] = 3 # Average + for x in 0 ..< width * channels: + # Move through the image data byte-by-byte + let + data = cast[ptr UncheckedArray[uint8]](data) + dataPos = y * width * channels + x + filteredPos = y * width * channels + y + 1 + x + var left, up: int + if x - channels >= 0: + left = data[dataPos - channels].int + if y - 1 >= 0: + up = data[(y - 1) * width * channels + x].int + let avg = ((left + up) div 2).uint8 + filtered[filteredPos] = data[dataPos] - avg + + let compressed = + try: + compress(filtered, DefaultCompression, dfZlib) + except ZippyError: + raise newException( + PixieError, "Unexpected error compressing PNG image data" + ) + if compressed.len > int32.high.int: + raise newException(PixieError, "Compressed PNG image data too large") + + result.addUint32(compressed.len.uint32.swap()) + result.add(cast[seq[uint8]]("IDAT")) + result.add(compressed) + result.addUint32( + crc32(result[result.len - compressed.len - 4 ..< result.len]).swap() + ) + + # Add IEND + result.addUint32(0) + result.addStr("IEND") + result.addUint32(crc32(result[result.len - 4 ..< result.len]).swap()) + +proc encodePng*(image: Image): string = + ## Encodes the image data into the PNG file format. + cast[string](encodePng( + image.width, image.height, 4, image.data[0].addr, image.data.len * 4 + )) + +when defined(release): + {.pop.} diff --git a/src/pixie/images.nim b/src/pixie/images.nim index 91b8629..0adbc21 100644 --- a/src/pixie/images.nim +++ b/src/pixie/images.nim @@ -1,4 +1,4 @@ -import strformat, chroma, chroma/blends, vmath +import chroma, chroma/blends, vmath type Image* = ref object diff --git a/tests/benchmark_png.nim b/tests/benchmark_png.nim new file mode 100644 index 0000000..1b9c586 --- /dev/null +++ b/tests/benchmark_png.nim @@ -0,0 +1,22 @@ +import pixie/fileformats/png, stb_image/read as stbi, fidget/opengl/perf, nimPNG + +let data = readFile("tests/data/lenna.png") + +timeIt "pixie": + for i in 0 ..< 100: + discard decodePng(cast[seq[uint8]](data)) + +timeIt "nimPNG": + for i in 0 ..< 100: + discard decodePNG32(data) + +timeIt "stb_image": + for i in 0 ..< 100: + var width, height, channels: int + discard loadFromMemory( + cast[seq[byte]](data), + width, + height, + channels, + stbi.RGBA + ) diff --git a/tests/data/lenna.png b/tests/data/lenna.png new file mode 100644 index 0000000..59ef68a Binary files /dev/null and b/tests/data/lenna.png differ diff --git a/tests/data/pngsuite/PngSuite.LICENSE b/tests/data/pngsuite/PngSuite.LICENSE new file mode 100644 index 0000000..8d4d1d0 --- /dev/null +++ b/tests/data/pngsuite/PngSuite.LICENSE @@ -0,0 +1,9 @@ +PngSuite +-------- + +Permission to use, copy, modify and distribute these images for any +purpose and without fee is hereby granted. + + +(c) Willem van Schaik, 1996, 2011 + diff --git a/tests/data/pngsuite/PngSuite.README b/tests/data/pngsuite/PngSuite.README new file mode 100644 index 0000000..3ef8f24 --- /dev/null +++ b/tests/data/pngsuite/PngSuite.README @@ -0,0 +1,25 @@ + PNGSUITE +---------------- + + testset for PNG-(de)coders + created by Willem van Schaik +------------------------------------ + +This is a collection of graphics images created to test the png applications +like viewers, converters and editors. All (as far as that is possible) +formats supported by the PNG standard are represented. + +The suite consists of the following files: + +- PngSuite.README - this file +- PngSuite.LICENSE - the PngSuite is freeware +- PngSuite.png - image with PngSuite logo +- PngSuite.tgz - archive of all PNG testfiles +- PngSuite.zip - same in .zip format for PCs + + +-------- + (c) Willem van Schaik + willem@schaik.com + Calgary, April 2011 + diff --git a/tests/data/pngsuite/PngSuite.png b/tests/data/pngsuite/PngSuite.png new file mode 100644 index 0000000..205460d Binary files /dev/null and b/tests/data/pngsuite/PngSuite.png differ diff --git a/tests/data/pngsuite/basi0g01.png b/tests/data/pngsuite/basi0g01.png new file mode 100644 index 0000000..556fa72 Binary files /dev/null and b/tests/data/pngsuite/basi0g01.png differ diff --git a/tests/data/pngsuite/basi0g02.png b/tests/data/pngsuite/basi0g02.png new file mode 100644 index 0000000..ce09821 Binary files /dev/null and b/tests/data/pngsuite/basi0g02.png differ diff --git a/tests/data/pngsuite/basi0g04.png b/tests/data/pngsuite/basi0g04.png new file mode 100644 index 0000000..3853273 Binary files /dev/null and b/tests/data/pngsuite/basi0g04.png differ diff --git a/tests/data/pngsuite/basi0g08.png b/tests/data/pngsuite/basi0g08.png new file mode 100644 index 0000000..faed8be Binary files /dev/null and b/tests/data/pngsuite/basi0g08.png differ diff --git a/tests/data/pngsuite/basi0g16.png b/tests/data/pngsuite/basi0g16.png new file mode 100644 index 0000000..a9f2816 Binary files /dev/null and b/tests/data/pngsuite/basi0g16.png differ diff --git a/tests/data/pngsuite/basi2c08.png b/tests/data/pngsuite/basi2c08.png new file mode 100644 index 0000000..2aab44d Binary files /dev/null and b/tests/data/pngsuite/basi2c08.png differ diff --git a/tests/data/pngsuite/basi2c16.png b/tests/data/pngsuite/basi2c16.png new file mode 100644 index 0000000..cd7e50f Binary files /dev/null and b/tests/data/pngsuite/basi2c16.png differ diff --git a/tests/data/pngsuite/basi3p01.png b/tests/data/pngsuite/basi3p01.png new file mode 100644 index 0000000..00a7cea Binary files /dev/null and b/tests/data/pngsuite/basi3p01.png differ diff --git a/tests/data/pngsuite/basi3p02.png b/tests/data/pngsuite/basi3p02.png new file mode 100644 index 0000000..bb16b44 Binary files /dev/null and b/tests/data/pngsuite/basi3p02.png differ diff --git a/tests/data/pngsuite/basi3p04.png b/tests/data/pngsuite/basi3p04.png new file mode 100644 index 0000000..b4e888e Binary files /dev/null and b/tests/data/pngsuite/basi3p04.png differ diff --git a/tests/data/pngsuite/basi3p08.png b/tests/data/pngsuite/basi3p08.png new file mode 100644 index 0000000..50a6d1c Binary files /dev/null and b/tests/data/pngsuite/basi3p08.png differ diff --git a/tests/data/pngsuite/basi4a08.png b/tests/data/pngsuite/basi4a08.png new file mode 100644 index 0000000..398132b Binary files /dev/null and b/tests/data/pngsuite/basi4a08.png differ diff --git a/tests/data/pngsuite/basi4a16.png b/tests/data/pngsuite/basi4a16.png new file mode 100644 index 0000000..51192e7 Binary files /dev/null and b/tests/data/pngsuite/basi4a16.png differ diff --git a/tests/data/pngsuite/basi6a08.png b/tests/data/pngsuite/basi6a08.png new file mode 100644 index 0000000..aecb32e Binary files /dev/null and b/tests/data/pngsuite/basi6a08.png differ diff --git a/tests/data/pngsuite/basi6a16.png b/tests/data/pngsuite/basi6a16.png new file mode 100644 index 0000000..4181533 Binary files /dev/null and b/tests/data/pngsuite/basi6a16.png differ diff --git a/tests/data/pngsuite/basn0g01.png b/tests/data/pngsuite/basn0g01.png new file mode 100644 index 0000000..1d72242 Binary files /dev/null and b/tests/data/pngsuite/basn0g01.png differ diff --git a/tests/data/pngsuite/basn0g02.png b/tests/data/pngsuite/basn0g02.png new file mode 100644 index 0000000..5083324 Binary files /dev/null and b/tests/data/pngsuite/basn0g02.png differ diff --git a/tests/data/pngsuite/basn0g04.png b/tests/data/pngsuite/basn0g04.png new file mode 100644 index 0000000..0bf3687 Binary files /dev/null and b/tests/data/pngsuite/basn0g04.png differ diff --git a/tests/data/pngsuite/basn0g08.png b/tests/data/pngsuite/basn0g08.png new file mode 100644 index 0000000..23c8237 Binary files /dev/null and b/tests/data/pngsuite/basn0g08.png differ diff --git a/tests/data/pngsuite/basn0g16.png b/tests/data/pngsuite/basn0g16.png new file mode 100644 index 0000000..e7c82f7 Binary files /dev/null and b/tests/data/pngsuite/basn0g16.png differ diff --git a/tests/data/pngsuite/basn2c08.png b/tests/data/pngsuite/basn2c08.png new file mode 100644 index 0000000..db5ad15 Binary files /dev/null and b/tests/data/pngsuite/basn2c08.png differ diff --git a/tests/data/pngsuite/basn2c16.png b/tests/data/pngsuite/basn2c16.png new file mode 100644 index 0000000..50c1cb9 Binary files /dev/null and b/tests/data/pngsuite/basn2c16.png differ diff --git a/tests/data/pngsuite/basn3p01.png b/tests/data/pngsuite/basn3p01.png new file mode 100644 index 0000000..b145c2b Binary files /dev/null and b/tests/data/pngsuite/basn3p01.png differ diff --git a/tests/data/pngsuite/basn3p02.png b/tests/data/pngsuite/basn3p02.png new file mode 100644 index 0000000..8985b3d Binary files /dev/null and b/tests/data/pngsuite/basn3p02.png differ diff --git a/tests/data/pngsuite/basn3p04.png b/tests/data/pngsuite/basn3p04.png new file mode 100644 index 0000000..0fbf9e8 Binary files /dev/null and b/tests/data/pngsuite/basn3p04.png differ diff --git a/tests/data/pngsuite/basn3p08.png b/tests/data/pngsuite/basn3p08.png new file mode 100644 index 0000000..0ddad07 Binary files /dev/null and b/tests/data/pngsuite/basn3p08.png differ diff --git a/tests/data/pngsuite/basn4a08.png b/tests/data/pngsuite/basn4a08.png new file mode 100644 index 0000000..3e13052 Binary files /dev/null and b/tests/data/pngsuite/basn4a08.png differ diff --git a/tests/data/pngsuite/basn4a16.png b/tests/data/pngsuite/basn4a16.png new file mode 100644 index 0000000..8243644 Binary files /dev/null and b/tests/data/pngsuite/basn4a16.png differ diff --git a/tests/data/pngsuite/basn6a08.png b/tests/data/pngsuite/basn6a08.png new file mode 100644 index 0000000..e608738 Binary files /dev/null and b/tests/data/pngsuite/basn6a08.png differ diff --git a/tests/data/pngsuite/basn6a16.png b/tests/data/pngsuite/basn6a16.png new file mode 100644 index 0000000..984a995 Binary files /dev/null and b/tests/data/pngsuite/basn6a16.png differ diff --git a/tests/data/pngsuite/bgai4a08.png b/tests/data/pngsuite/bgai4a08.png new file mode 100644 index 0000000..398132b Binary files /dev/null and b/tests/data/pngsuite/bgai4a08.png differ diff --git a/tests/data/pngsuite/bgai4a16.png b/tests/data/pngsuite/bgai4a16.png new file mode 100644 index 0000000..51192e7 Binary files /dev/null and b/tests/data/pngsuite/bgai4a16.png differ diff --git a/tests/data/pngsuite/bgan6a08.png b/tests/data/pngsuite/bgan6a08.png new file mode 100644 index 0000000..e608738 Binary files /dev/null and b/tests/data/pngsuite/bgan6a08.png differ diff --git a/tests/data/pngsuite/bgan6a16.png b/tests/data/pngsuite/bgan6a16.png new file mode 100644 index 0000000..984a995 Binary files /dev/null and b/tests/data/pngsuite/bgan6a16.png differ diff --git a/tests/data/pngsuite/bgbn4a08.png b/tests/data/pngsuite/bgbn4a08.png new file mode 100644 index 0000000..7cbefc3 Binary files /dev/null and b/tests/data/pngsuite/bgbn4a08.png differ diff --git a/tests/data/pngsuite/bggn4a16.png b/tests/data/pngsuite/bggn4a16.png new file mode 100644 index 0000000..13fd85b Binary files /dev/null and b/tests/data/pngsuite/bggn4a16.png differ diff --git a/tests/data/pngsuite/bgwn6a08.png b/tests/data/pngsuite/bgwn6a08.png new file mode 100644 index 0000000..a67ff20 Binary files /dev/null and b/tests/data/pngsuite/bgwn6a08.png differ diff --git a/tests/data/pngsuite/bgyn6a16.png b/tests/data/pngsuite/bgyn6a16.png new file mode 100644 index 0000000..ae3e9be Binary files /dev/null and b/tests/data/pngsuite/bgyn6a16.png differ diff --git a/tests/data/pngsuite/ccwn2c08.png b/tests/data/pngsuite/ccwn2c08.png new file mode 100644 index 0000000..47c2481 Binary files /dev/null and b/tests/data/pngsuite/ccwn2c08.png differ diff --git a/tests/data/pngsuite/ccwn3p08.png b/tests/data/pngsuite/ccwn3p08.png new file mode 100644 index 0000000..8bb2c10 Binary files /dev/null and b/tests/data/pngsuite/ccwn3p08.png differ diff --git a/tests/data/pngsuite/cdfn2c08.png b/tests/data/pngsuite/cdfn2c08.png new file mode 100644 index 0000000..559e526 Binary files /dev/null and b/tests/data/pngsuite/cdfn2c08.png differ diff --git a/tests/data/pngsuite/cdhn2c08.png b/tests/data/pngsuite/cdhn2c08.png new file mode 100644 index 0000000..3e07e8e Binary files /dev/null and b/tests/data/pngsuite/cdhn2c08.png differ diff --git a/tests/data/pngsuite/cdsn2c08.png b/tests/data/pngsuite/cdsn2c08.png new file mode 100644 index 0000000..076c32c Binary files /dev/null and b/tests/data/pngsuite/cdsn2c08.png differ diff --git a/tests/data/pngsuite/cdun2c08.png b/tests/data/pngsuite/cdun2c08.png new file mode 100644 index 0000000..846033b Binary files /dev/null and b/tests/data/pngsuite/cdun2c08.png differ diff --git a/tests/data/pngsuite/ch1n3p04.png b/tests/data/pngsuite/ch1n3p04.png new file mode 100644 index 0000000..17cd12d Binary files /dev/null and b/tests/data/pngsuite/ch1n3p04.png differ diff --git a/tests/data/pngsuite/ch2n3p08.png b/tests/data/pngsuite/ch2n3p08.png new file mode 100644 index 0000000..25c1798 Binary files /dev/null and b/tests/data/pngsuite/ch2n3p08.png differ diff --git a/tests/data/pngsuite/cm0n0g04.png b/tests/data/pngsuite/cm0n0g04.png new file mode 100644 index 0000000..9fba5db Binary files /dev/null and b/tests/data/pngsuite/cm0n0g04.png differ diff --git a/tests/data/pngsuite/cm7n0g04.png b/tests/data/pngsuite/cm7n0g04.png new file mode 100644 index 0000000..f7dc46e Binary files /dev/null and b/tests/data/pngsuite/cm7n0g04.png differ diff --git a/tests/data/pngsuite/cm9n0g04.png b/tests/data/pngsuite/cm9n0g04.png new file mode 100644 index 0000000..dd70911 Binary files /dev/null and b/tests/data/pngsuite/cm9n0g04.png differ diff --git a/tests/data/pngsuite/cs3n2c16.png b/tests/data/pngsuite/cs3n2c16.png new file mode 100644 index 0000000..bf5fd20 Binary files /dev/null and b/tests/data/pngsuite/cs3n2c16.png differ diff --git a/tests/data/pngsuite/cs3n3p08.png b/tests/data/pngsuite/cs3n3p08.png new file mode 100644 index 0000000..f4a6623 Binary files /dev/null and b/tests/data/pngsuite/cs3n3p08.png differ diff --git a/tests/data/pngsuite/cs5n2c08.png b/tests/data/pngsuite/cs5n2c08.png new file mode 100644 index 0000000..40f947c Binary files /dev/null and b/tests/data/pngsuite/cs5n2c08.png differ diff --git a/tests/data/pngsuite/cs5n3p08.png b/tests/data/pngsuite/cs5n3p08.png new file mode 100644 index 0000000..dfd6e6e Binary files /dev/null and b/tests/data/pngsuite/cs5n3p08.png differ diff --git a/tests/data/pngsuite/cs8n2c08.png b/tests/data/pngsuite/cs8n2c08.png new file mode 100644 index 0000000..8e01d32 Binary files /dev/null and b/tests/data/pngsuite/cs8n2c08.png differ diff --git a/tests/data/pngsuite/cs8n3p08.png b/tests/data/pngsuite/cs8n3p08.png new file mode 100644 index 0000000..a44066e Binary files /dev/null and b/tests/data/pngsuite/cs8n3p08.png differ diff --git a/tests/data/pngsuite/ct0n0g04.png b/tests/data/pngsuite/ct0n0g04.png new file mode 100644 index 0000000..40d1e06 Binary files /dev/null and b/tests/data/pngsuite/ct0n0g04.png differ diff --git a/tests/data/pngsuite/ct1n0g04.png b/tests/data/pngsuite/ct1n0g04.png new file mode 100644 index 0000000..3ba110a Binary files /dev/null and b/tests/data/pngsuite/ct1n0g04.png differ diff --git a/tests/data/pngsuite/cten0g04.png b/tests/data/pngsuite/cten0g04.png new file mode 100644 index 0000000..a6a56fa Binary files /dev/null and b/tests/data/pngsuite/cten0g04.png differ diff --git a/tests/data/pngsuite/ctfn0g04.png b/tests/data/pngsuite/ctfn0g04.png new file mode 100644 index 0000000..353873e Binary files /dev/null and b/tests/data/pngsuite/ctfn0g04.png differ diff --git a/tests/data/pngsuite/ctgn0g04.png b/tests/data/pngsuite/ctgn0g04.png new file mode 100644 index 0000000..453f2b0 Binary files /dev/null and b/tests/data/pngsuite/ctgn0g04.png differ diff --git a/tests/data/pngsuite/cthn0g04.png b/tests/data/pngsuite/cthn0g04.png new file mode 100644 index 0000000..8fce253 Binary files /dev/null and b/tests/data/pngsuite/cthn0g04.png differ diff --git a/tests/data/pngsuite/ctjn0g04.png b/tests/data/pngsuite/ctjn0g04.png new file mode 100644 index 0000000..a77b8d2 Binary files /dev/null and b/tests/data/pngsuite/ctjn0g04.png differ diff --git a/tests/data/pngsuite/ctzn0g04.png b/tests/data/pngsuite/ctzn0g04.png new file mode 100644 index 0000000..b4401c9 Binary files /dev/null and b/tests/data/pngsuite/ctzn0g04.png differ diff --git a/tests/data/pngsuite/exif2c08.png b/tests/data/pngsuite/exif2c08.png new file mode 100644 index 0000000..56eb734 Binary files /dev/null and b/tests/data/pngsuite/exif2c08.png differ diff --git a/tests/data/pngsuite/f00n0g08.png b/tests/data/pngsuite/f00n0g08.png new file mode 100644 index 0000000..45a0075 Binary files /dev/null and b/tests/data/pngsuite/f00n0g08.png differ diff --git a/tests/data/pngsuite/f00n2c08.png b/tests/data/pngsuite/f00n2c08.png new file mode 100644 index 0000000..d6a1fff Binary files /dev/null and b/tests/data/pngsuite/f00n2c08.png differ diff --git a/tests/data/pngsuite/f01n0g08.png b/tests/data/pngsuite/f01n0g08.png new file mode 100644 index 0000000..4a1107b Binary files /dev/null and b/tests/data/pngsuite/f01n0g08.png differ diff --git a/tests/data/pngsuite/f01n2c08.png b/tests/data/pngsuite/f01n2c08.png new file mode 100644 index 0000000..26fee95 Binary files /dev/null and b/tests/data/pngsuite/f01n2c08.png differ diff --git a/tests/data/pngsuite/f02n0g08.png b/tests/data/pngsuite/f02n0g08.png new file mode 100644 index 0000000..bfe410c Binary files /dev/null and b/tests/data/pngsuite/f02n0g08.png differ diff --git a/tests/data/pngsuite/f02n2c08.png b/tests/data/pngsuite/f02n2c08.png new file mode 100644 index 0000000..e590f12 Binary files /dev/null and b/tests/data/pngsuite/f02n2c08.png differ diff --git a/tests/data/pngsuite/f03n0g08.png b/tests/data/pngsuite/f03n0g08.png new file mode 100644 index 0000000..ed01e29 Binary files /dev/null and b/tests/data/pngsuite/f03n0g08.png differ diff --git a/tests/data/pngsuite/f03n2c08.png b/tests/data/pngsuite/f03n2c08.png new file mode 100644 index 0000000..7581150 Binary files /dev/null and b/tests/data/pngsuite/f03n2c08.png differ diff --git a/tests/data/pngsuite/f04n0g08.png b/tests/data/pngsuite/f04n0g08.png new file mode 100644 index 0000000..663fdae Binary files /dev/null and b/tests/data/pngsuite/f04n0g08.png differ diff --git a/tests/data/pngsuite/f04n2c08.png b/tests/data/pngsuite/f04n2c08.png new file mode 100644 index 0000000..3c8b511 Binary files /dev/null and b/tests/data/pngsuite/f04n2c08.png differ diff --git a/tests/data/pngsuite/f99n0g04.png b/tests/data/pngsuite/f99n0g04.png new file mode 100644 index 0000000..0b521c1 Binary files /dev/null and b/tests/data/pngsuite/f99n0g04.png differ diff --git a/tests/data/pngsuite/g03n0g16.png b/tests/data/pngsuite/g03n0g16.png new file mode 100644 index 0000000..41083ca Binary files /dev/null and b/tests/data/pngsuite/g03n0g16.png differ diff --git a/tests/data/pngsuite/g03n2c08.png b/tests/data/pngsuite/g03n2c08.png new file mode 100644 index 0000000..a9354db Binary files /dev/null and b/tests/data/pngsuite/g03n2c08.png differ diff --git a/tests/data/pngsuite/g03n3p04.png b/tests/data/pngsuite/g03n3p04.png new file mode 100644 index 0000000..60396c9 Binary files /dev/null and b/tests/data/pngsuite/g03n3p04.png differ diff --git a/tests/data/pngsuite/g04n0g16.png b/tests/data/pngsuite/g04n0g16.png new file mode 100644 index 0000000..32395b7 Binary files /dev/null and b/tests/data/pngsuite/g04n0g16.png differ diff --git a/tests/data/pngsuite/g04n2c08.png b/tests/data/pngsuite/g04n2c08.png new file mode 100644 index 0000000..a652b0c Binary files /dev/null and b/tests/data/pngsuite/g04n2c08.png differ diff --git a/tests/data/pngsuite/g04n3p04.png b/tests/data/pngsuite/g04n3p04.png new file mode 100644 index 0000000..5661cc3 Binary files /dev/null and b/tests/data/pngsuite/g04n3p04.png differ diff --git a/tests/data/pngsuite/g05n0g16.png b/tests/data/pngsuite/g05n0g16.png new file mode 100644 index 0000000..70b37f0 Binary files /dev/null and b/tests/data/pngsuite/g05n0g16.png differ diff --git a/tests/data/pngsuite/g05n2c08.png b/tests/data/pngsuite/g05n2c08.png new file mode 100644 index 0000000..932c136 Binary files /dev/null and b/tests/data/pngsuite/g05n2c08.png differ diff --git a/tests/data/pngsuite/g05n3p04.png b/tests/data/pngsuite/g05n3p04.png new file mode 100644 index 0000000..9619930 Binary files /dev/null and b/tests/data/pngsuite/g05n3p04.png differ diff --git a/tests/data/pngsuite/g07n0g16.png b/tests/data/pngsuite/g07n0g16.png new file mode 100644 index 0000000..d6a47c2 Binary files /dev/null and b/tests/data/pngsuite/g07n0g16.png differ diff --git a/tests/data/pngsuite/g07n2c08.png b/tests/data/pngsuite/g07n2c08.png new file mode 100644 index 0000000..5973464 Binary files /dev/null and b/tests/data/pngsuite/g07n2c08.png differ diff --git a/tests/data/pngsuite/g07n3p04.png b/tests/data/pngsuite/g07n3p04.png new file mode 100644 index 0000000..c73fb61 Binary files /dev/null and b/tests/data/pngsuite/g07n3p04.png differ diff --git a/tests/data/pngsuite/g10n0g16.png b/tests/data/pngsuite/g10n0g16.png new file mode 100644 index 0000000..85f2c95 Binary files /dev/null and b/tests/data/pngsuite/g10n0g16.png differ diff --git a/tests/data/pngsuite/g10n2c08.png b/tests/data/pngsuite/g10n2c08.png new file mode 100644 index 0000000..b303997 Binary files /dev/null and b/tests/data/pngsuite/g10n2c08.png differ diff --git a/tests/data/pngsuite/g10n3p04.png b/tests/data/pngsuite/g10n3p04.png new file mode 100644 index 0000000..1b6a6be Binary files /dev/null and b/tests/data/pngsuite/g10n3p04.png differ diff --git a/tests/data/pngsuite/g25n0g16.png b/tests/data/pngsuite/g25n0g16.png new file mode 100644 index 0000000..a9f6787 Binary files /dev/null and b/tests/data/pngsuite/g25n0g16.png differ diff --git a/tests/data/pngsuite/g25n2c08.png b/tests/data/pngsuite/g25n2c08.png new file mode 100644 index 0000000..03f505a Binary files /dev/null and b/tests/data/pngsuite/g25n2c08.png differ diff --git a/tests/data/pngsuite/g25n3p04.png b/tests/data/pngsuite/g25n3p04.png new file mode 100644 index 0000000..4f943c6 Binary files /dev/null and b/tests/data/pngsuite/g25n3p04.png differ diff --git a/tests/data/pngsuite/oi1n0g16.png b/tests/data/pngsuite/oi1n0g16.png new file mode 100644 index 0000000..e7c82f7 Binary files /dev/null and b/tests/data/pngsuite/oi1n0g16.png differ diff --git a/tests/data/pngsuite/oi1n2c16.png b/tests/data/pngsuite/oi1n2c16.png new file mode 100644 index 0000000..50c1cb9 Binary files /dev/null and b/tests/data/pngsuite/oi1n2c16.png differ diff --git a/tests/data/pngsuite/oi2n0g16.png b/tests/data/pngsuite/oi2n0g16.png new file mode 100644 index 0000000..14d64c5 Binary files /dev/null and b/tests/data/pngsuite/oi2n0g16.png differ diff --git a/tests/data/pngsuite/oi2n2c16.png b/tests/data/pngsuite/oi2n2c16.png new file mode 100644 index 0000000..4c2e3e3 Binary files /dev/null and b/tests/data/pngsuite/oi2n2c16.png differ diff --git a/tests/data/pngsuite/oi4n0g16.png b/tests/data/pngsuite/oi4n0g16.png new file mode 100644 index 0000000..69e73ed Binary files /dev/null and b/tests/data/pngsuite/oi4n0g16.png differ diff --git a/tests/data/pngsuite/oi4n2c16.png b/tests/data/pngsuite/oi4n2c16.png new file mode 100644 index 0000000..93691e3 Binary files /dev/null and b/tests/data/pngsuite/oi4n2c16.png differ diff --git a/tests/data/pngsuite/oi9n0g16.png b/tests/data/pngsuite/oi9n0g16.png new file mode 100644 index 0000000..9248413 Binary files /dev/null and b/tests/data/pngsuite/oi9n0g16.png differ diff --git a/tests/data/pngsuite/oi9n2c16.png b/tests/data/pngsuite/oi9n2c16.png new file mode 100644 index 0000000..f0512e4 Binary files /dev/null and b/tests/data/pngsuite/oi9n2c16.png differ diff --git a/tests/data/pngsuite/pp0n2c16.png b/tests/data/pngsuite/pp0n2c16.png new file mode 100644 index 0000000..8f2aad7 Binary files /dev/null and b/tests/data/pngsuite/pp0n2c16.png differ diff --git a/tests/data/pngsuite/pp0n6a08.png b/tests/data/pngsuite/pp0n6a08.png new file mode 100644 index 0000000..4ed7a30 Binary files /dev/null and b/tests/data/pngsuite/pp0n6a08.png differ diff --git a/tests/data/pngsuite/ps1n0g08.png b/tests/data/pngsuite/ps1n0g08.png new file mode 100644 index 0000000..99625fa Binary files /dev/null and b/tests/data/pngsuite/ps1n0g08.png differ diff --git a/tests/data/pngsuite/ps1n2c16.png b/tests/data/pngsuite/ps1n2c16.png new file mode 100644 index 0000000..0c7a6b3 Binary files /dev/null and b/tests/data/pngsuite/ps1n2c16.png differ diff --git a/tests/data/pngsuite/ps2n0g08.png b/tests/data/pngsuite/ps2n0g08.png new file mode 100644 index 0000000..90b2979 Binary files /dev/null and b/tests/data/pngsuite/ps2n0g08.png differ diff --git a/tests/data/pngsuite/ps2n2c16.png b/tests/data/pngsuite/ps2n2c16.png new file mode 100644 index 0000000..a4a181e Binary files /dev/null and b/tests/data/pngsuite/ps2n2c16.png differ diff --git a/tests/data/pngsuite/s01i3p01.png b/tests/data/pngsuite/s01i3p01.png new file mode 100644 index 0000000..6c0fad1 Binary files /dev/null and b/tests/data/pngsuite/s01i3p01.png differ diff --git a/tests/data/pngsuite/s01n3p01.png b/tests/data/pngsuite/s01n3p01.png new file mode 100644 index 0000000..cb2c8c7 Binary files /dev/null and b/tests/data/pngsuite/s01n3p01.png differ diff --git a/tests/data/pngsuite/s02i3p01.png b/tests/data/pngsuite/s02i3p01.png new file mode 100644 index 0000000..2defaed Binary files /dev/null and b/tests/data/pngsuite/s02i3p01.png differ diff --git a/tests/data/pngsuite/s02n3p01.png b/tests/data/pngsuite/s02n3p01.png new file mode 100644 index 0000000..2b1b669 Binary files /dev/null and b/tests/data/pngsuite/s02n3p01.png differ diff --git a/tests/data/pngsuite/s03i3p01.png b/tests/data/pngsuite/s03i3p01.png new file mode 100644 index 0000000..c23fdc4 Binary files /dev/null and b/tests/data/pngsuite/s03i3p01.png differ diff --git a/tests/data/pngsuite/s03n3p01.png b/tests/data/pngsuite/s03n3p01.png new file mode 100644 index 0000000..6d96ee4 Binary files /dev/null and b/tests/data/pngsuite/s03n3p01.png differ diff --git a/tests/data/pngsuite/s04i3p01.png b/tests/data/pngsuite/s04i3p01.png new file mode 100644 index 0000000..0e710c2 Binary files /dev/null and b/tests/data/pngsuite/s04i3p01.png differ diff --git a/tests/data/pngsuite/s04n3p01.png b/tests/data/pngsuite/s04n3p01.png new file mode 100644 index 0000000..956396c Binary files /dev/null and b/tests/data/pngsuite/s04n3p01.png differ diff --git a/tests/data/pngsuite/s05i3p02.png b/tests/data/pngsuite/s05i3p02.png new file mode 100644 index 0000000..d14cbd3 Binary files /dev/null and b/tests/data/pngsuite/s05i3p02.png differ diff --git a/tests/data/pngsuite/s05n3p02.png b/tests/data/pngsuite/s05n3p02.png new file mode 100644 index 0000000..bf940f0 Binary files /dev/null and b/tests/data/pngsuite/s05n3p02.png differ diff --git a/tests/data/pngsuite/s06i3p02.png b/tests/data/pngsuite/s06i3p02.png new file mode 100644 index 0000000..456ada3 Binary files /dev/null and b/tests/data/pngsuite/s06i3p02.png differ diff --git a/tests/data/pngsuite/s06n3p02.png b/tests/data/pngsuite/s06n3p02.png new file mode 100644 index 0000000..501064d Binary files /dev/null and b/tests/data/pngsuite/s06n3p02.png differ diff --git a/tests/data/pngsuite/s07i3p02.png b/tests/data/pngsuite/s07i3p02.png new file mode 100644 index 0000000..44b66ba Binary files /dev/null and b/tests/data/pngsuite/s07i3p02.png differ diff --git a/tests/data/pngsuite/s07n3p02.png b/tests/data/pngsuite/s07n3p02.png new file mode 100644 index 0000000..6a58259 Binary files /dev/null and b/tests/data/pngsuite/s07n3p02.png differ diff --git a/tests/data/pngsuite/s08i3p02.png b/tests/data/pngsuite/s08i3p02.png new file mode 100644 index 0000000..acf74f3 Binary files /dev/null and b/tests/data/pngsuite/s08i3p02.png differ diff --git a/tests/data/pngsuite/s08n3p02.png b/tests/data/pngsuite/s08n3p02.png new file mode 100644 index 0000000..b7094e1 Binary files /dev/null and b/tests/data/pngsuite/s08n3p02.png differ diff --git a/tests/data/pngsuite/s09i3p02.png b/tests/data/pngsuite/s09i3p02.png new file mode 100644 index 0000000..0bfae8e Binary files /dev/null and b/tests/data/pngsuite/s09i3p02.png differ diff --git a/tests/data/pngsuite/s09n3p02.png b/tests/data/pngsuite/s09n3p02.png new file mode 100644 index 0000000..711ab82 Binary files /dev/null and b/tests/data/pngsuite/s09n3p02.png differ diff --git a/tests/data/pngsuite/s32i3p04.png b/tests/data/pngsuite/s32i3p04.png new file mode 100644 index 0000000..0841910 Binary files /dev/null and b/tests/data/pngsuite/s32i3p04.png differ diff --git a/tests/data/pngsuite/s32n3p04.png b/tests/data/pngsuite/s32n3p04.png new file mode 100644 index 0000000..fa58e3e Binary files /dev/null and b/tests/data/pngsuite/s32n3p04.png differ diff --git a/tests/data/pngsuite/s33i3p04.png b/tests/data/pngsuite/s33i3p04.png new file mode 100644 index 0000000..ab0dc14 Binary files /dev/null and b/tests/data/pngsuite/s33i3p04.png differ diff --git a/tests/data/pngsuite/s33n3p04.png b/tests/data/pngsuite/s33n3p04.png new file mode 100644 index 0000000..764f1a3 Binary files /dev/null and b/tests/data/pngsuite/s33n3p04.png differ diff --git a/tests/data/pngsuite/s34i3p04.png b/tests/data/pngsuite/s34i3p04.png new file mode 100644 index 0000000..bd99039 Binary files /dev/null and b/tests/data/pngsuite/s34i3p04.png differ diff --git a/tests/data/pngsuite/s34n3p04.png b/tests/data/pngsuite/s34n3p04.png new file mode 100644 index 0000000..9cbc68b Binary files /dev/null and b/tests/data/pngsuite/s34n3p04.png differ diff --git a/tests/data/pngsuite/s35i3p04.png b/tests/data/pngsuite/s35i3p04.png new file mode 100644 index 0000000..e2a5e0a Binary files /dev/null and b/tests/data/pngsuite/s35i3p04.png differ diff --git a/tests/data/pngsuite/s35n3p04.png b/tests/data/pngsuite/s35n3p04.png new file mode 100644 index 0000000..90b892e Binary files /dev/null and b/tests/data/pngsuite/s35n3p04.png differ diff --git a/tests/data/pngsuite/s36i3p04.png b/tests/data/pngsuite/s36i3p04.png new file mode 100644 index 0000000..eb61b6f Binary files /dev/null and b/tests/data/pngsuite/s36i3p04.png differ diff --git a/tests/data/pngsuite/s36n3p04.png b/tests/data/pngsuite/s36n3p04.png new file mode 100644 index 0000000..b38d179 Binary files /dev/null and b/tests/data/pngsuite/s36n3p04.png differ diff --git a/tests/data/pngsuite/s37i3p04.png b/tests/data/pngsuite/s37i3p04.png new file mode 100644 index 0000000..6e2b1e9 Binary files /dev/null and b/tests/data/pngsuite/s37i3p04.png differ diff --git a/tests/data/pngsuite/s37n3p04.png b/tests/data/pngsuite/s37n3p04.png new file mode 100644 index 0000000..4d3054d Binary files /dev/null and b/tests/data/pngsuite/s37n3p04.png differ diff --git a/tests/data/pngsuite/s38i3p04.png b/tests/data/pngsuite/s38i3p04.png new file mode 100644 index 0000000..a0a8a14 Binary files /dev/null and b/tests/data/pngsuite/s38i3p04.png differ diff --git a/tests/data/pngsuite/s38n3p04.png b/tests/data/pngsuite/s38n3p04.png new file mode 100644 index 0000000..1233ed0 Binary files /dev/null and b/tests/data/pngsuite/s38n3p04.png differ diff --git a/tests/data/pngsuite/s39i3p04.png b/tests/data/pngsuite/s39i3p04.png new file mode 100644 index 0000000..04fee93 Binary files /dev/null and b/tests/data/pngsuite/s39i3p04.png differ diff --git a/tests/data/pngsuite/s39n3p04.png b/tests/data/pngsuite/s39n3p04.png new file mode 100644 index 0000000..c750100 Binary files /dev/null and b/tests/data/pngsuite/s39n3p04.png differ diff --git a/tests/data/pngsuite/s40i3p04.png b/tests/data/pngsuite/s40i3p04.png new file mode 100644 index 0000000..68f358b Binary files /dev/null and b/tests/data/pngsuite/s40i3p04.png differ diff --git a/tests/data/pngsuite/s40n3p04.png b/tests/data/pngsuite/s40n3p04.png new file mode 100644 index 0000000..864b6b9 Binary files /dev/null and b/tests/data/pngsuite/s40n3p04.png differ diff --git a/tests/data/pngsuite/tbbn0g04.png b/tests/data/pngsuite/tbbn0g04.png new file mode 100644 index 0000000..39a7050 Binary files /dev/null and b/tests/data/pngsuite/tbbn0g04.png differ diff --git a/tests/data/pngsuite/tbbn2c16.png b/tests/data/pngsuite/tbbn2c16.png new file mode 100644 index 0000000..dd3168e Binary files /dev/null and b/tests/data/pngsuite/tbbn2c16.png differ diff --git a/tests/data/pngsuite/tbbn3p08.png b/tests/data/pngsuite/tbbn3p08.png new file mode 100644 index 0000000..0ede357 Binary files /dev/null and b/tests/data/pngsuite/tbbn3p08.png differ diff --git a/tests/data/pngsuite/tbgn2c16.png b/tests/data/pngsuite/tbgn2c16.png new file mode 100644 index 0000000..85cec39 Binary files /dev/null and b/tests/data/pngsuite/tbgn2c16.png differ diff --git a/tests/data/pngsuite/tbgn3p08.png b/tests/data/pngsuite/tbgn3p08.png new file mode 100644 index 0000000..8cf2e6f Binary files /dev/null and b/tests/data/pngsuite/tbgn3p08.png differ diff --git a/tests/data/pngsuite/tbrn2c08.png b/tests/data/pngsuite/tbrn2c08.png new file mode 100644 index 0000000..5cca0d6 Binary files /dev/null and b/tests/data/pngsuite/tbrn2c08.png differ diff --git a/tests/data/pngsuite/tbwn0g16.png b/tests/data/pngsuite/tbwn0g16.png new file mode 100644 index 0000000..99bdeed Binary files /dev/null and b/tests/data/pngsuite/tbwn0g16.png differ diff --git a/tests/data/pngsuite/tbwn3p08.png b/tests/data/pngsuite/tbwn3p08.png new file mode 100644 index 0000000..eacab7a Binary files /dev/null and b/tests/data/pngsuite/tbwn3p08.png differ diff --git a/tests/data/pngsuite/tbyn3p08.png b/tests/data/pngsuite/tbyn3p08.png new file mode 100644 index 0000000..656db09 Binary files /dev/null and b/tests/data/pngsuite/tbyn3p08.png differ diff --git a/tests/data/pngsuite/tm3n3p02.png b/tests/data/pngsuite/tm3n3p02.png new file mode 100644 index 0000000..fb3ef1d Binary files /dev/null and b/tests/data/pngsuite/tm3n3p02.png differ diff --git a/tests/data/pngsuite/tp0n0g08.png b/tests/data/pngsuite/tp0n0g08.png new file mode 100644 index 0000000..333465f Binary files /dev/null and b/tests/data/pngsuite/tp0n0g08.png differ diff --git a/tests/data/pngsuite/tp0n2c08.png b/tests/data/pngsuite/tp0n2c08.png new file mode 100644 index 0000000..fc6e42c Binary files /dev/null and b/tests/data/pngsuite/tp0n2c08.png differ diff --git a/tests/data/pngsuite/tp0n3p08.png b/tests/data/pngsuite/tp0n3p08.png new file mode 100644 index 0000000..69a69e5 Binary files /dev/null and b/tests/data/pngsuite/tp0n3p08.png differ diff --git a/tests/data/pngsuite/tp1n3p08.png b/tests/data/pngsuite/tp1n3p08.png new file mode 100644 index 0000000..a6c9f35 Binary files /dev/null and b/tests/data/pngsuite/tp1n3p08.png differ diff --git a/tests/data/pngsuite/xc1n0g08.png b/tests/data/pngsuite/xc1n0g08.png new file mode 100644 index 0000000..9404227 Binary files /dev/null and b/tests/data/pngsuite/xc1n0g08.png differ diff --git a/tests/data/pngsuite/xc9n2c08.png b/tests/data/pngsuite/xc9n2c08.png new file mode 100644 index 0000000..b11c2a7 Binary files /dev/null and b/tests/data/pngsuite/xc9n2c08.png differ diff --git a/tests/data/pngsuite/xcrn0g04.png b/tests/data/pngsuite/xcrn0g04.png new file mode 100644 index 0000000..48abba1 Binary files /dev/null and b/tests/data/pngsuite/xcrn0g04.png differ diff --git a/tests/data/pngsuite/xcsn0g01.png b/tests/data/pngsuite/xcsn0g01.png new file mode 100644 index 0000000..9863a26 Binary files /dev/null and b/tests/data/pngsuite/xcsn0g01.png differ diff --git a/tests/data/pngsuite/xd0n2c08.png b/tests/data/pngsuite/xd0n2c08.png new file mode 100644 index 0000000..2f00161 Binary files /dev/null and b/tests/data/pngsuite/xd0n2c08.png differ diff --git a/tests/data/pngsuite/xd3n2c08.png b/tests/data/pngsuite/xd3n2c08.png new file mode 100644 index 0000000..9e4a3ff Binary files /dev/null and b/tests/data/pngsuite/xd3n2c08.png differ diff --git a/tests/data/pngsuite/xd9n2c08.png b/tests/data/pngsuite/xd9n2c08.png new file mode 100644 index 0000000..2c3b91a Binary files /dev/null and b/tests/data/pngsuite/xd9n2c08.png differ diff --git a/tests/data/pngsuite/xdtn0g01.png b/tests/data/pngsuite/xdtn0g01.png new file mode 100644 index 0000000..1a81abe Binary files /dev/null and b/tests/data/pngsuite/xdtn0g01.png differ diff --git a/tests/data/pngsuite/xhdn0g08.png b/tests/data/pngsuite/xhdn0g08.png new file mode 100644 index 0000000..fcb8737 Binary files /dev/null and b/tests/data/pngsuite/xhdn0g08.png differ diff --git a/tests/data/pngsuite/xlfn0g04.png b/tests/data/pngsuite/xlfn0g04.png new file mode 100644 index 0000000..d9ec53e Binary files /dev/null and b/tests/data/pngsuite/xlfn0g04.png differ diff --git a/tests/data/pngsuite/xs1n0g01.png b/tests/data/pngsuite/xs1n0g01.png new file mode 100644 index 0000000..1817c51 Binary files /dev/null and b/tests/data/pngsuite/xs1n0g01.png differ diff --git a/tests/data/pngsuite/xs2n0g01.png b/tests/data/pngsuite/xs2n0g01.png new file mode 100644 index 0000000..b8147f2 Binary files /dev/null and b/tests/data/pngsuite/xs2n0g01.png differ diff --git a/tests/data/pngsuite/xs4n0g01.png b/tests/data/pngsuite/xs4n0g01.png new file mode 100644 index 0000000..45237a1 Binary files /dev/null and b/tests/data/pngsuite/xs4n0g01.png differ diff --git a/tests/data/pngsuite/xs7n0g01.png b/tests/data/pngsuite/xs7n0g01.png new file mode 100644 index 0000000..3f307f1 Binary files /dev/null and b/tests/data/pngsuite/xs7n0g01.png differ diff --git a/tests/data/pngsuite/z00n2c08.png b/tests/data/pngsuite/z00n2c08.png new file mode 100644 index 0000000..7669eb8 Binary files /dev/null and b/tests/data/pngsuite/z00n2c08.png differ diff --git a/tests/data/pngsuite/z03n2c08.png b/tests/data/pngsuite/z03n2c08.png new file mode 100644 index 0000000..bfb10de Binary files /dev/null and b/tests/data/pngsuite/z03n2c08.png differ diff --git a/tests/data/pngsuite/z06n2c08.png b/tests/data/pngsuite/z06n2c08.png new file mode 100644 index 0000000..b90ebc1 Binary files /dev/null and b/tests/data/pngsuite/z06n2c08.png differ diff --git a/tests/data/pngsuite/z09n2c08.png b/tests/data/pngsuite/z09n2c08.png new file mode 100644 index 0000000..5f191a7 Binary files /dev/null and b/tests/data/pngsuite/z09n2c08.png differ diff --git a/tests/fuzz_png.nim b/tests/fuzz_png.nim new file mode 100644 index 0000000..fc15db4 --- /dev/null +++ b/tests/fuzz_png.nim @@ -0,0 +1,16 @@ +import random, strformat, pixie/fileformats/png, pixie/common, pngsuite + +randomize() + +for i in 0 ..< 10_000: + let file = pngSuiteFiles[rand(pngSuiteFiles.len - 1)] + var data = cast[seq[uint8]](readFile(&"tests/data/pngsuite/{file}.png")) + let + pos = 29 + rand(data.len - 30) + value = rand(255).uint8 + data[pos] = value + echo &"{i} {file} {pos} {value}" + try: + discard decodePng(data) + except PixieError: + discard diff --git a/tests/pngsuite.nim b/tests/pngsuite.nim new file mode 100644 index 0000000..d843c73 --- /dev/null +++ b/tests/pngsuite.nim @@ -0,0 +1,73 @@ +const pngSuiteFiles* = [ + # Basic + "basn0g01", # black & white + "basn0g02", # 2 bit (4 level) grayscale + "basn0g04", # 4 bit (16 level) grayscale + "basn0g08", # 8 bit (256 level) grayscale + # "basn0g16", # 16 bit (64k level) grayscale + "basn2c08", # 3x8 bits rgb color + # "basn2c16", # 3x16 bits rgb color + "basn3p01", # 1 bit (2 color) paletted + "basn3p02", # 2 bit (4 color) paletted + "basn3p04", # 4 bit (16 color) paletted + "basn3p08", # 8 bit (256 color) paletted + "basn4a08", # 8 bit grayscale + 8 bit alpha-channel + # "basn4a16", # 16 bit grayscale + 16 bit alpha-channel + "basn6a08", # 3x8 bits rgb color + 8 bit alpha-channel + # "basn6a16", # 3x16 bits rgb color + 16 bit alpha-channel + + # Interlaced + # "basi0g01", # black & white + # "basi0g02", # 2 bit (4 level) grayscale + # "basi0g04", # 4 bit (16 level) grayscale + # "basi0g08", # 8 bit (256 level) grayscale + # "basi0g16", # 16 bit (64k level) grayscale + # "basi2c08", # 3x8 bits rgb color + # "basi2c16", # 3x16 bits rgb color + # "basi3p01", # 1 bit (2 color) paletted + # "basi3p02", # 2 bit (4 color) paletted + # "basi3p04", # 4 bit (16 color) paletted + # "basi3p08", # 8 bit (256 color) paletted + # "basi4a08", # 8 bit grayscale + 8 bit alpha-channel + # "basi4a16", # 16 bit grayscale + 16 bit alpha-channel + # "basi6a08", # 3x8 bits rgb color + 8 bit alpha-channel + # "basi6a16", # 3x16 bits rgb color + 16 bit alpha-channel + + # Odd sizes + # "s01i3p01", # 1x1 paletted file, interlaced + "s01n3p01", # 1x1 paletted file, no interlacing + # "s02i3p01", # 2x2 paletted file, interlaced + "s02n3p01", # 2x2 paletted file, no interlacing + # "s03i3p01", # 3x3 paletted file, interlaced + "s03n3p01", # 3x3 paletted file, no interlacing + # "s04i3p01", # 4x4 paletted file, interlaced + "s04n3p01", # 4x4 paletted file, no interlacing + # "s05i3p02", # 5x5 paletted file, interlaced + "s05n3p02", # 5x5 paletted file, no interlacing + # "s06i3p02", # 6x6 paletted file, interlaced + "s06n3p02", # 6x6 paletted file, no interlacing + # "s07i3p02", # 7x7 paletted file, interlaced + "s07n3p02", # 7x7 paletted file, no interlacing + # "s08i3p02", # 8x8 paletted file, interlaced + "s08n3p02", # 8x8 paletted file, no interlacing + # "s09i3p02", # 9x9 paletted file, interlaced + "s09n3p02", # 9x9 paletted file, no interlacing + # "s32i3p04", # 32x32 paletted file, interlaced + "s32n3p04", # 32x32 paletted file, no interlacing + # "s33i3p04", # 33x33 paletted file, interlaced + "s33n3p04", # 33x33 paletted file, no interlacing + # "s34i3p04", # 34x34 paletted file, interlaced + "s34n3p04", # 34x34 paletted file, no interlacing + # "s35i3p04", # 35x35 paletted file, interlaced + "s35n3p04", # 35x35 paletted file, no interlacing + # "s36i3p04", # 36x36 paletted file, interlaced + "s36n3p04", # 36x36 paletted file, no interlacing + # "s37i3p04", # 37x37 paletted file, interlaced + "s37n3p04", # 37x37 paletted file, no interlacing + # "s38i3p04", # 38x38 paletted file, interlaced + "s38n3p04", # 38x38 paletted file, no interlacing + # "s39i3p04", # 39x39 paletted file, interlaced + "s39n3p04", # 39x39 paletted file, no interlacing + # "s40i3p04", # 40x40 paletted file, interlaced + "s40n3p04", # 40x40 paletted file, no interlacing +] diff --git a/tests/test_png.nim b/tests/test_png.nim new file mode 100644 index 0000000..5ad64fe --- /dev/null +++ b/tests/test_png.nim @@ -0,0 +1,22 @@ +import pixie/fileformats/png, strformat, pngsuite + +for file in pngSuiteFiles: + let + original = cast[seq[uint8]](readFile(&"tests/data/pngsuite/{file}.png")) + decoded = decodePng(original) + encoded = encodePng(decoded) + decoded2 = decodePng(cast[seq[uint8]](encoded)) + + doAssert decoded.height == decoded2.height + doAssert decoded.width == decoded2.width + doAssert decoded.data == decoded2.data + +for channels in 1 .. 4: + var data: seq[uint8] + for x in 0 ..< 16: + for y in 0 ..< 16: + var components = newSeq[uint8](channels) + for i in 0 ..< channels: + components[i] = (x * 16).uint8 + data.add(components) + let encoded = encodePng(16, 16, channels, data[0].addr, data.len) diff --git a/tests/validate_png.nim b/tests/validate_png.nim new file mode 100644 index 0000000..4acc22a --- /dev/null +++ b/tests/validate_png.nim @@ -0,0 +1,32 @@ +import chroma, pixie/fileformats/png, stb_image/read as stbi, strformat, pngsuite + +for file in pngSuiteFiles: + let + data = readFile(&"tests/data/pngsuite/{file}.png") + pixieLoaded = decodePng(cast[seq[uint8]](data)) + + var + width, height, channels: int + stbiLoadedData = loadFromMemory( + cast[seq[byte]](data), + width, + height, + channels, + stbi.RGBA + ) + stbiLoadedRGBA: seq[ColorRGBA] + + var i: int + while i < stbiLoadedData.len: + stbiLoadedRGBA.add(ColorRGBA( + r: stbiLoadedData[i + 0], + g: stbiLoadedData[i + 1], + b: stbiLoadedData[i + 2], + a: stbiLoadedData[i + 3] + )) + i += 4 + + doAssert pixieLoaded.width == width + doAssert pixieLoaded.height == height + doAssert pixieLoaded.data.len == stbiLoadedRGBA.len + doAssert pixieLoaded.data == stbiLoadedRGBA