mirror of
				https://github.com/python-pillow/Pillow.git
				synced 2025-10-29 23:17:49 +03:00 
			
		
		
		
	Format with Black
This commit is contained in:
		
							parent
							
								
									a986fed5b4
								
							
						
					
					
						commit
						d08475442b
					
				|  | @ -4,5 +4,5 @@ from PIL import Image | |||
| import sys | ||||
| 
 | ||||
| 
 | ||||
| if sys.maxsize < 2**32: | ||||
|     im = Image.new('L', (999999, 999999), 0) | ||||
| if sys.maxsize < 2 ** 32: | ||||
|     im = Image.new("L", (999999, 999999), 0) | ||||
|  |  | |||
|  | @ -26,18 +26,21 @@ def timer(func, label, *args): | |||
|     starttime = time.time() | ||||
|     for x in range(iterations): | ||||
|         func(*args) | ||||
|         if time.time()-starttime > 10: | ||||
|             print("%s: breaking at %s iterations, %.6f per iteration" % ( | ||||
|                 label, x+1, (time.time()-starttime)/(x+1.0))) | ||||
|         if time.time() - starttime > 10: | ||||
|             print( | ||||
|                 "%s: breaking at %s iterations, %.6f per iteration" | ||||
|                 % (label, x + 1, (time.time() - starttime) / (x + 1.0)) | ||||
|             ) | ||||
|             break | ||||
|     if x == iterations-1: | ||||
|     if x == iterations - 1: | ||||
|         endtime = time.time() | ||||
|         print("%s: %.4f s  %.6f per iteration" % ( | ||||
|             label, endtime-starttime, (endtime-starttime)/(x+1.0))) | ||||
|         print( | ||||
|             "%s: %.4f s  %.6f per iteration" | ||||
|             % (label, endtime - starttime, (endtime - starttime) / (x + 1.0)) | ||||
|         ) | ||||
| 
 | ||||
| 
 | ||||
| class BenchCffiAccess(PillowTestCase): | ||||
| 
 | ||||
|     def test_direct(self): | ||||
|         im = hopper() | ||||
|         im.load() | ||||
|  | @ -48,11 +51,11 @@ class BenchCffiAccess(PillowTestCase): | |||
|         self.assertEqual(caccess[(0, 0)], access[(0, 0)]) | ||||
| 
 | ||||
|         print("Size: %sx%s" % im.size) | ||||
|         timer(iterate_get, 'PyAccess - get', im.size, access) | ||||
|         timer(iterate_set, 'PyAccess - set', im.size, access) | ||||
|         timer(iterate_get, 'C-api - get', im.size, caccess) | ||||
|         timer(iterate_set, 'C-api - set', im.size, caccess) | ||||
|         timer(iterate_get, "PyAccess - get", im.size, access) | ||||
|         timer(iterate_set, "PyAccess - set", im.size, access) | ||||
|         timer(iterate_get, "C-api - get", im.size, caccess) | ||||
|         timer(iterate_set, "C-api - set", im.size, caccess) | ||||
| 
 | ||||
| 
 | ||||
| if __name__ == '__main__': | ||||
| if __name__ == "__main__": | ||||
|     unittest.main() | ||||
|  |  | |||
|  | @ -2,6 +2,7 @@ from . import helper | |||
| import timeit | ||||
| 
 | ||||
| import sys | ||||
| 
 | ||||
| sys.path.insert(0, ".") | ||||
| 
 | ||||
| 
 | ||||
|  |  | |||
|  | @ -12,5 +12,5 @@ class TestFliOverflow(PillowTestCase): | |||
|         im.load() | ||||
| 
 | ||||
| 
 | ||||
| if __name__ == '__main__': | ||||
| if __name__ == "__main__": | ||||
|     unittest.main() | ||||
|  |  | |||
|  | @ -6,7 +6,6 @@ from PIL._util import py3 | |||
| from io import BytesIO | ||||
| 
 | ||||
| if py3: | ||||
|     Image.open(BytesIO(bytes('icns\x00\x00\x00\x10hang\x00\x00\x00\x00', | ||||
|                              'latin-1'))) | ||||
|     Image.open(BytesIO(bytes("icns\x00\x00\x00\x10hang\x00\x00\x00\x00", "latin-1"))) | ||||
| else: | ||||
|     Image.open(BytesIO(bytes('icns\x00\x00\x00\x10hang\x00\x00\x00\x00'))) | ||||
|     Image.open(BytesIO(bytes("icns\x00\x00\x00\x10hang\x00\x00\x00\x00"))) | ||||
|  |  | |||
|  | @ -9,11 +9,11 @@ min_iterations = 100 | |||
| max_iterations = 10000 | ||||
| 
 | ||||
| 
 | ||||
| @unittest.skipIf(sys.platform.startswith('win32'), "requires Unix or macOS") | ||||
| @unittest.skipIf(sys.platform.startswith("win32"), "requires Unix or macOS") | ||||
| class TestImagingLeaks(PillowTestCase): | ||||
| 
 | ||||
|     def _get_mem_usage(self): | ||||
|         from resource import getpagesize, getrusage, RUSAGE_SELF | ||||
| 
 | ||||
|         mem = getrusage(RUSAGE_SELF).ru_maxrss | ||||
|         return mem * getpagesize() / 1024 / 1024 | ||||
| 
 | ||||
|  | @ -25,20 +25,22 @@ class TestImagingLeaks(PillowTestCase): | |||
|             if i < min_iterations: | ||||
|                 mem_limit = mem + 1 | ||||
|                 continue | ||||
|             msg = 'memory usage limit exceeded after %d iterations' % (i + 1) | ||||
|             msg = "memory usage limit exceeded after %d iterations" % (i + 1) | ||||
|             self.assertLessEqual(mem, mem_limit, msg) | ||||
| 
 | ||||
|     def test_leak_putdata(self): | ||||
|         im = Image.new('RGB', (25, 25)) | ||||
|         self._test_leak(min_iterations, max_iterations, | ||||
|                         im.putdata, im.getdata()) | ||||
|         im = Image.new("RGB", (25, 25)) | ||||
|         self._test_leak(min_iterations, max_iterations, im.putdata, im.getdata()) | ||||
| 
 | ||||
|     def test_leak_getlist(self): | ||||
|         im = Image.new('P', (25, 25)) | ||||
|         self._test_leak(min_iterations, max_iterations, | ||||
|                         # Pass a new list at each iteration. | ||||
|                         lambda: im.point(range(256))) | ||||
|         im = Image.new("P", (25, 25)) | ||||
|         self._test_leak( | ||||
|             min_iterations, | ||||
|             max_iterations, | ||||
|             # Pass a new list at each iteration. | ||||
|             lambda: im.point(range(256)), | ||||
|         ) | ||||
| 
 | ||||
| 
 | ||||
| if __name__ == '__main__': | ||||
| if __name__ == "__main__": | ||||
|     unittest.main() | ||||
|  |  | |||
|  | @ -6,10 +6,16 @@ from PIL._util import py3 | |||
| from io import BytesIO | ||||
| 
 | ||||
| if py3: | ||||
|     Image.open(BytesIO(bytes( | ||||
|         '\x00\x00\x00\x0cjP\x20\x20\x0d\x0a\x87\x0a\x00\x00\x00\x00hang', | ||||
|         'latin-1'))) | ||||
|     Image.open( | ||||
|         BytesIO( | ||||
|             bytes( | ||||
|                 "\x00\x00\x00\x0cjP\x20\x20\x0d\x0a\x87\x0a\x00\x00\x00\x00hang", | ||||
|                 "latin-1", | ||||
|             ) | ||||
|         ) | ||||
|     ) | ||||
| 
 | ||||
| else: | ||||
|     Image.open(BytesIO(bytes( | ||||
|         '\x00\x00\x00\x0cjP\x20\x20\x0d\x0a\x87\x0a\x00\x00\x00\x00hang'))) | ||||
|     Image.open( | ||||
|         BytesIO(bytes("\x00\x00\x00\x0cjP\x20\x20\x0d\x0a\x87\x0a\x00\x00\x00\x00hang")) | ||||
|     ) | ||||
|  |  | |||
|  | @ -4,21 +4,22 @@ from PIL import Image | |||
| from io import BytesIO | ||||
| 
 | ||||
| # Limits for testing the leak | ||||
| mem_limit = 1024*1048576 | ||||
| stack_size = 8*1048576 | ||||
| iterations = int((mem_limit/stack_size)*2) | ||||
| mem_limit = 1024 * 1048576 | ||||
| stack_size = 8 * 1048576 | ||||
| iterations = int((mem_limit / stack_size) * 2) | ||||
| codecs = dir(Image.core) | ||||
| test_file = "Tests/images/rgb_trns_ycbc.jp2" | ||||
| 
 | ||||
| 
 | ||||
| @unittest.skipIf(sys.platform.startswith('win32'), "requires Unix or macOS") | ||||
| @unittest.skipIf(sys.platform.startswith("win32"), "requires Unix or macOS") | ||||
| class TestJpegLeaks(PillowTestCase): | ||||
|     def setUp(self): | ||||
|         if "jpeg2k_encoder" not in codecs or "jpeg2k_decoder" not in codecs: | ||||
|             self.skipTest('JPEG 2000 support not available') | ||||
|             self.skipTest("JPEG 2000 support not available") | ||||
| 
 | ||||
|     def test_leak_load(self): | ||||
|         from resource import setrlimit, RLIMIT_AS, RLIMIT_STACK | ||||
| 
 | ||||
|         setrlimit(RLIMIT_STACK, (stack_size, stack_size)) | ||||
|         setrlimit(RLIMIT_AS, (mem_limit, mem_limit)) | ||||
|         for _ in range(iterations): | ||||
|  | @ -27,6 +28,7 @@ class TestJpegLeaks(PillowTestCase): | |||
| 
 | ||||
|     def test_leak_save(self): | ||||
|         from resource import setrlimit, RLIMIT_AS, RLIMIT_STACK | ||||
| 
 | ||||
|         setrlimit(RLIMIT_STACK, (stack_size, stack_size)) | ||||
|         setrlimit(RLIMIT_AS, (mem_limit, mem_limit)) | ||||
|         for _ in range(iterations): | ||||
|  | @ -38,5 +40,5 @@ class TestJpegLeaks(PillowTestCase): | |||
|                 test_output.read() | ||||
| 
 | ||||
| 
 | ||||
| if __name__ == '__main__': | ||||
| if __name__ == "__main__": | ||||
|     unittest.main() | ||||
|  |  | |||
|  | @ -5,11 +5,11 @@ from .helper import unittest, PillowTestCase | |||
| class TestJ2kEncodeOverflow(PillowTestCase): | ||||
|     def test_j2k_overflow(self): | ||||
| 
 | ||||
|         im = Image.new('RGBA', (1024, 131584)) | ||||
|         target = self.tempfile('temp.jpc') | ||||
|         im = Image.new("RGBA", (1024, 131584)) | ||||
|         target = self.tempfile("temp.jpc") | ||||
|         with self.assertRaises(IOError): | ||||
|             im.save(target) | ||||
| 
 | ||||
| 
 | ||||
| if __name__ == '__main__': | ||||
| if __name__ == "__main__": | ||||
|     unittest.main() | ||||
|  |  | |||
|  | @ -14,7 +14,7 @@ valgrind --tool=massif python test-installed.py -s -v Tests/check_jpeg_leaks.py | |||
| """ | ||||
| 
 | ||||
| 
 | ||||
| @unittest.skipIf(sys.platform.startswith('win32'), "requires Unix or macOS") | ||||
| @unittest.skipIf(sys.platform.startswith("win32"), "requires Unix or macOS") | ||||
| class TestJpegLeaks(PillowTestCase): | ||||
| 
 | ||||
|     """ | ||||
|  | @ -74,9 +74,11 @@ post-patch: | |||
| """ | ||||
| 
 | ||||
|     def test_qtables_leak(self): | ||||
|         im = hopper('RGB') | ||||
|         im = hopper("RGB") | ||||
| 
 | ||||
|         standard_l_qtable = [int(s) for s in """ | ||||
|         standard_l_qtable = [ | ||||
|             int(s) | ||||
|             for s in """ | ||||
|             16  11  10  16  24  40  51  61 | ||||
|             12  12  14  19  26  58  60  55 | ||||
|             14  13  16  24  40  57  69  56 | ||||
|  | @ -85,9 +87,14 @@ post-patch: | |||
|             24  35  55  64  81 104 113  92 | ||||
|             49  64  78  87 103 121 120 101 | ||||
|             72  92  95  98 112 100 103  99 | ||||
|             """.split(None)] | ||||
|             """.split( | ||||
|                 None | ||||
|             ) | ||||
|         ] | ||||
| 
 | ||||
|         standard_chrominance_qtable = [int(s) for s in """ | ||||
|         standard_chrominance_qtable = [ | ||||
|             int(s) | ||||
|             for s in """ | ||||
|             17  18  24  47  99  99  99  99 | ||||
|             18  21  26  66  99  99  99  99 | ||||
|             24  26  56  99  99  99  99  99 | ||||
|  | @ -96,10 +103,12 @@ post-patch: | |||
|             99  99  99  99  99  99  99  99 | ||||
|             99  99  99  99  99  99  99  99 | ||||
|             99  99  99  99  99  99  99  99 | ||||
|             """.split(None)] | ||||
|             """.split( | ||||
|                 None | ||||
|             ) | ||||
|         ] | ||||
| 
 | ||||
|         qtables = [standard_l_qtable, | ||||
|                    standard_chrominance_qtable] | ||||
|         qtables = [standard_l_qtable, standard_chrominance_qtable] | ||||
| 
 | ||||
|         for _ in range(iterations): | ||||
|             test_output = BytesIO() | ||||
|  | @ -161,8 +170,8 @@ post patch: | |||
|      0                                                                   11.33 | ||||
| 
 | ||||
| """ | ||||
|         im = hopper('RGB') | ||||
|         exif = b'12345678'*4096 | ||||
|         im = hopper("RGB") | ||||
|         exif = b"12345678" * 4096 | ||||
| 
 | ||||
