def testUnfilterScanlinePaeth(self): """This tests more edge cases in the paeth unfilter""" scanprev = array('B', [2, 0, 0, 0, 9, 11]) scanline = array('B', [4, 6, 10, 9, 100, 101, 102]) filter_ = png.Filter(24, prev=scanprev) out = filter_.undo_filter(scanline[0], scanline[1:]) self.assertEqual(list(out), [8, 10, 9, 108, 111, 113]) # paeth
def testFilterScanline(self): """Test filtering with previous line""" prev = array('B', [20, 21, 22, 210, 211, 212]) line = array('B', [30, 32, 34, 230, 233, 236]) filter_ = png.Filter(24, prev=prev) res = filter_.filter_all(line) # None self.assertEqual(list(res[0]), [0, 30, 32, 34, 230, 233, 236]) # sub self.assertEqual(list(res[1]), [1, 30, 32, 34, 200, 201, 202]) # up self.assertEqual(list(res[2]), [2, 10, 11, 12, 20, 22, 24]) # average self.assertEqual(list(res[3]), [3, 20, 22, 23, 110, 112, 113]) # paeth self.assertEqual(list(res[4]), [4, self.paeth(30, 0, 20, 0), self.paeth(32, 0, 21, 0), self.paeth(34, 0, 22, 0), self.paeth(230, 30, 210, 20), self.paeth(233, 32, 211, 21), self.paeth(236, 34, 212, 22)])
def testUnfilterScanline(self): """Test unfiltering""" scanprev = array('B', [20, 21, 22, 210, 211, 212]) scanline = array('B', [30, 32, 34, 230, 233, 236]) def undo_filter(filter_type, line, prev): """undoing filter""" filter_ = png.Filter(24, prev=prev) line = array('B', line) return filter_.undo_filter(filter_type, line) out = undo_filter(0, scanline, scanprev) self.assertEqual(list(out), list(scanline)) # none out = undo_filter(1, scanline, scanprev) self.assertEqual(list(out), [30, 32, 34, 4, 9, 14]) # sub out = undo_filter(2, scanline, scanprev) self.assertEqual(list(out), [50, 53, 56, 184, 188, 192]) # up out = undo_filter(3, scanline, scanprev) self.assertEqual(list(out), [40, 42, 45, 99, 103, 108]) # average out = undo_filter(4, scanline, scanprev) self.assertEqual(list(out), [50, 53, 56, 184, 188, 192]) # paeth
def testL2(self): """Test L with depth 2. Also tests asRGB8.""" w = png.Writer(1, 4, greyscale=True, bitdepth=2) f = BytesIO() w.write_array(f, array('B', range(4))) r = png.Reader(bytes=f.getvalue()) x, y, pixels, _ = r.asRGB8() self.assertEqual(x, 1) self.assertEqual(y, 4) for i, row in enumerate(pixels): self.assertEqual(len(row), 3) self.assertEqual(list(row), [0x55 * i] * 3)
def helperLN(self, n): """Helper for L-tests""" mask = (1 << n) - 1 # Use small chunk_limit so that multiple chunk writing is tested. w = png.Writer(15, 17, greyscale=True, bitdepth=n, chunk_limit=99) f = BytesIO() w.write_array(f, array('B', [mask & it for it in range(1, 256)])) r = png.Reader(bytes=f.getvalue()) x, y, pixels, _ = r.read() self.assertEqual(x, 15) self.assertEqual(y, 17) self.assertEqual(list(itertools.chain(*pixels)), [mask & it for it in range(1, 256)])
def testP2(self): """2-bit palette.""" a = (255, 255, 255) b = (200, 120, 120) c = (50, 99, 50) w = png.Writer(1, 4, bitdepth=2, palette=[a, b, c]) f = BytesIO() w.write_array(f, array('B', (0, 1, 1, 2))) r = png.Reader(bytes=f.getvalue()) x, y, pixels = r.asRGB8()[:3] self.assertEqual(x, 1) self.assertEqual(y, 4) self.assertEqual([list(p) for p in pixels], [list(p) for p in (a, b, b, c)])
def testFilterScanline(self): """Test filtering with previous line""" prev = array('B', [20, 21, 22, 210, 211, 212]) line = array('B', [30, 32, 34, 230, 233, 236]) filter_ = png.Filter(24, prev=prev) res = filter_.filter_all(line) # None self.assertEqual(list(res[0]), [0, 30, 32, 34, 230, 233, 236]) # sub self.assertEqual(list(res[1]), [1, 30, 32, 34, 200, 201, 202]) # up self.assertEqual(list(res[2]), [2, 10, 11, 12, 20, 22, 24]) # average self.assertEqual(list(res[3]), [3, 20, 22, 23, 110, 112, 113]) # paeth self.assertEqual(list(res[4]), [ 4, self.paeth(30, 0, 20, 0), self.paeth(32, 0, 21, 0), self.paeth(34, 0, 22, 0), self.paeth(230, 30, 210, 20), self.paeth(233, 32, 211, 21), self.paeth(236, 34, 212, 22) ])
def testFilterScanlineFirstLine(self): """Test filter without previous line""" line = array('B', [30, 31, 32, 230, 231, 232]) filter_ = png.Filter(24, prev=None) res = filter_.filter_all(line) # none self.assertEqual(list(res[0]), [0, 30, 31, 32, 230, 231, 232]) # sub self.assertEqual(list(res[1]), [1, 30, 31, 32, 200, 200, 200]) # up self.assertEqual(list(res[2]), [2, 30, 31, 32, 230, 231, 232]) # average self.assertEqual(list(res[3]), [3, 30, 31, 32, 215, 216, 216]) # paeth self.assertEqual(list(res[4]), [4, self.paeth(30, 0, 0, 0), self.paeth(31, 0, 0, 0), self.paeth(32, 0, 0, 0), self.paeth(230, 30, 0, 0), self.paeth(231, 31, 0, 0), self.paeth(232, 32, 0, 0)])
def ascii_scanlines(infile, width, height, planes, bitdepth): """ Generates boxed rows in flat pixel format, from the input file. It assumes that the input file is in a "Netpbm-like" ASCII format, and is positioned at the beginning of the first pixel. The number of pixels to read is taken from the image dimensions (`width`, `height`, `planes`) and the number of bytes per value is implied by the image `bitdepth`. """ # Values per row vpr = width * planes if bitdepth > 8: assert bitdepth == 16 typecode = 'H' else: typecode = 'B' for _ in range(height): line = read_int_tokens(infile, vpr, True) yield array(typecode, line)
def testPtrns(self): """Test colour type 3 and tRNS chunk (and 4-bit palette).""" a = (50, 99, 50, 50) b = (200, 120, 120, 80) c = (255, 255, 255) d = (200, 120, 120) e = (50, 99, 50) w = png.Writer(3, 3, bitdepth=4, palette=[a, b, c, d, e]) f = BytesIO() w.write_array(f, array('B', (4, 3, 2, 3, 2, 0, 2, 0, 1))) r = png.Reader(bytes=f.getvalue()) x, y, pixels = r.asRGBA8()[:3] self.assertEqual(x, 3) self.assertEqual(y, 3) c = c + (255, ) d = d + (255, ) e = e + (255, ) boxed = [(e, d, c), (d, c, a), (c, a, b)] flat = [itertools.chain(*row) for row in boxed] self.assertEqual([list(it) for it in pixels], [list(it) for it in flat])
def testPtrns(self): """Test colour type 3 and tRNS chunk (and 4-bit palette).""" a = (50, 99, 50, 50) b = (200, 120, 120, 80) c = (255, 255, 255) d = (200, 120, 120) e = (50, 99, 50) w = png.Writer(3, 3, bitdepth=4, palette=[a, b, c, d, e]) f = BytesIO() w.write_array(f, array('B', (4, 3, 2, 3, 2, 0, 2, 0, 1))) r = png.Reader(bytes=f.getvalue()) x, y, pixels = r.asRGBA8()[:3] self.assertEqual(x, 3) self.assertEqual(y, 3) c = c + (255,) d = d + (255,) e = e + (255,) boxed = [(e, d, c), (d, c, a), (c, a, b)] flat = [itertools.chain(*row) for row in boxed] self.assertEqual([list(it) for it in pixels], [list(it) for it in flat])
def testFilterScanlineFirstLine(self): """Test filter without previous line""" line = array('B', [30, 31, 32, 230, 231, 232]) filter_ = png.Filter(24, prev=None) res = filter_.filter_all(line) # none self.assertEqual(list(res[0]), [0, 30, 31, 32, 230, 231, 232]) # sub self.assertEqual(list(res[1]), [1, 30, 31, 32, 200, 200, 200]) # up self.assertEqual(list(res[2]), [2, 30, 31, 32, 230, 231, 232]) # average self.assertEqual(list(res[3]), [3, 30, 31, 32, 215, 216, 216]) # paeth self.assertEqual(list(res[4]), [ 4, self.paeth(30, 0, 0, 0), self.paeth(31, 0, 0, 0), self.paeth(32, 0, 0, 0), self.paeth(230, 30, 0, 0), self.paeth(231, 31, 0, 0), self.paeth(232, 32, 0, 0) ])
def line(): return array('H', struct.unpack(fmt, infile.read(row_bytes)))
def undo_filter(filter_type, line, prev): """undoing filter""" filter_ = png.Filter(24, prev=prev) line = array('B', line) return filter_.undo_filter(filter_type, line)