|         for _ in range(iterations): | ||||
|             test_output = BytesIO() | ||||
|  | @ -195,12 +204,12 @@ base case: | |||
|    0 +----------------------------------------------------------------------->Gi | ||||
|      0                                                                   7.882 | ||||
| """ | ||||
|         im = hopper('RGB') | ||||
|         im = hopper("RGB") | ||||
| 
 | ||||
|         for _ in range(iterations): | ||||
|             test_output = BytesIO() | ||||
|             im.save(test_output, "JPEG") | ||||
| 
 | ||||
| 
 | ||||
| if __name__ == '__main__': | ||||
| if __name__ == "__main__": | ||||
|     unittest.main() | ||||
|  |  | |||
|  | @ -22,12 +22,11 @@ YDIM = 32769 | |||
| XDIM = 48000 | ||||
| 
 | ||||
| 
 | ||||
| @unittest.skipIf(sys.maxsize <= 2**32, "requires 64-bit system") | ||||
| @unittest.skipIf(sys.maxsize <= 2 ** 32, "requires 64-bit system") | ||||
| class LargeMemoryTest(PillowTestCase): | ||||
| 
 | ||||
|     def _write_png(self, xdim, ydim): | ||||
|         f = self.tempfile('temp.png') | ||||
|         im = Image.new('L', (xdim, ydim), 0) | ||||
|         f = self.tempfile("temp.png") | ||||
|         im = Image.new("L", (xdim, ydim), 0) | ||||
|         im.save(f) | ||||
| 
 | ||||
|     def test_large(self): | ||||
|  | @ -44,5 +43,5 @@ class LargeMemoryTest(PillowTestCase): | |||
|         Image.fromarray(arr) | ||||
| 
 | ||||
| 
 | ||||
| if __name__ == '__main__': | ||||
| if __name__ == "__main__": | ||||
|     unittest.main() | ||||
|  |  | |||
|  | @ -11,6 +11,7 @@ from .helper import unittest, PillowTestCase | |||
| # Raspberry Pis). | ||||
| 
 | ||||
| from PIL import Image | ||||
| 
 | ||||
| try: | ||||
|     import numpy as np | ||||
| except ImportError: | ||||
|  | @ -20,14 +21,13 @@ YDIM = 32769 | |||
| XDIM = 48000 | ||||
| 
 | ||||
| 
 | ||||
| @unittest.skipIf(sys.maxsize <= 2**32, "requires 64-bit system") | ||||
| @unittest.skipIf(sys.maxsize <= 2 ** 32, "requires 64-bit system") | ||||
| class LargeMemoryNumpyTest(PillowTestCase): | ||||
| 
 | ||||
|     def _write_png(self, xdim, ydim): | ||||
|         dtype = np.uint8 | ||||
|         a = np.zeros((xdim, ydim), dtype=dtype) | ||||
|         f = self.tempfile('temp.png') | ||||
|         im = Image.fromarray(a, 'L') | ||||
|         f = self.tempfile("temp.png") | ||||
|         im = Image.fromarray(a, "L") | ||||
|         im.save(f) | ||||
| 
 | ||||
|     def test_large(self): | ||||
|  | @ -39,5 +39,5 @@ class LargeMemoryNumpyTest(PillowTestCase): | |||
|         self._write_png(XDIM, XDIM) | ||||
| 
 | ||||
| 
 | ||||
| if __name__ == '__main__': | ||||
| if __name__ == "__main__": | ||||
|     unittest.main() | ||||
|  |  | |||
|  | @ -15,5 +15,5 @@ class TestLibtiffSegfault(PillowTestCase): | |||
|             im.load() | ||||
| 
 | ||||
| 
 | ||||
| if __name__ == '__main__': | ||||
| if __name__ == "__main__": | ||||
|     unittest.main() | ||||
|  |  | |||
|  | @ -17,10 +17,10 @@ class TestPngDos(PillowTestCase): | |||
|             ImageFile.LOAD_TRUNCATED_IMAGES = False | ||||
| 
 | ||||
|         for s in im.text.values(): | ||||
|             self.assertLess(len(s), 1024*1024, "Text chunk larger than 1M") | ||||
|             self.assertLess(len(s), 1024 * 1024, "Text chunk larger than 1M") | ||||
| 
 | ||||
|         for s in im.info.values(): | ||||
|             self.assertLess(len(s), 1024*1024, "Text chunk larger than 1M") | ||||
|             self.assertLess(len(s), 1024 * 1024, "Text chunk larger than 1M") | ||||
| 
 | ||||
|     def test_dos_text(self): | ||||
| 
 | ||||
|  | @ -32,20 +32,20 @@ class TestPngDos(PillowTestCase): | |||
|             return | ||||
| 
 | ||||
|         for s in im.text.values(): | ||||
|             self.assertLess(len(s), 1024*1024, "Text chunk larger than 1M") | ||||
|             self.assertLess(len(s), 1024 * 1024, "Text chunk larger than 1M") | ||||
| 
 | ||||
|     def test_dos_total_memory(self): | ||||
|         im = Image.new('L', (1, 1)) | ||||
|         compressed_data = zlib.compress(b'a'*1024*1023) | ||||
|         im = Image.new("L", (1, 1)) | ||||
|         compressed_data = zlib.compress(b"a" * 1024 * 1023) | ||||
| 
 | ||||
|         info = PngImagePlugin.PngInfo() | ||||
| 
 | ||||
|         for x in range(64): | ||||
|             info.add_text('t%s' % x, compressed_data, zip=True) | ||||
|             info.add_itxt('i%s' % x, compressed_data, zip=True) | ||||
|             info.add_text("t%s" % x, compressed_data, zip=True) | ||||
|             info.add_itxt("i%s" % x, compressed_data, zip=True) | ||||
| 
 | ||||
|         b = BytesIO() | ||||
|         im.save(b, 'PNG', pnginfo=info) | ||||
|         im.save(b, "PNG", pnginfo=info) | ||||
|         b.seek(0) | ||||
| 
 | ||||
|         try: | ||||
|  | @ -57,9 +57,10 @@ class TestPngDos(PillowTestCase): | |||
|         total_len = 0 | ||||
|         for txt in im2.text.values(): | ||||
|             total_len += len(txt) | ||||
|         self.assertLess(total_len, 64*1024*1024, | ||||
|                         "Total text chunks greater than 64M") | ||||
|         self.assertLess( | ||||
|             total_len, 64 * 1024 * 1024, "Total text chunks greater than 64M" | ||||
|         ) | ||||
| 
 | ||||
| 
 | ||||
| if __name__ == '__main__': | ||||
| if __name__ == "__main__": | ||||
|     unittest.main() | ||||
|  |  | |||
							
								
								
									
										136
									
								
								Tests/helper.py
									
									
									
									
									
								
							
							
						
						
									
										136
									
								
								Tests/helper.py
									
									
									
									
									
								
							|  | @ -11,12 +11,13 @@ from PIL import Image, ImageMath | |||
| from PIL._util import py3 | ||||
| 
 | ||||
| import logging | ||||
| 
 | ||||
| logger = logging.getLogger(__name__) | ||||
| 
 | ||||
| 
 | ||||
| HAS_UPLOADER = False | ||||
| 
 | ||||
| if os.environ.get('SHOW_ERRORS', None): | ||||
| if os.environ.get("SHOW_ERRORS", None): | ||||
|     # local img.show for errors. | ||||
|     HAS_UPLOADER = True | ||||
| 
 | ||||
|  | @ -25,9 +26,12 @@ if os.environ.get('SHOW_ERRORS', None): | |||
|         def upload(self, a, b): | ||||
|             a.show() | ||||
|             b.show() | ||||
| 
 | ||||
| 
 | ||||
| else: | ||||
|     try: | ||||
|         import test_image_results | ||||
| 
 | ||||
|         HAS_UPLOADER = True | ||||
|     except ImportError: | ||||
|         pass | ||||
|  | @ -35,19 +39,18 @@ else: | |||
| 
 | ||||
| def convert_to_comparable(a, b): | ||||
|     new_a, new_b = a, b | ||||
|     if a.mode == 'P': | ||||
|         new_a = Image.new('L', a.size) | ||||
|         new_b = Image.new('L', b.size) | ||||
|     if a.mode == "P": | ||||
|         new_a = Image.new("L", a.size) | ||||
|         new_b = Image.new("L", b.size) | ||||
|         new_a.putdata(a.getdata()) | ||||
|         new_b.putdata(b.getdata()) | ||||
|     elif a.mode == 'I;16': | ||||
|         new_a = a.convert('I') | ||||
|         new_b = b.convert('I') | ||||
|     elif a.mode == "I;16": | ||||
|         new_a = a.convert("I") | ||||
|         new_b = b.convert("I") | ||||
|     return new_a, new_b | ||||
| 
 | ||||
| 
 | ||||
| class PillowTestCase(unittest.TestCase): | ||||
| 
 | ||||
|     def __init__(self, *args, **kwargs): | ||||
|         unittest.TestCase.__init__(self, *args, **kwargs) | ||||
|         # holds last result object passed to run method: | ||||
|  | @ -75,32 +78,32 @@ class PillowTestCase(unittest.TestCase): | |||
|     def assert_deep_equal(self, a, b, msg=None): | ||||
|         try: | ||||
|             self.assertEqual( | ||||
|                 len(a), len(b), | ||||
|                 msg or "got length %s, expected %s" % (len(a), len(b))) | ||||
|                 len(a), len(b), msg or "got length %s, expected %s" % (len(a), len(b)) | ||||
|             ) | ||||
|             self.assertTrue( | ||||
|                 all(x == y for x, y in zip(a, b)), | ||||
|                 msg or "got %s, expected %s" % (a, b)) | ||||
|                 all(x == y for x, y in zip(a, b)), msg or "got %s, expected %s" % (a, b) | ||||
|             ) | ||||
|         except Exception: | ||||
|             self.assertEqual(a, b, msg) | ||||
| 
 | ||||
|     def assert_image(self, im, mode, size, msg=None): | ||||
|         if mode is not None: | ||||
|             self.assertEqual( | ||||
|                 im.mode, mode, | ||||
|                 msg or "got mode %r, expected %r" % (im.mode, mode)) | ||||
|                 im.mode, mode, msg or "got mode %r, expected %r" % (im.mode, mode) | ||||
|             ) | ||||
| 
 | ||||
|         if size is not None: | ||||
|             self.assertEqual( | ||||
|                 im.size, size, | ||||
|                 msg or "got size %r, expected %r" % (im.size, size)) | ||||
|                 im.size, size, msg or "got size %r, expected %r" % (im.size, size) | ||||
|             ) | ||||
| 
 | ||||
|     def assert_image_equal(self, a, b, msg=None): | ||||
|         self.assertEqual( | ||||
|             a.mode, b.mode, | ||||
|             msg or "got mode %r, expected %r" % (a.mode, b.mode)) | ||||
|             a.mode, b.mode, msg or "got mode %r, expected %r" % (a.mode, b.mode) | ||||
|         ) | ||||
|         self.assertEqual( | ||||
|             a.size, b.size, | ||||
|             msg or "got size %r, expected %r" % (a.size, b.size)) | ||||
|             a.size, b.size, msg or "got size %r, expected %r" % (a.size, b.size) | ||||
|         ) | ||||
|         if a.tobytes() != b.tobytes(): | ||||
|             if HAS_UPLOADER: | ||||
|                 try: | ||||
|  | @ -120,26 +123,28 @@ class PillowTestCase(unittest.TestCase): | |||
|     def assert_image_similar(self, a, b, epsilon, msg=None): | ||||
|         epsilon = float(epsilon) | ||||
|         self.assertEqual( | ||||
|             a.mode, b.mode, | ||||
|             msg or "got mode %r, expected %r" % (a.mode, b.mode)) | ||||
|             a.mode, b.mode, msg or "got mode %r, expected %r" % (a.mode, b.mode) | ||||
|         ) | ||||
|         self.assertEqual( | ||||
|             a.size, b.size, | ||||
|             msg or "got size %r, expected %r" % (a.size, b.size)) | ||||
|             a.size, b.size, msg or "got size %r, expected %r" % (a.size, b.size) | ||||
|         ) | ||||
| 
 | ||||
|         a, b = convert_to_comparable(a, b) | ||||
| 
 | ||||
|         diff = 0 | ||||
|         for ach, bch in zip(a.split(), b.split()): | ||||
|             chdiff = ImageMath.eval("abs(a - b)", a=ach, b=bch).convert('L') | ||||
|             chdiff = ImageMath.eval("abs(a - b)", a=ach, b=bch).convert("L") | ||||
|             diff += sum(i * num for i, num in enumerate(chdiff.histogram())) | ||||
| 
 | ||||
|         ave_diff = float(diff)/(a.size[0]*a.size[1]) | ||||
|         ave_diff = float(diff) / (a.size[0] * a.size[1]) | ||||
|         try: | ||||
|             self.assertGreaterEqual( | ||||
|                 epsilon, ave_diff, | ||||
|                 (msg or '') + | ||||
|                 " average pixel value difference %.4f > epsilon %.4f" % ( | ||||
|                     ave_diff, epsilon)) | ||||
|                 epsilon, | ||||
|                 ave_diff, | ||||
|                 (msg or "") | ||||
|                 + " average pixel value difference %.4f > epsilon %.4f" | ||||
|                 % (ave_diff, epsilon), | ||||
|             ) | ||||
|         except Exception as e: | ||||
|             if HAS_UPLOADER: | ||||
|                 try: | ||||
|  | @ -149,8 +154,7 @@ class PillowTestCase(unittest.TestCase): | |||
|                     pass | ||||
|             raise e | ||||
| 
 | ||||
|     def assert_image_similar_tofile(self, a, filename, epsilon, msg=None, | ||||
|                                     mode=None): | ||||
|     def assert_image_similar_tofile(self, a, filename, epsilon, msg=None, mode=None): | ||||
|         with Image.open(filename) as img: | ||||
|             if mode: | ||||
|                 img = img.convert(mode) | ||||
|  | @ -168,9 +172,9 @@ class PillowTestCase(unittest.TestCase): | |||
| 
 | ||||
|             # Verify some things. | ||||
|             if warn_class is None: | ||||
|                 self.assertEqual(len(w), 0, | ||||
|                                  "Expected no warnings, got %s" % | ||||
|                                  [v.category for v in w]) | ||||
|                 self.assertEqual( | ||||
|                     len(w), 0, "Expected no warnings, got %s" % [v.category for v in w] | ||||
|                 ) | ||||
|             else: | ||||
|                 self.assertGreaterEqual(len(w), 1) | ||||
|                 found = False | ||||
|  | @ -192,27 +196,26 @@ class PillowTestCase(unittest.TestCase): | |||
| 
 | ||||
|         value = True | ||||
|         for i, target in enumerate(targets): | ||||
|             value *= (target - threshold <= actuals[i] <= target + threshold) | ||||
|             value *= target - threshold <= actuals[i] <= target + threshold | ||||
| 
 | ||||
|         self.assertTrue(value, | ||||
|                         msg + ': ' + repr(actuals) + ' != ' + repr(targets)) | ||||
|         self.assertTrue(value, msg + ": " + repr(actuals) + " != " + repr(targets)) | ||||
| 
 | ||||
|     def skipKnownBadTest(self, msg=None, platform=None, | ||||
|                          travis=None, interpreter=None): | ||||
|     def skipKnownBadTest(self, msg=None, platform=None, travis=None, interpreter=None): | ||||
|         # Skip if platform/travis matches, and | ||||
|         # PILLOW_RUN_KNOWN_BAD is not true in the environment. | ||||
|         if os.environ.get('PILLOW_RUN_KNOWN_BAD', False): | ||||
|             print(os.environ.get('PILLOW_RUN_KNOWN_BAD', False)) | ||||
|         if os.environ.get("PILLOW_RUN_KNOWN_BAD", False): | ||||
|             print(os.environ.get("PILLOW_RUN_KNOWN_BAD", False)) | ||||
|             return | ||||
| 
 | ||||
|         skip = True | ||||
|         if platform is not None: | ||||
|             skip = sys.platform.startswith(platform) | ||||
|         if travis is not None: | ||||
|             skip = skip and (travis == bool(os.environ.get('TRAVIS', False))) | ||||
|             skip = skip and (travis == bool(os.environ.get("TRAVIS", False))) | ||||
|         if interpreter is not None: | ||||
|             skip = skip and (interpreter == 'pypy' and | ||||
|                              hasattr(sys, 'pypy_version_info')) | ||||
|             skip = skip and ( | ||||
|                 interpreter == "pypy" and hasattr(sys, "pypy_version_info") | ||||
|             ) | ||||
|         if skip: | ||||
|             self.skipTest(msg or "Known Bad Test") | ||||
| 
 | ||||
|  | @ -234,7 +237,7 @@ class PillowTestCase(unittest.TestCase): | |||
|         raise IOError() | ||||
| 
 | ||||
| 
 | ||||
| @unittest.skipIf(sys.platform.startswith('win32'), "requires Unix or macOS") | ||||
| @unittest.skipIf(sys.platform.startswith("win32"), "requires Unix or macOS") | ||||
| class PillowLeakTestCase(PillowTestCase): | ||||
|     # requires unix/macOS | ||||
|     iterations = 100  # count | ||||
|  | @ -249,8 +252,9 @@ class PillowLeakTestCase(PillowTestCase): | |||
|         """ | ||||
| 
 | ||||
|         from resource import getrusage, RUSAGE_SELF | ||||
| 
 | ||||
|         mem = getrusage(RUSAGE_SELF).ru_maxrss | ||||
|         if sys.platform == 'darwin': | ||||
|         if sys.platform == "darwin": | ||||
|             # man 2 getrusage: | ||||
|             #     ru_maxrss | ||||
|             # This is the maximum resident set size utilized (in bytes). | ||||
|  | @ -266,8 +270,8 @@ class PillowLeakTestCase(PillowTestCase): | |||
|         start_mem = self._get_mem_usage() | ||||
|         for cycle in range(self.iterations): | ||||
|             core() | ||||
|             mem = (self._get_mem_usage() - start_mem) | ||||
|             msg = 'memory usage limit exceeded in iteration %d' % cycle | ||||
|             mem = self._get_mem_usage() - start_mem | ||||
|             msg = "memory usage limit exceeded in iteration %d" % cycle | ||||
|             self.assertLess(mem, self.mem_limit, msg) | ||||
| 
 | ||||
| 
 | ||||
|  | @ -281,11 +285,13 @@ if not py3: | |||
| 
 | ||||
| def fromstring(data): | ||||
|     from io import BytesIO | ||||
| 
 | ||||
|     return Image.open(BytesIO(data)) | ||||
| 
 | ||||
| 
 | ||||
| def tostring(im, string_format, **options): | ||||
|     from io import BytesIO | ||||
| 
 | ||||
|     out = BytesIO() | ||||
|     im.save(out, string_format, **options) | ||||
|     return out.getvalue() | ||||
|  | @ -318,7 +324,8 @@ def command_succeeds(cmd): | |||
|     command succeeds, or False if an OSError was raised by subprocess.Popen. | ||||
|     """ | ||||
|     import subprocess | ||||
|     with open(os.devnull, 'wb') as f: | ||||
| 
 | ||||
|     with open(os.devnull, "wb") as f: | ||||
|         try: | ||||
|             subprocess.call(cmd, stdout=f, stderr=subprocess.STDOUT) | ||||
|         except OSError: | ||||
|  | @ -327,40 +334,41 @@ def command_succeeds(cmd): | |||
| 
 | ||||
| 
 | ||||
| def djpeg_available(): | ||||
|     return command_succeeds(['djpeg', '-version']) | ||||
|     return command_succeeds(["djpeg", "-version"]) | ||||
| 
 | ||||
| 
 | ||||
| def cjpeg_available(): | ||||
|     return command_succeeds(['cjpeg', '-version']) | ||||
|     return command_succeeds(["cjpeg", "-version"]) | ||||
| 
 | ||||
| 
 | ||||
| def netpbm_available(): | ||||
|     return (command_succeeds(["ppmquant", "--version"]) and | ||||
|             command_succeeds(["ppmtogif", "--version"])) | ||||
|     return command_succeeds(["ppmquant", "--version"]) and command_succeeds( | ||||
|         ["ppmtogif", "--version"] | ||||
|     ) | ||||
| 
 | ||||
| 
 | ||||
| def imagemagick_available(): | ||||
|     return IMCONVERT and command_succeeds([IMCONVERT, '-version']) | ||||
|     return IMCONVERT and command_succeeds([IMCONVERT, "-version"]) | ||||
| 
 | ||||
| 
 | ||||
| def on_appveyor(): | ||||
|     return 'APPVEYOR' in os.environ | ||||
|     return "APPVEYOR" in os.environ | ||||
| 
 | ||||
| 
 | ||||
| if sys.platform == 'win32': | ||||
|     IMCONVERT = os.environ.get('MAGICK_HOME', '') | ||||
| if sys.platform == "win32": | ||||
|     IMCONVERT = os.environ.get("MAGICK_HOME", "") | ||||
|     if IMCONVERT: | ||||
|         IMCONVERT = os.path.join(IMCONVERT, 'convert.exe') | ||||
|         IMCONVERT = os.path.join(IMCONVERT, "convert.exe") | ||||
| else: | ||||
|     IMCONVERT = 'convert' | ||||
|     IMCONVERT = "convert" | ||||
| 
 | ||||
| 
 | ||||
| def distro(): | ||||
|     if os.path.exists('/etc/os-release'): | ||||
|         with open('/etc/os-release', 'r') as f: | ||||
|     if os.path.exists("/etc/os-release"): | ||||
|         with open("/etc/os-release", "r") as f: | ||||
|             for line in f: | ||||
|                 if 'ID=' in line: | ||||
|                     return line.strip().split('=')[1] | ||||
|                 if "ID=" in line: | ||||
|                     return line.strip().split("=")[1] | ||||
| 
 | ||||
| 
 | ||||
| class cached_property(object): | ||||
|  |  | |||
|  | @ -5,6 +5,7 @@ import os | |||
| import traceback | ||||
| 
 | ||||
| import sys | ||||
| 
 | ||||
| sys.path.insert(0, ".") | ||||
| 
 | ||||
| for file in glob.glob("src/PIL/*.py"): | ||||
|  |  | |||
|  | @ -4,21 +4,33 @@ from __future__ import print_function | |||
| 
 | ||||
| modes = [ | ||||
|     "1", | ||||
|     "L", "LA", "La", | ||||
|     "I", "I;16", "I;16L", "I;16B", "I;32L", "I;32B", | ||||
|     "L", | ||||
|     "LA", | ||||
|     "La", | ||||
|     "I", | ||||
|     "I;16", | ||||
|     "I;16L", | ||||
|     "I;16B", | ||||
|     "I;32L", | ||||
|     "I;32B", | ||||
|     "F", | ||||
|     "P", "PA", | ||||
|     "RGB", "RGBA", "RGBa", "RGBX", | ||||
|     "P", | ||||
|     "PA", | ||||
|     "RGB", | ||||
|     "RGBA", | ||||
|     "RGBa", | ||||
|     "RGBX", | ||||
|     "CMYK", | ||||
|     "YCbCr", | ||||
|     "LAB", "HSV", | ||||
|     ] | ||||
|     "LAB", | ||||
|     "HSV", | ||||
| ] | ||||
| 
 | ||||
| 
 | ||||
| def hash(s, i): | ||||
|     # djb2 hash: multiply by 33 and xor character | ||||
|     for c in s: | ||||
|         i = (((i << 5) + i) ^ ord(c)) & 0xffffffff | ||||
|         i = (((i << 5) + i) ^ ord(c)) & 0xFFFFFFFF | ||||
|     return i | ||||
| 
 | ||||
| 
 | ||||
|  |  | |||
|  | @ -5,7 +5,6 @@ import PIL.Image | |||
| 
 | ||||
| 
 | ||||
| class TestSanity(PillowTestCase): | ||||
| 
 | ||||
|     def test_sanity(self): | ||||
| 
 | ||||
|         # Make sure we have the binary extension | ||||
|  | @ -13,7 +12,7 @@ class TestSanity(PillowTestCase): | |||
| 
 | ||||
|         # Create an image and do stuff with it. | ||||
|         im = PIL.Image.new("1", (100, 100)) | ||||
|         self.assertEqual((im.mode, im.size), ('1', (100, 100))) | ||||
|         self.assertEqual((im.mode, im.size), ("1", (100, 100))) | ||||
|         self.assertEqual(len(im.tobytes()), 1300) | ||||
| 
 | ||||
|         # Create images in all remaining major modes. | ||||
|  |  | |||
|  | @ -4,21 +4,20 @@ from PIL import _binary | |||
| 
 | ||||
| 
 | ||||
| class TestBinary(PillowTestCase): | ||||
| 
 | ||||
|     def test_standard(self): | ||||
|         self.assertEqual(_binary.i8(b'*'), 42) | ||||
|         self.assertEqual(_binary.o8(42), b'*') | ||||
|         self.assertEqual(_binary.i8(b"*"), 42) | ||||
|         self.assertEqual(_binary.o8(42), b"*") | ||||
| 
 | ||||
|     def test_little_endian(self): | ||||
|         self.assertEqual(_binary.i16le(b'\xff\xff\x00\x00'), 65535) | ||||
|         self.assertEqual(_binary.i32le(b'\xff\xff\x00\x00'), 65535) | ||||
|         self.assertEqual(_binary.i16le(b"\xff\xff\x00\x00"), 65535) | ||||
|         self.assertEqual(_binary.i32le(b"\xff\xff\x00\x00"), 65535) | ||||
| 
 | ||||
|         self.assertEqual(_binary.o16le(65535), b'\xff\xff') | ||||
|         self.assertEqual(_binary.o32le(65535), b'\xff\xff\x00\x00') | ||||
|         self.assertEqual(_binary.o16le(65535), b"\xff\xff") | ||||
|         self.assertEqual(_binary.o32le(65535), b"\xff\xff\x00\x00") | ||||
| 
 | ||||
|     def test_big_endian(self): | ||||
|         self.assertEqual(_binary.i16be(b'\x00\x00\xff\xff'), 0) | ||||
|         self.assertEqual(_binary.i32be(b'\x00\x00\xff\xff'), 65535) | ||||
|         self.assertEqual(_binary.i16be(b"\x00\x00\xff\xff"), 0) | ||||
|         self.assertEqual(_binary.i32be(b"\x00\x00\xff\xff"), 65535) | ||||
| 
 | ||||
|         self.assertEqual(_binary.o16be(65535), b'\xff\xff') | ||||
|         self.assertEqual(_binary.o32be(65535), b'\x00\x00\xff\xff') | ||||
|         self.assertEqual(_binary.o16be(65535), b"\xff\xff") | ||||
|         self.assertEqual(_binary.o32be(65535), b"\x00\x00\xff\xff") | ||||
|  |  | |||
|  | @ -4,19 +4,22 @@ from .helper import PillowTestCase | |||
| from PIL import Image | ||||
| import os | ||||
| 
 | ||||
| base = os.path.join('Tests', 'images', 'bmp') | ||||
| base = os.path.join("Tests", "images", "bmp") | ||||
| 
 | ||||
| 
 | ||||
| class TestBmpReference(PillowTestCase): | ||||
| 
 | ||||
|     def get_files(self, d, ext='.bmp'): | ||||
|         return [os.path.join(base, d, f) for f | ||||
|                 in os.listdir(os.path.join(base, d)) if ext in f] | ||||
|     def get_files(self, d, ext=".bmp"): | ||||
|         return [ | ||||
|             os.path.join(base, d, f) | ||||
|             for f in os.listdir(os.path.join(base, d)) | ||||
|             if ext in f | ||||
|         ] | ||||
| 
 | ||||
|     def test_bad(self): | ||||
|         """ These shouldn't crash/dos, but they shouldn't return anything | ||||
|         either """ | ||||
|         for f in self.get_files('b'): | ||||
|         for f in self.get_files("b"): | ||||
| 
 | ||||
|             def open(f): | ||||
|                 try: | ||||
|                     im = Image.open(f) | ||||
|  | @ -41,13 +44,12 @@ class TestBmpReference(PillowTestCase): | |||
|             "pal8os2sp.bmp", | ||||
|             "rgb32bf-xbgr.bmp", | ||||
|         ] | ||||
|         for f in self.get_files('q'): | ||||
|         for f in self.get_files("q"): | ||||
|             try: | ||||
|                 im = Image.open(f) | ||||
|                 im.load() | ||||
|                 if os.path.basename(f) not in supported: | ||||
|                     print("Please add %s to the partially supported" | ||||
|                           " bmp specs." % f) | ||||
|                     print("Please add %s to the partially supported bmp specs." % f) | ||||
|             except Exception:  # as msg: | ||||
|                 if os.path.basename(f) in supported: | ||||
|                     raise | ||||
|  | @ -57,49 +59,52 @@ class TestBmpReference(PillowTestCase): | |||
|         html directory that we can compare against. """ | ||||
| 
 | ||||
|         # Target files, if they're not just replacing the extension | ||||
|         file_map = {'pal1wb.bmp': 'pal1.png', | ||||
|                     'pal4rle.bmp': 'pal4.png', | ||||
|                     'pal8-0.bmp': 'pal8.png', | ||||
|                     'pal8rle.bmp': 'pal8.png', | ||||
|                     'pal8topdown.bmp': 'pal8.png', | ||||
|                     'pal8nonsquare.bmp': 'pal8nonsquare-v.png', | ||||
|                     'pal8os2.bmp': 'pal8.png', | ||||
|                     'pal8os2sp.bmp': 'pal8.png', | ||||
|                     'pal8os2v2.bmp': 'pal8.png', | ||||
|                     'pal8os2v2-16.bmp': 'pal8.png', | ||||
|                     'pal8v4.bmp': 'pal8.png', | ||||
|                     'pal8v5.bmp': 'pal8.png', | ||||
|                     'rgb16-565pal.bmp': 'rgb16-565.png', | ||||
|                     'rgb24pal.bmp': 'rgb24.png', | ||||
|                     'rgb32.bmp': 'rgb24.png', | ||||
|                     'rgb32bf.bmp': 'rgb24.png' | ||||
|                     } | ||||
|         file_map = { | ||||
|             "pal1wb.bmp": "pal1.png", | ||||
|             "pal4rle.bmp": "pal4.png", | ||||
|             "pal8-0.bmp": "pal8.png", | ||||
|             "pal8rle.bmp": "pal8.png", | ||||
|             "pal8topdown.bmp": "pal8.png", | ||||
|             "pal8nonsquare.bmp": "pal8nonsquare-v.png", | ||||
|             "pal8os2.bmp": "pal8.png", | ||||
|             "pal8os2sp.bmp": "pal8.png", | ||||
|             "pal8os2v2.bmp": "pal8.png", | ||||
|             "pal8os2v2-16.bmp": "pal8.png", | ||||
|             "pal8v4.bmp": "pal8.png", | ||||
|             "pal8v5.bmp": "pal8.png", | ||||
|             "rgb16-565pal.bmp": "rgb16-565.png", | ||||
|             "rgb24pal.bmp": "rgb24.png", | ||||
|             "rgb32.bmp": "rgb24.png", | ||||
|             "rgb32bf.bmp": "rgb24.png", | ||||
|         } | ||||
| 
 | ||||
|         def get_compare(f): | ||||
|             name = os.path.split(f)[1] | ||||
|             if name in file_map: | ||||
|                 return os.path.join(base, 'html', file_map[name]) | ||||
|                 return os.path.join(base, "html", file_map[name]) | ||||
|             name = os.path.splitext(name)[0] | ||||
|             return os.path.join(base, 'html', "%s.png" % name) | ||||
|             return os.path.join(base, "html", "%s.png" % name) | ||||
| 
 | ||||
|         for f in self.get_files('g'): | ||||
|         for f in self.get_files("g"): | ||||
|             try: | ||||
|                 im = Image.open(f) | ||||
|                 im.load() | ||||
|                 compare = Image.open(get_compare(f)) | ||||
|                 compare.load() | ||||
|                 if im.mode == 'P': | ||||
|                 if im.mode == "P": | ||||
|                     # assert image similar doesn't really work | ||||
|                     # with paletized image, since the palette might | ||||
|                     # be differently ordered for an equivalent image. | ||||
|                     im = im.convert('RGBA') | ||||
|                     compare = im.convert('RGBA') | ||||
|                     im = im.convert("RGBA") | ||||
|                     compare = im.convert("RGBA") | ||||
|                 self.assert_image_similar(im, compare, 5) | ||||
| 
 | ||||
|             except Exception as msg: | ||||
|                 # there are three here that are unsupported: | ||||
|                 unsupported = (os.path.join(base, 'g', 'rgb32bf.bmp'), | ||||
|                                os.path.join(base, 'g', 'pal8rle.bmp'), | ||||
|                                os.path.join(base, 'g', 'pal4rle.bmp')) | ||||
|                 unsupported = ( | ||||
|                     os.path.join(base, "g", "rgb32bf.bmp"), | ||||
|                     os.path.join(base, "g", "pal8rle.bmp"), | ||||
|                     os.path.join(base, "g", "pal4rle.bmp"), | ||||
|                 ) | ||||
|                 if f not in unsupported: | ||||
|                     self.fail("Unsupported Image %s: %s" % (f, msg)) | ||||
|  |  | |||
|  | @ -4,6 +4,7 @@ from PIL import Image, ImageFilter | |||
| 
 | ||||
| 
 | ||||
| sample = Image.new("L", (7, 5)) | ||||
| # fmt: off | ||||
| sample.putdata(sum([ | ||||
|     [210, 50,  20,  10,  220, 230, 80], | ||||
|     [190, 210, 20,  180, 170, 40,  110], | ||||
|  | @ -11,10 +12,10 @@ sample.putdata(sum([ | |||
|     [220, 40,  230, 80,  130, 250, 40], | ||||
|     [250, 0,   80,  30,  60,  20,  110], | ||||
| ], [])) | ||||
| # fmt: on | ||||
| 
 | ||||
| 
 | ||||
| class TestBoxBlurApi(PillowTestCase): | ||||
| 
 | ||||
|     def test_imageops_box_blur(self): | ||||
|         i = sample.filter(ImageFilter.BoxBlur(1)) | ||||
|         self.assertEqual(i.mode, sample.mode) | ||||
|  | @ -23,7 +24,6 @@ class TestBoxBlurApi(PillowTestCase): | |||
| 
 | ||||
| 
 | ||||
| class TestBoxBlur(PillowTestCase): | ||||
| 
 | ||||
|     def box_blur(self, image, radius=1, n=1): | ||||
|         return image._new(image.im.box_blur(radius, n)) | ||||
| 
 | ||||
|  | @ -32,8 +32,7 @@ class TestBoxBlur(PillowTestCase): | |||
|         for data_row in data: | ||||
|             im_row = [next(it) for _ in range(im.size[0])] | ||||
|             if any( | ||||
|                 abs(data_v - im_v) > delta | ||||
|                 for data_v, im_v in zip(data_row, im_row) | ||||
|                 abs(data_v - im_v) > delta for data_v, im_v in zip(data_row, im_row) | ||||
|             ): | ||||
|                 self.assertEqual(im_row, data_row) | ||||
|         self.assertRaises(StopIteration, next, it) | ||||
|  | @ -41,7 +40,7 @@ class TestBoxBlur(PillowTestCase): | |||
|     def assertBlur(self, im, radius, data, passes=1, delta=0): | ||||
|         # check grayscale image | ||||
|         self.assertImage(self.box_blur(im, radius, passes), data, delta) | ||||
|         rgba = Image.merge('RGBA', (im, im, im, im)) | ||||
|         rgba = Image.merge("RGBA", (im, im, im, im)) | ||||
|         for band in self.box_blur(rgba, radius, passes).split(): | ||||
|             self.assertImage(band, data, delta) | ||||
| 
 | ||||
|  | @ -61,110 +60,135 @@ class TestBoxBlur(PillowTestCase): | |||
| 
 | ||||
|     def test_radius_0(self): | ||||
|         self.assertBlur( | ||||
|             sample, 0, | ||||
|             sample, | ||||
|             0, | ||||
|             [ | ||||
|                 # fmt: off | ||||
|                 [210, 50,  20,  10,  220, 230, 80], | ||||
|                 [190, 210, 20,  180, 170, 40,  110], | ||||
|                 [120, 210, 250, 60,  220, 0,   220], | ||||
|                 [220, 40,  230, 80,  130, 250, 40], | ||||
|                 [250, 0,   80,  30,  60,  20,  110], | ||||
|             ] | ||||
|                 # fmt: on | ||||
|             ], | ||||
|         ) | ||||
| 
 | ||||
|     def test_radius_0_02(self): | ||||
|         self.assertBlur( | ||||
|             sample, 0.02, | ||||
|             sample, | ||||
|             0.02, | ||||
|             [ | ||||
|                 # fmt: off | ||||
|                 [206, 55,  20,  17,  215, 223, 83], | ||||
|                 [189, 203, 31,  171, 169, 46,  110], | ||||
|                 [125, 206, 241, 69,  210, 13,  210], | ||||
|                 [215, 49,  221, 82,  131, 235, 48], | ||||
|                 [244, 7,   80,  32,  60,  27,  107], | ||||
|                 # fmt: on | ||||
|             ], | ||||
|             delta=2, | ||||
|         ) | ||||
| 
 | ||||
|     def test_radius_0_05(self): | ||||
|         self.assertBlur( | ||||
|             sample, 0.05, | ||||
|             sample, | ||||
|             0.05, | ||||
|             [ | ||||
|                 # fmt: off | ||||
|                 [202, 62,  22,  27,  209, 215, 88], | ||||
|                 [188, 194, 44,  161, 168, 56,  111], | ||||
|                 [131, 201, 229, 81,  198, 31,  198], | ||||
|                 [209, 62,  209, 86,  133, 216, 59], | ||||
|                 [237, 17,  80,  36,  60,  35,  103], | ||||
|                 # fmt: on | ||||
|             ], | ||||
|             delta=2, | ||||
|         ) | ||||
| 
 | ||||
|     def test_radius_0_1(self): | ||||
|         self.assertBlur( | ||||
|             sample, 0.1, | ||||
|             sample, | ||||
|             0.1, | ||||
|             [ | ||||
|                 # fmt: off | ||||
|                 [196, 72,  24,  40,  200, 203, 93], | ||||
|                 [187, 183, 62,  148, 166, 68,  111], | ||||
|                 [139, 193, 213, 96,  182, 54,  182], | ||||
|                 [201, 78,  193, 91,  133, 191, 73], | ||||
|                 [227, 31,  80,  42,  61,  47,  99], | ||||
|                 # fmt: on | ||||
|             ], | ||||
|             delta=1, | ||||
|         ) | ||||
| 
 | ||||
|     def test_radius_0_5(self): | ||||
|         self.assertBlur( | ||||
|             sample, 0.5, | ||||
|             sample, | ||||
|             0.5, | ||||
|             [ | ||||
|                 # fmt: off | ||||
|                 [176, 101, 46,  83,  163, 165, 111], | ||||
|                 [176, 149, 108, 122, 144, 120, 117], | ||||
|                 [164, 171, 159, 141, 134, 119, 129], | ||||
|                 [170, 136, 133, 114, 116, 124, 109], | ||||
|                 [184, 95,  72,  70,  69,  81,  89], | ||||
|                 # fmt: on | ||||
|             ], | ||||
|             delta=1, | ||||
|         ) | ||||
| 
 | ||||
|     def test_radius_1(self): | ||||
|         self.assertBlur( | ||||
|             sample, 1, | ||||
|             sample, | ||||
|             1, | ||||
|             [ | ||||
|                 # fmt: off | ||||
|                 [170, 109, 63,  97,  146, 153, 116], | ||||
|                 [168, 142, 112, 128, 126, 143, 121], | ||||
|                 [169, 166, 142, 149, 126, 131, 114], | ||||
|                 [159, 156, 109, 127, 94,  117, 112], | ||||
|                 [164, 128, 63,  87,  76,  89,  90], | ||||
|                 # fmt: on | ||||
|             ], | ||||
|             delta=1, | ||||
|         ) | ||||
| 
 | ||||
|     def test_radius_1_5(self): | ||||
|         self.assertBlur( | ||||
|             sample, 1.5, | ||||
|             sample, | ||||
|             1.5, | ||||
|             [ | ||||
|                 # fmt: off | ||||
|                 [155, 120, 105, 112, 124, 137, 130], | ||||
|                 [160, 136, 124, 125, 127, 134, 130], | ||||
|                 [166, 147, 130, 125, 120, 121, 119], | ||||
|                 [168, 145, 119, 109, 103, 105, 110], | ||||
|                 [168, 134, 96,  85,  85,  89,  97], | ||||
|                 # fmt: on | ||||
|             ], | ||||
|             delta=1, | ||||
|         ) | ||||
| 
 | ||||
|     def test_radius_bigger_then_half(self): | ||||
|         self.assertBlur( | ||||
|             sample, 3, | ||||
|             sample, | ||||
|             3, | ||||
|             [ | ||||
|                 # fmt: off | ||||
|                 [144, 145, 142, 128, 114, 115, 117], | ||||
|                 [148, 145, 137, 122, 109, 111, 112], | ||||
|                 [152, 145, 131, 117, 103, 107, 108], | ||||
|                 [156, 144, 126, 111, 97,  102, 103], | ||||
|                 [160, 144, 121, 106, 92,  98,  99], | ||||
|                 # fmt: on | ||||
|             ], | ||||
|             delta=1, | ||||
|         ) | ||||
| 
 | ||||
|     def test_radius_bigger_then_width(self): | ||||
|         self.assertBlur( | ||||
|             sample, 10, | ||||
|             sample, | ||||
|             10, | ||||
|             [ | ||||
|                 [158, 153, 147, 141, 135, 129, 123], | ||||
|                 [159, 153, 147, 141, 136, 130, 124], | ||||
|  | @ -177,7 +201,8 @@ class TestBoxBlur(PillowTestCase): | |||
| 
 | ||||
|     def test_extreme_large_radius(self): | ||||
|         self.assertBlur( | ||||
|             sample, 600, | ||||
|             sample, | ||||
|             600, | ||||
|             [ | ||||
|                 [162, 162, 162, 162, 162, 162, 162], | ||||
|                 [162, 162, 162, 162, 162, 162, 162], | ||||
|  | @ -190,13 +215,16 @@ class TestBoxBlur(PillowTestCase): | |||
| 
 | ||||
|     def test_two_passes(self): | ||||
|         self.assertBlur( | ||||
|             sample, 1, | ||||
|             sample, | ||||
|             1, | ||||
|             [ | ||||
|                 # fmt: off | ||||
|                 [153, 123, 102, 109, 132, 135, 129], | ||||
|                 [159, 138, 123, 121, 133, 131, 126], | ||||
|                 [162, 147, 136, 124, 127, 121, 121], | ||||
|                 [159, 140, 125, 108, 111, 106, 108], | ||||
|                 [154, 126, 105, 87,  94,  93,  97], | ||||
|                 # fmt: on | ||||
|             ], | ||||
|             passes=2, | ||||
|             delta=1, | ||||
|  | @ -204,13 +232,16 @@ class TestBoxBlur(PillowTestCase): | |||
| 
 | ||||
|     def test_three_passes(self): | ||||
|         self.assertBlur( | ||||
|             sample, 1, | ||||
|             sample, | ||||
|             1, | ||||
|             [ | ||||
|                 # fmt: off | ||||
|                 [146, 131, 116, 118, 126, 131, 130], | ||||
|                 [151, 138, 125, 123, 126, 128, 127], | ||||
|                 [154, 143, 129, 123, 120, 120, 119], | ||||
|                 [152, 139, 122, 113, 108, 108, 108], | ||||
|                 [148, 132, 112, 102, 97,  99,  100], | ||||
|                 # fmt: on | ||||
|             ], | ||||
|             passes=3, | ||||
|             delta=1, | ||||
|  |  | |||
|  | @ -20,185 +20,197 @@ class TestColorLut3DCoreAPI(PillowTestCase): | |||
| 
 | ||||
|         table = [ | ||||
|             [ | ||||
|                 r / float(size1D-1) if size1D != 1 else 0, | ||||
|                 g / float(size2D-1) if size2D != 1 else 0, | ||||
|                 b / float(size3D-1) if size3D != 1 else 0, | ||||
|                 r / float(size1D-1) if size1D != 1 else 0, | ||||
|                 g / float(size2D-1) if size2D != 1 else 0, | ||||
|                 r / float(size1D - 1) if size1D != 1 else 0, | ||||
|                 g / float(size2D - 1) if size2D != 1 else 0, | ||||
|                 b / float(size3D - 1) if size3D != 1 else 0, | ||||
|                 r / float(size1D - 1) if size1D != 1 else 0, | ||||
|                 g / float(size2D - 1) if size2D != 1 else 0, | ||||
|             ][:channels] | ||||
|             for b in range(size3D) | ||||
|             for g in range(size2D) | ||||
|             for r in range(size1D) | ||||
|         ] | ||||
|         return ( | ||||
|             channels, size1D, size2D, size3D, | ||||
|             [item for sublist in table for item in sublist]) | ||||
|             channels, | ||||
|             size1D, | ||||
|             size2D, | ||||
|             size3D, | ||||
|             [item for sublist in table for item in sublist], | ||||
|         ) | ||||
| 
 | ||||
|     def test_wrong_args(self): | ||||
|         im = Image.new('RGB', (10, 10), 0) | ||||
|         im = Image.new("RGB", (10, 10), 0) | ||||
| 
 | ||||
|         with self.assertRaisesRegex(ValueError, "filter"): | ||||
|             im.im.color_lut_3d('RGB', | ||||
|                                Image.CUBIC, | ||||
|                                *self.generate_identity_table(3, 3)) | ||||
|             im.im.color_lut_3d("RGB", Image.CUBIC, *self.generate_identity_table(3, 3)) | ||||
| 
 | ||||
|         with self.assertRaisesRegex(ValueError, "image mode"): | ||||
|             im.im.color_lut_3d('wrong', | ||||
|                                Image.LINEAR, | ||||
|                                *self.generate_identity_table(3, 3)) | ||||
|             im.im.color_lut_3d( | ||||
|                 "wrong", Image.LINEAR, *self.generate_identity_table(3, 3) | ||||
|             ) | ||||
| 
 | ||||
|         with self.assertRaisesRegex(ValueError, "table_channels"): | ||||
|             im.im.color_lut_3d('RGB', | ||||
|                                Image.LINEAR, | ||||
|                                *self.generate_identity_table(5, 3)) | ||||
|             im.im.color_lut_3d("RGB", Image.LINEAR, *self.generate_identity_table(5, 3)) | ||||
| 
 | ||||
|         with self.assertRaisesRegex(ValueError, "table_channels"): | ||||
|             im.im.color_lut_3d('RGB', | ||||
|                                Image.LINEAR, | ||||
|                                *self.generate_identity_table(1, 3)) | ||||
|             im.im.color_lut_3d("RGB", Image.LINEAR, *self.generate_identity_table(1, 3)) | ||||
| 
 | ||||
|         with self.assertRaisesRegex(ValueError, "table_channels"): | ||||
|             im.im.color_lut_3d('RGB', | ||||
|                                Image.LINEAR, | ||||
|                                *self.generate_identity_table(2, 3)) | ||||
|             im.im.color_lut_3d("RGB", Image.LINEAR, *self.generate_identity_table(2, 3)) | ||||
| 
 | ||||
|         with self.assertRaisesRegex(ValueError, "Table size"): | ||||
|             im.im.color_lut_3d('RGB', | ||||
|                                Image.LINEAR, | ||||
|                                *self.generate_identity_table(3, (1, 3, 3))) | ||||
|             im.im.color_lut_3d( | ||||
|                 "RGB", Image.LINEAR, *self.generate_identity_table(3, (1, 3, 3)) | ||||
|             ) | ||||
| 
 | ||||
|         with self.assertRaisesRegex(ValueError, "Table size"): | ||||
|             im.im.color_lut_3d('RGB', | ||||
|                                Image.LINEAR, | ||||
|                                *self.generate_identity_table(3, (66, 3, 3))) | ||||
|             im.im.color_lut_3d( | ||||
|                 "RGB", Image.LINEAR, *self.generate_identity_table(3, (66, 3, 3)) | ||||
|             ) | ||||
| 
 | ||||
|         with self.assertRaisesRegex(ValueError, r"size1D \* size2D \* size3D"): | ||||
|             im.im.color_lut_3d('RGB', | ||||
|                                Image.LINEAR, | ||||
|                                3, 2, 2, 2, [0, 0, 0] * 7) | ||||
|             im.im.color_lut_3d("RGB", Image.LINEAR, 3, 2, 2, 2, [0, 0, 0] * 7) | ||||
| 
 | ||||
|         with self.assertRaisesRegex(ValueError, r"size1D \* size2D \* size3D"): | ||||
|             im.im.color_lut_3d('RGB', | ||||
|                                Image.LINEAR, | ||||
|                                3, 2, 2, 2, [0, 0, 0] * 9) | ||||
|             im.im.color_lut_3d("RGB", Image.LINEAR, 3, 2, 2, 2, [0, 0, 0] * 9) | ||||
| 
 | ||||
|         with self.assertRaises(TypeError): | ||||
|             im.im.color_lut_3d('RGB', | ||||
|                                Image.LINEAR, | ||||
|                                3, 2, 2, 2, [0, 0, "0"] * 8) | ||||
|             im.im.color_lut_3d("RGB", Image.LINEAR, 3, 2, 2, 2, [0, 0, "0"] * 8) | ||||
| 
 | ||||
|         with self.assertRaises(TypeError): | ||||
|             im.im.color_lut_3d('RGB', | ||||
|                                Image.LINEAR, | ||||
|                                3, 2, 2, 2, 16) | ||||
|             im.im.color_lut_3d("RGB", Image.LINEAR, 3, 2, 2, 2, 16) | ||||
| 
 | ||||
|     def test_correct_args(self): | ||||
|         im = Image.new('RGB', (10, 10), 0) | ||||
|         im = Image.new("RGB", (10, 10), 0) | ||||
| 
 | ||||
|         im.im.color_lut_3d('RGB', Image.LINEAR, | ||||
|                            *self.generate_identity_table(3, 3)) | ||||
|         im.im.color_lut_3d("RGB", Image.LINEAR, *self.generate_identity_table(3, 3)) | ||||
| 
 | ||||
|         im.im.color_lut_3d('CMYK', Image.LINEAR, | ||||
|                            *self.generate_identity_table(4, 3)) | ||||
|         im.im.color_lut_3d("CMYK", Image.LINEAR, *self.generate_identity_table(4, 3)) | ||||
| 
 | ||||
|         im.im.color_lut_3d('RGB', Image.LINEAR, | ||||
|                            *self.generate_identity_table(3, (2, 3, 3))) | ||||
|         im.im.color_lut_3d( | ||||
|             "RGB", Image.LINEAR, *self.generate_identity_table(3, (2, 3, 3)) | ||||
|         ) | ||||
| 
 | ||||
|         im.im.color_lut_3d('RGB', Image.LINEAR, | ||||
|                            *self.generate_identity_table(3, (65, 3, 3))) | ||||
|         im.im.color_lut_3d( | ||||
|             "RGB", Image.LINEAR, *self.generate_identity_table(3, (65, 3, 3)) | ||||
|         ) | ||||
| 
 | ||||
|         im.im.color_lut_3d('RGB', Image.LINEAR, | ||||
|                            *self.generate_identity_table(3, (3, 65, 3))) | ||||
|         im.im.color_lut_3d( | ||||
|             "RGB", Image.LINEAR, *self.generate_identity_table(3, (3, 65, 3)) | ||||
|         ) | ||||
| 
 | ||||
|         im.im.color_lut_3d('RGB', Image.LINEAR, | ||||
|                            *self.generate_identity_table(3, (3, 3, 65))) | ||||
|         im.im.color_lut_3d( | ||||
|             "RGB", Image.LINEAR, *self.generate_identity_table(3, (3, 3, 65)) | ||||
|         ) | ||||
| 
 | ||||
|     def test_wrong_mode(self): | ||||
|         with self.assertRaisesRegex(ValueError, "wrong mode"): | ||||
|             im = Image.new('L', (10, 10), 0) | ||||
|             im.im.color_lut_3d('RGB', Image.LINEAR, | ||||
|                                *self.generate_identity_table(3, 3)) | ||||
|             im = Image.new("L", (10, 10), 0) | ||||
|             im.im.color_lut_3d("RGB", Image.LINEAR, *self.generate_identity_table(3, 3)) | ||||
| 
 | ||||
|         with self.assertRaisesRegex(ValueError, "wrong mode"): | ||||
|             im = Image.new('RGB', (10, 10), 0) | ||||
|             im.im.color_lut_3d('L', Image.LINEAR, | ||||
|                                *self.generate_identity_table(3, 3)) | ||||
|             im = Image.new("RGB", (10, 10), 0) | ||||
|             im.im.color_lut_3d("L", Image.LINEAR, *self.generate_identity_table(3, 3)) | ||||
| 
 | ||||
|         with self.assertRaisesRegex(ValueError, "wrong mode"): | ||||
|             im = Image.new('L', (10, 10), 0) | ||||
|             im.im.color_lut_3d('L', Image.LINEAR, | ||||
|                                *self.generate_identity_table(3, 3)) | ||||
|             im = Image.new("L", (10, 10), 0) | ||||
|             im.im.color_lut_3d("L", Image.LINEAR, *self.generate_identity_table(3, 3)) | ||||
| 
 | ||||
|         with self.assertRaisesRegex(ValueError, "wrong mode"): | ||||
|             im = Image.new('RGB', (10, 10), 0) | ||||
|             im.im.color_lut_3d('RGBA', Image.LINEAR, | ||||
|                                *self.generate_identity_table(3, 3)) | ||||
|             im = Image.new("RGB", (10, 10), 0) | ||||
|             im.im.color_lut_3d( | ||||
|                 "RGBA", Image.LINEAR, *self.generate_identity_table(3, 3) | ||||
|             ) | ||||
| 
 | ||||
|         with self.assertRaisesRegex(ValueError, "wrong mode"): | ||||
|             im = Image.new('RGB', (10, 10), 0) | ||||
|             im.im.color_lut_3d('RGB', Image.LINEAR, | ||||
|                                *self.generate_identity_table(4, 3)) | ||||
|             im = Image.new("RGB", (10, 10), 0) | ||||
|             im.im.color_lut_3d("RGB", Image.LINEAR, *self.generate_identity_table(4, 3)) | ||||
| 
 | ||||
|     def test_correct_mode(self): | ||||
|         im = Image.new('RGBA', (10, 10), 0) | ||||
|         im.im.color_lut_3d('RGBA', Image.LINEAR, | ||||
|                            *self.generate_identity_table(3, 3)) | ||||
|         im = Image.new("RGBA", (10, 10), 0) | ||||
|         im.im.color_lut_3d("RGBA", Image.LINEAR, *self.generate_identity_table(3, 3)) | ||||
| 
 | ||||
|         im = Image.new('RGBA', (10, 10), 0) | ||||
|         im.im.color_lut_3d('RGBA', Image.LINEAR, | ||||
|                            *self.generate_identity_table(4, 3)) | ||||
|         im = Image.new("RGBA", (10, 10), 0) | ||||
|         im.im.color_lut_3d("RGBA", Image.LINEAR, *self.generate_identity_table(4, 3)) | ||||
| 
 | ||||
|         im = Image.new('RGB', (10, 10), 0) | ||||
|         im.im.color_lut_3d('HSV', Image.LINEAR, | ||||
|                            *self.generate_identity_table(3, 3)) | ||||
|         im = Image.new("RGB", (10, 10), 0) | ||||
|         im.im.color_lut_3d("HSV", Image.LINEAR, *self.generate_identity_table(3, 3)) | ||||
| 
 | ||||
|         im = Image.new('RGB', (10, 10), 0) | ||||
|         im.im.color_lut_3d('RGBA', Image.LINEAR, | ||||
|                            *self.generate_identity_table(4, 3)) | ||||
|         im = Image.new("RGB", (10, 10), 0) | ||||
|         im.im.color_lut_3d("RGBA", Image.LINEAR, *self.generate_identity_table(4, 3)) | ||||
| 
 | ||||
|     def test_identities(self): | ||||
|         g = Image.linear_gradient('L') | ||||
|         im = Image.merge('RGB', [g, g.transpose(Image.ROTATE_90), | ||||
|                                  g.transpose(Image.ROTATE_180)]) | ||||
|         g = Image.linear_gradient("L") | ||||
|         im = Image.merge( | ||||
|             "RGB", [g, g.transpose(Image.ROTATE_90), g.transpose(Image.ROTATE_180)] | ||||
|         ) | ||||
| 
 | ||||
|         # Fast test with small cubes | ||||
|         for size in [2, 3, 5, 7, 11, 16, 17]: | ||||
|             self.assert_image_equal(im, im._new( | ||||
|                 im.im.color_lut_3d('RGB', Image.LINEAR, | ||||
|                                    *self.generate_identity_table(3, size)))) | ||||
|             self.assert_image_equal( | ||||
|                 im, | ||||
|                 im._new( | ||||
|                     im.im.color_lut_3d( | ||||
|                         "RGB", Image.LINEAR, *self.generate_identity_table(3, size) | ||||
|                     ) | ||||
|                 ), | ||||
|             ) | ||||
| 
 | ||||
|         # Not so fast | ||||
|         self.assert_image_equal(im, im._new( | ||||
|             im.im.color_lut_3d('RGB', Image.LINEAR, | ||||
|                                *self.generate_identity_table(3, (2, 2, 65))))) | ||||
|         self.assert_image_equal( | ||||
|             im, | ||||
|             im._new( | ||||
|                 im.im.color_lut_3d( | ||||
|                     "RGB", Image.LINEAR, *self.generate_identity_table(3, (2, 2, 65)) | ||||
|                 ) | ||||
|             ), | ||||
|         ) | ||||
| 
 | ||||
|     def test_identities_4_channels(self): | ||||
|         g = Image.linear_gradient('L') | ||||
|         im = Image.merge('RGB', [g, g.transpose(Image.ROTATE_90), | ||||
|                                  g.transpose(Image.ROTATE_180)]) | ||||
|         g = Image.linear_gradient("L") | ||||
|         im = Image.merge( | ||||
|             "RGB", [g, g.transpose(Image.ROTATE_90), g.transpose(Image.ROTATE_180)] | ||||
|         ) | ||||
| 
 | ||||
|         # Red channel copied to alpha | ||||
|         self.assert_image_equal( | ||||
|             Image.merge('RGBA', (im.split()*2)[:4]), | ||||
|             im._new(im.im.color_lut_3d('RGBA', Image.LINEAR, | ||||
|                                        *self.generate_identity_table(4, 17)))) | ||||
|             Image.merge("RGBA", (im.split() * 2)[:4]), | ||||
|             im._new( | ||||
|                 im.im.color_lut_3d( | ||||
|                     "RGBA", Image.LINEAR, *self.generate_identity_table(4, 17) | ||||
|                 ) | ||||
|             ), | ||||
|         ) | ||||
| 
 | ||||
|     def test_copy_alpha_channel(self): | ||||
|         g = Image.linear_gradient('L') | ||||
|         im = Image.merge('RGBA', [g, g.transpose(Image.ROTATE_90), | ||||
|                                   g.transpose(Image.ROTATE_180), | ||||
|                                   g.transpose(Image.ROTATE_270)]) | ||||
|         g = Image.linear_gradient("L") | ||||
|         im = Image.merge( | ||||
|             "RGBA", | ||||
|             [ | ||||
|                 g, | ||||
|                 g.transpose(Image.ROTATE_90), | ||||
|                 g.transpose(Image.ROTATE_180), | ||||
|                 g.transpose(Image.ROTATE_270), | ||||
|             ], | ||||
|         ) | ||||
| 
 | ||||
|         self.assert_image_equal(im, im._new( | ||||
|             im.im.color_lut_3d('RGBA', Image.LINEAR, | ||||
|                                *self.generate_identity_table(3, 17)))) | ||||
|         self.assert_image_equal( | ||||
|             im, | ||||
|             im._new( | ||||
|                 im.im.color_lut_3d( | ||||
|                     "RGBA", Image.LINEAR, *self.generate_identity_table(3, 17) | ||||
|                 ) | ||||
|             ), | ||||
|         ) | ||||
| 
 | ||||
|     def test_channels_order(self): | ||||
|         g = Image.linear_gradient('L') | ||||
|         im = Image.merge('RGB', [g, g.transpose(Image.ROTATE_90), | ||||
|                                  g.transpose(Image.ROTATE_180)]) | ||||
|         g = Image.linear_gradient("L") | ||||
|         im = Image.merge( | ||||
|             "RGB", [g, g.transpose(Image.ROTATE_90), g.transpose(Image.ROTATE_180)] | ||||
|         ) | ||||
| 
 | ||||
|         # Reverse channels by splitting and using table | ||||
|         # fmt: off | ||||
|         self.assert_image_equal( | ||||
|             Image.merge('RGB', im.split()[::-1]), | ||||
|             im._new(im.im.color_lut_3d('RGB', Image.LINEAR, | ||||
|  | @ -209,12 +221,15 @@ class TestColorLut3DCoreAPI(PillowTestCase): | |||
|                         1, 0, 0,  1, 0, 1, | ||||
|                         1, 1, 0,  1, 1, 1, | ||||
|                     ]))) | ||||
|         # fmt: on | ||||
| 
 | ||||
|     def test_overflow(self): | ||||
|         g = Image.linear_gradient('L') | ||||
|         im = Image.merge('RGB', [g, g.transpose(Image.ROTATE_90), | ||||
|                                  g.transpose(Image.ROTATE_180)]) | ||||
|         g = Image.linear_gradient("L") | ||||
|         im = Image.merge( | ||||
|             "RGB", [g, g.transpose(Image.ROTATE_90), g.transpose(Image.ROTATE_180)] | ||||
|         ) | ||||
| 
 | ||||
|         # fmt: off | ||||
|         transformed = im._new(im.im.color_lut_3d('RGB', Image.LINEAR, | ||||
|                               3, 2, 2, 2, | ||||
|                               [ | ||||
|  | @ -224,6 +239,7 @@ class TestColorLut3DCoreAPI(PillowTestCase): | |||
|                                   -1, -1,  2,   2, -1,  2, | ||||
|                                   -1,  2,  2,   2,  2,  2, | ||||
|                               ])).load() | ||||
|         # fmt: on | ||||
|         self.assertEqual(transformed[0, 0], (0, 0, 255)) | ||||
|         self.assertEqual(transformed[50, 50], (0, 0, 255)) | ||||
|         self.assertEqual(transformed[255, 0], (0, 255, 255)) | ||||
|  | @ -233,6 +249,7 @@ class TestColorLut3DCoreAPI(PillowTestCase): | |||
|         self.assertEqual(transformed[255, 255], (255, 255, 0)) | ||||
|         self.assertEqual(transformed[205, 205], (255, 255, 0)) | ||||
| 
 | ||||
|         # fmt: off | ||||
|         transformed = im._new(im.im.color_lut_3d('RGB', Image.LINEAR, | ||||
|                               3, 2, 2, 2, | ||||
|                               [ | ||||
|  | @ -242,6 +259,7 @@ class TestColorLut3DCoreAPI(PillowTestCase): | |||
|                                   -3, -3,  5,   5, -3,  5, | ||||
|                                   -3,  5,  5,   5,  5,  5, | ||||
|                               ])).load() | ||||
|         # fmt: on | ||||
|         self.assertEqual(transformed[0, 0], (0, 0, 255)) | ||||
|         self.assertEqual(transformed[50, 50], (0, 0, 255)) | ||||
|         self.assertEqual(transformed[255, 0], (0, 255, 255)) | ||||
|  | @ -286,14 +304,15 @@ class TestColorLut3DFilter(PillowTestCase): | |||
|         self.assertEqual(tuple(lut.size), (2, 2, 2)) | ||||
|         self.assertEqual(lut.name, "Color 3D LUT") | ||||
| 
 | ||||
|         # fmt: off | ||||
|         lut = ImageFilter.Color3DLUT((2, 2, 2), [ | ||||
|             (0, 1, 2), (3, 4, 5), (6, 7, 8), (9, 10, 11), | ||||
|             (12, 13, 14), (15, 16, 17), (18, 19, 20), (21, 22, 23)]) | ||||
|         # fmt: on | ||||
|         self.assertEqual(tuple(lut.size), (2, 2, 2)) | ||||
|         self.assertEqual(lut.table, list(range(24))) | ||||
| 
 | ||||
|         lut = ImageFilter.Color3DLUT((2, 2, 2), [(0, 1, 2, 3)] * 8, | ||||
|                                      channels=4) | ||||
|         lut = ImageFilter.Color3DLUT((2, 2, 2), [(0, 1, 2, 3)] * 8, channels=4) | ||||
|         self.assertEqual(tuple(lut.size), (2, 2, 2)) | ||||
|         self.assertEqual(lut.table, list(range(4)) * 8) | ||||
| 
 | ||||
|  | @ -318,7 +337,7 @@ class TestColorLut3DFilter(PillowTestCase): | |||
|         self.assertEqual(lut.table.shape, (table.size,)) | ||||
| 
 | ||||
|         # Check application | ||||
|         Image.new('RGB', (10, 10), 0).filter(lut) | ||||
|         Image.new("RGB", (10, 10), 0).filter(lut) | ||||
| 
 | ||||
|         # Check copy | ||||
|         table[0] = 33 | ||||
|  | @ -332,40 +351,34 @@ class TestColorLut3DFilter(PillowTestCase): | |||
| 
 | ||||
|     @unittest.skipIf(numpy is None, "Numpy is not installed") | ||||
|     def test_numpy_formats(self): | ||||
|         g = Image.linear_gradient('L') | ||||
|         im = Image.merge('RGB', [g, g.transpose(Image.ROTATE_90), | ||||
|                                  g.transpose(Image.ROTATE_180)]) | ||||
|         g = Image.linear_gradient("L") | ||||
|         im = Image.merge( | ||||
|             "RGB", [g, g.transpose(Image.ROTATE_90), g.transpose(Image.ROTATE_180)] | ||||
|         ) | ||||
| 
 | ||||
|         lut = ImageFilter.Color3DLUT.generate((7, 9, 11), | ||||
|                                               lambda r, g, b: (r, g, b)) | ||||
|         lut = ImageFilter.Color3DLUT.generate((7, 9, 11), lambda r, g, b: (r, g, b)) | ||||
|         lut.table = numpy.array(lut.table, dtype=numpy.float32)[:-1] | ||||
|         with self.assertRaisesRegex(ValueError, "should have table_channels"): | ||||
|             im.filter(lut) | ||||
| 
 | ||||
|         lut = ImageFilter.Color3DLUT.generate((7, 9, 11), | ||||
|                                               lambda r, g, b: (r, g, b)) | ||||
|         lut.table = (numpy.array(lut.table, dtype=numpy.float32) | ||||
|                      .reshape((7 * 9 * 11), 3)) | ||||
|         lut = ImageFilter.Color3DLUT.generate((7, 9, 11), lambda r, g, b: (r, g, b)) | ||||
|         lut.table = numpy.array(lut.table, dtype=numpy.float32).reshape((7 * 9 * 11), 3) | ||||
|         with self.assertRaisesRegex(ValueError, "should have table_channels"): | ||||
|             im.filter(lut) | ||||
| 
 | ||||
|         lut = ImageFilter.Color3DLUT.generate((7, 9, 11), | ||||
|                                               lambda r, g, b: (r, g, b)) | ||||
|         lut = ImageFilter.Color3DLUT.generate((7, 9, 11), lambda r, g, b: (r, g, b)) | ||||
|         lut.table = numpy.array(lut.table, dtype=numpy.float16) | ||||
|         self.assert_image_equal(im, im.filter(lut)) | ||||
| 
 | ||||
|         lut = ImageFilter.Color3DLUT.generate((7, 9, 11), | ||||
|                                               lambda r, g, b: (r, g, b)) | ||||
|         lut = ImageFilter.Color3DLUT.generate((7, 9, 11), lambda r, g, b: (r, g, b)) | ||||
|         lut.table = numpy.array(lut.table, dtype=numpy.float32) | ||||
|         self.assert_image_equal(im, im.filter(lut)) | ||||
| 
 | ||||
|         lut = ImageFilter.Color3DLUT.generate((7, 9, 11), | ||||
|                                               lambda r, g, b: (r, g, b)) | ||||
|         lut = ImageFilter.Color3DLUT.generate((7, 9, 11), lambda r, g, b: (r, g, b)) | ||||
|         lut.table = numpy.array(lut.table, dtype=numpy.float64) | ||||
|         self.assert_image_equal(im, im.filter(lut)) | ||||
| 
 | ||||
|         lut = ImageFilter.Color3DLUT.generate((7, 9, 11), | ||||
|                                               lambda r, g, b: (r, g, b)) | ||||
|         lut = ImageFilter.Color3DLUT.generate((7, 9, 11), lambda r, g, b: (r, g, b)) | ||||
|         lut.table = numpy.array(lut.table, dtype=numpy.int32) | ||||
|         im.filter(lut) | ||||
|         lut.table = numpy.array(lut.table, dtype=numpy.int8) | ||||
|  | @ -373,54 +386,65 @@ class TestColorLut3DFilter(PillowTestCase): | |||
| 
 | ||||
|     def test_repr(self): | ||||
|         lut = ImageFilter.Color3DLUT(2, [0, 1, 2] * 8) | ||||
|         self.assertEqual(repr(lut), | ||||
|                          "<Color3DLUT from list size=2x2x2 channels=3>") | ||||
|         self.assertEqual(repr(lut), "<Color3DLUT from list size=2x2x2 channels=3>") | ||||
| 
 | ||||
|         lut = ImageFilter.Color3DLUT( | ||||
|             (3, 4, 5), array('f', [0, 0, 0, 0] * (3 * 4 * 5)), | ||||
|             channels=4, target_mode='YCbCr', _copy_table=False) | ||||
|             (3, 4, 5), | ||||
|             array("f", [0, 0, 0, 0] * (3 * 4 * 5)), | ||||
|             channels=4, | ||||
|             target_mode="YCbCr", | ||||
|             _copy_table=False, | ||||
|         ) | ||||
|         self.assertEqual( | ||||
|             repr(lut), | ||||
|             "<Color3DLUT from array size=3x4x5 channels=4 target_mode=YCbCr>") | ||||
|             repr(lut), "<Color3DLUT from array size=3x4x5 channels=4 target_mode=YCbCr>" | ||||
|         ) | ||||
| 
 | ||||
| 
 | ||||
| class TestGenerateColorLut3D(PillowTestCase): | ||||
|     def test_wrong_channels_count(self): | ||||
|         with self.assertRaisesRegex(ValueError, "3 or 4 output channels"): | ||||
|             ImageFilter.Color3DLUT.generate( | ||||
|                 5, channels=2, callback=lambda r, g, b: (r, g, b)) | ||||
|                 5, channels=2, callback=lambda r, g, b: (r, g, b) | ||||
|             ) | ||||
| 
 | ||||
|         with self.assertRaisesRegex(ValueError, "should have either channels"): | ||||
|             ImageFilter.Color3DLUT.generate(5, lambda r, g, b: (r, g, b, r)) | ||||
| 
 | ||||
|         with self.assertRaisesRegex(ValueError, "should have either channels"): | ||||
|             ImageFilter.Color3DLUT.generate( | ||||
|                 5, channels=4, callback=lambda r, g, b: (r, g, b)) | ||||
|                 5, channels=4, callback=lambda r, g, b: (r, g, b) | ||||
|             ) | ||||
| 
 | ||||
|     def test_3_channels(self): | ||||
|         lut = ImageFilter.Color3DLUT.generate(5, lambda r, g, b: (r, g, b)) | ||||
|         self.assertEqual(tuple(lut.size), (5, 5, 5)) | ||||
|         self.assertEqual(lut.name, "Color 3D LUT") | ||||
|         # fmt: off | ||||
|         self.assertEqual(lut.table[:24], [ | ||||
|             0.0, 0.0, 0.0,  0.25, 0.0, 0.0,  0.5, 0.0, 0.0,  0.75, 0.0, 0.0, | ||||
|             1.0, 0.0, 0.0,  0.0, 0.25, 0.0,  0.25, 0.25, 0.0,  0.5, 0.25, 0.0]) | ||||
|         # fmt: on | ||||
| 
 | ||||
|     def test_4_channels(self): | ||||
|         lut = ImageFilter.Color3DLUT.generate( | ||||
|             5, channels=4, callback=lambda r, g, b: (b, r, g, (r+g+b) / 2)) | ||||
|             5, channels=4, callback=lambda r, g, b: (b, r, g, (r + g + b) / 2) | ||||
|         ) | ||||
|         self.assertEqual(tuple(lut.size), (5, 5, 5)) | ||||
|         self.assertEqual(lut.name, "Color 3D LUT") | ||||
|         # fmt: off | ||||
|         self.assertEqual(lut.table[:24], [ | ||||
|             0.0, 0.0, 0.0, 0.0,  0.0, 0.25, 0.0, 0.125,  0.0, 0.5, 0.0, 0.25, | ||||
|             0.0, 0.75, 0.0, 0.375,  0.0, 1.0, 0.0, 0.5,  0.0, 0.0, 0.25, 0.125 | ||||
|         ]) | ||||
|         # fmt: on | ||||
| 
 | ||||
|     def test_apply(self): | ||||
|         lut = ImageFilter.Color3DLUT.generate(5, lambda r, g, b: (r, g, b)) | ||||
| 
 | ||||
|         g = Image.linear_gradient('L') | ||||
|         im = Image.merge('RGB', [g, g.transpose(Image.ROTATE_90), | ||||
|                                  g.transpose(Image.ROTATE_180)]) | ||||
|         g = Image.linear_gradient("L") | ||||
|         im = Image.merge( | ||||
|             "RGB", [g, g.transpose(Image.ROTATE_90), g.transpose(Image.ROTATE_180)] | ||||
|         ) | ||||
|         self.assertEqual(im, im.filter(lut)) | ||||
| 
 | ||||
| 
 | ||||
|  | @ -442,80 +466,96 @@ class TestTransformColorLut3D(PillowTestCase): | |||
| 
 | ||||
|     def test_target_mode(self): | ||||
|         source = ImageFilter.Color3DLUT.generate( | ||||
|             2, lambda r, g, b: (r, g, b), target_mode='HSV') | ||||
|             2, lambda r, g, b: (r, g, b), target_mode="HSV" | ||||
|         ) | ||||
| 
 | ||||
|         lut = source.transform(lambda r, g, b: (r, g, b)) | ||||
|         self.assertEqual(lut.mode, 'HSV') | ||||
|         self.assertEqual(lut.mode, "HSV") | ||||
| 
 | ||||
|         lut = source.transform(lambda r, g, b: (r, g, b), target_mode='RGB') | ||||
|         self.assertEqual(lut.mode, 'RGB') | ||||
|         lut = source.transform(lambda r, g, b: (r, g, b), target_mode="RGB") | ||||
|         self.assertEqual(lut.mode, "RGB") | ||||
| 
 | ||||
|     def test_3_to_3_channels(self): | ||||
|         source = ImageFilter.Color3DLUT.generate( | ||||
|             (3, 4, 5), lambda r, g, b: (r, g, b)) | ||||
|         lut = source.transform(lambda r, g, b: (r*r, g*g, b*b)) | ||||
|         source = ImageFilter.Color3DLUT.generate((3, 4, 5), lambda r, g, b: (r, g, b)) | ||||
|         lut = source.transform(lambda r, g, b: (r * r, g * g, b * b)) | ||||
|         self.assertEqual(tuple(lut.size), tuple(source.size)) | ||||
|         self.assertEqual(len(lut.table), len(source.table)) | ||||
|         self.assertNotEqual(lut.table, source.table) | ||||
|         self.assertEqual(lut.table[0:10], [ | ||||
|             0.0, 0.0, 0.0, 0.25, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0]) | ||||
|         self.assertEqual( | ||||
|             lut.table[0:10], [0.0, 0.0, 0.0, 0.25, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0] | ||||
|         ) | ||||
| 
 | ||||
|     def test_3_to_4_channels(self): | ||||
|         source = ImageFilter.Color3DLUT.generate( | ||||
|             (6, 5, 4), lambda r, g, b: (r, g, b)) | ||||
|         lut = source.transform(lambda r, g, b: (r*r, g*g, b*b, 1), channels=4) | ||||
|         source = ImageFilter.Color3DLUT.generate((6, 5, 4), lambda r, g, b: (r, g, b)) | ||||
|         lut = source.transform(lambda r, g, b: (r * r, g * g, b * b, 1), channels=4) | ||||
|         self.assertEqual(tuple(lut.size), tuple(source.size)) | ||||
|         self.assertNotEqual(len(lut.table), len(source.table)) | ||||
|         self.assertNotEqual(lut.table, source.table) | ||||
|         # fmt: off | ||||
|         self.assertEqual(lut.table[0:16], [ | ||||
|             0.0, 0.0, 0.0, 1,  0.2**2, 0.0, 0.0, 1, | ||||
|             0.4**2, 0.0, 0.0, 1,  0.6**2, 0.0, 0.0, 1]) | ||||
|         # fmt: on | ||||
| 
 | ||||
|     def test_4_to_3_channels(self): | ||||
|         source = ImageFilter.Color3DLUT.generate( | ||||
|             (3, 6, 5), lambda r, g, b: (r, g, b, 1), channels=4) | ||||
|         lut = source.transform(lambda r, g, b, a: (a - r*r, a - g*g, a - b*b), | ||||
|                                channels=3) | ||||
|             (3, 6, 5), lambda r, g, b: (r, g, b, 1), channels=4 | ||||
|         ) | ||||
|         lut = source.transform( | ||||
|             lambda r, g, b, a: (a - r * r, a - g * g, a - b * b), channels=3 | ||||
|         ) | ||||
|         self.assertEqual(tuple(lut.size), tuple(source.size)) | ||||
|         self.assertNotEqual(len(lut.table), len(source.table)) | ||||
|         self.assertNotEqual(lut.table, source.table) | ||||
|         # fmt: off | ||||
|         self.assertEqual(lut.table[0:18], [ | ||||
|             1.0, 1.0, 1.0,  0.75, 1.0, 1.0,  0.0, 1.0, 1.0, | ||||
|             1.0, 0.96, 1.0,  0.75, 0.96, 1.0,  0.0, 0.96, 1.0]) | ||||
|         # fmt: on | ||||
| 
 | ||||
|     def test_4_to_4_channels(self): | ||||
|         source = ImageFilter.Color3DLUT.generate( | ||||
|             (6, 5, 4), lambda r, g, b: (r, g, b, 1), channels=4) | ||||
|         lut = source.transform(lambda r, g, b, a: (r*r, g*g, b*b, a - 0.5)) | ||||
|             (6, 5, 4), lambda r, g, b: (r, g, b, 1), channels=4 | ||||
|         ) | ||||
|         lut = source.transform(lambda r, g, b, a: (r * r, g * g, b * b, a - 0.5)) | ||||
|         self.assertEqual(tuple(lut.size), tuple(source.size)) | ||||
|         self.assertEqual(len(lut.table), len(source.table)) | ||||
|         self.assertNotEqual(lut.table, source.table) | ||||
|         # fmt: off | ||||
|         self.assertEqual(lut.table[0:16], [ | ||||
|             0.0, 0.0, 0.0, 0.5,  0.2**2, 0.0, 0.0, 0.5, | ||||
|             0.4**2, 0.0, 0.0, 0.5,  0.6**2, 0.0, 0.0, 0.5]) | ||||
|         # fmt: on | ||||
| 
 | ||||
|     def test_with_normals_3_channels(self): | ||||
|         source = ImageFilter.Color3DLUT.generate( | ||||
|             (6, 5, 4), lambda r, g, b: (r*r, g*g, b*b)) | ||||
|             (6, 5, 4), lambda r, g, b: (r * r, g * g, b * b) | ||||
|         ) | ||||
|         lut = source.transform( | ||||
|             lambda nr, ng, nb, r, g, b: (nr - r, ng - g, nb - b), | ||||
|             with_normals=True) | ||||
|             lambda nr, ng, nb, r, g, b: (nr - r, ng - g, nb - b), with_normals=True | ||||
|         ) | ||||
|         self.assertEqual(tuple(lut.size), tuple(source.size)) | ||||
|         self.assertEqual(len(lut.table), len(source.table)) | ||||
|         self.assertNotEqual(lut.table, source.table) | ||||
|         # fmt: off | ||||
|         self.assertEqual(lut.table[0:18], [ | ||||
|             0.0, 0.0, 0.0,  0.16, 0.0, 0.0,  0.24, 0.0, 0.0, | ||||
|             0.24, 0.0, 0.0,  0.8 - (0.8**2), 0, 0,  0, 0, 0]) | ||||
|         # fmt: on | ||||
| 
 | ||||
|     def test_with_normals_4_channels(self): | ||||
|         source = ImageFilter.Color3DLUT.generate( | ||||
|             (3, 6, 5), lambda r, g, b: (r*r, g*g, b*b, 1), channels=4) | ||||
|             (3, 6, 5), lambda r, g, b: (r * r, g * g, b * b, 1), channels=4 | ||||
|         ) | ||||
|         lut = source.transform( | ||||
|             lambda nr, ng, nb, r, g, b, a: (nr - r, ng - g, nb - b, a-0.5), | ||||
|             with_normals=True) | ||||
|             lambda nr, ng, nb, r, g, b, a: (nr - r, ng - g, nb - b, a - 0.5), | ||||
|             with_normals=True, | ||||
|         ) | ||||
|         self.assertEqual(tuple(lut.size), tuple(source.size)) | ||||
|         self.assertEqual(len(lut.table), len(source.table)) | ||||
|         self.assertNotEqual(lut.table, source.table) | ||||
|         # fmt: off | ||||
|         self.assertEqual(lut.table[0:16], [ | ||||
|             0.0, 0.0, 0.0, 0.5,  0.25, 0.0, 0.0, 0.5, | ||||
|             0.0, 0.0, 0.0, 0.5,  0.0, 0.16, 0.0, 0.5]) | ||||
|         # fmt: on | ||||
|  |  | |||
|  | @ -6,39 +6,39 @@ from .helper import unittest, PillowTestCase | |||
| from PIL import Image | ||||
| 
 | ||||
| 
 | ||||
| is_pypy = hasattr(sys, 'pypy_version_info') | ||||
| is_pypy = hasattr(sys, "pypy_version_info") | ||||
| 
 | ||||
| 
 | ||||
| class TestCoreStats(PillowTestCase): | ||||
|     def test_get_stats(self): | ||||
|         # Create at least one image | ||||
|         Image.new('RGB', (10, 10)) | ||||
|         Image.new("RGB", (10, 10)) | ||||
| 
 | ||||
|         stats = Image.core.get_stats() | ||||
|         self.assertIn('new_count', stats) | ||||
|         self.assertIn('reused_blocks', stats) | ||||
|         self.assertIn('freed_blocks', stats) | ||||
|         self.assertIn('allocated_blocks', stats) | ||||
|         self.assertIn('reallocated_blocks', stats) | ||||
|         self.assertIn('blocks_cached', stats) | ||||
|         self.assertIn("new_count", stats) | ||||
|         self.assertIn("reused_blocks", stats) | ||||
|         self.assertIn("freed_blocks", stats) | ||||
|         self.assertIn("allocated_blocks", stats) | ||||
|         self.assertIn("reallocated_blocks", stats) | ||||
|         self.assertIn("blocks_cached", stats) | ||||
| 
 | ||||
|     def test_reset_stats(self): | ||||
|         Image.core.reset_stats() | ||||
| 
 | ||||
|         stats = Image.core.get_stats() | ||||
|         self.assertEqual(stats['new_count'], 0) | ||||
|         self.assertEqual(stats['reused_blocks'], 0) | ||||
|         self.assertEqual(stats['freed_blocks'], 0) | ||||
|         self.assertEqual(stats['allocated_blocks'], 0) | ||||
|         self.assertEqual(stats['reallocated_blocks'], 0) | ||||
|         self.assertEqual(stats['blocks_cached'], 0) | ||||
|         self.assertEqual(stats["new_count"], 0) | ||||
|         self.assertEqual(stats["reused_blocks"], 0) | ||||
|         self.assertEqual(stats["freed_blocks"], 0) | ||||
|         self.assertEqual(stats["allocated_blocks"], 0) | ||||
|         self.assertEqual(stats["reallocated_blocks"], 0) | ||||
|         self.assertEqual(stats["blocks_cached"], 0) | ||||
| 
 | ||||
| 
 | ||||
| class TestCoreMemory(PillowTestCase): | ||||
|     def tearDown(self): | ||||
|         # Restore default values | ||||
|         Image.core.set_alignment(1) | ||||
|         Image.core.set_block_size(1024*1024) | ||||
|         Image.core.set_block_size(1024 * 1024) | ||||
|         Image.core.set_blocks_max(0) | ||||
|         Image.core.clear_cache() | ||||
| 
 | ||||
|  | @ -54,7 +54,7 @@ class TestCoreMemory(PillowTestCase): | |||
|             self.assertEqual(alignment, i) | ||||
| 
 | ||||
|             # Try to construct new image | ||||
|             Image.new('RGB', (10, 10)) | ||||
|             Image.new("RGB", (10, 10)) | ||||
| 
 | ||||
|         self.assertRaises(ValueError, Image.core.set_alignment, 0) | ||||
|         self.assertRaises(ValueError, Image.core.set_alignment, -1) | ||||
|  | @ -66,13 +66,13 @@ class TestCoreMemory(PillowTestCase): | |||
|         self.assertGreaterEqual(block_size, 4096) | ||||
| 
 | ||||
|     def test_set_block_size(self): | ||||
|         for i in [4096, 2*4096, 3*4096]: | ||||
|         for i in [4096, 2 * 4096, 3 * 4096]: | ||||
|             Image.core.set_block_size(i) | ||||
|             block_size = Image.core.get_block_size() | ||||
|             self.assertEqual(block_size, i) | ||||
| 
 | ||||
|             # Try to construct new image | ||||
|             Image.new('RGB', (10, 10)) | ||||
|             Image.new("RGB", (10, 10)) | ||||
| 
 | ||||
|         self.assertRaises(ValueError, Image.core.set_block_size, 0) | ||||
|         self.assertRaises(ValueError, Image.core.set_block_size, -1) | ||||
|  | @ -82,13 +82,13 @@ class TestCoreMemory(PillowTestCase): | |||
|         Image.core.reset_stats() | ||||
|         Image.core.set_blocks_max(0) | ||||
|         Image.core.set_block_size(4096) | ||||
|         Image.new('RGB', (256, 256)) | ||||
|         Image.new("RGB", (256, 256)) | ||||
| 
 | ||||
|         stats = Image.core.get_stats() | ||||
|         self.assertGreaterEqual(stats['new_count'], 1) | ||||
|         self.assertGreaterEqual(stats['allocated_blocks'], 64) | ||||
|         self.assertGreaterEqual(stats["new_count"], 1) | ||||
|         self.assertGreaterEqual(stats["allocated_blocks"], 64) | ||||
|         if not is_pypy: | ||||
|             self.assertGreaterEqual(stats['freed_blocks'], 64) | ||||
|             self.assertGreaterEqual(stats["freed_blocks"], 64) | ||||
| 
 | ||||
|     def test_get_blocks_max(self): | ||||
|         blocks_max = Image.core.get_blocks_max() | ||||
|  | @ -102,7 +102,7 @@ class TestCoreMemory(PillowTestCase): | |||
|             self.assertEqual(blocks_max, i) | ||||
| 
 | ||||
|             # Try to construct new image | ||||
|             Image.new('RGB', (10, 10)) | ||||
|             Image.new("RGB", (10, 10)) | ||||
| 
 | ||||
|         self.assertRaises(ValueError, Image.core.set_blocks_max, -1) | ||||
| 
 | ||||
|  | @ -111,15 +111,15 @@ class TestCoreMemory(PillowTestCase): | |||
|         Image.core.reset_stats() | ||||
|         Image.core.set_blocks_max(128) | ||||
|         Image.core.set_block_size(4096) | ||||
|         Image.new('RGB', (256, 256)) | ||||
|         Image.new('RGB', (256, 256)) | ||||
|         Image.new("RGB", (256, 256)) | ||||
|         Image.new("RGB", (256, 256)) | ||||
| 
 | ||||
|         stats = Image.core.get_stats() | ||||
|         self.assertGreaterEqual(stats['new_count'], 2) | ||||
|         self.assertGreaterEqual(stats['allocated_blocks'], 64) | ||||
|         self.assertGreaterEqual(stats['reused_blocks'], 64) | ||||
|         self.assertEqual(stats['freed_blocks'], 0) | ||||
|         self.assertEqual(stats['blocks_cached'], 64) | ||||
|         self.assertGreaterEqual(stats["new_count"], 2) | ||||
|         self.assertGreaterEqual(stats["allocated_blocks"], 64) | ||||
|         self.assertGreaterEqual(stats["reused_blocks"], 64) | ||||
|         self.assertEqual(stats["freed_blocks"], 0) | ||||
|         self.assertEqual(stats["blocks_cached"], 64) | ||||
| 
 | ||||
|     @unittest.skipIf(is_pypy, "images are not collected") | ||||
|     def test_clear_cache_stats(self): | ||||
|  | @ -127,55 +127,55 @@ class TestCoreMemory(PillowTestCase): | |||
|         Image.core.clear_cache() | ||||
|         Image.core.set_blocks_max(128) | ||||
|         Image.core.set_block_size(4096) | ||||
|         Image.new('RGB', (256, 256)) | ||||
|         Image.new('RGB', (256, 256)) | ||||
|         Image.new("RGB", (256, 256)) | ||||
|         Image.new("RGB", (256, 256)) | ||||
|         # Keep 16 blocks in cache | ||||
|         Image.core.clear_cache(16) | ||||
| 
 | ||||
|         stats = Image.core.get_stats() | ||||
|         self.assertGreaterEqual(stats['new_count'], 2) | ||||
|         self.assertGreaterEqual(stats['allocated_blocks'], 64) | ||||
|         self.assertGreaterEqual(stats['reused_blocks'], 64) | ||||
|         self.assertGreaterEqual(stats['freed_blocks'], 48) | ||||
|         self.assertEqual(stats['blocks_cached'], 16) | ||||
|         self.assertGreaterEqual(stats["new_count"], 2) | ||||
|         self.assertGreaterEqual(stats["allocated_blocks"], 64) | ||||
|         self.assertGreaterEqual(stats["reused_blocks"], 64) | ||||
|         self.assertGreaterEqual(stats["freed_blocks"], 48) | ||||
|         self.assertEqual(stats["blocks_cached"], 16) | ||||
| 
 | ||||
|     def test_large_images(self): | ||||
|         Image.core.reset_stats() | ||||
|         Image.core.set_blocks_max(0) | ||||
|         Image.core.set_block_size(4096) | ||||
|         Image.new('RGB', (2048, 16)) | ||||
|         Image.new("RGB", (2048, 16)) | ||||
|         Image.core.clear_cache() | ||||
| 
 | ||||
|         stats = Image.core.get_stats() | ||||
|         self.assertGreaterEqual(stats['new_count'], 1) | ||||
|         self.assertGreaterEqual(stats['allocated_blocks'], 16) | ||||
|         self.assertGreaterEqual(stats['reused_blocks'], 0) | ||||
|         self.assertEqual(stats['blocks_cached'], 0) | ||||
|         self.assertGreaterEqual(stats["new_count"], 1) | ||||
|         self.assertGreaterEqual(stats["allocated_blocks"], 16) | ||||
|         self.assertGreaterEqual(stats["reused_blocks"], 0) | ||||
|         self.assertEqual(stats["blocks_cached"], 0) | ||||
|         if not is_pypy: | ||||
|             self.assertGreaterEqual(stats['freed_blocks'], 16) | ||||
|             self.assertGreaterEqual(stats["freed_blocks"], 16) | ||||
| 
 | ||||
| 
 | ||||
| class TestEnvVars(PillowTestCase): | ||||
|     def tearDown(self): | ||||
|         # Restore default values | ||||
|         Image.core.set_alignment(1) | ||||
|         Image.core.set_block_size(1024*1024) | ||||
|         Image.core.set_block_size(1024 * 1024) | ||||
|         Image.core.set_blocks_max(0) | ||||
|         Image.core.clear_cache() | ||||
| 
 | ||||
|     def test_units(self): | ||||
|         Image._apply_env_variables({'PILLOW_BLOCKS_MAX': '2K'}) | ||||
|         self.assertEqual(Image.core.get_blocks_max(), 2*1024) | ||||
|         Image._apply_env_variables({'PILLOW_BLOCK_SIZE': '2m'}) | ||||
|         self.assertEqual(Image.core.get_block_size(), 2*1024*1024) | ||||
|         Image._apply_env_variables({"PILLOW_BLOCKS_MAX": "2K"}) | ||||
|         self.assertEqual(Image.core.get_blocks_max(), 2 * 1024) | ||||
|         Image._apply_env_variables({"PILLOW_BLOCK_SIZE": "2m"}) | ||||
|         self.assertEqual(Image.core.get_block_size(), 2 * 1024 * 1024) | ||||
| 
 | ||||
|     def test_warnings(self): | ||||
|         self.assert_warning( | ||||
|             UserWarning, Image._apply_env_variables, | ||||
|             {'PILLOW_ALIGNMENT': '15'}) | ||||
|             UserWarning, Image._apply_env_variables, {"PILLOW_ALIGNMENT": "15"} | ||||
|         ) | ||||
|         self.assert_warning( | ||||
|             UserWarning, Image._apply_env_variables, | ||||
|             {'PILLOW_BLOCK_SIZE': '1024'}) | ||||
|             UserWarning, Image._apply_env_variables, {"PILLOW_BLOCK_SIZE": "1024"} | ||||
|         ) | ||||
|         self.assert_warning( | ||||
|             UserWarning, Image._apply_env_variables, | ||||
|             {'PILLOW_BLOCKS_MAX': 'wat'}) | ||||
|             UserWarning, Image._apply_env_variables, {"PILLOW_BLOCKS_MAX": "wat"} | ||||
|         ) | ||||
|  |  | |||
|  | @ -8,7 +8,6 @@ ORIGINAL_LIMIT = Image.MAX_IMAGE_PIXELS | |||
| 
 | ||||
| 
 | ||||
| class TestDecompressionBomb(PillowTestCase): | ||||
| 
 | ||||
|     def tearDown(self): | ||||
|         Image.MAX_IMAGE_PIXELS = ORIGINAL_LIMIT | ||||
| 
 | ||||
|  | @ -33,20 +32,17 @@ class TestDecompressionBomb(PillowTestCase): | |||
|         Image.MAX_IMAGE_PIXELS = 128 * 128 - 1 | ||||
|         self.assertEqual(Image.MAX_IMAGE_PIXELS, 128 * 128 - 1) | ||||
| 
 | ||||
|         self.assert_warning(Image.DecompressionBombWarning, | ||||
|                             Image.open, TEST_FILE) | ||||
|         self.assert_warning(Image.DecompressionBombWarning, Image.open, TEST_FILE) | ||||
| 
 | ||||
|     def test_exception(self): | ||||
|         # Set limit to trigger exception on the test file | ||||
|         Image.MAX_IMAGE_PIXELS = 64 * 128 - 1 | ||||
|         self.assertEqual(Image.MAX_IMAGE_PIXELS, 64 * 128 - 1) | ||||
| 
 | ||||
|         self.assertRaises(Image.DecompressionBombError, | ||||
|                           lambda: Image.open(TEST_FILE)) | ||||
|         self.assertRaises(Image.DecompressionBombError, lambda: Image.open(TEST_FILE)) | ||||
| 
 | ||||
| 
 | ||||
| class TestDecompressionCrop(PillowTestCase): | ||||
| 
 | ||||
|     def setUp(self): | ||||
|         self.src = hopper() | ||||
|         Image.MAX_IMAGE_PIXELS = self.src.height * self.src.width * 4 - 1 | ||||
|  | @ -58,21 +54,17 @@ class TestDecompressionCrop(PillowTestCase): | |||
|         # Crops can extend the extents, therefore we should have the | ||||
|         # same decompression bomb warnings on them. | ||||
|         box = (0, 0, self.src.width * 2, self.src.height * 2) | ||||
|         self.assert_warning(Image.DecompressionBombWarning, | ||||
|                             self.src.crop, box) | ||||
|         self.assert_warning(Image.DecompressionBombWarning, self.src.crop, box) | ||||
| 
 | ||||
|     def test_crop_decompression_checks(self): | ||||
| 
 | ||||
|         im = Image.new("RGB", (100, 100)) | ||||
| 
 | ||||
|         good_values = ((-9999, -9999, -9990, -9990), | ||||
|                        (-999, -999, -990, -990)) | ||||
|         good_values = ((-9999, -9999, -9990, -9990), (-999, -999, -990, -990)) | ||||
| 
 | ||||
|         warning_values = ((-160, -160, 99, 99), | ||||
|                           (160, 160, -99, -99)) | ||||
|         warning_values = ((-160, -160, 99, 99), (160, 160, -99, -99)) | ||||
| 
 | ||||
|         error_values = ((-99909, -99990, 99999, 99999), | ||||
|                         (99909, 99990, -99999, -99999)) | ||||
|         error_values = ((-99909, -99990, 99999, 99999), (99909, 99990, -99999, -99999)) | ||||
| 
 | ||||
|         for value in good_values: | ||||
|             self.assertEqual(im.crop(value).size, (9, 9)) | ||||
|  |  | |||
|  | @ -4,41 +4,36 @@ from PIL import features | |||
| 
 | ||||
| try: | ||||
|     from PIL import _webp | ||||
| 
 | ||||
|     HAVE_WEBP = True | ||||
| except ImportError: | ||||
|     HAVE_WEBP = False | ||||
| 
 | ||||
| 
 | ||||
| class TestFeatures(PillowTestCase): | ||||
| 
 | ||||
|     def test_check(self): | ||||
|         # Check the correctness of the convenience function | ||||
|         for module in features.modules: | ||||
|             self.assertEqual(features.check_module(module), | ||||
|                              features.check(module)) | ||||
|             self.assertEqual(features.check_module(module), features.check(module)) | ||||
|         for codec in features.codecs: | ||||
|             self.assertEqual(features.check_codec(codec), | ||||
|                              features.check(codec)) | ||||
|             self.assertEqual(features.check_codec(codec), features.check(codec)) | ||||
|         for feature in features.features: | ||||
|             self.assertEqual(features.check_feature(feature), | ||||
|                              features.check(feature)) | ||||
|             self.assertEqual(features.check_feature(feature), features.check(feature)) | ||||
| 
 | ||||
|     @unittest.skipUnless(HAVE_WEBP, "WebP not available") | ||||
|     def test_webp_transparency(self): | ||||
|         self.assertEqual(features.check('transp_webp'), | ||||
|                          not _webp.WebPDecoderBuggyAlpha()) | ||||
|         self.assertEqual(features.check('transp_webp'), | ||||
|                          _webp.HAVE_TRANSPARENCY) | ||||
|         self.assertEqual( | ||||
|             features.check("transp_webp"), not _webp.WebPDecoderBuggyAlpha() | ||||
|         ) | ||||
|         self.assertEqual(features.check("transp_webp"), _webp.HAVE_TRANSPARENCY) | ||||
| 
 | ||||
|     @unittest.skipUnless(HAVE_WEBP, "WebP not available") | ||||
|     def test_webp_mux(self): | ||||
|         self.assertEqual(features.check('webp_mux'), | ||||
|                          _webp.HAVE_WEBPMUX) | ||||
|         self.assertEqual(features.check("webp_mux"), _webp.HAVE_WEBPMUX) | ||||
| 
 | ||||
|     @unittest.skipUnless(HAVE_WEBP, "WebP not available") | ||||
|     def test_webp_anim(self): | ||||
|         self.assertEqual(features.check('webp_anim'), | ||||
|                          _webp.HAVE_WEBPANIM) | ||||
|         self.assertEqual(features.check("webp_anim"), _webp.HAVE_WEBPANIM) | ||||
| 
 | ||||
|     def test_check_modules(self): | ||||
|         for feature in features.modules: | ||||
|  |  | |||
|  | @ -5,11 +5,10 @@ import io | |||
| 
 | ||||
| 
 | ||||
| class TestFileBmp(PillowTestCase): | ||||
| 
 | ||||
|     def roundtrip(self, im): | ||||
|         outfile = self.tempfile("temp.bmp") | ||||
| 
 | ||||
|         im.save(outfile, 'BMP') | ||||
|         im.save(outfile, "BMP") | ||||
| 
 | ||||
|         reloaded = Image.open(outfile) | ||||
|         reloaded.load() | ||||
|  | @ -28,8 +27,7 @@ class TestFileBmp(PillowTestCase): | |||
| 
 | ||||
|     def test_invalid_file(self): | ||||
|         with open("Tests/images/flower.jpg", "rb") as fp: | ||||
|             self.assertRaises(SyntaxError, | ||||
|                               BmpImagePlugin.BmpImageFile, fp) | ||||
|             self.assertRaises(SyntaxError, BmpImagePlugin.BmpImageFile, fp) | ||||
| 
 | ||||
|     def test_save_to_bytes(self): | ||||
|         output = io.BytesIO() | ||||
|  | @ -62,27 +60,27 @@ class TestFileBmp(PillowTestCase): | |||
|         im = Image.open("Tests/images/hopper.bmp") | ||||
| 
 | ||||
|         # Act | ||||
|         im.save(outfile, 'JPEG', dpi=im.info['dpi']) | ||||
|         im.save(outfile, "JPEG", dpi=im.info["dpi"]) | ||||
| 
 | ||||
|         # Assert | ||||
|         reloaded = Image.open(outfile) | ||||
|         reloaded.load() | ||||
|         self.assertEqual(im.info['dpi'], reloaded.info['dpi']) | ||||
|         self.assertEqual(im.info["dpi"], reloaded.info["dpi"]) | ||||
|         self.assertEqual(im.size, reloaded.size) | ||||
|         self.assertEqual(reloaded.format, "JPEG") | ||||
| 
 | ||||
|     def test_load_dpi_rounding(self): | ||||
|         # Round up | ||||
|         im = Image.open('Tests/images/hopper.bmp') | ||||
|         im = Image.open("Tests/images/hopper.bmp") | ||||
|         self.assertEqual(im.info["dpi"], (96, 96)) | ||||
| 
 | ||||
|         # Round down | ||||
|         im = Image.open('Tests/images/hopper_roundDown.bmp') | ||||
|         im = Image.open("Tests/images/hopper_roundDown.bmp") | ||||
|         self.assertEqual(im.info["dpi"], (72, 72)) | ||||
| 
 | ||||
|     def test_save_dpi_rounding(self): | ||||
|         outfile = self.tempfile("temp.bmp") | ||||
|         im = Image.open('Tests/images/hopper.bmp') | ||||
|         im = Image.open("Tests/images/hopper.bmp") | ||||
| 
 | ||||
|         im.save(outfile, dpi=(72.2, 72.2)) | ||||
|         reloaded = Image.open(outfile) | ||||
|  | @ -94,17 +92,17 @@ class TestFileBmp(PillowTestCase): | |||
| 
 | ||||
|     def test_load_dib(self): | ||||
|         # test for #1293, Imagegrab returning Unsupported Bitfields Format | ||||
|         im = Image.open('Tests/images/clipboard.dib') | ||||
|         im = Image.open("Tests/images/clipboard.dib") | ||||
|         self.assertEqual(im.format, "DIB") | ||||
|         self.assertEqual(im.get_format_mimetype(), "image/bmp") | ||||
| 
 | ||||
|         target = Image.open('Tests/images/clipboard_target.png') | ||||
|         target = Image.open("Tests/images/clipboard_target.png") | ||||
|         self.assert_image_equal(im, target) | ||||
| 
 | ||||
|     def test_save_dib(self): | ||||
|         outfile = self.tempfile("temp.dib") | ||||
| 
 | ||||
|         im = Image.open('Tests/images/clipboard.dib') | ||||
|         im = Image.open("Tests/images/clipboard.dib") | ||||
|         im.save(outfile) | ||||
| 
 | ||||
|         reloaded = Image.open(outfile) | ||||
|  |  | |||
|  | @ -6,7 +6,6 @@ TEST_FILE = "Tests/images/gfs.t06z.rassda.tm00.bufr_d" | |||
| 
 | ||||
| 
 | ||||
| class TestFileBufrStub(PillowTestCase): | ||||
| 
 | ||||
|     def test_open(self): | ||||
|         # Act | ||||
|         im = Image.open(TEST_FILE) | ||||
|  | @ -23,8 +22,9 @@ class TestFileBufrStub(PillowTestCase): | |||
|         invalid_file = "Tests/images/flower.jpg" | ||||
| 
 | ||||
|         # Act / Assert | ||||
|         self.assertRaises(SyntaxError, | ||||
|                           BufrStubImagePlugin.BufrStubImageFile, invalid_file) | ||||
|         self.assertRaises( | ||||
|             SyntaxError, BufrStubImagePlugin.BufrStubImageFile, invalid_file | ||||
|         ) | ||||
| 
 | ||||
|     def test_load(self): | ||||
|         # Arrange | ||||
|  |  | |||
|  | @ -7,7 +7,6 @@ TEST_FILE = "Tests/images/dummy.container" | |||
| 
 | ||||
| 
 | ||||
| class TestFileContainer(PillowTestCase): | ||||
| 
 | ||||
|     def test_sanity(self): | ||||
|         dir(Image) | ||||
|         dir(ContainerIO) | ||||
|  | @ -106,14 +105,16 @@ class TestFileContainer(PillowTestCase): | |||
| 
 | ||||
|     def test_readlines(self): | ||||
|         # Arrange | ||||
|         expected = ["This is line 1\n", | ||||
|                     "This is line 2\n", | ||||
|                     "This is line 3\n", | ||||
|                     "This is line 4\n", | ||||
|                     "This is line 5\n", | ||||
|                     "This is line 6\n", | ||||
|                     "This is line 7\n", | ||||
|                     "This is line 8\n"] | ||||
|         expected = [ | ||||
|             "This is line 1\n", | ||||
|             "This is line 2\n", | ||||
|             "This is line 3\n", | ||||
|             "This is line 4\n", | ||||
|             "This is line 5\n", | ||||
|             "This is line 6\n", | ||||
|             "This is line 7\n", | ||||
|             "This is line 8\n", | ||||
|         ] | ||||
|         with open(TEST_FILE) as fh: | ||||
|             container = ContainerIO.ContainerIO(fh, 0, 120) | ||||
| 
 | ||||
|  |  | |||
|  | @ -6,7 +6,6 @@ TEST_FILE = "Tests/images/deerstalker.cur" | |||
| 
 | ||||
| 
 | ||||
| class TestFileCur(PillowTestCase): | ||||
| 
 | ||||
|     def test_sanity(self): | ||||
|         im = Image.open(TEST_FILE) | ||||
| 
 | ||||
|  | @ -20,8 +19,7 @@ class TestFileCur(PillowTestCase): | |||
|     def test_invalid_file(self): | ||||
|         invalid_file = "Tests/images/flower.jpg" | ||||
| 
 | ||||
|         self.assertRaises(SyntaxError, | ||||
|                           CurImagePlugin.CurImageFile, invalid_file) | ||||
|         self.assertRaises(SyntaxError, CurImagePlugin.CurImageFile, invalid_file) | ||||
| 
 | ||||
|         no_cursors_file = "Tests/images/no_cursors.cur" | ||||
| 
 | ||||
|  |  | |||
|  | @ -7,7 +7,6 @@ TEST_FILE = "Tests/images/hopper.dcx" | |||
| 
 | ||||
| 
 | ||||
| class TestFileDcx(PillowTestCase): | ||||
| 
 | ||||
|     def test_sanity(self): | ||||
|         # Arrange | ||||
| 
 | ||||
|  | @ -24,12 +23,12 @@ class TestFileDcx(PillowTestCase): | |||
|         def open(): | ||||
|             im = Image.open(TEST_FILE) | ||||
|             im.load() | ||||
| 
 | ||||
|         self.assert_warning(None, open) | ||||
| 
 | ||||
|     def test_invalid_file(self): | ||||
|         with open("Tests/images/flower.jpg", "rb") as fp: | ||||
|             self.assertRaises(SyntaxError, | ||||
|                               DcxImagePlugin.DcxImageFile, fp) | ||||
|             self.assertRaises(SyntaxError, DcxImagePlugin.DcxImageFile, fp) | ||||
| 
 | ||||
|     def test_tell(self): | ||||
|         # Arrange | ||||
|  | @ -55,7 +54,7 @@ class TestFileDcx(PillowTestCase): | |||
|         self.assertLess(im.tell(), n_frames) | ||||
| 
 | ||||
|         # Test that seeking to the last frame does not raise an error | ||||
|         im.seek(n_frames-1) | ||||
|         im.seek(n_frames - 1) | ||||
| 
 | ||||
|     def test_seek_too_far(self): | ||||
|         # Arrange | ||||
|  |  | |||
|  | @ -15,7 +15,7 @@ class TestFileDds(PillowTestCase): | |||
| 
 | ||||
|     def test_sanity_dxt1(self): | ||||
|         """Check DXT1 images can be opened""" | ||||
|         target = Image.open(TEST_FILE_DXT1.replace('.dds', '.png')) | ||||
|         target = Image.open(TEST_FILE_DXT1.replace(".dds", ".png")) | ||||
| 
 | ||||
|         im = Image.open(TEST_FILE_DXT1) | ||||
|         im.load() | ||||
|  | @ -24,12 +24,12 @@ class TestFileDds(PillowTestCase): | |||
|         self.assertEqual(im.mode, "RGBA") | ||||
|         self.assertEqual(im.size, (256, 256)) | ||||
| 
 | ||||
|         self.assert_image_equal(target.convert('RGBA'), im) | ||||
|         self.assert_image_equal(target.convert("RGBA"), im) | ||||
| 
 | ||||
|     def test_sanity_dxt5(self): | ||||
|         """Check DXT5 images can be opened""" | ||||
| 
 | ||||
|         target = Image.open(TEST_FILE_DXT5.replace('.dds', '.png')) | ||||
|         target = Image.open(TEST_FILE_DXT5.replace(".dds", ".png")) | ||||
| 
 | ||||
|         im = Image.open(TEST_FILE_DXT5) | ||||
|         im.load() | ||||
|  | @ -43,7 +43,7 @@ class TestFileDds(PillowTestCase): | |||
|     def test_sanity_dxt3(self): | ||||
|         """Check DXT3 images can be opened""" | ||||
| 
 | ||||
|         target = Image.open(TEST_FILE_DXT3.replace('.dds', '.png')) | ||||
|         target = Image.open(TEST_FILE_DXT3.replace(".dds", ".png")) | ||||
| 
 | ||||
|         im = Image.open(TEST_FILE_DXT3) | ||||
|         im.load() | ||||
|  | @ -57,7 +57,7 @@ class TestFileDds(PillowTestCase): | |||
|     def test_dx10_bc7(self): | ||||
|         """Check DX10 images can be opened""" | ||||
| 
 | ||||
|         target = Image.open(TEST_FILE_DX10_BC7.replace('.dds', '.png')) | ||||
|         target = Image.open(TEST_FILE_DX10_BC7.replace(".dds", ".png")) | ||||
| 
 | ||||
|         im = Image.open(TEST_FILE_DX10_BC7) | ||||
|         im.load() | ||||
|  | @ -69,13 +69,16 @@ class TestFileDds(PillowTestCase): | |||
|         self.assert_image_equal(target, im) | ||||
| 
 | ||||
|     def test_unimplemented_dxgi_format(self): | ||||
|         self.assertRaises(NotImplementedError, Image.open, | ||||
|                           "Tests/images/unimplemented_dxgi_format.dds") | ||||
|         self.assertRaises( | ||||
|             NotImplementedError, | ||||
|             Image.open, | ||||
|             "Tests/images/unimplemented_dxgi_format.dds", | ||||
|         ) | ||||
| 
 | ||||
|     def test_uncompressed_rgb(self): | ||||
|         """Check uncompressed RGB images can be opened""" | ||||
| 
 | ||||
|         target = Image.open(TEST_FILE_UNCOMPRESSED_RGB.replace('.dds', '.png')) | ||||
|         target = Image.open(TEST_FILE_UNCOMPRESSED_RGB.replace(".dds", ".png")) | ||||
| 
 | ||||
|         im = Image.open(TEST_FILE_UNCOMPRESSED_RGB) | ||||
|         im.load() | ||||
|  | @ -110,7 +113,7 @@ class TestFileDds(PillowTestCase): | |||
| 
 | ||||
|     def test_short_header(self): | ||||
|         """ Check a short header""" | ||||
|         with open(TEST_FILE_DXT5, 'rb') as f: | ||||
|         with open(TEST_FILE_DXT5, "rb") as f: | ||||
|             img_file = f.read() | ||||
| 
 | ||||
|         def short_header(): | ||||
|  | @ -121,7 +124,7 @@ class TestFileDds(PillowTestCase): | |||
|     def test_short_file(self): | ||||
|         """ Check that the appropriate error is thrown for a short file""" | ||||
| 
 | ||||
|         with open(TEST_FILE_DXT5, 'rb') as f: | ||||
|         with open(TEST_FILE_DXT5, "rb") as f: | ||||
|             img_file = f.read() | ||||
| 
 | ||||
|         def short_file(): | ||||
|  | @ -131,5 +134,8 @@ class TestFileDds(PillowTestCase): | |||
|         self.assertRaises(IOError, short_file) | ||||
| 
 | ||||
|     def test_unimplemented_pixel_format(self): | ||||
|         self.assertRaises(NotImplementedError, Image.open, | ||||
|                           "Tests/images/unimplemented_pixel_format.dds") | ||||
|         self.assertRaises( | ||||
|             NotImplementedError, | ||||
|             Image.open, | ||||
|             "Tests/images/unimplemented_pixel_format.dds", | ||||
|         ) | ||||
|  |  | |||
|  | @ -21,7 +21,6 @@ file3 = "Tests/images/binary_preview_map.eps" | |||
| 
 | ||||
| 
 | ||||
| class TestFileEps(PillowTestCase): | ||||
| 
 | ||||
|     @unittest.skipUnless(HAS_GHOSTSCRIPT, "Ghostscript not available") | ||||
|     def test_sanity(self): | ||||
|         # Regular scale | ||||
|  | @ -53,8 +52,7 @@ class TestFileEps(PillowTestCase): | |||
|     def test_invalid_file(self): | ||||
|         invalid_file = "Tests/images/flower.jpg" | ||||
| 
 | ||||
|         self.assertRaises(SyntaxError, | ||||
|                           EpsImagePlugin.EpsImageFile, invalid_file) | ||||
|         self.assertRaises(SyntaxError, EpsImagePlugin.EpsImageFile, invalid_file) | ||||
| 
 | ||||
|     @unittest.skipUnless(HAS_GHOSTSCRIPT, "Ghostscript not available") | ||||
|     def test_cmyk(self): | ||||
|  | @ -67,8 +65,8 @@ class TestFileEps(PillowTestCase): | |||
|         cmyk_image.load() | ||||
|         self.assertEqual(cmyk_image.mode, "RGB") | ||||
| 
 | ||||
|         if 'jpeg_decoder' in dir(Image.core): | ||||
|             target = Image.open('Tests/images/pil_sample_rgb.jpg') | ||||
|         if "jpeg_decoder" in dir(Image.core): | ||||
|             target = Image.open("Tests/images/pil_sample_rgb.jpg") | ||||
|             self.assert_image_similar(cmyk_image, target, 10) | ||||
| 
 | ||||
|     @unittest.skipUnless(HAS_GHOSTSCRIPT, "Ghostscript not available") | ||||
|  | @ -86,19 +84,19 @@ class TestFileEps(PillowTestCase): | |||
|     def test_file_object(self): | ||||
|         # issue 479 | ||||
|         image1 = Image.open(file1) | ||||
|         with open(self.tempfile('temp_file.eps'), 'wb') as fh: | ||||
|             image1.save(fh, 'EPS') | ||||
|         with open(self.tempfile("temp_file.eps"), "wb") as fh: | ||||
|             image1.save(fh, "EPS") | ||||
| 
 | ||||
|     @unittest.skipUnless(HAS_GHOSTSCRIPT, "Ghostscript not available") | ||||
|     def test_iobase_object(self): | ||||
|         # issue 479 | ||||
|         image1 = Image.open(file1) | ||||
|         with io.open(self.tempfile('temp_iobase.eps'), 'wb') as fh: | ||||
|             image1.save(fh, 'EPS') | ||||
|         with io.open(self.tempfile("temp_iobase.eps"), "wb") as fh: | ||||
|             image1.save(fh, "EPS") | ||||
| 
 | ||||
|     @unittest.skipUnless(HAS_GHOSTSCRIPT, "Ghostscript not available") | ||||
|     def test_bytesio_object(self): | ||||
|         with open(file1, 'rb') as f: | ||||
|         with open(file1, "rb") as f: | ||||
|             img_bytes = io.BytesIO(f.read()) | ||||
| 
 | ||||
|         img = Image.open(img_bytes) | ||||
|  | @ -110,7 +108,7 @@ class TestFileEps(PillowTestCase): | |||
| 
 | ||||
|     def test_image_mode_not_supported(self): | ||||
|         im = hopper("RGBA") | ||||
|         tmpfile = self.tempfile('temp.eps') | ||||
|         tmpfile = self.tempfile("temp.eps") | ||||
|         self.assertRaises(ValueError, im.save, tmpfile) | ||||
| 
 | ||||
|     @unittest.skipUnless(HAS_GHOSTSCRIPT, "Ghostscript not available") | ||||
|  | @ -195,33 +193,33 @@ class TestFileEps(PillowTestCase): | |||
|         Image.open(file3) | ||||
| 
 | ||||
|     def _test_readline(self, t, ending): | ||||
|         ending = "Failure with line ending: %s" % ("".join( | ||||
|                                                    "%s" % ord(s) | ||||
|                                                    for s in ending)) | ||||
|         self.assertEqual(t.readline().strip('\r\n'), 'something', ending) | ||||
|         self.assertEqual(t.readline().strip('\r\n'), 'else', ending) | ||||
|         self.assertEqual(t.readline().strip('\r\n'), 'baz', ending) | ||||
|         self.assertEqual(t.readline().strip('\r\n'), 'bif', ending) | ||||
|         ending = "Failure with line ending: %s" % ( | ||||
|             "".join("%s" % ord(s) for s in ending) | ||||
|         ) | ||||
|         self.assertEqual(t.readline().strip("\r\n"), "something", ending) | ||||
|         self.assertEqual(t.readline().strip("\r\n"), "else", ending) | ||||
|         self.assertEqual(t.readline().strip("\r\n"), "baz", ending) | ||||
|         self.assertEqual(t.readline().strip("\r\n"), "bif", ending) | ||||
| 
 | ||||
|     def _test_readline_io_psfile(self, test_string, ending): | ||||
|         f = io.BytesIO(test_string.encode('latin-1')) | ||||
|         f = io.BytesIO(test_string.encode("latin-1")) | ||||
|         t = EpsImagePlugin.PSFile(f) | ||||
|         self._test_readline(t, ending) | ||||
| 
 | ||||
|     def _test_readline_file_psfile(self, test_string, ending): | ||||
|         f = self.tempfile('temp.txt') | ||||
|         with open(f, 'wb') as w: | ||||
|             w.write(test_string.encode('latin-1')) | ||||
|         f = self.tempfile("temp.txt") | ||||
|         with open(f, "wb") as w: | ||||
|             w.write(test_string.encode("latin-1")) | ||||
| 
 | ||||
|         with open(f, 'rb') as r: | ||||
|         with open(f, "rb") as r: | ||||
|             t = EpsImagePlugin.PSFile(r) | ||||
|             self._test_readline(t, ending) | ||||
| 
 | ||||
|     def test_readline(self): | ||||
|         # check all the freaking line endings possible from the spec | ||||
|         # test_string = u'something\r\nelse\n\rbaz\rbif\n' | ||||
|         line_endings = ['\r\n', '\n', '\n\r', '\r'] | ||||
|         strings = ['something', 'else', 'baz', 'bif'] | ||||
|         line_endings = ["\r\n", "\n", "\n\r", "\r"] | ||||
|         strings = ["something", "else", "baz", "bif"] | ||||
| 
 | ||||
|         for ending in line_endings: | ||||
|             s = ending.join(strings) | ||||
|  | @ -231,10 +229,12 @@ class TestFileEps(PillowTestCase): | |||
|     def test_open_eps(self): | ||||
|         # https://github.com/python-pillow/Pillow/issues/1104 | ||||
|         # Arrange | ||||
|         FILES = ["Tests/images/illu10_no_preview.eps", | ||||
|                  "Tests/images/illu10_preview.eps", | ||||
|                  "Tests/images/illuCS6_no_preview.eps", | ||||
|                  "Tests/images/illuCS6_preview.eps"] | ||||
|         FILES = [ | ||||
|             "Tests/images/illu10_no_preview.eps", | ||||
|             "Tests/images/illu10_preview.eps", | ||||
|             "Tests/images/illuCS6_no_preview.eps", | ||||
|             "Tests/images/illuCS6_preview.eps", | ||||
|         ] | ||||
| 
 | ||||
|         # Act / Assert | ||||
|         for filename in FILES: | ||||
|  |  | |||
|  | @ -6,7 +6,6 @@ TEST_FILE = "Tests/images/hopper.fits" | |||
| 
 | ||||
| 
 | ||||
| class TestFileFitsStub(PillowTestCase): | ||||
| 
 | ||||
|     def test_open(self): | ||||
|         # Act | ||||
|         im = Image.open(TEST_FILE) | ||||
|  | @ -23,8 +22,9 @@ class TestFileFitsStub(PillowTestCase): | |||
|         invalid_file = "Tests/images/flower.jpg" | ||||
| 
 | ||||
|         # Act / Assert | ||||
|         self.assertRaises(SyntaxError, | ||||
|                           FitsStubImagePlugin.FITSStubImageFile, invalid_file) | ||||
|         self.assertRaises( | ||||
|             SyntaxError, FitsStubImagePlugin.FITSStubImageFile, invalid_file | ||||
|         ) | ||||
| 
 | ||||
|     def test_load(self): | ||||
|         # Arrange | ||||
|  | @ -42,5 +42,5 @@ class TestFileFitsStub(PillowTestCase): | |||
|         # Act / Assert: stub cannot save without an implemented handler | ||||
|         self.assertRaises(IOError, im.save, dummy_filename) | ||||
|         self.assertRaises( | ||||
|             IOError, | ||||
|             FitsStubImagePlugin._save, im, dummy_fp, dummy_filename) | ||||
|             IOError, FitsStubImagePlugin._save, im, dummy_fp, dummy_filename | ||||
|         ) | ||||
|  |  | |||
|  | @ -11,7 +11,6 @@ animated_test_file = "Tests/images/a.fli" | |||
| 
 | ||||
| 
 | ||||
| class TestFileFli(PillowTestCase): | ||||
| 
 | ||||
|     def test_sanity(self): | ||||
|         im = Image.open(static_test_file) | ||||
|         im.load() | ||||
|  | @ -31,6 +30,7 @@ class TestFileFli(PillowTestCase): | |||
|         def open(): | ||||
|             im = Image.open(static_test_file) | ||||
|             im.load() | ||||
| 
 | ||||
|         self.assert_warning(None, open) | ||||
| 
 | ||||
|     def test_tell(self): | ||||
|  | @ -46,8 +46,7 @@ class TestFileFli(PillowTestCase): | |||
|     def test_invalid_file(self): | ||||
|         invalid_file = "Tests/images/flower.jpg" | ||||
| 
 | ||||
|         self.assertRaises(SyntaxError, | ||||
|                           FliImagePlugin.FliImageFile, invalid_file) | ||||
|         self.assertRaises(SyntaxError, FliImagePlugin.FliImageFile, invalid_file) | ||||
| 
 | ||||
|     def test_n_frames(self): | ||||
|         im = Image.open(static_test_file) | ||||
|  | @ -67,7 +66,7 @@ class TestFileFli(PillowTestCase): | |||
|         self.assertLess(im.tell(), n_frames) | ||||
| 
 | ||||
|         # Test that seeking to the last frame does not raise an error | ||||
|         im.seek(n_frames-1) | ||||
|         im.seek(n_frames - 1) | ||||
| 
 | ||||
|     def test_seek_tell(self): | ||||
|         im = Image.open(animated_test_file) | ||||
|  |  | |||
|  | @ -10,14 +10,11 @@ else: | |||
| 
 | ||||
| @unittest.skipUnless(olefile_installed, "olefile package not installed") | ||||
| class TestFileFpx(PillowTestCase): | ||||
| 
 | ||||
|     def test_invalid_file(self): | ||||
|         # Test an invalid OLE file | ||||
|         invalid_file = "Tests/images/flower.jpg" | ||||
|         self.assertRaises(SyntaxError, | ||||
|                           FpxImagePlugin.FpxImageFile, invalid_file) | ||||
|         self.assertRaises(SyntaxError, FpxImagePlugin.FpxImageFile, invalid_file) | ||||
| 
 | ||||
|         # Test a valid OLE file, but not an FPX file | ||||
|         ole_file = "Tests/images/test-ole-file.doc" | ||||
|         self.assertRaises(SyntaxError, | ||||
|                           FpxImagePlugin.FpxImageFile, ole_file) | ||||
|         self.assertRaises(SyntaxError, FpxImagePlugin.FpxImageFile, ole_file) | ||||
|  |  | |||
|  | @ -3,14 +3,13 @@ from PIL import Image | |||
| 
 | ||||
| 
 | ||||
| class TestFileFtex(PillowTestCase): | ||||
| 
 | ||||
|     def test_load_raw(self): | ||||
|         im = Image.open('Tests/images/ftex_uncompressed.ftu') | ||||
|         target = Image.open('Tests/images/ftex_uncompressed.png') | ||||
|         im = Image.open("Tests/images/ftex_uncompressed.ftu") | ||||
|         target = Image.open("Tests/images/ftex_uncompressed.png") | ||||
| 
 | ||||
|         self.assert_image_equal(im, target) | ||||
| 
 | ||||
|     def test_load_dxt1(self): | ||||
|         im = Image.open('Tests/images/ftex_dxt1.ftc') | ||||
|         target = Image.open('Tests/images/ftex_dxt1.png') | ||||
|         self.assert_image_similar(im, target.convert('RGBA'), 15) | ||||
|         im = Image.open("Tests/images/ftex_dxt1.ftc") | ||||
|         target = Image.open("Tests/images/ftex_dxt1.png") | ||||
|         self.assert_image_similar(im, target.convert("RGBA"), 15) | ||||
|  |  | |||
|  | @ -4,16 +4,14 @@ from PIL import Image, GbrImagePlugin | |||
| 
 | ||||
| 
 | ||||
| class TestFileGbr(PillowTestCase): | ||||
| 
 | ||||
|     def test_invalid_file(self): | ||||
|         invalid_file = "Tests/images/flower.jpg" | ||||
| 
 | ||||
|         self.assertRaises(SyntaxError, | ||||
|                           GbrImagePlugin.GbrImageFile, invalid_file) | ||||
|         self.assertRaises(SyntaxError, GbrImagePlugin.GbrImageFile, invalid_file) | ||||
| 
 | ||||
|     def test_gbr_file(self): | ||||
|         im = Image.open('Tests/images/gbr.gbr') | ||||
|         im = Image.open("Tests/images/gbr.gbr") | ||||
| 
 | ||||
|         target = Image.open('Tests/images/gbr.png') | ||||
|         target = Image.open("Tests/images/gbr.png") | ||||
| 
 | ||||
|         self.assert_image_equal(target, im) | ||||
|  |  | |||
|  | @ -6,15 +6,13 @@ TEST_GD_FILE = "Tests/images/hopper.gd" | |||
| 
 | ||||
| 
 | ||||
| class TestFileGd(PillowTestCase): | ||||
| 
 | ||||
|     def test_sanity(self): | ||||
|         im = GdImageFile.open(TEST_GD_FILE) | ||||
|         self.assertEqual(im.size, (128, 128)) | ||||
|         self.assertEqual(im.format, "GD") | ||||
| 
 | ||||
|     def test_bad_mode(self): | ||||
|         self.assertRaises(ValueError, | ||||
|                           GdImageFile.open, TEST_GD_FILE, 'bad mode') | ||||
|         self.assertRaises(ValueError, GdImageFile.open, TEST_GD_FILE, "bad mode") | ||||
| 
 | ||||
|     def test_invalid_file(self): | ||||
|         invalid_file = "Tests/images/flower.jpg" | ||||
|  |  | |||
|  | @ -6,6 +6,7 @@ from io import BytesIO | |||
| 
 | ||||
| try: | ||||
|     from PIL import _webp | ||||
| 
 | ||||
|     HAVE_WEBP = True | ||||
| except ImportError: | ||||
|     HAVE_WEBP = False | ||||
|  | @ -20,7 +21,6 @@ with open(TEST_GIF, "rb") as f: | |||
| 
 | ||||
| 
 | ||||
| class TestFileGif(PillowTestCase): | ||||
| 
 | ||||
|     def setUp(self): | ||||
|         if "gif_encoder" not in codecs or "gif_decoder" not in codecs: | ||||
|             self.skipTest("gif support not available")  # can this happen? | ||||
|  | @ -37,13 +37,13 @@ class TestFileGif(PillowTestCase): | |||
|         def open(): | ||||
|             im = Image.open(TEST_GIF) | ||||
|             im.load() | ||||
| 
 | ||||
|         self.assert_warning(None, open) | ||||
| 
 | ||||
|     def test_invalid_file(self): | ||||
|         invalid_file = "Tests/images/flower.jpg" | ||||
| 
 | ||||
|         self.assertRaises(SyntaxError, | ||||
|                           GifImagePlugin.GifImageFile, invalid_file) | ||||
|         self.assertRaises(SyntaxError, GifImagePlugin.GifImageFile, invalid_file) | ||||
| 
 | ||||
|     def test_optimize(self): | ||||
|         def test_grayscale(optimize): | ||||
|  | @ -70,19 +70,22 @@ class TestFileGif(PillowTestCase): | |||
|         # Check for correctness after conversion back to RGB | ||||
|         def check(colors, size, expected_palette_length): | ||||
|             # make an image with empty colors in the start of the palette range | ||||
|             im = Image.frombytes('P', (colors, colors), | ||||
|                                  bytes(bytearray(range(256-colors, 256))*colors)) | ||||
|             im = Image.frombytes( | ||||
|                 "P", | ||||
|                 (colors, colors), | ||||
|                 bytes(bytearray(range(256 - colors, 256)) * colors), | ||||
|             ) | ||||
|             im = im.resize((size, size)) | ||||
|             outfile = BytesIO() | ||||
|             im.save(outfile, 'GIF') | ||||
|             im.save(outfile, "GIF") | ||||
|             outfile.seek(0) | ||||
|             reloaded = Image.open(outfile) | ||||
| 
 | ||||
|             # check palette length | ||||
|             palette_length = max(i+1 for i, v in enumerate(reloaded.histogram()) if v) | ||||
|             palette_length = max(i + 1 for i, v in enumerate(reloaded.histogram()) if v) | ||||
|             self.assertEqual(expected_palette_length, palette_length) | ||||
| 
 | ||||
|             self.assert_image_equal(im.convert('RGB'), reloaded.convert('RGB')) | ||||
|             self.assert_image_equal(im.convert("RGB"), reloaded.convert("RGB")) | ||||
| 
 | ||||
|         # These do optimize the palette | ||||
|         check(128, 511, 128) | ||||
|  | @ -106,79 +109,76 @@ class TestFileGif(PillowTestCase): | |||
|         self.assertEqual(im.mode, "L") | ||||
| 
 | ||||
|     def test_roundtrip(self): | ||||
|         out = self.tempfile('temp.gif') | ||||
|         out = self.tempfile("temp.gif") | ||||
|         im = hopper() | ||||
|         im.save(out) | ||||
|         reread = Image.open(out) | ||||
| 
 | ||||
|         self.assert_image_similar(reread.convert('RGB'), im, 50) | ||||
|         self.assert_image_similar(reread.convert("RGB"), im, 50) | ||||
| 
 | ||||
|     def test_roundtrip2(self): | ||||
|         # see https://github.com/python-pillow/Pillow/issues/403 | ||||
|         out = self.tempfile('temp.gif') | ||||
|         out = self.tempfile("temp.gif") | ||||
|         im = Image.open(TEST_GIF) | ||||
|         im2 = im.copy() | ||||
|         im2.save(out) | ||||
|         reread = Image.open(out) | ||||
| 
 | ||||
|         self.assert_image_similar(reread.convert('RGB'), hopper(), 50) | ||||
|         self.assert_image_similar(reread.convert("RGB"), hopper(), 50) | ||||
| 
 | ||||
|     def test_roundtrip_save_all(self): | ||||
|         # Single frame image | ||||
|         out = self.tempfile('temp.gif') | ||||
|         out = self.tempfile("temp.gif") | ||||
|         im = hopper() | ||||
|         im.save(out, save_all=True) | ||||
|         reread = Image.open(out) | ||||
| 
 | ||||
|         self.assert_image_similar(reread.convert('RGB'), im, 50) | ||||
|         self.assert_image_similar(reread.convert("RGB"), im, 50) | ||||
| 
 | ||||
|         # Multiframe image | ||||
|         im = Image.open("Tests/images/dispose_bgnd.gif") | ||||
| 
 | ||||
|         out = self.tempfile('temp.gif') | ||||
|         out = self.tempfile("temp.gif") | ||||
|         im.save(out, save_all=True) | ||||
|         reread = Image.open(out) | ||||
| 
 | ||||
|         self.assertEqual(reread.n_frames, 5) | ||||
| 
 | ||||
|     def test_headers_saving_for_animated_gifs(self): | ||||
|         important_headers = ['background', 'version', 'duration', 'loop'] | ||||
|         important_headers = ["background", "version", "duration", "loop"] | ||||
|         # Multiframe image | ||||
|         im = Image.open("Tests/images/dispose_bgnd.gif") | ||||
| 
 | ||||
|         info = im.info.copy() | ||||
| 
 | ||||
|         out = self.tempfile('temp.gif') | ||||
|         out = self.tempfile("temp.gif") | ||||
|         im.save(out, save_all=True) | ||||
|         reread = Image.open(out) | ||||
| 
 | ||||
|         for header in important_headers: | ||||
|             self.assertEqual( | ||||
|                 info[header], | ||||
|                 reread.info[header] | ||||
|             ) | ||||
|             self.assertEqual(info[header], reread.info[header]) | ||||
| 
 | ||||
|     def test_palette_handling(self): | ||||
|         # see https://github.com/python-pillow/Pillow/issues/513 | ||||
| 
 | ||||
|         im = Image.open(TEST_GIF) | ||||
|         im = im.convert('RGB') | ||||
|         im = im.convert("RGB") | ||||
| 
 | ||||
|         im = im.resize((100, 100), Image.LANCZOS) | ||||
|         im2 = im.convert('P', palette=Image.ADAPTIVE, colors=256) | ||||
|         im2 = im.convert("P", palette=Image.ADAPTIVE, colors=256) | ||||
| 
 | ||||
|         f = self.tempfile('temp.gif') | ||||
|         f = self.tempfile("temp.gif") | ||||
|         im2.save(f, optimize=True) | ||||
| 
 | ||||
|         reloaded = Image.open(f) | ||||
| 
 | ||||
|         self.assert_image_similar(im, reloaded.convert('RGB'), 10) | ||||
|         self.assert_image_similar(im, reloaded.convert("RGB"), 10) | ||||
| 
 | ||||
|     def test_palette_434(self): | ||||
|         # see https://github.com/python-pillow/Pillow/issues/434 | ||||
| 
 | ||||
|         def roundtrip(im, *args, **kwargs): | ||||
|             out = self.tempfile('temp.gif') | ||||
|             out = self.tempfile("temp.gif") | ||||
|             im.copy().save(out, *args, **kwargs) | ||||
|             reloaded = Image.open(out) | ||||
| 
 | ||||
|  | @ -192,7 +192,7 @@ class TestFileGif(PillowTestCase): | |||
| 
 | ||||
|         im = im.convert("RGB") | ||||
|         # check automatic P conversion | ||||
|         reloaded = roundtrip(im).convert('RGB') | ||||
|         reloaded = roundtrip(im).convert("RGB") | ||||
|         self.assert_image_equal(im, reloaded) | ||||
| 
 | ||||
|     @unittest.skipUnless(netpbm_available(), "netpbm not available") | ||||
|  | @ -240,10 +240,7 @@ class TestFileGif(PillowTestCase): | |||
|         self.assert_image_equal(im, expected) | ||||
| 
 | ||||
|     def test_n_frames(self): | ||||
|         for path, n_frames in [ | ||||
|             [TEST_GIF, 1], | ||||
|             ['Tests/images/iss634.gif', 42] | ||||
|         ]: | ||||
|         for path, n_frames in [[TEST_GIF, 1], ["Tests/images/iss634.gif", 42]]: | ||||
|             # Test is_animated before n_frames | ||||
|             im = Image.open(path) | ||||
|             self.assertEqual(im.is_animated, n_frames != 1) | ||||
|  | @ -262,7 +259,7 @@ class TestFileGif(PillowTestCase): | |||
|         self.assertLess(im.tell(), n_frames) | ||||
| 
 | ||||
|         # Test that seeking to the last frame does not raise an error | ||||
|         im.seek(n_frames-1) | ||||
|         im.seek(n_frames - 1) | ||||
| 
 | ||||
|     def test_dispose_none(self): | ||||
|         img = Image.open("Tests/images/dispose_none.gif") | ||||
|  | @ -292,18 +289,15 @@ class TestFileGif(PillowTestCase): | |||
|             pass | ||||
| 
 | ||||
|     def test_save_dispose(self): | ||||
|         out = self.tempfile('temp.gif') | ||||
|         out = self.tempfile("temp.gif") | ||||
|         im_list = [ | ||||
|             Image.new('L', (100, 100), '#000'), | ||||
|             Image.new('L', (100, 100), '#111'), | ||||
|             Image.new('L', (100, 100), '#222'), | ||||
|             Image.new("L", (100, 100), "#000"), | ||||
|             Image.new("L", (100, 100), "#111"), | ||||
|             Image.new("L", (100, 100), "#222"), | ||||
|         ] | ||||
|         for method in range(0, 4): | ||||
|             im_list[0].save( | ||||
|                 out, | ||||
|                 save_all=True, | ||||
|                 append_images=im_list[1:], | ||||
|                 disposal=method | ||||
|                 out, save_all=True, append_images=im_list[1:], disposal=method | ||||
|             ) | ||||
|             img = Image.open(out) | ||||
|             for _ in range(2): | ||||
|  | @ -315,14 +309,14 @@ class TestFileGif(PillowTestCase): | |||
|             out, | ||||
|             save_all=True, | ||||
|             append_images=im_list[1:], | ||||
|             disposal=tuple(range(len(im_list))) | ||||
|             ) | ||||
|             disposal=tuple(range(len(im_list))), | ||||
|         ) | ||||
| 
 | ||||
|         img = Image.open(out) | ||||
| 
 | ||||
|         for i in range(2): | ||||
|             img.seek(img.tell() + 1) | ||||
|             self.assertEqual(img.disposal_method, i+1) | ||||
|             self.assertEqual(img.disposal_method, i + 1) | ||||
| 
 | ||||
|     def test_iss634(self): | ||||
|         img = Image.open("Tests/images/iss634.gif") | ||||
|  | @ -330,42 +324,39 @@ class TestFileGif(PillowTestCase): | |||
|         img.seek(img.tell() + 1) | ||||
|         # all transparent pixels should be replaced with the color from the | ||||
|         # first frame | ||||
|         self.assertEqual(img.histogram()[img.info['transparency']], 0) | ||||
|         self.assertEqual(img.histogram()[img.info["transparency"]], 0) | ||||
| 
 | ||||
|     def test_duration(self): | ||||
|         duration = 1000 | ||||
| 
 | ||||
|         out = self.tempfile('temp.gif') | ||||
|         im = Image.new('L', (100, 100), '#000') | ||||
|         out = self.tempfile("temp.gif") | ||||
|         im = Image.new("L", (100, 100), "#000") | ||||
| 
 | ||||
|         # Check that the argument has priority over the info settings | ||||
|         im.info['duration'] = 100 | ||||
|         im.info["duration"] = 100 | ||||
|         im.save(out, duration=duration) | ||||
| 
 | ||||
|         reread = Image.open(out) | ||||
|         self.assertEqual(reread.info['duration'], duration) | ||||
|         self.assertEqual(reread.info["duration"], duration) | ||||
| 
 | ||||
|     def test_multiple_duration(self): | ||||
|         duration_list = [1000, 2000, 3000] | ||||
| 
 | ||||
|         out = self.tempfile('temp.gif') | ||||
|         out = self.tempfile("temp.gif") | ||||
|         im_list = [ | ||||
|             Image.new('L', (100, 100), '#000'), | ||||
|             Image.new('L', (100, 100), '#111'), | ||||
|             Image.new('L', (100, 100), '#222') | ||||
|             Image.new("L", (100, 100), "#000"), | ||||
|             Image.new("L", (100, 100), "#111"), | ||||
|             Image.new("L", (100, 100), "#222"), | ||||
|         ] | ||||
| 
 | ||||
|         # duration as list | ||||
|         im_list[0].save( | ||||
|             out, | ||||
|             save_all=True, | ||||
|             append_images=im_list[1:], | ||||
|             duration=duration_list | ||||
|             out, save_all=True, append_images=im_list[1:], duration=duration_list | ||||
|         ) | ||||
|         reread = Image.open(out) | ||||
| 
 | ||||
|         for duration in duration_list: | ||||
|             self.assertEqual(reread.info['duration'], duration) | ||||
|             self.assertEqual(reread.info["duration"], duration) | ||||
|             try: | ||||
|                 reread.seek(reread.tell() + 1) | ||||
|             except EOFError: | ||||
|  | @ -373,15 +364,12 @@ class TestFileGif(PillowTestCase): | |||
| 
 | ||||
|         # duration as tuple | ||||
|         im_list[0].save( | ||||
|             out, | ||||
|             save_all=True, | ||||
|             append_images=im_list[1:], | ||||
|             duration=tuple(duration_list) | ||||
|             out, save_all=True, append_images=im_list[1:], duration=tuple(duration_list) | ||||
|         ) | ||||
|         reread = Image.open(out) | ||||
| 
 | ||||
|         for duration in duration_list: | ||||
|             self.assertEqual(reread.info['duration'], duration) | ||||
|             self.assertEqual(reread.info["duration"], duration) | ||||
|             try: | ||||
|                 reread.seek(reread.tell() + 1) | ||||
|             except EOFError: | ||||
|  | @ -390,20 +378,17 @@ class TestFileGif(PillowTestCase): | |||
|     def test_identical_frames(self): | ||||
|         duration_list = [1000, 1500, 2000, 4000] | ||||
| 
 | ||||
|         out = self.tempfile('temp.gif') | ||||
|         out = self.tempfile("temp.gif") | ||||
|         im_list = [ | ||||
|             Image.new('L', (100, 100), '#000'), | ||||
|             Image.new('L', (100, 100), '#000'), | ||||
|             Image.new('L', (100, 100), '#000'), | ||||
|             Image.new('L', (100, 100), '#111') | ||||
|             Image.new("L", (100, 100), "#000"), | ||||
|             Image.new("L", (100, 100), "#000"), | ||||
|             Image.new("L", (100, 100), "#000"), | ||||
|             Image.new("L", (100, 100), "#111"), | ||||
|         ] | ||||
| 
 | ||||
|         # duration as list | ||||
|         im_list[0].save( | ||||
|             out, | ||||
|             save_all=True, | ||||
|             append_images=im_list[1:], | ||||
|             duration=duration_list | ||||
|             out, save_all=True, append_images=im_list[1:], duration=duration_list | ||||
|         ) | ||||
|         reread = Image.open(out) | ||||
| 
 | ||||
|  | @ -411,64 +396,63 @@ class TestFileGif(PillowTestCase): | |||
|         self.assertEqual(reread.n_frames, 2) | ||||
| 
 | ||||
|         # Assert that the new duration is the total of the identical frames | ||||
|         self.assertEqual(reread.info['duration'], 4500) | ||||
|         self.assertEqual(reread.info["duration"], 4500) | ||||
| 
 | ||||
|     def test_number_of_loops(self): | ||||
|         number_of_loops = 2 | ||||
| 
 | ||||
|         out = self.tempfile('temp.gif') | ||||
|         im = Image.new('L', (100, 100), '#000') | ||||
|         out = self.tempfile("temp.gif") | ||||
|         im = Image.new("L", (100, 100), "#000") | ||||
|         im.save(out, loop=number_of_loops) | ||||
|         reread = Image.open(out) | ||||
| 
 | ||||
|         self.assertEqual(reread.info['loop'], number_of_loops) | ||||
|         self.assertEqual(reread.info["loop"], number_of_loops) | ||||
| 
 | ||||
|     def test_background(self): | ||||
|         out = self.tempfile('temp.gif') | ||||
|         im = Image.new('L', (100, 100), '#000') | ||||
|         im.info['background'] = 1 | ||||
|         out = self.tempfile("temp.gif") | ||||
|         im = Image.new("L", (100, 100), "#000") | ||||
|         im.info["background"] = 1 | ||||
|         im.save(out) | ||||
|         reread = Image.open(out) | ||||
| 
 | ||||
|         self.assertEqual(reread.info['background'], im.info['background']) | ||||
|         self.assertEqual(reread.info["background"], im.info["background"]) | ||||
| 
 | ||||
|         if HAVE_WEBP and _webp.HAVE_WEBPANIM: | ||||
|             im = Image.open("Tests/images/hopper.webp") | ||||
|             self.assertIsInstance(im.info['background'], tuple) | ||||
|             self.assertIsInstance(im.info["background"], tuple) | ||||
|             im.save(out) | ||||
| 
 | ||||
|     def test_comment(self): | ||||
|         im = Image.open(TEST_GIF) | ||||
|         self.assertEqual(im.info['comment'], | ||||
|                          b"File written by Adobe Photoshop\xa8 4.0") | ||||
|         self.assertEqual(im.info["comment"], b"File written by Adobe Photoshop\xa8 4.0") | ||||
| 
 | ||||
|         out = self.tempfile('temp.gif') | ||||
|         im = Image.new('L', (100, 100), '#000') | ||||
|         im.info['comment'] = b"Test comment text" | ||||
|         out = self.tempfile("temp.gif") | ||||
|         im = Image.new("L", (100, 100), "#000") | ||||
|         im.info["comment"] = b"Test comment text" | ||||
|         im.save(out) | ||||
|         reread = Image.open(out) | ||||
| 
 | ||||
|         self.assertEqual(reread.info['comment'], im.info['comment']) | ||||
|         self.assertEqual(reread.info["comment"], im.info["comment"]) | ||||
| 
 | ||||
|     def test_comment_over_255(self): | ||||
|         out = self.tempfile('temp.gif') | ||||
|         im = Image.new('L', (100, 100), '#000') | ||||
|         out = self.tempfile("temp.gif") | ||||
|         im = Image.new("L", (100, 100), "#000") | ||||
|         comment = b"Test comment text" | ||||
|         while len(comment) < 256: | ||||
|             comment += comment | ||||
|         im.info['comment'] = comment | ||||
|         im.info["comment"] = comment | ||||
|         im.save(out) | ||||
|         reread = Image.open(out) | ||||
| 
 | ||||
|         self.assertEqual(reread.info['comment'], comment) | ||||
|         self.assertEqual(reread.info["comment"], comment) | ||||
| 
 | ||||
|     def test_zero_comment_subblocks(self): | ||||
|         im = Image.open('Tests/images/hopper_zero_comment_subblocks.gif') | ||||
|         im = Image.open("Tests/images/hopper_zero_comment_subblocks.gif") | ||||
|         expected = Image.open(TEST_GIF) | ||||
|         self.assert_image_equal(im, expected) | ||||
| 
 | ||||
|     def test_version(self): | ||||
|         out = self.tempfile('temp.gif') | ||||
|         out = self.tempfile("temp.gif") | ||||
| 
 | ||||
|         def assertVersionAfterSave(im, version): | ||||
|             im.save(out) | ||||
|  | @ -476,11 +460,11 @@ class TestFileGif(PillowTestCase): | |||
|             self.assertEqual(reread.info["version"], version) | ||||
| 
 | ||||
|         # Test that GIF87a is used by default | ||||
|         im = Image.new('L', (100, 100), '#000') | ||||
|         im = Image.new("L", (100, 100), "#000") | ||||
|         assertVersionAfterSave(im, b"GIF87a") | ||||
| 
 | ||||
|         # Test setting the version to 89a | ||||
|         im = Image.new('L', (100, 100), '#000') | ||||
|         im = Image.new("L", (100, 100), "#000") | ||||
|         im.info["version"] = b"89a" | ||||
|         assertVersionAfterSave(im, b"GIF89a") | ||||
| 
 | ||||
|  | @ -497,12 +481,11 @@ class TestFileGif(PillowTestCase): | |||
|         assertVersionAfterSave(im, b"GIF87a") | ||||
| 
 | ||||
|     def test_append_images(self): | ||||
|         out = self.tempfile('temp.gif') | ||||
|         out = self.tempfile("temp.gif") | ||||
| 
 | ||||
|         # Test appending single frame images | ||||
|         im = Image.new('RGB', (100, 100), '#f00') | ||||
|         ims = [Image.new('RGB', (100, 100), color) for color | ||||
|                in ['#0f0', '#00f']] | ||||
|         im = Image.new("RGB", (100, 100), "#f00") | ||||
|         ims = [Image.new("RGB", (100, 100), color) for color in ["#0f0", "#00f"]] | ||||
|         im.copy().save(out, save_all=True, append_images=ims) | ||||
| 
 | ||||
|         reread = Image.open(out) | ||||
|  | @ -512,6 +495,7 @@ class TestFileGif(PillowTestCase): | |||
|         def imGenerator(ims): | ||||
|             for im in ims: | ||||
|                 yield im | ||||
| 
 | ||||
|         im.save(out, save_all=True, append_images=imGenerator(ims)) | ||||
| 
 | ||||
|         reread = Image.open(out) | ||||
|  | @ -533,44 +517,43 @@ class TestFileGif(PillowTestCase): | |||
|         # the top palette entry to trigger the bug. | ||||
| 
 | ||||
|         data = bytes(bytearray(range(1, 254))) | ||||
|         palette = ImagePalette.ImagePalette("RGB", list(range(256))*3) | ||||
|         palette = ImagePalette.ImagePalette("RGB", list(range(256)) * 3) | ||||
| 
 | ||||
|         im = Image.new('L', (253, 1)) | ||||
|         im = Image.new("L", (253, 1)) | ||||
|         im.frombytes(data) | ||||
|         im.putpalette(palette) | ||||
| 
 | ||||
|         out = self.tempfile('temp.gif') | ||||
|         out = self.tempfile("temp.gif") | ||||
|         im.save(out, transparency=253) | ||||
|         reloaded = Image.open(out) | ||||
| 
 | ||||
|         self.assertEqual(reloaded.info['transparency'], 253) | ||||
|         self.assertEqual(reloaded.info["transparency"], 253) | ||||
| 
 | ||||
|     def test_rgb_transparency(self): | ||||
|         out = self.tempfile('temp.gif') | ||||
|         out = self.tempfile("temp.gif") | ||||
| 
 | ||||
|         # Single frame | ||||
|         im = Image.new('RGB', (1, 1)) | ||||
|         im.info['transparency'] = (255, 0, 0) | ||||
|         im = Image.new("RGB", (1, 1)) | ||||
|         im.info["transparency"] = (255, 0, 0) | ||||
|         self.assert_warning(UserWarning, im.save, out) | ||||
| 
 | ||||
|         reloaded = Image.open(out) | ||||
|         self.assertNotIn('transparency', reloaded.info) | ||||
|         self.assertNotIn("transparency", reloaded.info) | ||||
| 
 | ||||
|         # Multiple frames | ||||
|         im = Image.new('RGB', (1, 1)) | ||||
|         im.info['transparency'] = b"" | ||||
|         ims = [Image.new('RGB', (1, 1))] | ||||
|         self.assert_warning(UserWarning, | ||||
|                             im.save, out, save_all=True, append_images=ims) | ||||
|         im = Image.new("RGB", (1, 1)) | ||||
|         im.info["transparency"] = b"" | ||||
|         ims = [Image.new("RGB", (1, 1))] | ||||
|         self.assert_warning(UserWarning, im.save, out, save_all=True, append_images=ims) | ||||
| 
 | ||||
|         reloaded = Image.open(out) | ||||
|         self.assertNotIn('transparency', reloaded.info) | ||||
|         self.assertNotIn("transparency", reloaded.info) | ||||
| 
 | ||||
|     def test_bbox(self): | ||||
|         out = self.tempfile('temp.gif') | ||||
|         out = self.tempfile("temp.gif") | ||||
| 
 | ||||
|         im = Image.new('RGB', (100, 100), '#fff') | ||||
|         ims = [Image.new("RGB", (100, 100), '#000')] | ||||
|         im = Image.new("RGB", (100, 100), "#fff") | ||||
|         ims = [Image.new("RGB", (100, 100), "#000")] | ||||
|         im.save(out, save_all=True, append_images=ims) | ||||
| 
 | ||||
|         reread = Image.open(out) | ||||
|  | @ -579,26 +562,26 @@ class TestFileGif(PillowTestCase): | |||
|     def test_palette_save_L(self): | ||||
|         # generate an L mode image with a separate palette | ||||
| 
 | ||||
|         im = hopper('P') | ||||
|         im_l = Image.frombytes('L', im.size, im.tobytes()) | ||||
|         im = hopper("P") | ||||
|         im_l = Image.frombytes("L", im.size, im.tobytes()) | ||||
|         palette = bytes(bytearray(im.getpalette())) | ||||
| 
 | ||||
|         out = self.tempfile('temp.gif') | ||||
|         out = self.tempfile("temp.gif") | ||||
|         im_l.save(out, palette=palette) | ||||
| 
 | ||||
|         reloaded = Image.open(out) | ||||
| 
 | ||||
|         self.assert_image_equal(reloaded.convert('RGB'), im.convert('RGB')) | ||||
|         self.assert_image_equal(reloaded.convert("RGB"), im.convert("RGB")) | ||||
| 
 | ||||
|     def test_palette_save_P(self): | ||||
|         # pass in a different palette, then construct what the image | ||||
|         # would look like. | ||||
|         # Forcing a non-straight grayscale palette. | ||||
| 
 | ||||
|         im = hopper('P') | ||||
|         palette = bytes(bytearray([255-i//3 for i in range(768)])) | ||||
|         im = hopper("P") | ||||
|         palette = bytes(bytearray([255 - i // 3 for i in range(768)])) | ||||
| 
 | ||||
|         out = self.tempfile('temp.gif') | ||||
|         out = self.tempfile("temp.gif") | ||||
|         im.save(out, palette=palette) | ||||
| 
 | ||||
|         reloaded = Image.open(out) | ||||
|  | @ -609,10 +592,10 @@ class TestFileGif(PillowTestCase): | |||
|         # pass in a different palette, as an ImagePalette.ImagePalette | ||||
|         # effectively the same as test_palette_save_P | ||||
| 
 | ||||
|         im = hopper('P') | ||||
|         palette = ImagePalette.ImagePalette('RGB', list(range(256))[::-1]*3) | ||||
|         im = hopper("P") | ||||
|         palette = ImagePalette.ImagePalette("RGB", list(range(256))[::-1] * 3) | ||||
| 
 | ||||
|         out = self.tempfile('temp.gif') | ||||
|         out = self.tempfile("temp.gif") | ||||
|         im.save(out, palette=palette) | ||||
| 
 | ||||
|         reloaded = Image.open(out) | ||||
|  | @ -622,22 +605,22 @@ class TestFileGif(PillowTestCase): | |||
|     def test_save_I(self): | ||||
|         # Test saving something that would trigger the auto-convert to 'L' | ||||
| 
 | ||||
|         im = hopper('I') | ||||
|         im = hopper("I") | ||||
| 
 | ||||
|         out = self.tempfile('temp.gif') | ||||
|         out = self.tempfile("temp.gif") | ||||
|         im.save(out) | ||||
| 
 | ||||
|         reloaded = Image.open(out) | ||||
|         self.assert_image_equal(reloaded.convert('L'), im.convert('L')) | ||||
|         self.assert_image_equal(reloaded.convert("L"), im.convert("L")) | ||||
| 
 | ||||
|     def test_getdata(self): | ||||
|         # test getheader/getdata against legacy values | ||||
|         # Create a 'P' image with holes in the palette | ||||
|         im = Image._wedge().resize((16, 16)) | ||||
|         im.putpalette(ImagePalette.ImagePalette('RGB')) | ||||
|         im.info = {'background': 0} | ||||
|         im.putpalette(ImagePalette.ImagePalette("RGB")) | ||||
|         im.info = {"background": 0} | ||||
| 
 | ||||
|         passed_palette = bytes(bytearray([255-i//3 for i in range(768)])) | ||||
|         passed_palette = bytes(bytearray([255 - i // 3 for i in range(768)])) | ||||
| 
 | ||||
|         GifImagePlugin._FORCE_OPTIMIZE = True | ||||
|         try: | ||||
|  | @ -645,10 +628,11 @@ class TestFileGif(PillowTestCase): | |||
|             d = GifImagePlugin.getdata(im) | ||||
| 
 | ||||
|             import pickle | ||||
| 
 | ||||
|             # Enable to get target values on pre-refactor version | ||||
|             # with open('Tests/images/gif_header_data.pkl', 'wb') as f: | ||||
|             #    pickle.dump((h, d), f, 1) | ||||
|             with open('Tests/images/gif_header_data.pkl', 'rb') as f: | ||||
|             with open("Tests/images/gif_header_data.pkl", "rb") as f: | ||||
|                 (h_target, d_target) = pickle.load(f) | ||||
| 
 | ||||
|             self.assertEqual(h, h_target) | ||||
|  | @ -658,14 +642,14 @@ class TestFileGif(PillowTestCase): | |||
| 
 | ||||
|     def test_lzw_bits(self): | ||||
|         # see https://github.com/python-pillow/Pillow/issues/2811 | ||||
|         im = Image.open('Tests/images/issue_2811.gif') | ||||
|         im = Image.open("Tests/images/issue_2811.gif") | ||||
| 
 | ||||
|         self.assertEqual(im.tile[0][3][0], 11)  # LZW bits | ||||
|         # codec error prepatch | ||||
|         im.load() | ||||
| 
 | ||||
|     def test_extents(self): | ||||
|         im = Image.open('Tests/images/test_extents.gif') | ||||
|         im = Image.open("Tests/images/test_extents.gif") | ||||
|         self.assertEqual(im.size, (100, 100)) | ||||
|         im.seek(1) | ||||
|         self.assertEqual(im.size, (150, 150)) | ||||
|  |  | |||
|  | @ -4,7 +4,6 @@ from PIL import GimpGradientFile | |||
| 
 | ||||
| 
 | ||||
| class TestImage(PillowTestCase): | ||||
| 
 | ||||
|     def test_linear_pos_le_middle(self): | ||||
|         # Arrange | ||||
|         middle = 0.5 | ||||
|  | @ -96,6 +95,7 @@ class TestImage(PillowTestCase): | |||
|     def test_load_via_imagepalette(self): | ||||
|         # Arrange | ||||
|         from PIL import ImagePalette | ||||
| 
 | ||||
|         test_file = "Tests/images/gimp_gradient.ggr" | ||||
| 
 | ||||
|         # Act | ||||
|  | @ -109,6 +109,7 @@ class TestImage(PillowTestCase): | |||
|     def test_load_1_3_via_imagepalette(self): | ||||
|         # Arrange | ||||
|         from PIL import ImagePalette | ||||
| 
 | ||||
|         # GIMP 1.3 gradient files contain a name field | ||||
|         test_file = "Tests/images/gimp_gradient_with_name.ggr" | ||||
| 
 | ||||
|  |  | |||
		Loading…
	
		Reference in New Issue
	
	Block a user