mirror of
				https://github.com/python-pillow/Pillow.git
				synced 2025-11-01 00:17:27 +03:00 
			
		
		
		
	Replace unittest with pytest
This commit is contained in:
		
							parent
							
								
									098406c304
								
							
						
					
					
						commit
						affade7595
					
				|  | @ -1,7 +1,6 @@ | |||
| import pytest | ||||
| from PIL import Image, ImageFilter | ||||
| 
 | ||||
| from .helper import PillowTestCase | ||||
| 
 | ||||
| sample = Image.new("L", (7, 5)) | ||||
| # fmt: off | ||||
| sample.putdata(sum([ | ||||
|  | @ -21,226 +20,244 @@ def test_imageops_box_blur(): | |||
|     assert isinstance(i, Image.Image) | ||||
| 
 | ||||
| 
 | ||||
| class TestBoxBlur(PillowTestCase): | ||||
|     def box_blur(self, image, radius=1, n=1): | ||||
|         return image._new(image.im.box_blur(radius, n)) | ||||
| def box_blur(image, radius=1, n=1): | ||||
|     return image._new(image.im.box_blur(radius, n)) | ||||
| 
 | ||||
|     def assertImage(self, im, data, delta=0): | ||||
|         it = iter(im.getdata()) | ||||
|         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) | ||||
|             ): | ||||
|                 self.assertEqual(im_row, data_row) | ||||
|         self.assertRaises(StopIteration, next, it) | ||||
| 
 | ||||
|     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)) | ||||
|         for band in self.box_blur(rgba, radius, passes).split(): | ||||
|             self.assertImage(band, data, delta) | ||||
| def assertImage(im, data, delta=0): | ||||
|     it = iter(im.getdata()) | ||||
|     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)): | ||||
|             assert im_row == data_row | ||||
|     with pytest.raises(StopIteration): | ||||
|         next(it) | ||||
| 
 | ||||
|     def test_color_modes(self): | ||||
|         self.assertRaises(ValueError, self.box_blur, sample.convert("1")) | ||||
|         self.assertRaises(ValueError, self.box_blur, sample.convert("P")) | ||||
|         self.box_blur(sample.convert("L")) | ||||
|         self.box_blur(sample.convert("LA")) | ||||
|         self.box_blur(sample.convert("LA").convert("La")) | ||||
|         self.assertRaises(ValueError, self.box_blur, sample.convert("I")) | ||||
|         self.assertRaises(ValueError, self.box_blur, sample.convert("F")) | ||||
|         self.box_blur(sample.convert("RGB")) | ||||
|         self.box_blur(sample.convert("RGBA")) | ||||
|         self.box_blur(sample.convert("RGBA").convert("RGBa")) | ||||
|         self.box_blur(sample.convert("CMYK")) | ||||
|         self.assertRaises(ValueError, self.box_blur, sample.convert("YCbCr")) | ||||
| 
 | ||||
|     def test_radius_0(self): | ||||
|         self.assertBlur( | ||||
|             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 assertBlur(im, radius, data, passes=1, delta=0): | ||||
|     # check grayscale image | ||||
|     assertImage(box_blur(im, radius, passes), data, delta) | ||||
|     rgba = Image.merge("RGBA", (im, im, im, im)) | ||||
|     for band in box_blur(rgba, radius, passes).split(): | ||||
|         assertImage(band, data, delta) | ||||
| 
 | ||||
|     def test_radius_0_02(self): | ||||
|         self.assertBlur( | ||||
|             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, | ||||
|             [ | ||||
|                 # 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_color_modes(): | ||||
|     with pytest.raises(ValueError): | ||||
|         box_blur(sample.convert("1")) | ||||
|     with pytest.raises(ValueError): | ||||
|         box_blur(sample.convert("P")) | ||||
|     box_blur(sample.convert("L")) | ||||
|     box_blur(sample.convert("LA")) | ||||
|     box_blur(sample.convert("LA").convert("La")) | ||||
|     with pytest.raises(ValueError): | ||||
|         box_blur(sample.convert("I")) | ||||
|     with pytest.raises(ValueError): | ||||
|         box_blur(sample.convert("F")) | ||||
|     box_blur(sample.convert("RGB")) | ||||
|     box_blur(sample.convert("RGBA")) | ||||
|     box_blur(sample.convert("RGBA").convert("RGBa")) | ||||
|     box_blur(sample.convert("CMYK")) | ||||
|     with pytest.raises(ValueError): | ||||
|         box_blur(sample.convert("YCbCr")) | ||||
| 
 | ||||
|     def test_radius_0_1(self): | ||||
|         self.assertBlur( | ||||
|             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, | ||||
|             [ | ||||
|                 # 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_0(): | ||||
|     assertBlur( | ||||
|         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_1(self): | ||||
|         self.assertBlur( | ||||
|             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, | ||||
|             [ | ||||
|                 # 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_0_02(): | ||||
|     assertBlur( | ||||
|         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_bigger_then_half(self): | ||||
|         self.assertBlur( | ||||
|             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, | ||||
|             [ | ||||
|                 [158, 153, 147, 141, 135, 129, 123], | ||||
|                 [159, 153, 147, 141, 136, 130, 124], | ||||
|                 [159, 154, 148, 142, 136, 130, 124], | ||||
|                 [160, 154, 148, 142, 137, 131, 125], | ||||
|                 [160, 155, 149, 143, 137, 131, 125], | ||||
|             ], | ||||
|             delta=0, | ||||
|         ) | ||||
| def test_radius_0_05(): | ||||
|     assertBlur( | ||||
|         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_extreme_large_radius(self): | ||||
|         self.assertBlur( | ||||
|             sample, | ||||
|             600, | ||||
|             [ | ||||
|                 [162, 162, 162, 162, 162, 162, 162], | ||||
|                 [162, 162, 162, 162, 162, 162, 162], | ||||
|                 [162, 162, 162, 162, 162, 162, 162], | ||||
|                 [162, 162, 162, 162, 162, 162, 162], | ||||
|                 [162, 162, 162, 162, 162, 162, 162], | ||||
|             ], | ||||
|             delta=1, | ||||
|         ) | ||||
| 
 | ||||
|     def test_two_passes(self): | ||||
|         self.assertBlur( | ||||
|             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, | ||||
|         ) | ||||
| def test_radius_0_1(): | ||||
|     assertBlur( | ||||
|         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_three_passes(self): | ||||
|         self.assertBlur( | ||||
|             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, | ||||
|         ) | ||||
| 
 | ||||
| def test_radius_0_5(): | ||||
|     assertBlur( | ||||
|         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(): | ||||
|     assertBlur( | ||||
|         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(): | ||||
|     assertBlur( | ||||
|         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(): | ||||
|     assertBlur( | ||||
|         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(): | ||||
|     assertBlur( | ||||
|         sample, | ||||
|         10, | ||||
|         [ | ||||
|             [158, 153, 147, 141, 135, 129, 123], | ||||
|             [159, 153, 147, 141, 136, 130, 124], | ||||
|             [159, 154, 148, 142, 136, 130, 124], | ||||
|             [160, 154, 148, 142, 137, 131, 125], | ||||
|             [160, 155, 149, 143, 137, 131, 125], | ||||
|         ], | ||||
|         delta=0, | ||||
|     ) | ||||
| 
 | ||||
| 
 | ||||
| def test_extreme_large_radius(): | ||||
|     assertBlur( | ||||
|         sample, | ||||
|         600, | ||||
|         [ | ||||
|             [162, 162, 162, 162, 162, 162, 162], | ||||
|             [162, 162, 162, 162, 162, 162, 162], | ||||
|             [162, 162, 162, 162, 162, 162, 162], | ||||
|             [162, 162, 162, 162, 162, 162, 162], | ||||
|             [162, 162, 162, 162, 162, 162, 162], | ||||
|         ], | ||||
|         delta=1, | ||||
|     ) | ||||
| 
 | ||||
| 
 | ||||
| def test_two_passes(): | ||||
|     assertBlur( | ||||
|         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, | ||||
|     ) | ||||
| 
 | ||||
| 
 | ||||
| def test_three_passes(): | ||||
|     assertBlur( | ||||
|         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, | ||||
|     ) | ||||
|  |  | |||
|  | @ -22,7 +22,7 @@ class TestDecompressionBomb(PillowTestCase): | |||
|         # Arrange | ||||
|         # Turn limit off | ||||
|         Image.MAX_IMAGE_PIXELS = None | ||||
|         self.assertIsNone(Image.MAX_IMAGE_PIXELS) | ||||
|         assert Image.MAX_IMAGE_PIXELS is None | ||||
| 
 | ||||
|         # Act / Assert | ||||
|         # Implicit assert: no warning. | ||||
|  | @ -33,7 +33,7 @@ class TestDecompressionBomb(PillowTestCase): | |||
|     def test_warning(self): | ||||
|         # Set limit to trigger warning on the test file | ||||
|         Image.MAX_IMAGE_PIXELS = 128 * 128 - 1 | ||||
|         self.assertEqual(Image.MAX_IMAGE_PIXELS, 128 * 128 - 1) | ||||
|         assert Image.MAX_IMAGE_PIXELS == 128 * 128 - 1 | ||||
| 
 | ||||
|         def open(): | ||||
|             with Image.open(TEST_FILE): | ||||
|  | @ -44,18 +44,18 @@ class TestDecompressionBomb(PillowTestCase): | |||
|     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) | ||||
|         assert Image.MAX_IMAGE_PIXELS == 64 * 128 - 1 | ||||
| 
 | ||||
|         with self.assertRaises(Image.DecompressionBombError): | ||||
|         with pytest.raises(Image.DecompressionBombError): | ||||
|             with Image.open(TEST_FILE): | ||||
|                 pass | ||||
| 
 | ||||
|     def test_exception_ico(self): | ||||
|         with self.assertRaises(Image.DecompressionBombError): | ||||
|         with pytest.raises(Image.DecompressionBombError): | ||||
|             Image.open("Tests/images/decompression_bomb.ico") | ||||
| 
 | ||||
|     def test_exception_gif(self): | ||||
|         with self.assertRaises(Image.DecompressionBombError): | ||||
|         with pytest.raises(Image.DecompressionBombError): | ||||
|             Image.open("Tests/images/decompression_bomb.gif") | ||||
| 
 | ||||
| 
 | ||||
|  | @ -85,11 +85,11 @@ class TestDecompressionCrop(PillowTestCase): | |||
|         error_values = ((-99909, -99990, 99999, 99999), (99909, 99990, -99999, -99999)) | ||||
| 
 | ||||
|         for value in good_values: | ||||
|             self.assertEqual(im.crop(value).size, (9, 9)) | ||||
|             assert im.crop(value).size == (9, 9) | ||||
| 
 | ||||
|         for value in warning_values: | ||||
|             pytest.warns(Image.DecompressionBombWarning, im.crop, value) | ||||
| 
 | ||||
|         for value in error_values: | ||||
|             with self.assertRaises(Image.DecompressionBombError): | ||||
|             with pytest.raises(Image.DecompressionBombError): | ||||
|                 im.crop(value) | ||||
|  |  | |||
|  | @ -1,84 +1,92 @@ | |||
| import unittest | ||||
| 
 | ||||
| import pytest | ||||
| from PIL import DcxImagePlugin, Image | ||||
| 
 | ||||
| from .helper import PillowTestCase, assert_image_equal, hopper, is_pypy | ||||
| from .helper import assert_image_equal, hopper, is_pypy | ||||
| 
 | ||||
| # Created with ImageMagick: convert hopper.ppm hopper.dcx | ||||
| TEST_FILE = "Tests/images/hopper.dcx" | ||||
| 
 | ||||
| 
 | ||||
| class TestFileDcx(PillowTestCase): | ||||
|     def test_sanity(self): | ||||
|         # Arrange | ||||
| def test_sanity(): | ||||
|     # Arrange | ||||
| 
 | ||||
|     # Act | ||||
|     with Image.open(TEST_FILE) as im: | ||||
| 
 | ||||
|         # Assert | ||||
|         assert im.size == (128, 128) | ||||
|         assert isinstance(im, DcxImagePlugin.DcxImageFile) | ||||
|         orig = hopper() | ||||
|         assert_image_equal(im, orig) | ||||
| 
 | ||||
| 
 | ||||
| @pytest.mark.skipif(is_pypy(), reason="Requires CPython") | ||||
| def test_unclosed_file(): | ||||
|     def open(): | ||||
|         im = Image.open(TEST_FILE) | ||||
|         im.load() | ||||
| 
 | ||||
|     pytest.warns(ResourceWarning, open) | ||||
| 
 | ||||
| 
 | ||||
| def test_closed_file(): | ||||
|     def open(): | ||||
|         im = Image.open(TEST_FILE) | ||||
|         im.load() | ||||
|         im.close() | ||||
| 
 | ||||
|     pytest.warns(None, open) | ||||
| 
 | ||||
| 
 | ||||
| def test_context_manager(): | ||||
|     def open(): | ||||
|         with Image.open(TEST_FILE) as im: | ||||
|             im.load() | ||||
| 
 | ||||
|     pytest.warns(None, open) | ||||
| 
 | ||||
| 
 | ||||
| def test_invalid_file(): | ||||
|     with open("Tests/images/flower.jpg", "rb") as fp: | ||||
|         with pytest.raises(SyntaxError): | ||||
|             DcxImagePlugin.DcxImageFile(fp) | ||||
| 
 | ||||
| 
 | ||||
| def test_tell(): | ||||
|     # Arrange | ||||
|     with Image.open(TEST_FILE) as im: | ||||
| 
 | ||||
|         # Act | ||||
|         with Image.open(TEST_FILE) as im: | ||||
|         frame = im.tell() | ||||
| 
 | ||||
|             # Assert | ||||
|             self.assertEqual(im.size, (128, 128)) | ||||
|             self.assertIsInstance(im, DcxImagePlugin.DcxImageFile) | ||||
|             orig = hopper() | ||||
|             assert_image_equal(im, orig) | ||||
|         # Assert | ||||
|         assert frame == 0 | ||||
| 
 | ||||
|     @unittest.skipIf(is_pypy(), "Requires CPython") | ||||
|     def test_unclosed_file(self): | ||||
|         def open(): | ||||
|             im = Image.open(TEST_FILE) | ||||
|             im.load() | ||||
| 
 | ||||
|         pytest.warns(ResourceWarning, open) | ||||
| def test_n_frames(): | ||||
|     with Image.open(TEST_FILE) as im: | ||||
|         assert im.n_frames == 1 | ||||
|         assert not im.is_animated | ||||
| 
 | ||||
|     def test_closed_file(self): | ||||
|         def open(): | ||||
|             im = Image.open(TEST_FILE) | ||||
|             im.load() | ||||
|             im.close() | ||||
| 
 | ||||
|         pytest.warns(None, open) | ||||
| def test_eoferror(): | ||||
|     with Image.open(TEST_FILE) as im: | ||||
|         n_frames = im.n_frames | ||||
| 
 | ||||
|     def test_context_manager(self): | ||||
|         def open(): | ||||
|             with Image.open(TEST_FILE) as im: | ||||
|                 im.load() | ||||
|         # Test seeking past the last frame | ||||
|         with pytest.raises(EOFError): | ||||
|             im.seek(n_frames) | ||||
|         assert im.tell() < n_frames | ||||
| 
 | ||||
|         pytest.warns(None, open) | ||||
|         # Test that seeking to the last frame does not raise an error | ||||
|         im.seek(n_frames - 1) | ||||
| 
 | ||||
|     def test_invalid_file(self): | ||||
|         with open("Tests/images/flower.jpg", "rb") as fp: | ||||
|             self.assertRaises(SyntaxError, DcxImagePlugin.DcxImageFile, fp) | ||||
| 
 | ||||
|     def test_tell(self): | ||||
|         # Arrange | ||||
|         with Image.open(TEST_FILE) as im: | ||||
| def test_seek_too_far(): | ||||
|     # Arrange | ||||
|     with Image.open(TEST_FILE) as im: | ||||
|         frame = 999  # too big on purpose | ||||
| 
 | ||||
|             # Act | ||||
|             frame = im.tell() | ||||
| 
 | ||||
|             # Assert | ||||
|             self.assertEqual(frame, 0) | ||||
| 
 | ||||
|     def test_n_frames(self): | ||||
|         with Image.open(TEST_FILE) as im: | ||||
|             self.assertEqual(im.n_frames, 1) | ||||
|             self.assertFalse(im.is_animated) | ||||
| 
 | ||||
|     def test_eoferror(self): | ||||
|         with Image.open(TEST_FILE) as im: | ||||
|             n_frames = im.n_frames | ||||
| 
 | ||||
|             # Test seeking past the last frame | ||||
|             self.assertRaises(EOFError, im.seek, n_frames) | ||||
|             self.assertLess(im.tell(), n_frames) | ||||
| 
 | ||||
|             # Test that seeking to the last frame does not raise an error | ||||
|             im.seek(n_frames - 1) | ||||
| 
 | ||||
|     def test_seek_too_far(self): | ||||
|         # Arrange | ||||
|         with Image.open(TEST_FILE) as im: | ||||
|             frame = 999  # too big on purpose | ||||
| 
 | ||||
|         # Act / Assert | ||||
|         self.assertRaises(EOFError, im.seek, frame) | ||||
|     # Act / Assert | ||||
|     with pytest.raises(EOFError): | ||||
|         im.seek(frame) | ||||
|  |  | |||
|  | @ -1,8 +1,10 @@ | |||
| """Test DdsImagePlugin""" | ||||
| from io import BytesIO | ||||
| 
 | ||||
| import pytest | ||||
| from PIL import DdsImagePlugin, Image | ||||
| 
 | ||||
| from .helper import PillowTestCase, assert_image_equal | ||||
| from .helper import assert_image_equal | ||||
| 
 | ||||
| TEST_FILE_DXT1 = "Tests/images/dxt1-rgb-4bbp-noalpha_MipMaps-1.dds" | ||||
| TEST_FILE_DXT3 = "Tests/images/dxt3-argb-8bbp-explicitalpha_MipMaps-1.dds" | ||||
|  | @ -12,146 +14,148 @@ TEST_FILE_DX10_BC7_UNORM_SRGB = "Tests/images/DXGI_FORMAT_BC7_UNORM_SRGB.dds" | |||
| TEST_FILE_UNCOMPRESSED_RGB = "Tests/images/uncompressed_rgb.dds" | ||||
| 
 | ||||
| 
 | ||||
| class TestFileDds(PillowTestCase): | ||||
|     """Test DdsImagePlugin""" | ||||
| def test_sanity_dxt1(): | ||||
|     """Check DXT1 images can be opened""" | ||||
|     with Image.open(TEST_FILE_DXT1.replace(".dds", ".png")) as target: | ||||
|         target = target.convert("RGBA") | ||||
|     with Image.open(TEST_FILE_DXT1) as im: | ||||
|         im.load() | ||||
| 
 | ||||
|     def test_sanity_dxt1(self): | ||||
|         """Check DXT1 images can be opened""" | ||||
|         with Image.open(TEST_FILE_DXT1.replace(".dds", ".png")) as target: | ||||
|             target = target.convert("RGBA") | ||||
|         with Image.open(TEST_FILE_DXT1) as im: | ||||
|         assert im.format == "DDS" | ||||
|         assert im.mode == "RGBA" | ||||
|         assert im.size == (256, 256) | ||||
| 
 | ||||
|         assert_image_equal(im, target) | ||||
| 
 | ||||
| 
 | ||||
| def test_sanity_dxt5(): | ||||
|     """Check DXT5 images can be opened""" | ||||
| 
 | ||||
|     with Image.open(TEST_FILE_DXT5) as im: | ||||
|         im.load() | ||||
| 
 | ||||
|     assert im.format == "DDS" | ||||
|     assert im.mode == "RGBA" | ||||
|     assert im.size == (256, 256) | ||||
| 
 | ||||
|     with Image.open(TEST_FILE_DXT5.replace(".dds", ".png")) as target: | ||||
|         assert_image_equal(target, im) | ||||
| 
 | ||||
| 
 | ||||
| def test_sanity_dxt3(): | ||||
|     """Check DXT3 images can be opened""" | ||||
| 
 | ||||
|     with Image.open(TEST_FILE_DXT3.replace(".dds", ".png")) as target: | ||||
|         with Image.open(TEST_FILE_DXT3) as im: | ||||
|             im.load() | ||||
| 
 | ||||
|             self.assertEqual(im.format, "DDS") | ||||
|             self.assertEqual(im.mode, "RGBA") | ||||
|             self.assertEqual(im.size, (256, 256)) | ||||
|             assert im.format == "DDS" | ||||
|             assert im.mode == "RGBA" | ||||
|             assert im.size == (256, 256) | ||||
| 
 | ||||
|             assert_image_equal(im, target) | ||||
| 
 | ||||
|     def test_sanity_dxt5(self): | ||||
|         """Check DXT5 images can be opened""" | ||||
| 
 | ||||
|         with Image.open(TEST_FILE_DXT5) as im: | ||||
|             im.load() | ||||
| 
 | ||||
|         self.assertEqual(im.format, "DDS") | ||||
|         self.assertEqual(im.mode, "RGBA") | ||||
|         self.assertEqual(im.size, (256, 256)) | ||||
| 
 | ||||
|         with Image.open(TEST_FILE_DXT5.replace(".dds", ".png")) as target: | ||||
|             assert_image_equal(target, im) | ||||
| 
 | ||||
|     def test_sanity_dxt3(self): | ||||
|         """Check DXT3 images can be opened""" | ||||
| 
 | ||||
|         with Image.open(TEST_FILE_DXT3.replace(".dds", ".png")) as target: | ||||
|             with Image.open(TEST_FILE_DXT3) as im: | ||||
|                 im.load() | ||||
| def test_dx10_bc7(): | ||||
|     """Check DX10 images can be opened""" | ||||
| 
 | ||||
|                 self.assertEqual(im.format, "DDS") | ||||
|                 self.assertEqual(im.mode, "RGBA") | ||||
|                 self.assertEqual(im.size, (256, 256)) | ||||
|     with Image.open(TEST_FILE_DX10_BC7) as im: | ||||
|         im.load() | ||||
| 
 | ||||
|                 assert_image_equal(target, im) | ||||
|         assert im.format == "DDS" | ||||
|         assert im.mode == "RGBA" | ||||
|         assert im.size == (256, 256) | ||||
| 
 | ||||
|     def test_dx10_bc7(self): | ||||
|         """Check DX10 images can be opened""" | ||||
|         with Image.open(TEST_FILE_DX10_BC7.replace(".dds", ".png")) as target: | ||||
|             assert_image_equal(target, im) | ||||
| 
 | ||||
|         with Image.open(TEST_FILE_DX10_BC7) as im: | ||||
| 
 | ||||
| def test_dx10_bc7_unorm_srgb(): | ||||
|     """Check DX10 unsigned normalized integer images can be opened""" | ||||
| 
 | ||||
|     with Image.open(TEST_FILE_DX10_BC7_UNORM_SRGB) as im: | ||||
|         im.load() | ||||
| 
 | ||||
|         assert im.format == "DDS" | ||||
|         assert im.mode == "RGBA" | ||||
|         assert im.size == (16, 16) | ||||
|         assert im.info["gamma"] == 1 / 2.2 | ||||
| 
 | ||||
|         with Image.open( | ||||
|             TEST_FILE_DX10_BC7_UNORM_SRGB.replace(".dds", ".png") | ||||
|         ) as target: | ||||
|             assert_image_equal(target, im) | ||||
| 
 | ||||
| 
 | ||||
| def test_unimplemented_dxgi_format(): | ||||
|     with pytest.raises(NotImplementedError): | ||||
|         Image.open("Tests/images/unimplemented_dxgi_format.dds",) | ||||
| 
 | ||||
| 
 | ||||
| def test_uncompressed_rgb(): | ||||
|     """Check uncompressed RGB images can be opened""" | ||||
| 
 | ||||
|     with Image.open(TEST_FILE_UNCOMPRESSED_RGB) as im: | ||||
|         im.load() | ||||
| 
 | ||||
|         assert im.format == "DDS" | ||||
|         assert im.mode == "RGBA" | ||||
|         assert im.size == (800, 600) | ||||
| 
 | ||||
|         with Image.open(TEST_FILE_UNCOMPRESSED_RGB.replace(".dds", ".png")) as target: | ||||
|             assert_image_equal(target, im) | ||||
| 
 | ||||
| 
 | ||||
| def test__validate_true(): | ||||
|     """Check valid prefix""" | ||||
|     # Arrange | ||||
|     prefix = b"DDS etc" | ||||
| 
 | ||||
|     # Act | ||||
|     output = DdsImagePlugin._validate(prefix) | ||||
| 
 | ||||
|     # Assert | ||||
|     assert output | ||||
| 
 | ||||
| 
 | ||||
| def test__validate_false(): | ||||
|     """Check invalid prefix""" | ||||
|     # Arrange | ||||
|     prefix = b"something invalid" | ||||
| 
 | ||||
|     # Act | ||||
|     output = DdsImagePlugin._validate(prefix) | ||||
| 
 | ||||
|     # Assert | ||||
|     assert not output | ||||
| 
 | ||||
| 
 | ||||
| def test_short_header(): | ||||
|     """ Check a short header""" | ||||
|     with open(TEST_FILE_DXT5, "rb") as f: | ||||
|         img_file = f.read() | ||||
| 
 | ||||
|     def short_header(): | ||||
|         Image.open(BytesIO(img_file[:119])) | ||||
| 
 | ||||
|     with pytest.raises(IOError): | ||||
|         short_header() | ||||
| 
 | ||||
| 
 | ||||
| def test_short_file(): | ||||
|     """ Check that the appropriate error is thrown for a short file""" | ||||
| 
 | ||||
|     with open(TEST_FILE_DXT5, "rb") as f: | ||||
|         img_file = f.read() | ||||
| 
 | ||||
|     def short_file(): | ||||
|         with Image.open(BytesIO(img_file[:-100])) as im: | ||||
|             im.load() | ||||
| 
 | ||||
|             self.assertEqual(im.format, "DDS") | ||||
|             self.assertEqual(im.mode, "RGBA") | ||||
|             self.assertEqual(im.size, (256, 256)) | ||||
|     with pytest.raises(IOError): | ||||
|         short_file() | ||||
| 
 | ||||
|             with Image.open(TEST_FILE_DX10_BC7.replace(".dds", ".png")) as target: | ||||
|                 assert_image_equal(target, im) | ||||
| 
 | ||||
|     def test_dx10_bc7_unorm_srgb(self): | ||||
|         """Check DX10 unsigned normalized integer images can be opened""" | ||||
| 
 | ||||
|         with Image.open(TEST_FILE_DX10_BC7_UNORM_SRGB) as im: | ||||
|             im.load() | ||||
| 
 | ||||
|             self.assertEqual(im.format, "DDS") | ||||
|             self.assertEqual(im.mode, "RGBA") | ||||
|             self.assertEqual(im.size, (16, 16)) | ||||
|             self.assertEqual(im.info["gamma"], 1 / 2.2) | ||||
| 
 | ||||
|             with Image.open( | ||||
|                 TEST_FILE_DX10_BC7_UNORM_SRGB.replace(".dds", ".png") | ||||
|             ) as target: | ||||
|                 assert_image_equal(target, im) | ||||
| 
 | ||||
|     def test_unimplemented_dxgi_format(self): | ||||
|         self.assertRaises( | ||||
|             NotImplementedError, | ||||
|             Image.open, | ||||
|             "Tests/images/unimplemented_dxgi_format.dds", | ||||
|         ) | ||||
| 
 | ||||
|     def test_uncompressed_rgb(self): | ||||
|         """Check uncompressed RGB images can be opened""" | ||||
| 
 | ||||
|         with Image.open(TEST_FILE_UNCOMPRESSED_RGB) as im: | ||||
|             im.load() | ||||
| 
 | ||||
|             self.assertEqual(im.format, "DDS") | ||||
|             self.assertEqual(im.mode, "RGBA") | ||||
|             self.assertEqual(im.size, (800, 600)) | ||||
| 
 | ||||
|             with Image.open( | ||||
|                 TEST_FILE_UNCOMPRESSED_RGB.replace(".dds", ".png") | ||||
|             ) as target: | ||||
|                 assert_image_equal(target, im) | ||||
| 
 | ||||
|     def test__validate_true(self): | ||||
|         """Check valid prefix""" | ||||
|         # Arrange | ||||
|         prefix = b"DDS etc" | ||||
| 
 | ||||
|         # Act | ||||
|         output = DdsImagePlugin._validate(prefix) | ||||
| 
 | ||||
|         # Assert | ||||
|         self.assertTrue(output) | ||||
| 
 | ||||
|     def test__validate_false(self): | ||||
|         """Check invalid prefix""" | ||||
|         # Arrange | ||||
|         prefix = b"something invalid" | ||||
| 
 | ||||
|         # Act | ||||
|         output = DdsImagePlugin._validate(prefix) | ||||
| 
 | ||||
|         # Assert | ||||
|         self.assertFalse(output) | ||||
| 
 | ||||
|     def test_short_header(self): | ||||
|         """ Check a short header""" | ||||
|         with open(TEST_FILE_DXT5, "rb") as f: | ||||
|             img_file = f.read() | ||||
| 
 | ||||
|         def short_header(): | ||||
|             Image.open(BytesIO(img_file[:119])) | ||||
| 
 | ||||
|         self.assertRaises(IOError, short_header) | ||||
| 
 | ||||
|     def test_short_file(self): | ||||
|         """ Check that the appropriate error is thrown for a short file""" | ||||
| 
 | ||||
|         with open(TEST_FILE_DXT5, "rb") as f: | ||||
|             img_file = f.read() | ||||
| 
 | ||||
|         def short_file(): | ||||
|             with Image.open(BytesIO(img_file[:-100])) as im: | ||||
|                 im.load() | ||||
| 
 | ||||
|         self.assertRaises(IOError, short_file) | ||||
| 
 | ||||
|     def test_unimplemented_pixel_format(self): | ||||
|         self.assertRaises( | ||||
|             NotImplementedError, | ||||
|             Image.open, | ||||
|             "Tests/images/unimplemented_pixel_format.dds", | ||||
|         ) | ||||
| def test_unimplemented_pixel_format(): | ||||
|     with pytest.raises(NotImplementedError): | ||||
|         Image.open("Tests/images/unimplemented_pixel_format.dds",) | ||||
|  |  | |||
|  | @ -1,9 +1,7 @@ | |||
| import unittest | ||||
| 
 | ||||
| import pytest | ||||
| from PIL import FliImagePlugin, Image | ||||
| 
 | ||||
| from .helper import PillowTestCase, assert_image_equal, is_pypy | ||||
| from .helper import assert_image_equal, is_pypy | ||||
| 
 | ||||
| # created as an export of a palette image from Gimp2.6 | ||||
| # save as...-> hopper.fli, default options. | ||||
|  | @ -13,105 +11,115 @@ static_test_file = "Tests/images/hopper.fli" | |||
| animated_test_file = "Tests/images/a.fli" | ||||
| 
 | ||||
| 
 | ||||
| class TestFileFli(PillowTestCase): | ||||
|     def test_sanity(self): | ||||
| def test_sanity(): | ||||
|     with Image.open(static_test_file) as im: | ||||
|         im.load() | ||||
|         assert im.mode == "P" | ||||
|         assert im.size == (128, 128) | ||||
|         assert im.format == "FLI" | ||||
|         assert not im.is_animated | ||||
| 
 | ||||
|     with Image.open(animated_test_file) as im: | ||||
|         assert im.mode == "P" | ||||
|         assert im.size == (320, 200) | ||||
|         assert im.format == "FLI" | ||||
|         assert im.info["duration"] == 71 | ||||
|         assert im.is_animated | ||||
| 
 | ||||
| 
 | ||||
| @pytest.mark.skipif(is_pypy(), reason="Requires CPython") | ||||
| def test_unclosed_file(): | ||||
|     def open(): | ||||
|         im = Image.open(static_test_file) | ||||
|         im.load() | ||||
| 
 | ||||
|     pytest.warns(ResourceWarning, open) | ||||
| 
 | ||||
| 
 | ||||
| def test_closed_file(): | ||||
|     def open(): | ||||
|         im = Image.open(static_test_file) | ||||
|         im.load() | ||||
|         im.close() | ||||
| 
 | ||||
|     pytest.warns(None, open) | ||||
| 
 | ||||
| 
 | ||||
| def test_context_manager(): | ||||
|     def open(): | ||||
|         with Image.open(static_test_file) as im: | ||||
|             im.load() | ||||
|             self.assertEqual(im.mode, "P") | ||||
|             self.assertEqual(im.size, (128, 128)) | ||||
|             self.assertEqual(im.format, "FLI") | ||||
|             self.assertFalse(im.is_animated) | ||||
| 
 | ||||
|         with Image.open(animated_test_file) as im: | ||||
|             self.assertEqual(im.mode, "P") | ||||
|             self.assertEqual(im.size, (320, 200)) | ||||
|             self.assertEqual(im.format, "FLI") | ||||
|             self.assertEqual(im.info["duration"], 71) | ||||
|             self.assertTrue(im.is_animated) | ||||
|     pytest.warns(None, open) | ||||
| 
 | ||||
|     @unittest.skipIf(is_pypy(), "Requires CPython") | ||||
|     def test_unclosed_file(self): | ||||
|         def open(): | ||||
|             im = Image.open(static_test_file) | ||||
|             im.load() | ||||
| 
 | ||||
|         pytest.warns(ResourceWarning, open) | ||||
| def test_tell(): | ||||
|     # Arrange | ||||
|     with Image.open(static_test_file) as im: | ||||
| 
 | ||||
|     def test_closed_file(self): | ||||
|         def open(): | ||||
|             im = Image.open(static_test_file) | ||||
|             im.load() | ||||
|             im.close() | ||||
|         # Act | ||||
|         frame = im.tell() | ||||
| 
 | ||||
|         pytest.warns(None, open) | ||||
|         # Assert | ||||
|         assert frame == 0 | ||||
| 
 | ||||
|     def test_context_manager(self): | ||||
|         def open(): | ||||
|             with Image.open(static_test_file) as im: | ||||
|                 im.load() | ||||
| 
 | ||||
|         pytest.warns(None, open) | ||||
| def test_invalid_file(): | ||||
|     invalid_file = "Tests/images/flower.jpg" | ||||
| 
 | ||||
|     def test_tell(self): | ||||
|         # Arrange | ||||
|         with Image.open(static_test_file) as im: | ||||
|     with pytest.raises(SyntaxError): | ||||
|         FliImagePlugin.FliImageFile(invalid_file) | ||||
| 
 | ||||
|             # Act | ||||
|             frame = im.tell() | ||||
| 
 | ||||
|             # Assert | ||||
|             self.assertEqual(frame, 0) | ||||
| def test_n_frames(): | ||||
|     with Image.open(static_test_file) as im: | ||||
|         assert im.n_frames == 1 | ||||
|         assert not im.is_animated | ||||
| 
 | ||||
|     def test_invalid_file(self): | ||||
|         invalid_file = "Tests/images/flower.jpg" | ||||
|     with Image.open(animated_test_file) as im: | ||||
|         assert im.n_frames == 384 | ||||
|         assert im.is_animated | ||||
| 
 | ||||
|         self.assertRaises(SyntaxError, FliImagePlugin.FliImageFile, invalid_file) | ||||
| 
 | ||||
|     def test_n_frames(self): | ||||
|         with Image.open(static_test_file) as im: | ||||
|             self.assertEqual(im.n_frames, 1) | ||||
|             self.assertFalse(im.is_animated) | ||||
| def test_eoferror(): | ||||
|     with Image.open(animated_test_file) as im: | ||||
|         n_frames = im.n_frames | ||||
| 
 | ||||
|         with Image.open(animated_test_file) as im: | ||||
|             self.assertEqual(im.n_frames, 384) | ||||
|             self.assertTrue(im.is_animated) | ||||
|         # Test seeking past the last frame | ||||
|         with pytest.raises(EOFError): | ||||
|             im.seek(n_frames) | ||||
|         assert im.tell() < n_frames | ||||
| 
 | ||||
|     def test_eoferror(self): | ||||
|         with Image.open(animated_test_file) as im: | ||||
|             n_frames = im.n_frames | ||||
|         # Test that seeking to the last frame does not raise an error | ||||
|         im.seek(n_frames - 1) | ||||
| 
 | ||||
|             # Test seeking past the last frame | ||||
|             self.assertRaises(EOFError, im.seek, n_frames) | ||||
|             self.assertLess(im.tell(), n_frames) | ||||
| 
 | ||||
|             # Test that seeking to the last frame does not raise an error | ||||
|             im.seek(n_frames - 1) | ||||
| def test_seek_tell(): | ||||
|     with Image.open(animated_test_file) as im: | ||||
| 
 | ||||
|     def test_seek_tell(self): | ||||
|         with Image.open(animated_test_file) as im: | ||||
|         layer_number = im.tell() | ||||
|         assert layer_number == 0 | ||||
| 
 | ||||
|             layer_number = im.tell() | ||||
|             self.assertEqual(layer_number, 0) | ||||
|         im.seek(0) | ||||
|         layer_number = im.tell() | ||||
|         assert layer_number == 0 | ||||
| 
 | ||||
|             im.seek(0) | ||||
|             layer_number = im.tell() | ||||
|             self.assertEqual(layer_number, 0) | ||||
|         im.seek(1) | ||||
|         layer_number = im.tell() | ||||
|         assert layer_number == 1 | ||||
| 
 | ||||
|             im.seek(1) | ||||
|             layer_number = im.tell() | ||||
|             self.assertEqual(layer_number, 1) | ||||
|         im.seek(2) | ||||
|         layer_number = im.tell() | ||||
|         assert layer_number == 2 | ||||
| 
 | ||||
|             im.seek(2) | ||||
|             layer_number = im.tell() | ||||
|             self.assertEqual(layer_number, 2) | ||||
|         im.seek(1) | ||||
|         layer_number = im.tell() | ||||
|         assert layer_number == 1 | ||||
| 
 | ||||
|             im.seek(1) | ||||
|             layer_number = im.tell() | ||||
|             self.assertEqual(layer_number, 1) | ||||
| 
 | ||||
|     def test_seek(self): | ||||
|         with Image.open(animated_test_file) as im: | ||||
|             im.seek(50) | ||||
| def test_seek(): | ||||
|     with Image.open(animated_test_file) as im: | ||||
|         im.seek(50) | ||||
| 
 | ||||
|             with Image.open("Tests/images/a_fli.png") as expected: | ||||
|                 assert_image_equal(im, expected) | ||||
|         with Image.open("Tests/images/a_fli.png") as expected: | ||||
|             assert_image_equal(im, expected) | ||||
|  |  | |||
|  | @ -1,9 +1,6 @@ | |||
| import unittest | ||||
| 
 | ||||
| import pytest | ||||
| from PIL import Image | ||||
| 
 | ||||
| from .helper import PillowTestCase | ||||
| 
 | ||||
| try: | ||||
|     from PIL import FpxImagePlugin | ||||
| except ImportError: | ||||
|  | @ -11,18 +8,23 @@ except ImportError: | |||
| else: | ||||
|     olefile_installed = True | ||||
| 
 | ||||
| pytestmark = pytest.mark.skipif( | ||||
|     not olefile_installed, reason="olefile package not installed" | ||||
| ) | ||||
| 
 | ||||
| @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) | ||||
| 
 | ||||
|         # 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) | ||||
| def test_invalid_file(): | ||||
|     # Test an invalid OLE file | ||||
|     invalid_file = "Tests/images/flower.jpg" | ||||
|     with pytest.raises(SyntaxError): | ||||
|         FpxImagePlugin.FpxImageFile(invalid_file) | ||||
| 
 | ||||
|     def test_fpx_invalid_number_of_bands(self): | ||||
|         with self.assertRaisesRegex(IOError, "Invalid number of bands"): | ||||
|             Image.open("Tests/images/input_bw_five_bands.fpx") | ||||
|     # Test a valid OLE file, but not an FPX file | ||||
|     ole_file = "Tests/images/test-ole-file.doc" | ||||
|     with pytest.raises(SyntaxError): | ||||
|         FpxImagePlugin.FpxImageFile(ole_file) | ||||
| 
 | ||||
| 
 | ||||
| def test_fpx_invalid_number_of_bands(): | ||||
|     with pytest.raises(IOError, match="Invalid number of bands"): | ||||
|         Image.open("Tests/images/input_bw_five_bands.fpx") | ||||
|  |  | |||
|  | @ -1,15 +1,17 @@ | |||
| import pytest | ||||
| from PIL import GbrImagePlugin, Image | ||||
| 
 | ||||
| from .helper import PillowTestCase, assert_image_equal | ||||
| from .helper import assert_image_equal | ||||
| 
 | ||||
| 
 | ||||
| class TestFileGbr(PillowTestCase): | ||||
|     def test_invalid_file(self): | ||||
|         invalid_file = "Tests/images/flower.jpg" | ||||
| def test_invalid_file(): | ||||
|     invalid_file = "Tests/images/flower.jpg" | ||||
| 
 | ||||
|         self.assertRaises(SyntaxError, GbrImagePlugin.GbrImageFile, invalid_file) | ||||
|     with pytest.raises(SyntaxError): | ||||
|         GbrImagePlugin.GbrImageFile(invalid_file) | ||||
| 
 | ||||
|     def test_gbr_file(self): | ||||
|         with Image.open("Tests/images/gbr.gbr") as im: | ||||
|             with Image.open("Tests/images/gbr.png") as target: | ||||
|                 assert_image_equal(target, im) | ||||
| 
 | ||||
| def test_gbr_file(): | ||||
|     with Image.open("Tests/images/gbr.gbr") as im: | ||||
|         with Image.open("Tests/images/gbr.png") as target: | ||||
|             assert_image_equal(target, im) | ||||
|  |  | |||
|  | @ -1,122 +1,128 @@ | |||
| from PIL import GimpGradientFile | ||||
| 
 | ||||
| from .helper import PillowTestCase | ||||
| 
 | ||||
| def test_linear_pos_le_middle(): | ||||
|     # Arrange | ||||
|     middle = 0.5 | ||||
|     pos = 0.25 | ||||
| 
 | ||||
|     # Act | ||||
|     ret = GimpGradientFile.linear(middle, pos) | ||||
| 
 | ||||
|     # Assert | ||||
|     assert ret == 0.25 | ||||
| 
 | ||||
| 
 | ||||
| class TestImage(PillowTestCase): | ||||
|     def test_linear_pos_le_middle(self): | ||||
|         # Arrange | ||||
|         middle = 0.5 | ||||
|         pos = 0.25 | ||||
| def test_linear_pos_le_small_middle(): | ||||
|     # Arrange | ||||
|     middle = 1e-11 | ||||
|     pos = 1e-12 | ||||
| 
 | ||||
|         # Act | ||||
|         ret = GimpGradientFile.linear(middle, pos) | ||||
|     # Act | ||||
|     ret = GimpGradientFile.linear(middle, pos) | ||||
| 
 | ||||
|         # Assert | ||||
|         self.assertEqual(ret, 0.25) | ||||
|     # Assert | ||||
|     assert ret == 0.0 | ||||
| 
 | ||||
|     def test_linear_pos_le_small_middle(self): | ||||
|         # Arrange | ||||
|         middle = 1e-11 | ||||
|         pos = 1e-12 | ||||
| 
 | ||||
|         # Act | ||||
|         ret = GimpGradientFile.linear(middle, pos) | ||||
| def test_linear_pos_gt_middle(): | ||||
|     # Arrange | ||||
|     middle = 0.5 | ||||
|     pos = 0.75 | ||||
| 
 | ||||
|         # Assert | ||||
|         self.assertEqual(ret, 0.0) | ||||
|     # Act | ||||
|     ret = GimpGradientFile.linear(middle, pos) | ||||
| 
 | ||||
|     def test_linear_pos_gt_middle(self): | ||||
|         # Arrange | ||||
|         middle = 0.5 | ||||
|         pos = 0.75 | ||||
|     # Assert | ||||
|     assert ret == 0.75 | ||||
| 
 | ||||
|         # Act | ||||
|         ret = GimpGradientFile.linear(middle, pos) | ||||
| 
 | ||||
|         # Assert | ||||
|         self.assertEqual(ret, 0.75) | ||||
| def test_linear_pos_gt_small_middle(): | ||||
|     # Arrange | ||||
|     middle = 1 - 1e-11 | ||||
|     pos = 1 - 1e-12 | ||||
| 
 | ||||
|     def test_linear_pos_gt_small_middle(self): | ||||
|         # Arrange | ||||
|         middle = 1 - 1e-11 | ||||
|         pos = 1 - 1e-12 | ||||
|     # Act | ||||
|     ret = GimpGradientFile.linear(middle, pos) | ||||
| 
 | ||||
|         # Act | ||||
|         ret = GimpGradientFile.linear(middle, pos) | ||||
|     # Assert | ||||
|     assert ret == 1.0 | ||||
| 
 | ||||
|         # Assert | ||||
|         self.assertEqual(ret, 1.0) | ||||
| 
 | ||||
|     def test_curved(self): | ||||
|         # Arrange | ||||
|         middle = 0.5 | ||||
|         pos = 0.75 | ||||
| def test_curved(): | ||||
|     # Arrange | ||||
|     middle = 0.5 | ||||
|     pos = 0.75 | ||||
| 
 | ||||
|         # Act | ||||
|         ret = GimpGradientFile.curved(middle, pos) | ||||
|     # Act | ||||
|     ret = GimpGradientFile.curved(middle, pos) | ||||
| 
 | ||||
|         # Assert | ||||
|         self.assertEqual(ret, 0.75) | ||||
|     # Assert | ||||
|     assert ret == 0.75 | ||||
| 
 | ||||
|     def test_sine(self): | ||||
|         # Arrange | ||||
|         middle = 0.5 | ||||
|         pos = 0.75 | ||||
| 
 | ||||
|         # Act | ||||
|         ret = GimpGradientFile.sine(middle, pos) | ||||
| def test_sine(): | ||||
|     # Arrange | ||||
|     middle = 0.5 | ||||
|     pos = 0.75 | ||||
| 
 | ||||
|         # Assert | ||||
|         self.assertEqual(ret, 0.8535533905932737) | ||||
|     # Act | ||||
|     ret = GimpGradientFile.sine(middle, pos) | ||||
| 
 | ||||
|     def test_sphere_increasing(self): | ||||
|         # Arrange | ||||
|         middle = 0.5 | ||||
|         pos = 0.75 | ||||
|     # Assert | ||||
|     assert ret == 0.8535533905932737 | ||||
| 
 | ||||
|         # Act | ||||
|         ret = GimpGradientFile.sphere_increasing(middle, pos) | ||||
| 
 | ||||
|         # Assert | ||||
|         self.assertAlmostEqual(ret, 0.9682458365518543) | ||||
| def test_sphere_increasing(): | ||||
|     # Arrange | ||||
|     middle = 0.5 | ||||
|     pos = 0.75 | ||||
| 
 | ||||
|     def test_sphere_decreasing(self): | ||||
|         # Arrange | ||||
|         middle = 0.5 | ||||
|         pos = 0.75 | ||||
|     # Act | ||||
|     ret = GimpGradientFile.sphere_increasing(middle, pos) | ||||
| 
 | ||||
|         # Act | ||||
|         ret = GimpGradientFile.sphere_decreasing(middle, pos) | ||||
|     # Assert | ||||
|     assert round(abs(ret - 0.9682458365518543), 7) == 0 | ||||
| 
 | ||||
|         # Assert | ||||
|         self.assertEqual(ret, 0.3385621722338523) | ||||
| 
 | ||||
|     def test_load_via_imagepalette(self): | ||||
|         # Arrange | ||||
|         from PIL import ImagePalette | ||||
| def test_sphere_decreasing(): | ||||
|     # Arrange | ||||
|     middle = 0.5 | ||||
|     pos = 0.75 | ||||
| 
 | ||||
|         test_file = "Tests/images/gimp_gradient.ggr" | ||||
|     # Act | ||||
|     ret = GimpGradientFile.sphere_decreasing(middle, pos) | ||||
| 
 | ||||
|         # Act | ||||
|         palette = ImagePalette.load(test_file) | ||||
|     # Assert | ||||
|     assert ret == 0.3385621722338523 | ||||
| 
 | ||||
|         # Assert | ||||
|         # load returns raw palette information | ||||
|         self.assertEqual(len(palette[0]), 1024) | ||||
|         self.assertEqual(palette[1], "RGBA") | ||||
| 
 | ||||
|     def test_load_1_3_via_imagepalette(self): | ||||
|         # Arrange | ||||
|         from PIL import ImagePalette | ||||
| def test_load_via_imagepalette(): | ||||
|     # Arrange | ||||
|     from PIL import ImagePalette | ||||
| 
 | ||||
|         # GIMP 1.3 gradient files contain a name field | ||||
|         test_file = "Tests/images/gimp_gradient_with_name.ggr" | ||||
|     test_file = "Tests/images/gimp_gradient.ggr" | ||||
| 
 | ||||
|         # Act | ||||
|         palette = ImagePalette.load(test_file) | ||||
|     # Act | ||||
|     palette = ImagePalette.load(test_file) | ||||
| 
 | ||||
|         # Assert | ||||
|         # load returns raw palette information | ||||
|         self.assertEqual(len(palette[0]), 1024) | ||||
|         self.assertEqual(palette[1], "RGBA") | ||||
|     # Assert | ||||
|     # load returns raw palette information | ||||
|     assert len(palette[0]) == 1024 | ||||
|     assert palette[1] == "RGBA" | ||||
| 
 | ||||
| 
 | ||||
| def test_load_1_3_via_imagepalette(): | ||||
|     # Arrange | ||||
|     from PIL import ImagePalette | ||||
| 
 | ||||
|     # GIMP 1.3 gradient files contain a name field | ||||
|     test_file = "Tests/images/gimp_gradient_with_name.ggr" | ||||
| 
 | ||||
|     # Act | ||||
|     palette = ImagePalette.load(test_file) | ||||
| 
 | ||||
|     # Assert | ||||
|     # load returns raw palette information | ||||
|     assert len(palette[0]) == 1024 | ||||
|     assert palette[1] == "RGBA" | ||||
|  |  | |||
|  | @ -1,28 +1,30 @@ | |||
| import pytest | ||||
| from PIL import Image, McIdasImagePlugin | ||||
| 
 | ||||
| from .helper import PillowTestCase, assert_image_equal | ||||
| from .helper import assert_image_equal | ||||
| 
 | ||||
| 
 | ||||
| class TestFileMcIdas(PillowTestCase): | ||||
|     def test_invalid_file(self): | ||||
|         invalid_file = "Tests/images/flower.jpg" | ||||
| def test_invalid_file(): | ||||
|     invalid_file = "Tests/images/flower.jpg" | ||||
| 
 | ||||
|         self.assertRaises(SyntaxError, McIdasImagePlugin.McIdasImageFile, invalid_file) | ||||
|     with pytest.raises(SyntaxError): | ||||
|         McIdasImagePlugin.McIdasImageFile(invalid_file) | ||||
| 
 | ||||
|     def test_valid_file(self): | ||||
|         # Arrange | ||||
|         # https://ghrc.nsstc.nasa.gov/hydro/details/cmx3g8 | ||||
|         # https://ghrc.nsstc.nasa.gov/pub/fieldCampaigns/camex3/cmx3g8/browse/ | ||||
|         test_file = "Tests/images/cmx3g8_wv_1998.260_0745_mcidas.ara" | ||||
|         saved_file = "Tests/images/cmx3g8_wv_1998.260_0745_mcidas.png" | ||||
| 
 | ||||
|         # Act | ||||
|         with Image.open(test_file) as im: | ||||
|             im.load() | ||||
| def test_valid_file(): | ||||
|     # Arrange | ||||
|     # https://ghrc.nsstc.nasa.gov/hydro/details/cmx3g8 | ||||
|     # https://ghrc.nsstc.nasa.gov/pub/fieldCampaigns/camex3/cmx3g8/browse/ | ||||
|     test_file = "Tests/images/cmx3g8_wv_1998.260_0745_mcidas.ara" | ||||
|     saved_file = "Tests/images/cmx3g8_wv_1998.260_0745_mcidas.png" | ||||
| 
 | ||||
|             # Assert | ||||
|             self.assertEqual(im.format, "MCIDAS") | ||||
|             self.assertEqual(im.mode, "I") | ||||
|             self.assertEqual(im.size, (1800, 400)) | ||||
|             with Image.open(saved_file) as im2: | ||||
|                 assert_image_equal(im, im2) | ||||
|     # Act | ||||
|     with Image.open(test_file) as im: | ||||
|         im.load() | ||||
| 
 | ||||
|         # Assert | ||||
|         assert im.format == "MCIDAS" | ||||
|         assert im.mode == "I" | ||||
|         assert im.size == (1800, 400) | ||||
|         with Image.open(saved_file) as im2: | ||||
|             assert_image_equal(im, im2) | ||||
|  |  | |||
|  | @ -1,8 +1,7 @@ | |||
| import unittest | ||||
| 
 | ||||
| import pytest | ||||
| from PIL import Image, ImagePalette, features | ||||
| 
 | ||||
| from .helper import PillowTestCase, assert_image_similar, hopper | ||||
| from .helper import assert_image_similar, hopper | ||||
| 
 | ||||
| try: | ||||
|     from PIL import MicImagePlugin | ||||
|  | @ -14,52 +13,59 @@ else: | |||
| TEST_FILE = "Tests/images/hopper.mic" | ||||
| 
 | ||||
| 
 | ||||
| @unittest.skipUnless(olefile_installed, "olefile package not installed") | ||||
| @unittest.skipUnless(features.check("libtiff"), "libtiff not installed") | ||||
| class TestFileMic(PillowTestCase): | ||||
|     def test_sanity(self): | ||||
|         with Image.open(TEST_FILE) as im: | ||||
|             im.load() | ||||
|             self.assertEqual(im.mode, "RGBA") | ||||
|             self.assertEqual(im.size, (128, 128)) | ||||
|             self.assertEqual(im.format, "MIC") | ||||
| pytestmark = [ | ||||
|     pytest.mark.skipif(not olefile_installed, reason="olefile package not installed"), | ||||
|     pytest.mark.skipif(not features.check("libtiff"), reason="libtiff not installed"), | ||||
| ] | ||||
| 
 | ||||
|             # Adjust for the gamma of 2.2 encoded into the file | ||||
|             lut = ImagePalette.make_gamma_lut(1 / 2.2) | ||||
|             im = Image.merge("RGBA", [chan.point(lut) for chan in im.split()]) | ||||
| 
 | ||||
|             im2 = hopper("RGBA") | ||||
|             assert_image_similar(im, im2, 10) | ||||
| def test_sanity(): | ||||
|     with Image.open(TEST_FILE) as im: | ||||
|         im.load() | ||||
|         assert im.mode == "RGBA" | ||||
|         assert im.size == (128, 128) | ||||
|         assert im.format == "MIC" | ||||
| 
 | ||||
|     def test_n_frames(self): | ||||
|         with Image.open(TEST_FILE) as im: | ||||
|         # Adjust for the gamma of 2.2 encoded into the file | ||||
|         lut = ImagePalette.make_gamma_lut(1 / 2.2) | ||||
|         im = Image.merge("RGBA", [chan.point(lut) for chan in im.split()]) | ||||
| 
 | ||||
|             self.assertEqual(im.n_frames, 1) | ||||
|         im2 = hopper("RGBA") | ||||
|         assert_image_similar(im, im2, 10) | ||||
| 
 | ||||
|     def test_is_animated(self): | ||||
|         with Image.open(TEST_FILE) as im: | ||||
| 
 | ||||
|             self.assertFalse(im.is_animated) | ||||
| def test_n_frames(): | ||||
|     with Image.open(TEST_FILE) as im: | ||||
|         assert im.n_frames == 1 | ||||
| 
 | ||||
|     def test_tell(self): | ||||
|         with Image.open(TEST_FILE) as im: | ||||
| 
 | ||||
|             self.assertEqual(im.tell(), 0) | ||||
| def test_is_animated(): | ||||
|     with Image.open(TEST_FILE) as im: | ||||
|         assert not im.is_animated | ||||
| 
 | ||||
|     def test_seek(self): | ||||
|         with Image.open(TEST_FILE) as im: | ||||
| 
 | ||||
|             im.seek(0) | ||||
|             self.assertEqual(im.tell(), 0) | ||||
| def test_tell(): | ||||
|     with Image.open(TEST_FILE) as im: | ||||
|         assert im.tell() == 0 | ||||
| 
 | ||||
|             self.assertRaises(EOFError, im.seek, 99) | ||||
|             self.assertEqual(im.tell(), 0) | ||||
| 
 | ||||
|     def test_invalid_file(self): | ||||
|         # Test an invalid OLE file | ||||
|         invalid_file = "Tests/images/flower.jpg" | ||||
|         self.assertRaises(SyntaxError, MicImagePlugin.MicImageFile, invalid_file) | ||||
| def test_seek(): | ||||
|     with Image.open(TEST_FILE) as im: | ||||
|         im.seek(0) | ||||
|         assert im.tell() == 0 | ||||
| 
 | ||||
|         # Test a valid OLE file, but not a MIC file | ||||
|         ole_file = "Tests/images/test-ole-file.doc" | ||||
|         self.assertRaises(SyntaxError, MicImagePlugin.MicImageFile, ole_file) | ||||
|         with pytest.raises(EOFError): | ||||
|             im.seek(99) | ||||
|         assert im.tell() == 0 | ||||
| 
 | ||||
| 
 | ||||
| def test_invalid_file(): | ||||
|     # Test an invalid OLE file | ||||
|     invalid_file = "Tests/images/flower.jpg" | ||||
|     with pytest.raises(SyntaxError): | ||||
|         MicImagePlugin.MicImageFile(invalid_file) | ||||
| 
 | ||||
|     # Test a valid OLE file, but not a MIC file | ||||
|     ole_file = "Tests/images/test-ole-file.doc" | ||||
|     with pytest.raises(SyntaxError): | ||||
|         MicImagePlugin.MicImageFile(ole_file) | ||||
|  |  | |||
|  | @ -1,202 +1,221 @@ | |||
| import unittest | ||||
| from io import BytesIO | ||||
| 
 | ||||
| import pytest | ||||
| from PIL import Image | ||||
| 
 | ||||
| from .helper import PillowTestCase, assert_image_similar, is_pypy | ||||
| from .helper import assert_image_similar, is_pypy | ||||
| 
 | ||||
| test_files = ["Tests/images/sugarshack.mpo", "Tests/images/frozenpond.mpo"] | ||||
| 
 | ||||
| 
 | ||||
| class TestFileMpo(PillowTestCase): | ||||
|     def setUp(self): | ||||
|         codecs = dir(Image.core) | ||||
|         if "jpeg_encoder" not in codecs or "jpeg_decoder" not in codecs: | ||||
|             self.skipTest("jpeg support not available") | ||||
| def setup_module(): | ||||
|     codecs = dir(Image.core) | ||||
|     if "jpeg_encoder" not in codecs or "jpeg_decoder" not in codecs: | ||||
|         pytest.skip("jpeg support not available") | ||||
| 
 | ||||
|     def frame_roundtrip(self, im, **options): | ||||
|         # Note that for now, there is no MPO saving functionality | ||||
|         out = BytesIO() | ||||
|         im.save(out, "MPO", **options) | ||||
|         test_bytes = out.tell() | ||||
|         out.seek(0) | ||||
|         im = Image.open(out) | ||||
|         im.bytes = test_bytes  # for testing only | ||||
|         return im | ||||
| 
 | ||||
|     def test_sanity(self): | ||||
|         for test_file in test_files: | ||||
|             with Image.open(test_file) as im: | ||||
|                 im.load() | ||||
|                 self.assertEqual(im.mode, "RGB") | ||||
|                 self.assertEqual(im.size, (640, 480)) | ||||
|                 self.assertEqual(im.format, "MPO") | ||||
| def frame_roundtrip(im, **options): | ||||
|     # Note that for now, there is no MPO saving functionality | ||||
|     out = BytesIO() | ||||
|     im.save(out, "MPO", **options) | ||||
|     test_bytes = out.tell() | ||||
|     out.seek(0) | ||||
|     im = Image.open(out) | ||||
|     im.bytes = test_bytes  # for testing only | ||||
|     return im | ||||
| 
 | ||||
|     @unittest.skipIf(is_pypy(), "Requires CPython") | ||||
|     def test_unclosed_file(self): | ||||
|         def open(): | ||||
|             im = Image.open(test_files[0]) | ||||
| 
 | ||||
| def test_sanity(): | ||||
|     for test_file in test_files: | ||||
|         with Image.open(test_file) as im: | ||||
|             im.load() | ||||
|             assert im.mode == "RGB" | ||||
|             assert im.size == (640, 480) | ||||
|             assert im.format == "MPO" | ||||
| 
 | ||||
| 
 | ||||
| @pytest.mark.skipif(is_pypy(), reason="Requires CPython") | ||||
| def test_unclosed_file(): | ||||
|     def open(): | ||||
|         im = Image.open(test_files[0]) | ||||
|         im.load() | ||||
| 
 | ||||
|     pytest.warns(ResourceWarning, open) | ||||
| 
 | ||||
| 
 | ||||
| def test_closed_file(): | ||||
|     def open(): | ||||
|         im = Image.open(test_files[0]) | ||||
|         im.load() | ||||
|         im.close() | ||||
| 
 | ||||
|     pytest.warns(None, open) | ||||
| 
 | ||||
| 
 | ||||
| def test_context_manager(): | ||||
|     def open(): | ||||
|         with Image.open(test_files[0]) as im: | ||||
|             im.load() | ||||
| 
 | ||||
|         pytest.warns(ResourceWarning, open) | ||||
|     pytest.warns(None, open) | ||||
| 
 | ||||
|     def test_closed_file(self): | ||||
|         def open(): | ||||
|             im = Image.open(test_files[0]) | ||||
|             im.load() | ||||
|             im.close() | ||||
| 
 | ||||
|         pytest.warns(None, open) | ||||
| 
 | ||||
|     def test_context_manager(self): | ||||
|         def open(): | ||||
|             with Image.open(test_files[0]) as im: | ||||
|                 im.load() | ||||
| 
 | ||||
|         pytest.warns(None, open) | ||||
| 
 | ||||
|     def test_app(self): | ||||
|         for test_file in test_files: | ||||
|             # Test APP/COM reader (@PIL135) | ||||
|             with Image.open(test_file) as im: | ||||
|                 self.assertEqual(im.applist[0][0], "APP1") | ||||
|                 self.assertEqual(im.applist[1][0], "APP2") | ||||
|                 self.assertEqual( | ||||
|                     im.applist[1][1][:16], | ||||
|                     b"MPF\x00MM\x00*\x00\x00\x00\x08\x00\x03\xb0\x00", | ||||
|                 ) | ||||
|                 self.assertEqual(len(im.applist), 2) | ||||
| 
 | ||||
|     def test_exif(self): | ||||
|         for test_file in test_files: | ||||
|             with Image.open(test_file) as im: | ||||
|                 info = im._getexif() | ||||
|                 self.assertEqual(info[272], "Nintendo 3DS") | ||||
|                 self.assertEqual(info[296], 2) | ||||
|                 self.assertEqual(info[34665], 188) | ||||
| 
 | ||||
|     def test_frame_size(self): | ||||
|         # This image has been hexedited to contain a different size | ||||
|         # in the EXIF data of the second frame | ||||
|         with Image.open("Tests/images/sugarshack_frame_size.mpo") as im: | ||||
|             self.assertEqual(im.size, (640, 480)) | ||||
| 
 | ||||
|             im.seek(1) | ||||
|             self.assertEqual(im.size, (680, 480)) | ||||
| 
 | ||||
|     def test_parallax(self): | ||||
|         # Nintendo | ||||
|         with Image.open("Tests/images/sugarshack.mpo") as im: | ||||
|             exif = im.getexif() | ||||
|             self.assertEqual( | ||||
|                 exif.get_ifd(0x927C)[0x1101]["Parallax"], -44.798187255859375 | ||||
| def test_app(): | ||||
|     for test_file in test_files: | ||||
|         # Test APP/COM reader (@PIL135) | ||||
|         with Image.open(test_file) as im: | ||||
|             assert im.applist[0][0] == "APP1" | ||||
|             assert im.applist[1][0] == "APP2" | ||||
|             assert ( | ||||
|                 im.applist[1][1][:16] | ||||
|                 == b"MPF\x00MM\x00*\x00\x00\x00\x08\x00\x03\xb0\x00" | ||||
|             ) | ||||
|             assert len(im.applist) == 2 | ||||
| 
 | ||||
|         # Fujifilm | ||||
|         with Image.open("Tests/images/fujifilm.mpo") as im: | ||||
|             im.seek(1) | ||||
|             exif = im.getexif() | ||||
|             self.assertEqual(exif.get_ifd(0x927C)[0xB211], -3.125) | ||||
| 
 | ||||
|     def test_mp(self): | ||||
|         for test_file in test_files: | ||||
|             with Image.open(test_file) as im: | ||||
|                 mpinfo = im._getmp() | ||||
|                 self.assertEqual(mpinfo[45056], b"0100") | ||||
|                 self.assertEqual(mpinfo[45057], 2) | ||||
| def test_exif(): | ||||
|     for test_file in test_files: | ||||
|         with Image.open(test_file) as im: | ||||
|             info = im._getexif() | ||||
|             assert info[272] == "Nintendo 3DS" | ||||
|             assert info[296] == 2 | ||||
|             assert info[34665] == 188 | ||||
| 
 | ||||
|     def test_mp_offset(self): | ||||
|         # This image has been manually hexedited to have an IFD offset of 10 | ||||
|         # in APP2 data, in contrast to normal 8 | ||||
|         with Image.open("Tests/images/sugarshack_ifd_offset.mpo") as im: | ||||
| 
 | ||||
| def test_frame_size(): | ||||
|     # This image has been hexedited to contain a different size | ||||
|     # in the EXIF data of the second frame | ||||
|     with Image.open("Tests/images/sugarshack_frame_size.mpo") as im: | ||||
|         assert im.size == (640, 480) | ||||
| 
 | ||||
|         im.seek(1) | ||||
|         assert im.size == (680, 480) | ||||
| 
 | ||||
| 
 | ||||
| def test_parallax(): | ||||
|     # Nintendo | ||||
|     with Image.open("Tests/images/sugarshack.mpo") as im: | ||||
|         exif = im.getexif() | ||||
|         assert exif.get_ifd(0x927C)[0x1101]["Parallax"] == -44.798187255859375 | ||||
| 
 | ||||
|     # Fujifilm | ||||
|     with Image.open("Tests/images/fujifilm.mpo") as im: | ||||
|         im.seek(1) | ||||
|         exif = im.getexif() | ||||
|         assert exif.get_ifd(0x927C)[0xB211] == -3.125 | ||||
| 
 | ||||
| 
 | ||||
| def test_mp(): | ||||
|     for test_file in test_files: | ||||
|         with Image.open(test_file) as im: | ||||
|             mpinfo = im._getmp() | ||||
|             self.assertEqual(mpinfo[45056], b"0100") | ||||
|             self.assertEqual(mpinfo[45057], 2) | ||||
|             assert mpinfo[45056] == b"0100" | ||||
|             assert mpinfo[45057] == 2 | ||||
| 
 | ||||
|     def test_mp_no_data(self): | ||||
|         # This image has been manually hexedited to have the second frame | ||||
|         # beyond the end of the file | ||||
|         with Image.open("Tests/images/sugarshack_no_data.mpo") as im: | ||||
|             with self.assertRaises(ValueError): | ||||
|                 im.seek(1) | ||||
| 
 | ||||
|     def test_mp_attribute(self): | ||||
|         for test_file in test_files: | ||||
|             with Image.open(test_file) as im: | ||||
|                 mpinfo = im._getmp() | ||||
|             frameNumber = 0 | ||||
|             for mpentry in mpinfo[45058]: | ||||
|                 mpattr = mpentry["Attribute"] | ||||
|                 if frameNumber: | ||||
|                     self.assertFalse(mpattr["RepresentativeImageFlag"]) | ||||
|                 else: | ||||
|                     self.assertTrue(mpattr["RepresentativeImageFlag"]) | ||||
|                 self.assertFalse(mpattr["DependentParentImageFlag"]) | ||||
|                 self.assertFalse(mpattr["DependentChildImageFlag"]) | ||||
|                 self.assertEqual(mpattr["ImageDataFormat"], "JPEG") | ||||
|                 self.assertEqual(mpattr["MPType"], "Multi-Frame Image: (Disparity)") | ||||
|                 self.assertEqual(mpattr["Reserved"], 0) | ||||
|                 frameNumber += 1 | ||||
| def test_mp_offset(): | ||||
|     # This image has been manually hexedited to have an IFD offset of 10 | ||||
|     # in APP2 data, in contrast to normal 8 | ||||
|     with Image.open("Tests/images/sugarshack_ifd_offset.mpo") as im: | ||||
|         mpinfo = im._getmp() | ||||
|         assert mpinfo[45056] == b"0100" | ||||
|         assert mpinfo[45057] == 2 | ||||
| 
 | ||||
|     def test_seek(self): | ||||
|         for test_file in test_files: | ||||
|             with Image.open(test_file) as im: | ||||
|                 self.assertEqual(im.tell(), 0) | ||||
|                 # prior to first image raises an error, both blatant and borderline | ||||
|                 self.assertRaises(EOFError, im.seek, -1) | ||||
|                 self.assertRaises(EOFError, im.seek, -523) | ||||
|                 # after the final image raises an error, | ||||
|                 # both blatant and borderline | ||||
|                 self.assertRaises(EOFError, im.seek, 2) | ||||
|                 self.assertRaises(EOFError, im.seek, 523) | ||||
|                 # bad calls shouldn't change the frame | ||||
|                 self.assertEqual(im.tell(), 0) | ||||
|                 # this one will work | ||||
|                 im.seek(1) | ||||
|                 self.assertEqual(im.tell(), 1) | ||||
|                 # and this one, too | ||||
|                 im.seek(0) | ||||
|                 self.assertEqual(im.tell(), 0) | ||||
| 
 | ||||
|     def test_n_frames(self): | ||||
|         with Image.open("Tests/images/sugarshack.mpo") as im: | ||||
|             self.assertEqual(im.n_frames, 2) | ||||
|             self.assertTrue(im.is_animated) | ||||
| def test_mp_no_data(): | ||||
|     # This image has been manually hexedited to have the second frame | ||||
|     # beyond the end of the file | ||||
|     with Image.open("Tests/images/sugarshack_no_data.mpo") as im: | ||||
|         with pytest.raises(ValueError): | ||||
|             im.seek(1) | ||||
| 
 | ||||
|     def test_eoferror(self): | ||||
|         with Image.open("Tests/images/sugarshack.mpo") as im: | ||||
|             n_frames = im.n_frames | ||||
| 
 | ||||
|             # Test seeking past the last frame | ||||
|             self.assertRaises(EOFError, im.seek, n_frames) | ||||
|             self.assertLess(im.tell(), n_frames) | ||||
| def test_mp_attribute(): | ||||
|     for test_file in test_files: | ||||
|         with Image.open(test_file) as im: | ||||
|             mpinfo = im._getmp() | ||||
|         frameNumber = 0 | ||||
|         for mpentry in mpinfo[45058]: | ||||
|             mpattr = mpentry["Attribute"] | ||||
|             if frameNumber: | ||||
|                 assert not mpattr["RepresentativeImageFlag"] | ||||
|             else: | ||||
|                 assert mpattr["RepresentativeImageFlag"] | ||||
|             assert not mpattr["DependentParentImageFlag"] | ||||
|             assert not mpattr["DependentChildImageFlag"] | ||||
|             assert mpattr["ImageDataFormat"] == "JPEG" | ||||
|             assert mpattr["MPType"] == "Multi-Frame Image: (Disparity)" | ||||
|             assert mpattr["Reserved"] == 0 | ||||
|             frameNumber += 1 | ||||
| 
 | ||||
|             # Test that seeking to the last frame does not raise an error | ||||
|             im.seek(n_frames - 1) | ||||
| 
 | ||||
|     def test_image_grab(self): | ||||
|         for test_file in test_files: | ||||
|             with Image.open(test_file) as im: | ||||
|                 self.assertEqual(im.tell(), 0) | ||||
|                 im0 = im.tobytes() | ||||
|                 im.seek(1) | ||||
|                 self.assertEqual(im.tell(), 1) | ||||
|                 im1 = im.tobytes() | ||||
|                 im.seek(0) | ||||
|                 self.assertEqual(im.tell(), 0) | ||||
|                 im02 = im.tobytes() | ||||
|                 self.assertEqual(im0, im02) | ||||
|                 self.assertNotEqual(im0, im1) | ||||
| def test_seek(): | ||||
|     for test_file in test_files: | ||||
|         with Image.open(test_file) as im: | ||||
|             assert im.tell() == 0 | ||||
|             # prior to first image raises an error, both blatant and borderline | ||||
|             with pytest.raises(EOFError): | ||||
|                 im.seek(-1) | ||||
|             with pytest.raises(EOFError): | ||||
|                 im.seek(-523) | ||||
|             # after the final image raises an error, | ||||
|             # both blatant and borderline | ||||
|             with pytest.raises(EOFError): | ||||
|                 im.seek(2) | ||||
|             with pytest.raises(EOFError): | ||||
|                 im.seek(523) | ||||
|             # bad calls shouldn't change the frame | ||||
|             assert im.tell() == 0 | ||||
|             # this one will work | ||||
|             im.seek(1) | ||||
|             assert im.tell() == 1 | ||||
|             # and this one, too | ||||
|             im.seek(0) | ||||
|             assert im.tell() == 0 | ||||
| 
 | ||||
|     def test_save(self): | ||||
|         # Note that only individual frames can be saved at present | ||||
|         for test_file in test_files: | ||||
|             with Image.open(test_file) as im: | ||||
|                 self.assertEqual(im.tell(), 0) | ||||
|                 jpg0 = self.frame_roundtrip(im) | ||||
|                 assert_image_similar(im, jpg0, 30) | ||||
|                 im.seek(1) | ||||
|                 self.assertEqual(im.tell(), 1) | ||||
|                 jpg1 = self.frame_roundtrip(im) | ||||
|                 assert_image_similar(im, jpg1, 30) | ||||
| 
 | ||||
| def test_n_frames(): | ||||
|     with Image.open("Tests/images/sugarshack.mpo") as im: | ||||
|         assert im.n_frames == 2 | ||||
|         assert im.is_animated | ||||
| 
 | ||||
| 
 | ||||
| def test_eoferror(): | ||||
|     with Image.open("Tests/images/sugarshack.mpo") as im: | ||||
|         n_frames = im.n_frames | ||||
| 
 | ||||
|         # Test seeking past the last frame | ||||
|         with pytest.raises(EOFError): | ||||
|             im.seek(n_frames) | ||||
|         assert im.tell() < n_frames | ||||
| 
 | ||||
|         # Test that seeking to the last frame does not raise an error | ||||
|         im.seek(n_frames - 1) | ||||
| 
 | ||||
| 
 | ||||
| def test_image_grab(): | ||||
|     for test_file in test_files: | ||||
|         with Image.open(test_file) as im: | ||||
|             assert im.tell() == 0 | ||||
|             im0 = im.tobytes() | ||||
|             im.seek(1) | ||||
|             assert im.tell() == 1 | ||||
|             im1 = im.tobytes() | ||||
|             im.seek(0) | ||||
|             assert im.tell() == 0 | ||||
|             im02 = im.tobytes() | ||||
|             assert im0 == im02 | ||||
|             assert im0 != im1 | ||||
| 
 | ||||
| 
 | ||||
| def test_save(): | ||||
|     # Note that only individual frames can be saved at present | ||||
|     for test_file in test_files: | ||||
|         with Image.open(test_file) as im: | ||||
|             assert im.tell() == 0 | ||||
|             jpg0 = frame_roundtrip(im) | ||||
|             assert_image_similar(im, jpg0, 30) | ||||
|             im.seek(1) | ||||
|             assert im.tell() == 1 | ||||
|             jpg1 = frame_roundtrip(im) | ||||
|             assert_image_similar(im, jpg1, 30) | ||||
|  |  | |||
|  | @ -1,23 +1,25 @@ | |||
| import pytest | ||||
| from PIL import Image, PixarImagePlugin | ||||
| 
 | ||||
| from .helper import PillowTestCase, assert_image_similar, hopper | ||||
| from .helper import assert_image_similar, hopper | ||||
| 
 | ||||
| TEST_FILE = "Tests/images/hopper.pxr" | ||||
| 
 | ||||
| 
 | ||||
| class TestFilePixar(PillowTestCase): | ||||
|     def test_sanity(self): | ||||
|         with Image.open(TEST_FILE) as im: | ||||
|             im.load() | ||||
|             self.assertEqual(im.mode, "RGB") | ||||
|             self.assertEqual(im.size, (128, 128)) | ||||
|             self.assertEqual(im.format, "PIXAR") | ||||
|             self.assertIsNone(im.get_format_mimetype()) | ||||
| def test_sanity(): | ||||
|     with Image.open(TEST_FILE) as im: | ||||
|         im.load() | ||||
|         assert im.mode == "RGB" | ||||
|         assert im.size == (128, 128) | ||||
|         assert im.format == "PIXAR" | ||||
|         assert im.get_format_mimetype() is None | ||||
| 
 | ||||
|             im2 = hopper() | ||||
|             assert_image_similar(im, im2, 4.8) | ||||
|         im2 = hopper() | ||||
|         assert_image_similar(im, im2, 4.8) | ||||
| 
 | ||||
|     def test_invalid_file(self): | ||||
|         invalid_file = "Tests/images/flower.jpg" | ||||
| 
 | ||||
|         self.assertRaises(SyntaxError, PixarImagePlugin.PixarImageFile, invalid_file) | ||||
| def test_invalid_file(): | ||||
|     invalid_file = "Tests/images/flower.jpg" | ||||
| 
 | ||||
|     with pytest.raises(SyntaxError): | ||||
|         PixarImagePlugin.PixarImageFile(invalid_file) | ||||
|  |  | |||
|  | @ -1,116 +1,129 @@ | |||
| import unittest | ||||
| 
 | ||||
| import pytest | ||||
| from PIL import Image, PsdImagePlugin | ||||
| 
 | ||||
| from .helper import PillowTestCase, assert_image_similar, hopper, is_pypy | ||||
| from .helper import assert_image_similar, hopper, is_pypy | ||||
| 
 | ||||
| test_file = "Tests/images/hopper.psd" | ||||
| 
 | ||||
| 
 | ||||
| class TestImagePsd(PillowTestCase): | ||||
|     def test_sanity(self): | ||||
| def test_sanity(): | ||||
|     with Image.open(test_file) as im: | ||||
|         im.load() | ||||
|         assert im.mode == "RGB" | ||||
|         assert im.size == (128, 128) | ||||
|         assert im.format == "PSD" | ||||
| 
 | ||||
|         im2 = hopper() | ||||
|         assert_image_similar(im, im2, 4.8) | ||||
| 
 | ||||
| 
 | ||||
| @pytest.mark.skipif(is_pypy(), reason="Requires CPython") | ||||
| def test_unclosed_file(): | ||||
|     def open(): | ||||
|         im = Image.open(test_file) | ||||
|         im.load() | ||||
| 
 | ||||
|     pytest.warns(ResourceWarning, open) | ||||
| 
 | ||||
| 
 | ||||
| def test_closed_file(): | ||||
|     def open(): | ||||
|         im = Image.open(test_file) | ||||
|         im.load() | ||||
|         im.close() | ||||
| 
 | ||||
|     pytest.warns(None, open) | ||||
| 
 | ||||
| 
 | ||||
| def test_context_manager(): | ||||
|     def open(): | ||||
|         with Image.open(test_file) as im: | ||||
|             im.load() | ||||
|             self.assertEqual(im.mode, "RGB") | ||||
|             self.assertEqual(im.size, (128, 128)) | ||||
|             self.assertEqual(im.format, "PSD") | ||||
| 
 | ||||
|             im2 = hopper() | ||||
|             assert_image_similar(im, im2, 4.8) | ||||
|     pytest.warns(None, open) | ||||
| 
 | ||||
|     @unittest.skipIf(is_pypy(), "Requires CPython") | ||||
|     def test_unclosed_file(self): | ||||
|         def open(): | ||||
|             im = Image.open(test_file) | ||||
|             im.load() | ||||
| 
 | ||||
|         pytest.warns(ResourceWarning, open) | ||||
| def test_invalid_file(): | ||||
|     invalid_file = "Tests/images/flower.jpg" | ||||
| 
 | ||||
|     def test_closed_file(self): | ||||
|         def open(): | ||||
|             im = Image.open(test_file) | ||||
|             im.load() | ||||
|             im.close() | ||||
|     with pytest.raises(SyntaxError): | ||||
|         PsdImagePlugin.PsdImageFile(invalid_file) | ||||
| 
 | ||||
|         pytest.warns(None, open) | ||||
| 
 | ||||
|     def test_context_manager(self): | ||||
|         def open(): | ||||
|             with Image.open(test_file) as im: | ||||
|                 im.load() | ||||
| def test_n_frames(): | ||||
|     with Image.open("Tests/images/hopper_merged.psd") as im: | ||||
|         assert im.n_frames == 1 | ||||
|         assert not im.is_animated | ||||
| 
 | ||||
|         pytest.warns(None, open) | ||||
|     with Image.open(test_file) as im: | ||||
|         assert im.n_frames == 2 | ||||
|         assert im.is_animated | ||||
| 
 | ||||
|     def test_invalid_file(self): | ||||
|         invalid_file = "Tests/images/flower.jpg" | ||||
| 
 | ||||
|         self.assertRaises(SyntaxError, PsdImagePlugin.PsdImageFile, invalid_file) | ||||
| def test_eoferror(): | ||||
|     with Image.open(test_file) as im: | ||||
|         # PSD seek index starts at 1 rather than 0 | ||||
|         n_frames = im.n_frames + 1 | ||||
| 
 | ||||
|     def test_n_frames(self): | ||||
|         with Image.open("Tests/images/hopper_merged.psd") as im: | ||||
|             self.assertEqual(im.n_frames, 1) | ||||
|             self.assertFalse(im.is_animated) | ||||
|         # Test seeking past the last frame | ||||
|         with pytest.raises(EOFError): | ||||
|             im.seek(n_frames) | ||||
|         assert im.tell() < n_frames | ||||
| 
 | ||||
|         with Image.open(test_file) as im: | ||||
|             self.assertEqual(im.n_frames, 2) | ||||
|             self.assertTrue(im.is_animated) | ||||
|         # Test that seeking to the last frame does not raise an error | ||||
|         im.seek(n_frames - 1) | ||||
| 
 | ||||
|     def test_eoferror(self): | ||||
|         with Image.open(test_file) as im: | ||||
|             # PSD seek index starts at 1 rather than 0 | ||||
|             n_frames = im.n_frames + 1 | ||||
| 
 | ||||
|             # Test seeking past the last frame | ||||
|             self.assertRaises(EOFError, im.seek, n_frames) | ||||
|             self.assertLess(im.tell(), n_frames) | ||||
| def test_seek_tell(): | ||||
|     with Image.open(test_file) as im: | ||||
| 
 | ||||
|             # Test that seeking to the last frame does not raise an error | ||||
|             im.seek(n_frames - 1) | ||||
|         layer_number = im.tell() | ||||
|         assert layer_number == 1 | ||||
| 
 | ||||
|     def test_seek_tell(self): | ||||
|         with Image.open(test_file) as im: | ||||
|         with pytest.raises(EOFError): | ||||
|             im.seek(0) | ||||
| 
 | ||||
|             layer_number = im.tell() | ||||
|             self.assertEqual(layer_number, 1) | ||||
|         im.seek(1) | ||||
|         layer_number = im.tell() | ||||
|         assert layer_number == 1 | ||||
| 
 | ||||
|             self.assertRaises(EOFError, im.seek, 0) | ||||
|         im.seek(2) | ||||
|         layer_number = im.tell() | ||||
|         assert layer_number == 2 | ||||
| 
 | ||||
|             im.seek(1) | ||||
|             layer_number = im.tell() | ||||
|             self.assertEqual(layer_number, 1) | ||||
| 
 | ||||
|             im.seek(2) | ||||
|             layer_number = im.tell() | ||||
|             self.assertEqual(layer_number, 2) | ||||
| def test_seek_eoferror(): | ||||
|     with Image.open(test_file) as im: | ||||
| 
 | ||||
|     def test_seek_eoferror(self): | ||||
|         with Image.open(test_file) as im: | ||||
|         with pytest.raises(EOFError): | ||||
|             im.seek(-1) | ||||
| 
 | ||||
|             self.assertRaises(EOFError, im.seek, -1) | ||||
| 
 | ||||
|     def test_open_after_exclusive_load(self): | ||||
|         with Image.open(test_file) as im: | ||||
|             im.load() | ||||
|             im.seek(im.tell() + 1) | ||||
|             im.load() | ||||
| def test_open_after_exclusive_load(): | ||||
|     with Image.open(test_file) as im: | ||||
|         im.load() | ||||
|         im.seek(im.tell() + 1) | ||||
|         im.load() | ||||
| 
 | ||||
|     def test_icc_profile(self): | ||||
|         with Image.open(test_file) as im: | ||||
|             self.assertIn("icc_profile", im.info) | ||||
| 
 | ||||
|             icc_profile = im.info["icc_profile"] | ||||
|             self.assertEqual(len(icc_profile), 3144) | ||||
| def test_icc_profile(): | ||||
|     with Image.open(test_file) as im: | ||||
|         assert "icc_profile" in im.info | ||||
| 
 | ||||
|     def test_no_icc_profile(self): | ||||
|         with Image.open("Tests/images/hopper_merged.psd") as im: | ||||
|             self.assertNotIn("icc_profile", im.info) | ||||
|         icc_profile = im.info["icc_profile"] | ||||
|         assert len(icc_profile) == 3144 | ||||
| 
 | ||||
|     def test_combined_larger_than_size(self): | ||||
|         # The 'combined' sizes of the individual parts is larger than the | ||||
|         # declared 'size' of the extra data field, resulting in a backwards seek. | ||||
| 
 | ||||
|         # If we instead take the 'size' of the extra data field as the source of truth, | ||||
|         # then the seek can't be negative | ||||
|         with self.assertRaises(IOError): | ||||
|             Image.open("Tests/images/combined_larger_than_size.psd") | ||||
| def test_no_icc_profile(): | ||||
|     with Image.open("Tests/images/hopper_merged.psd") as im: | ||||
|         assert "icc_profile" not in im.info | ||||
| 
 | ||||
| 
 | ||||
| def test_combined_larger_than_size(): | ||||
|     # The 'combined' sizes of the individual parts is larger than the | ||||
|     # declared 'size' of the extra data field, resulting in a backwards seek. | ||||
| 
 | ||||
|     # If we instead take the 'size' of the extra data field as the source of truth, | ||||
|     # then the seek can't be negative | ||||
|     with pytest.raises(IOError): | ||||
|         Image.open("Tests/images/combined_larger_than_size.psd") | ||||
|  |  | |||
|  | @ -1,47 +1,51 @@ | |||
| import os | ||||
| import unittest | ||||
| 
 | ||||
| import pytest | ||||
| from PIL import Image, SunImagePlugin | ||||
| 
 | ||||
| from .helper import PillowTestCase, assert_image_equal, assert_image_similar, hopper | ||||
| from .helper import assert_image_equal, assert_image_similar, hopper | ||||
| 
 | ||||
| EXTRA_DIR = "Tests/images/sunraster" | ||||
| 
 | ||||
| 
 | ||||
| class TestFileSun(PillowTestCase): | ||||
|     def test_sanity(self): | ||||
|         # Arrange | ||||
|         # Created with ImageMagick: convert hopper.jpg hopper.ras | ||||
|         test_file = "Tests/images/hopper.ras" | ||||
| def test_sanity(): | ||||
|     # Arrange | ||||
|     # Created with ImageMagick: convert hopper.jpg hopper.ras | ||||
|     test_file = "Tests/images/hopper.ras" | ||||
| 
 | ||||
|         # Act | ||||
|         with Image.open(test_file) as im: | ||||
|     # Act | ||||
|     with Image.open(test_file) as im: | ||||
| 
 | ||||
|             # Assert | ||||
|             self.assertEqual(im.size, (128, 128)) | ||||
|         # Assert | ||||
|         assert im.size == (128, 128) | ||||
| 
 | ||||
|             assert_image_similar(im, hopper(), 5)  # visually verified | ||||
|         assert_image_similar(im, hopper(), 5)  # visually verified | ||||
| 
 | ||||
|         invalid_file = "Tests/images/flower.jpg" | ||||
|         self.assertRaises(SyntaxError, SunImagePlugin.SunImageFile, invalid_file) | ||||
|     invalid_file = "Tests/images/flower.jpg" | ||||
|     with pytest.raises(SyntaxError): | ||||
|         SunImagePlugin.SunImageFile(invalid_file) | ||||
| 
 | ||||
|     def test_im1(self): | ||||
|         with Image.open("Tests/images/sunraster.im1") as im: | ||||
|             with Image.open("Tests/images/sunraster.im1.png") as target: | ||||
| 
 | ||||
| def test_im1(): | ||||
|     with Image.open("Tests/images/sunraster.im1") as im: | ||||
|         with Image.open("Tests/images/sunraster.im1.png") as target: | ||||
|             assert_image_equal(im, target) | ||||
| 
 | ||||
| 
 | ||||
| @pytest.mark.skipif( | ||||
|     not os.path.exists(EXTRA_DIR), reason="Extra image files not installed" | ||||
| ) | ||||
| def test_others(): | ||||
|     files = ( | ||||
|         os.path.join(EXTRA_DIR, f) | ||||
|         for f in os.listdir(EXTRA_DIR) | ||||
|         if os.path.splitext(f)[1] in (".sun", ".SUN", ".ras") | ||||
|     ) | ||||
|     for path in files: | ||||
|         with Image.open(path) as im: | ||||
|             im.load() | ||||
|             assert isinstance(im, SunImagePlugin.SunImageFile) | ||||
|             target_path = "%s.png" % os.path.splitext(path)[0] | ||||
|             # im.save(target_file) | ||||
|             with Image.open(target_path) as target: | ||||
|                 assert_image_equal(im, target) | ||||
| 
 | ||||
|     @unittest.skipUnless(os.path.exists(EXTRA_DIR), "Extra image files not installed") | ||||
|     def test_others(self): | ||||
|         files = ( | ||||
|             os.path.join(EXTRA_DIR, f) | ||||
|             for f in os.listdir(EXTRA_DIR) | ||||
|             if os.path.splitext(f)[1] in (".sun", ".SUN", ".ras") | ||||
|         ) | ||||
|         for path in files: | ||||
|             with Image.open(path) as im: | ||||
|                 im.load() | ||||
|                 self.assertIsInstance(im, SunImagePlugin.SunImageFile) | ||||
|                 target_path = "%s.png" % os.path.splitext(path)[0] | ||||
|                 # im.save(target_file) | ||||
|                 with Image.open(target_path) as target: | ||||
|                     assert_image_equal(im, target) | ||||
|  |  | |||
|  | @ -1,9 +1,7 @@ | |||
| import unittest | ||||
| 
 | ||||
| import pytest | ||||
| from PIL import Image, TarIO | ||||
| 
 | ||||
| from .helper import PillowTestCase, is_pypy | ||||
| from .helper import is_pypy | ||||
| 
 | ||||
| codecs = dir(Image.core) | ||||
| 
 | ||||
|  | @ -11,41 +9,44 @@ codecs = dir(Image.core) | |||
| TEST_TAR_FILE = "Tests/images/hopper.tar" | ||||
| 
 | ||||
| 
 | ||||
| class TestFileTar(PillowTestCase): | ||||
|     def setUp(self): | ||||
|         if "zip_decoder" not in codecs and "jpeg_decoder" not in codecs: | ||||
|             self.skipTest("neither jpeg nor zip support available") | ||||
| def setup_module(): | ||||
|     if "zip_decoder" not in codecs and "jpeg_decoder" not in codecs: | ||||
|         pytest.skip("neither jpeg nor zip support available") | ||||
| 
 | ||||
|     def test_sanity(self): | ||||
|         for codec, test_path, format in [ | ||||
|             ["zip_decoder", "hopper.png", "PNG"], | ||||
|             ["jpeg_decoder", "hopper.jpg", "JPEG"], | ||||
|         ]: | ||||
|             if codec in codecs: | ||||
|                 with TarIO.TarIO(TEST_TAR_FILE, test_path) as tar: | ||||
|                     with Image.open(tar) as im: | ||||
|                         im.load() | ||||
|                         self.assertEqual(im.mode, "RGB") | ||||
|                         self.assertEqual(im.size, (128, 128)) | ||||
|                         self.assertEqual(im.format, format) | ||||
| 
 | ||||
|     @unittest.skipIf(is_pypy(), "Requires CPython") | ||||
|     def test_unclosed_file(self): | ||||
|         def open(): | ||||
|             TarIO.TarIO(TEST_TAR_FILE, "hopper.jpg") | ||||
| def test_sanity(): | ||||
|     for codec, test_path, format in [ | ||||
|         ["zip_decoder", "hopper.png", "PNG"], | ||||
|         ["jpeg_decoder", "hopper.jpg", "JPEG"], | ||||
|     ]: | ||||
|         if codec in codecs: | ||||
|             with TarIO.TarIO(TEST_TAR_FILE, test_path) as tar: | ||||
|                 with Image.open(tar) as im: | ||||
|                     im.load() | ||||
|                     assert im.mode == "RGB" | ||||
|                     assert im.size == (128, 128) | ||||
|                     assert im.format == format | ||||
| 
 | ||||
|         pytest.warns(ResourceWarning, open) | ||||
| 
 | ||||
|     def test_close(self): | ||||
|         def open(): | ||||
|             tar = TarIO.TarIO(TEST_TAR_FILE, "hopper.jpg") | ||||
|             tar.close() | ||||
| @pytest.mark.skipif(is_pypy(), reason="Requires CPython") | ||||
| def test_unclosed_file(): | ||||
|     def open(): | ||||
|         TarIO.TarIO(TEST_TAR_FILE, "hopper.jpg") | ||||
| 
 | ||||
|         pytest.warns(None, open) | ||||
|     pytest.warns(ResourceWarning, open) | ||||
| 
 | ||||
|     def test_contextmanager(self): | ||||
|         def open(): | ||||
|             with TarIO.TarIO(TEST_TAR_FILE, "hopper.jpg"): | ||||
|                 pass | ||||
| 
 | ||||
|         pytest.warns(None, open) | ||||
| def test_close(): | ||||
|     def open(): | ||||
|         tar = TarIO.TarIO(TEST_TAR_FILE, "hopper.jpg") | ||||
|         tar.close() | ||||
| 
 | ||||
|     pytest.warns(None, open) | ||||
| 
 | ||||
| 
 | ||||
| def test_contextmanager(): | ||||
|     def open(): | ||||
|         with TarIO.TarIO(TEST_TAR_FILE, "hopper.jpg"): | ||||
|             pass | ||||
| 
 | ||||
|     pytest.warns(None, open) | ||||
|  |  | |||
|  | @ -1,33 +1,36 @@ | |||
| import pytest | ||||
| from PIL import Image, XpmImagePlugin | ||||
| 
 | ||||
| from .helper import PillowTestCase, assert_image_similar, hopper | ||||
| from .helper import assert_image_similar, hopper | ||||
| 
 | ||||
| TEST_FILE = "Tests/images/hopper.xpm" | ||||
| 
 | ||||
| 
 | ||||
| class TestFileXpm(PillowTestCase): | ||||
|     def test_sanity(self): | ||||
|         with Image.open(TEST_FILE) as im: | ||||
|             im.load() | ||||
|             self.assertEqual(im.mode, "P") | ||||
|             self.assertEqual(im.size, (128, 128)) | ||||
|             self.assertEqual(im.format, "XPM") | ||||
| def test_sanity(): | ||||
|     with Image.open(TEST_FILE) as im: | ||||
|         im.load() | ||||
|         assert im.mode == "P" | ||||
|         assert im.size == (128, 128) | ||||
|         assert im.format == "XPM" | ||||
| 
 | ||||
|             # large error due to quantization->44 colors. | ||||
|             assert_image_similar(im.convert("RGB"), hopper("RGB"), 60) | ||||
|         # large error due to quantization->44 colors. | ||||
|         assert_image_similar(im.convert("RGB"), hopper("RGB"), 60) | ||||
| 
 | ||||
|     def test_invalid_file(self): | ||||
|         invalid_file = "Tests/images/flower.jpg" | ||||
| 
 | ||||
|         self.assertRaises(SyntaxError, XpmImagePlugin.XpmImageFile, invalid_file) | ||||
| def test_invalid_file(): | ||||
|     invalid_file = "Tests/images/flower.jpg" | ||||
| 
 | ||||
|     def test_load_read(self): | ||||
|         # Arrange | ||||
|         with Image.open(TEST_FILE) as im: | ||||
|             dummy_bytes = 1 | ||||
|     with pytest.raises(SyntaxError): | ||||
|         XpmImagePlugin.XpmImageFile(invalid_file) | ||||
| 
 | ||||
|             # Act | ||||
|             data = im.load_read(dummy_bytes) | ||||
| 
 | ||||
|         # Assert | ||||
|         self.assertEqual(len(data), 16384) | ||||
| def test_load_read(): | ||||
|     # Arrange | ||||
|     with Image.open(TEST_FILE) as im: | ||||
|         dummy_bytes = 1 | ||||
| 
 | ||||
|         # Act | ||||
|         data = im.load_read(dummy_bytes) | ||||
| 
 | ||||
|     # Assert | ||||
|     assert len(data) == 16384 | ||||
|  |  | |||
|  | @ -1,35 +1,37 @@ | |||
| import pytest | ||||
| from PIL import Image, XVThumbImagePlugin | ||||
| 
 | ||||
| from .helper import PillowTestCase, assert_image_similar, hopper | ||||
| from .helper import assert_image_similar, hopper | ||||
| 
 | ||||
| TEST_FILE = "Tests/images/hopper.p7" | ||||
| 
 | ||||
| 
 | ||||
| class TestFileXVThumb(PillowTestCase): | ||||
|     def test_open(self): | ||||
|         # Act | ||||
|         with Image.open(TEST_FILE) as im: | ||||
| def test_open(): | ||||
|     # Act | ||||
|     with Image.open(TEST_FILE) as im: | ||||
| 
 | ||||
|             # Assert | ||||
|             self.assertEqual(im.format, "XVThumb") | ||||
|         # Assert | ||||
|         assert im.format == "XVThumb" | ||||
| 
 | ||||
|             # Create a Hopper image with a similar XV palette | ||||
|             im_hopper = hopper().quantize(palette=im) | ||||
|             assert_image_similar(im, im_hopper, 9) | ||||
|         # Create a Hopper image with a similar XV palette | ||||
|         im_hopper = hopper().quantize(palette=im) | ||||
|         assert_image_similar(im, im_hopper, 9) | ||||
| 
 | ||||
|     def test_unexpected_eof(self): | ||||
|         # Test unexpected EOF reading XV thumbnail file | ||||
|         # Arrange | ||||
|         bad_file = "Tests/images/hopper_bad.p7" | ||||
| 
 | ||||
|         # Act / Assert | ||||
|         self.assertRaises(SyntaxError, XVThumbImagePlugin.XVThumbImageFile, bad_file) | ||||
| def test_unexpected_eof(): | ||||
|     # Test unexpected EOF reading XV thumbnail file | ||||
|     # Arrange | ||||
|     bad_file = "Tests/images/hopper_bad.p7" | ||||
| 
 | ||||
|     def test_invalid_file(self): | ||||
|         # Arrange | ||||
|         invalid_file = "Tests/images/flower.jpg" | ||||
|     # Act / Assert | ||||
|     with pytest.raises(SyntaxError): | ||||
|         XVThumbImagePlugin.XVThumbImageFile(bad_file) | ||||
| 
 | ||||
|         # Act / Assert | ||||
|         self.assertRaises( | ||||
|             SyntaxError, XVThumbImagePlugin.XVThumbImageFile, invalid_file | ||||
|         ) | ||||
| 
 | ||||
| def test_invalid_file(): | ||||
|     # Arrange | ||||
|     invalid_file = "Tests/images/flower.jpg" | ||||
| 
 | ||||
|     # Act / Assert | ||||
|     with pytest.raises(SyntaxError): | ||||
|         XVThumbImagePlugin.XVThumbImageFile(invalid_file) | ||||
|  |  | |||
|  | @ -1,103 +1,109 @@ | |||
| import pytest | ||||
| from PIL import Image | ||||
| 
 | ||||
| from .helper import PillowTestCase, assert_image_equal, hopper | ||||
| from .helper import assert_image_equal, hopper | ||||
| 
 | ||||
| 
 | ||||
| class TestImageCrop(PillowTestCase): | ||||
|     def test_crop(self): | ||||
|         def crop(mode): | ||||
|             im = hopper(mode) | ||||
|             assert_image_equal(im.crop(), im) | ||||
| def test_crop(): | ||||
|     def crop(mode): | ||||
|         im = hopper(mode) | ||||
|         assert_image_equal(im.crop(), im) | ||||
| 
 | ||||
|             cropped = im.crop((50, 50, 100, 100)) | ||||
|             self.assertEqual(cropped.mode, mode) | ||||
|             self.assertEqual(cropped.size, (50, 50)) | ||||
|         cropped = im.crop((50, 50, 100, 100)) | ||||
|         assert cropped.mode == mode | ||||
|         assert cropped.size == (50, 50) | ||||
| 
 | ||||
|         for mode in "1", "P", "L", "RGB", "I", "F": | ||||
|             crop(mode) | ||||
|     for mode in "1", "P", "L", "RGB", "I", "F": | ||||
|         crop(mode) | ||||
| 
 | ||||
|     def test_wide_crop(self): | ||||
|         def crop(*bbox): | ||||
|             i = im.crop(bbox) | ||||
|             h = i.histogram() | ||||
|             while h and not h[-1]: | ||||
|                 del h[-1] | ||||
|             return tuple(h) | ||||
| 
 | ||||
|         im = Image.new("L", (100, 100), 1) | ||||
| def test_wide_crop(): | ||||
|     def crop(*bbox): | ||||
|         i = im.crop(bbox) | ||||
|         h = i.histogram() | ||||
|         while h and not h[-1]: | ||||
|             del h[-1] | ||||
|         return tuple(h) | ||||
| 
 | ||||
|         self.assertEqual(crop(0, 0, 100, 100), (0, 10000)) | ||||
|         self.assertEqual(crop(25, 25, 75, 75), (0, 2500)) | ||||
|     im = Image.new("L", (100, 100), 1) | ||||
| 
 | ||||
|         # sides | ||||
|         self.assertEqual(crop(-25, 0, 25, 50), (1250, 1250)) | ||||
|         self.assertEqual(crop(0, -25, 50, 25), (1250, 1250)) | ||||
|         self.assertEqual(crop(75, 0, 125, 50), (1250, 1250)) | ||||
|         self.assertEqual(crop(0, 75, 50, 125), (1250, 1250)) | ||||
|     assert crop(0, 0, 100, 100) == (0, 10000) | ||||
|     assert crop(25, 25, 75, 75) == (0, 2500) | ||||
| 
 | ||||
|         self.assertEqual(crop(-25, 25, 125, 75), (2500, 5000)) | ||||
|         self.assertEqual(crop(25, -25, 75, 125), (2500, 5000)) | ||||
|     # sides | ||||
|     assert crop(-25, 0, 25, 50) == (1250, 1250) | ||||
|     assert crop(0, -25, 50, 25) == (1250, 1250) | ||||
|     assert crop(75, 0, 125, 50) == (1250, 1250) | ||||
|     assert crop(0, 75, 50, 125) == (1250, 1250) | ||||
| 
 | ||||
|         # corners | ||||
|         self.assertEqual(crop(-25, -25, 25, 25), (1875, 625)) | ||||
|         self.assertEqual(crop(75, -25, 125, 25), (1875, 625)) | ||||
|         self.assertEqual(crop(75, 75, 125, 125), (1875, 625)) | ||||
|         self.assertEqual(crop(-25, 75, 25, 125), (1875, 625)) | ||||
|     assert crop(-25, 25, 125, 75) == (2500, 5000) | ||||
|     assert crop(25, -25, 75, 125) == (2500, 5000) | ||||
| 
 | ||||
|     def test_negative_crop(self): | ||||
|         # Check negative crop size (@PIL171) | ||||
|     # corners | ||||
|     assert crop(-25, -25, 25, 25) == (1875, 625) | ||||
|     assert crop(75, -25, 125, 25) == (1875, 625) | ||||
|     assert crop(75, 75, 125, 125) == (1875, 625) | ||||
|     assert crop(-25, 75, 25, 125) == (1875, 625) | ||||
| 
 | ||||
|         im = Image.new("L", (512, 512)) | ||||
|         im = im.crop((400, 400, 200, 200)) | ||||
| 
 | ||||
|         self.assertEqual(im.size, (0, 0)) | ||||
|         self.assertEqual(len(im.getdata()), 0) | ||||
|         self.assertRaises(IndexError, lambda: im.getdata()[0]) | ||||
| def test_negative_crop(): | ||||
|     # Check negative crop size (@PIL171) | ||||
| 
 | ||||
|     def test_crop_float(self): | ||||
|         # Check cropping floats are rounded to nearest integer | ||||
|         # https://github.com/python-pillow/Pillow/issues/1744 | ||||
|     im = Image.new("L", (512, 512)) | ||||
|     im = im.crop((400, 400, 200, 200)) | ||||
| 
 | ||||
|         # Arrange | ||||
|         im = Image.new("RGB", (10, 10)) | ||||
|         self.assertEqual(im.size, (10, 10)) | ||||
|     assert im.size == (0, 0) | ||||
|     assert len(im.getdata()) == 0 | ||||
|     with pytest.raises(IndexError): | ||||
|         im.getdata()[0] | ||||
| 
 | ||||
|         # Act | ||||
|         cropped = im.crop((0.9, 1.1, 4.2, 5.8)) | ||||
| 
 | ||||
|         # Assert | ||||
|         self.assertEqual(cropped.size, (3, 5)) | ||||
| def test_crop_float(): | ||||
|     # Check cropping floats are rounded to nearest integer | ||||
|     # https://github.com/python-pillow/Pillow/issues/1744 | ||||
| 
 | ||||
|     def test_crop_crash(self): | ||||
|         # Image.crop crashes prepatch with an access violation | ||||
|         # apparently a use after free on windows, see | ||||
|         # https://github.com/python-pillow/Pillow/issues/1077 | ||||
|     # Arrange | ||||
|     im = Image.new("RGB", (10, 10)) | ||||
|     assert im.size == (10, 10) | ||||
| 
 | ||||
|         test_img = "Tests/images/bmp/g/pal8-0.bmp" | ||||
|         extents = (1, 1, 10, 10) | ||||
|         # works prepatch | ||||
|         with Image.open(test_img) as img: | ||||
|             img2 = img.crop(extents) | ||||
|         img2.load() | ||||
|     # Act | ||||
|     cropped = im.crop((0.9, 1.1, 4.2, 5.8)) | ||||
| 
 | ||||
|         # fail prepatch | ||||
|         with Image.open(test_img) as img: | ||||
|             img = img.crop(extents) | ||||
|         img.load() | ||||
|     # Assert | ||||
|     assert cropped.size == (3, 5) | ||||
| 
 | ||||
|     def test_crop_zero(self): | ||||
| 
 | ||||
|         im = Image.new("RGB", (0, 0), "white") | ||||
| def test_crop_crash(): | ||||
|     # Image.crop crashes prepatch with an access violation | ||||
|     # apparently a use after free on Windows, see | ||||
|     # https://github.com/python-pillow/Pillow/issues/1077 | ||||
| 
 | ||||
|         cropped = im.crop((0, 0, 0, 0)) | ||||
|         self.assertEqual(cropped.size, (0, 0)) | ||||
|     test_img = "Tests/images/bmp/g/pal8-0.bmp" | ||||
|     extents = (1, 1, 10, 10) | ||||
|     # works prepatch | ||||
|     with Image.open(test_img) as img: | ||||
|         img2 = img.crop(extents) | ||||
|     img2.load() | ||||
| 
 | ||||
|         cropped = im.crop((10, 10, 20, 20)) | ||||
|         self.assertEqual(cropped.size, (10, 10)) | ||||
|         self.assertEqual(cropped.getdata()[0], (0, 0, 0)) | ||||
|     # fail prepatch | ||||
|     with Image.open(test_img) as img: | ||||
|         img = img.crop(extents) | ||||
|     img.load() | ||||
| 
 | ||||
|         im = Image.new("RGB", (0, 0)) | ||||
| 
 | ||||
|         cropped = im.crop((10, 10, 20, 20)) | ||||
|         self.assertEqual(cropped.size, (10, 10)) | ||||
|         self.assertEqual(cropped.getdata()[2], (0, 0, 0)) | ||||
| def test_crop_zero(): | ||||
| 
 | ||||
|     im = Image.new("RGB", (0, 0), "white") | ||||
| 
 | ||||
|     cropped = im.crop((0, 0, 0, 0)) | ||||
|     assert cropped.size == (0, 0) | ||||
| 
 | ||||
|     cropped = im.crop((10, 10, 20, 20)) | ||||
|     assert cropped.size == (10, 10) | ||||
|     assert cropped.getdata()[0] == (0, 0, 0) | ||||
| 
 | ||||
|     im = Image.new("RGB", (0, 0)) | ||||
| 
 | ||||
|     cropped = im.crop((10, 10, 20, 20)) | ||||
|     assert cropped.size == (10, 10) | ||||
|     assert cropped.getdata()[2] == (0, 0, 0) | ||||
|  |  | |||
|  | @ -1,73 +1,77 @@ | |||
| import pytest | ||||
| from PIL import Image | ||||
| 
 | ||||
| from .helper import PillowTestCase, fromstring, tostring | ||||
| from .helper import fromstring, tostring | ||||
| 
 | ||||
| 
 | ||||
| class TestImageDraft(PillowTestCase): | ||||
|     def setUp(self): | ||||
|         codecs = dir(Image.core) | ||||
|         if "jpeg_encoder" not in codecs or "jpeg_decoder" not in codecs: | ||||
|             self.skipTest("jpeg support not available") | ||||
| def setup_module(): | ||||
|     codecs = dir(Image.core) | ||||
|     if "jpeg_encoder" not in codecs or "jpeg_decoder" not in codecs: | ||||
|         pytest.skip("jpeg support not available") | ||||
| 
 | ||||
|     def draft_roundtrip(self, in_mode, in_size, req_mode, req_size): | ||||
|         im = Image.new(in_mode, in_size) | ||||
|         data = tostring(im, "JPEG") | ||||
|         im = fromstring(data) | ||||
|         mode, box = im.draft(req_mode, req_size) | ||||
|         scale, _ = im.decoderconfig | ||||
|         self.assertEqual(box[:2], (0, 0)) | ||||
|         self.assertTrue((im.width - scale) < box[2] <= im.width) | ||||
|         self.assertTrue((im.height - scale) < box[3] <= im.height) | ||||
|         return im | ||||
| 
 | ||||
|     def test_size(self): | ||||
|         for in_size, req_size, out_size in [ | ||||
|             ((435, 361), (2048, 2048), (435, 361)),  # bigger | ||||
|             ((435, 361), (435, 361), (435, 361)),  # same | ||||
|             ((128, 128), (64, 64), (64, 64)), | ||||
|             ((128, 128), (32, 32), (32, 32)), | ||||
|             ((128, 128), (16, 16), (16, 16)), | ||||
|             # large requested width | ||||
|             ((435, 361), (218, 128), (435, 361)),  # almost 2x | ||||
|             ((435, 361), (217, 128), (218, 181)),  # more than 2x | ||||
|             ((435, 361), (109, 64), (218, 181)),  # almost 4x | ||||
|             ((435, 361), (108, 64), (109, 91)),  # more than 4x | ||||
|             ((435, 361), (55, 32), (109, 91)),  # almost 8x | ||||
|             ((435, 361), (54, 32), (55, 46)),  # more than 8x | ||||
|             ((435, 361), (27, 16), (55, 46)),  # more than 16x | ||||
|             # and vice versa | ||||
|             ((435, 361), (128, 181), (435, 361)),  # almost 2x | ||||
|             ((435, 361), (128, 180), (218, 181)),  # more than 2x | ||||
|             ((435, 361), (64, 91), (218, 181)),  # almost 4x | ||||
|             ((435, 361), (64, 90), (109, 91)),  # more than 4x | ||||
|             ((435, 361), (32, 46), (109, 91)),  # almost 8x | ||||
|             ((435, 361), (32, 45), (55, 46)),  # more than 8x | ||||
|             ((435, 361), (16, 22), (55, 46)),  # more than 16x | ||||
|         ]: | ||||
|             im = self.draft_roundtrip("L", in_size, None, req_size) | ||||
|             im.load() | ||||
|             self.assertEqual(im.size, out_size) | ||||
| def draft_roundtrip(in_mode, in_size, req_mode, req_size): | ||||
|     im = Image.new(in_mode, in_size) | ||||
|     data = tostring(im, "JPEG") | ||||
|     im = fromstring(data) | ||||
|     mode, box = im.draft(req_mode, req_size) | ||||
|     scale, _ = im.decoderconfig | ||||
|     assert box[:2] == (0, 0) | ||||
|     assert (im.width - scale) < box[2] <= im.width | ||||
|     assert (im.height - scale) < box[3] <= im.height | ||||
|     return im | ||||
| 
 | ||||
|     def test_mode(self): | ||||
|         for in_mode, req_mode, out_mode in [ | ||||
|             ("RGB", "1", "RGB"), | ||||
|             ("RGB", "L", "L"), | ||||
|             ("RGB", "RGB", "RGB"), | ||||
|             ("RGB", "YCbCr", "YCbCr"), | ||||
|             ("L", "1", "L"), | ||||
|             ("L", "L", "L"), | ||||
|             ("L", "RGB", "L"), | ||||
|             ("L", "YCbCr", "L"), | ||||
|             ("CMYK", "1", "CMYK"), | ||||
|             ("CMYK", "L", "CMYK"), | ||||
|             ("CMYK", "RGB", "CMYK"), | ||||
|             ("CMYK", "YCbCr", "CMYK"), | ||||
|         ]: | ||||
|             im = self.draft_roundtrip(in_mode, (64, 64), req_mode, None) | ||||
|             im.load() | ||||
|             self.assertEqual(im.mode, out_mode) | ||||
| 
 | ||||
|     def test_several_drafts(self): | ||||
|         im = self.draft_roundtrip("L", (128, 128), None, (64, 64)) | ||||
|         im.draft(None, (64, 64)) | ||||
| def test_size(): | ||||
|     for in_size, req_size, out_size in [ | ||||
|         ((435, 361), (2048, 2048), (435, 361)),  # bigger | ||||
|         ((435, 361), (435, 361), (435, 361)),  # same | ||||
|         ((128, 128), (64, 64), (64, 64)), | ||||
|         ((128, 128), (32, 32), (32, 32)), | ||||
|         ((128, 128), (16, 16), (16, 16)), | ||||
|         # large requested width | ||||
|         ((435, 361), (218, 128), (435, 361)),  # almost 2x | ||||
|         ((435, 361), (217, 128), (218, 181)),  # more than 2x | ||||
|         ((435, 361), (109, 64), (218, 181)),  # almost 4x | ||||
|         ((435, 361), (108, 64), (109, 91)),  # more than 4x | ||||
|         ((435, 361), (55, 32), (109, 91)),  # almost 8x | ||||
|         ((435, 361), (54, 32), (55, 46)),  # more than 8x | ||||
|         ((435, 361), (27, 16), (55, 46)),  # more than 16x | ||||
|         # and vice versa | ||||
|         ((435, 361), (128, 181), (435, 361)),  # almost 2x | ||||
|         ((435, 361), (128, 180), (218, 181)),  # more than 2x | ||||
|         ((435, 361), (64, 91), (218, 181)),  # almost 4x | ||||
|         ((435, 361), (64, 90), (109, 91)),  # more than 4x | ||||
|         ((435, 361), (32, 46), (109, 91)),  # almost 8x | ||||
|         ((435, 361), (32, 45), (55, 46)),  # more than 8x | ||||
|         ((435, 361), (16, 22), (55, 46)),  # more than 16x | ||||
|     ]: | ||||
|         im = draft_roundtrip("L", in_size, None, req_size) | ||||
|         im.load() | ||||
|         assert im.size == out_size | ||||
| 
 | ||||
| 
 | ||||
| def test_mode(): | ||||
|     for in_mode, req_mode, out_mode in [ | ||||
|         ("RGB", "1", "RGB"), | ||||
|         ("RGB", "L", "L"), | ||||
|         ("RGB", "RGB", "RGB"), | ||||
|         ("RGB", "YCbCr", "YCbCr"), | ||||
|         ("L", "1", "L"), | ||||
|         ("L", "L", "L"), | ||||
|         ("L", "RGB", "L"), | ||||
|         ("L", "YCbCr", "L"), | ||||
|         ("CMYK", "1", "CMYK"), | ||||
|         ("CMYK", "L", "CMYK"), | ||||
|         ("CMYK", "RGB", "CMYK"), | ||||
|         ("CMYK", "YCbCr", "CMYK"), | ||||
|     ]: | ||||
|         im = draft_roundtrip(in_mode, (64, 64), req_mode, None) | ||||
|         im.load() | ||||
|         assert im.mode == out_mode | ||||
| 
 | ||||
| 
 | ||||
| def test_several_drafts(): | ||||
|     im = draft_roundtrip("L", (128, 128), None, (64, 64)) | ||||
|     im.draft(None, (64, 64)) | ||||
|     im.load() | ||||
|  |  | |||
|  | @ -1,17 +1,16 @@ | |||
| from .helper import PillowTestCase, hopper | ||||
| from .helper import hopper | ||||
| 
 | ||||
| 
 | ||||
| class TestImageEntropy(PillowTestCase): | ||||
|     def test_entropy(self): | ||||
|         def entropy(mode): | ||||
|             return hopper(mode).entropy() | ||||
| def test_entropy(): | ||||
|     def entropy(mode): | ||||
|         return hopper(mode).entropy() | ||||
| 
 | ||||
|         self.assertAlmostEqual(entropy("1"), 0.9138803254693582) | ||||
|         self.assertAlmostEqual(entropy("L"), 7.063008716585465) | ||||
|         self.assertAlmostEqual(entropy("I"), 7.063008716585465) | ||||
|         self.assertAlmostEqual(entropy("F"), 7.063008716585465) | ||||
|         self.assertAlmostEqual(entropy("P"), 5.0530452472519745) | ||||
|         self.assertAlmostEqual(entropy("RGB"), 8.821286587714319) | ||||
|         self.assertAlmostEqual(entropy("RGBA"), 7.42724306524488) | ||||
|         self.assertAlmostEqual(entropy("CMYK"), 7.4272430652448795) | ||||
|         self.assertAlmostEqual(entropy("YCbCr"), 7.698360534903628) | ||||
|     assert round(abs(entropy("1") - 0.9138803254693582), 7) == 0 | ||||
|     assert round(abs(entropy("L") - 7.063008716585465), 7) == 0 | ||||
|     assert round(abs(entropy("I") - 7.063008716585465), 7) == 0 | ||||
|     assert round(abs(entropy("F") - 7.063008716585465), 7) == 0 | ||||
|     assert round(abs(entropy("P") - 5.0530452472519745), 7) == 0 | ||||
|     assert round(abs(entropy("RGB") - 8.821286587714319), 7) == 0 | ||||
|     assert round(abs(entropy("RGBA") - 7.42724306524488), 7) == 0 | ||||
|     assert round(abs(entropy("CMYK") - 7.4272430652448795), 7) == 0 | ||||
|     assert round(abs(entropy("YCbCr") - 7.698360534903628), 7) == 0 | ||||
|  |  | |||
|  | @ -1,143 +1,155 @@ | |||
| import pytest | ||||
| from PIL import Image, ImageFilter | ||||
| 
 | ||||
| from .helper import PillowTestCase, assert_image_equal, hopper | ||||
| from .helper import assert_image_equal, hopper | ||||
| 
 | ||||
| 
 | ||||
| class TestImageFilter(PillowTestCase): | ||||
|     def test_sanity(self): | ||||
|         def filter(filter): | ||||
|             for mode in ["L", "RGB", "CMYK"]: | ||||
|                 im = hopper(mode) | ||||
|                 out = im.filter(filter) | ||||
|                 self.assertEqual(out.mode, im.mode) | ||||
|                 self.assertEqual(out.size, im.size) | ||||
| def test_sanity(): | ||||
|     def apply_filter(filter_to_apply): | ||||
|         for mode in ["L", "RGB", "CMYK"]: | ||||
|             im = hopper(mode) | ||||
|             out = im.filter(filter_to_apply) | ||||
|             assert out.mode == im.mode | ||||
|             assert out.size == im.size | ||||
| 
 | ||||
|         filter(ImageFilter.BLUR) | ||||
|         filter(ImageFilter.CONTOUR) | ||||
|         filter(ImageFilter.DETAIL) | ||||
|         filter(ImageFilter.EDGE_ENHANCE) | ||||
|         filter(ImageFilter.EDGE_ENHANCE_MORE) | ||||
|         filter(ImageFilter.EMBOSS) | ||||
|         filter(ImageFilter.FIND_EDGES) | ||||
|         filter(ImageFilter.SMOOTH) | ||||
|         filter(ImageFilter.SMOOTH_MORE) | ||||
|         filter(ImageFilter.SHARPEN) | ||||
|         filter(ImageFilter.MaxFilter) | ||||
|         filter(ImageFilter.MedianFilter) | ||||
|         filter(ImageFilter.MinFilter) | ||||
|         filter(ImageFilter.ModeFilter) | ||||
|         filter(ImageFilter.GaussianBlur) | ||||
|         filter(ImageFilter.GaussianBlur(5)) | ||||
|         filter(ImageFilter.BoxBlur(5)) | ||||
|         filter(ImageFilter.UnsharpMask) | ||||
|         filter(ImageFilter.UnsharpMask(10)) | ||||
|     apply_filter(ImageFilter.BLUR) | ||||
|     apply_filter(ImageFilter.CONTOUR) | ||||
|     apply_filter(ImageFilter.DETAIL) | ||||
|     apply_filter(ImageFilter.EDGE_ENHANCE) | ||||
|     apply_filter(ImageFilter.EDGE_ENHANCE_MORE) | ||||
|     apply_filter(ImageFilter.EMBOSS) | ||||
|     apply_filter(ImageFilter.FIND_EDGES) | ||||
|     apply_filter(ImageFilter.SMOOTH) | ||||
|     apply_filter(ImageFilter.SMOOTH_MORE) | ||||
|     apply_filter(ImageFilter.SHARPEN) | ||||
|     apply_filter(ImageFilter.MaxFilter) | ||||
|     apply_filter(ImageFilter.MedianFilter) | ||||
|     apply_filter(ImageFilter.MinFilter) | ||||
|     apply_filter(ImageFilter.ModeFilter) | ||||
|     apply_filter(ImageFilter.GaussianBlur) | ||||
|     apply_filter(ImageFilter.GaussianBlur(5)) | ||||
|     apply_filter(ImageFilter.BoxBlur(5)) | ||||
|     apply_filter(ImageFilter.UnsharpMask) | ||||
|     apply_filter(ImageFilter.UnsharpMask(10)) | ||||
| 
 | ||||
|         self.assertRaises(TypeError, filter, "hello") | ||||
|     with pytest.raises(TypeError): | ||||
|         apply_filter("hello") | ||||
| 
 | ||||
|     def test_crash(self): | ||||
| 
 | ||||
|         # crashes on small images | ||||
|         im = Image.new("RGB", (1, 1)) | ||||
|         im.filter(ImageFilter.SMOOTH) | ||||
| def test_crash(): | ||||
| 
 | ||||
|         im = Image.new("RGB", (2, 2)) | ||||
|         im.filter(ImageFilter.SMOOTH) | ||||
|     # crashes on small images | ||||
|     im = Image.new("RGB", (1, 1)) | ||||
|     im.filter(ImageFilter.SMOOTH) | ||||
| 
 | ||||
|         im = Image.new("RGB", (3, 3)) | ||||
|         im.filter(ImageFilter.SMOOTH) | ||||
|     im = Image.new("RGB", (2, 2)) | ||||
|     im.filter(ImageFilter.SMOOTH) | ||||
| 
 | ||||
|     def test_modefilter(self): | ||||
|         def modefilter(mode): | ||||
|             im = Image.new(mode, (3, 3), None) | ||||
|             im.putdata(list(range(9))) | ||||
|             # image is: | ||||
|             #   0 1 2 | ||||
|             #   3 4 5 | ||||
|             #   6 7 8 | ||||
|             mod = im.filter(ImageFilter.ModeFilter).getpixel((1, 1)) | ||||
|             im.putdata([0, 0, 1, 2, 5, 1, 5, 2, 0])  # mode=0 | ||||
|             mod2 = im.filter(ImageFilter.ModeFilter).getpixel((1, 1)) | ||||
|             return mod, mod2 | ||||
|     im = Image.new("RGB", (3, 3)) | ||||
|     im.filter(ImageFilter.SMOOTH) | ||||
| 
 | ||||
|         self.assertEqual(modefilter("1"), (4, 0)) | ||||
|         self.assertEqual(modefilter("L"), (4, 0)) | ||||
|         self.assertEqual(modefilter("P"), (4, 0)) | ||||
|         self.assertEqual(modefilter("RGB"), ((4, 0, 0), (0, 0, 0))) | ||||
| 
 | ||||
|     def test_rankfilter(self): | ||||
|         def rankfilter(mode): | ||||
|             im = Image.new(mode, (3, 3), None) | ||||
|             im.putdata(list(range(9))) | ||||
|             # image is: | ||||
|             #   0 1 2 | ||||
|             #   3 4 5 | ||||
|             #   6 7 8 | ||||
|             minimum = im.filter(ImageFilter.MinFilter).getpixel((1, 1)) | ||||
|             med = im.filter(ImageFilter.MedianFilter).getpixel((1, 1)) | ||||
|             maximum = im.filter(ImageFilter.MaxFilter).getpixel((1, 1)) | ||||
|             return minimum, med, maximum | ||||
| def test_modefilter(): | ||||
|     def modefilter(mode): | ||||
|         im = Image.new(mode, (3, 3), None) | ||||
|         im.putdata(list(range(9))) | ||||
|         # image is: | ||||
|         #   0 1 2 | ||||
|         #   3 4 5 | ||||
|         #   6 7 8 | ||||
|         mod = im.filter(ImageFilter.ModeFilter).getpixel((1, 1)) | ||||
|         im.putdata([0, 0, 1, 2, 5, 1, 5, 2, 0])  # mode=0 | ||||
|         mod2 = im.filter(ImageFilter.ModeFilter).getpixel((1, 1)) | ||||
|         return mod, mod2 | ||||
| 
 | ||||
|         self.assertEqual(rankfilter("1"), (0, 4, 8)) | ||||
|         self.assertEqual(rankfilter("L"), (0, 4, 8)) | ||||
|         self.assertRaises(ValueError, rankfilter, "P") | ||||
|         self.assertEqual(rankfilter("RGB"), ((0, 0, 0), (4, 0, 0), (8, 0, 0))) | ||||
|         self.assertEqual(rankfilter("I"), (0, 4, 8)) | ||||
|         self.assertEqual(rankfilter("F"), (0.0, 4.0, 8.0)) | ||||
|     assert modefilter("1") == (4, 0) | ||||
|     assert modefilter("L") == (4, 0) | ||||
|     assert modefilter("P") == (4, 0) | ||||
|     assert modefilter("RGB") == ((4, 0, 0), (0, 0, 0)) | ||||
| 
 | ||||
|     def test_rankfilter_properties(self): | ||||
|         rankfilter = ImageFilter.RankFilter(1, 2) | ||||
| 
 | ||||
|         self.assertEqual(rankfilter.size, 1) | ||||
|         self.assertEqual(rankfilter.rank, 2) | ||||
| def test_rankfilter(): | ||||
|     def rankfilter(mode): | ||||
|         im = Image.new(mode, (3, 3), None) | ||||
|         im.putdata(list(range(9))) | ||||
|         # image is: | ||||
|         #   0 1 2 | ||||
|         #   3 4 5 | ||||
|         #   6 7 8 | ||||
|         minimum = im.filter(ImageFilter.MinFilter).getpixel((1, 1)) | ||||
|         med = im.filter(ImageFilter.MedianFilter).getpixel((1, 1)) | ||||
|         maximum = im.filter(ImageFilter.MaxFilter).getpixel((1, 1)) | ||||
|         return minimum, med, maximum | ||||
| 
 | ||||
|     def test_builtinfilter_p(self): | ||||
|         builtinFilter = ImageFilter.BuiltinFilter() | ||||
|     assert rankfilter("1") == (0, 4, 8) | ||||
|     assert rankfilter("L") == (0, 4, 8) | ||||
|     with pytest.raises(ValueError): | ||||
|         rankfilter("P") | ||||
|     assert rankfilter("RGB") == ((0, 0, 0), (4, 0, 0), (8, 0, 0)) | ||||
|     assert rankfilter("I") == (0, 4, 8) | ||||
|     assert rankfilter("F") == (0.0, 4.0, 8.0) | ||||
| 
 | ||||
|         self.assertRaises(ValueError, builtinFilter.filter, hopper("P")) | ||||
| 
 | ||||
|     def test_kernel_not_enough_coefficients(self): | ||||
|         self.assertRaises(ValueError, lambda: ImageFilter.Kernel((3, 3), (0, 0))) | ||||
| def test_rankfilter_properties(): | ||||
|     rankfilter = ImageFilter.RankFilter(1, 2) | ||||
| 
 | ||||
|     def test_consistency_3x3(self): | ||||
|         with Image.open("Tests/images/hopper.bmp") as source: | ||||
|             with Image.open("Tests/images/hopper_emboss.bmp") as reference: | ||||
|                 kernel = ImageFilter.Kernel(  # noqa: E127 | ||||
|                     (3, 3), | ||||
|                     # fmt: off | ||||
|                     (-1, -1,  0, | ||||
|                      -1,  0,  1, | ||||
|                       0,  1,  1), | ||||
|                     # fmt: on | ||||
|                     0.3, | ||||
|     assert rankfilter.size == 1 | ||||
|     assert rankfilter.rank == 2 | ||||
| 
 | ||||
| 
 | ||||
| def test_builtinfilter_p(): | ||||
|     builtinFilter = ImageFilter.BuiltinFilter() | ||||
| 
 | ||||
|     with pytest.raises(ValueError): | ||||
|         builtinFilter.filter(hopper("P")) | ||||
| 
 | ||||
| 
 | ||||
| def test_kernel_not_enough_coefficients(): | ||||
|     with pytest.raises(ValueError): | ||||
|         ImageFilter.Kernel((3, 3), (0, 0)) | ||||
| 
 | ||||
| 
 | ||||
| def test_consistency_3x3(): | ||||
|     with Image.open("Tests/images/hopper.bmp") as source: | ||||
|         with Image.open("Tests/images/hopper_emboss.bmp") as reference: | ||||
|             kernel = ImageFilter.Kernel(  # noqa: E127 | ||||
|                 (3, 3), | ||||
|                 # fmt: off | ||||
|                 (-1, -1,  0, | ||||
|                  -1,  0,  1, | ||||
|                   0,  1,  1), | ||||
|                 # fmt: on | ||||
|                 0.3, | ||||
|             ) | ||||
|             source = source.split() * 2 | ||||
|             reference = reference.split() * 2 | ||||
| 
 | ||||
|             for mode in ["L", "LA", "RGB", "CMYK"]: | ||||
|                 assert_image_equal( | ||||
|                     Image.merge(mode, source[: len(mode)]).filter(kernel), | ||||
|                     Image.merge(mode, reference[: len(mode)]), | ||||
|                 ) | ||||
|                 source = source.split() * 2 | ||||
|                 reference = reference.split() * 2 | ||||
| 
 | ||||
|                 for mode in ["L", "LA", "RGB", "CMYK"]: | ||||
|                     assert_image_equal( | ||||
|                         Image.merge(mode, source[: len(mode)]).filter(kernel), | ||||
|                         Image.merge(mode, reference[: len(mode)]), | ||||
|                     ) | ||||
| 
 | ||||
|     def test_consistency_5x5(self): | ||||
|         with Image.open("Tests/images/hopper.bmp") as source: | ||||
|             with Image.open("Tests/images/hopper_emboss_more.bmp") as reference: | ||||
|                 kernel = ImageFilter.Kernel(  # noqa: E127 | ||||
|                     (5, 5), | ||||
|                     # fmt: off | ||||
|                     (-1, -1, -1, -1,  0, | ||||
|                      -1, -1, -1,  0,  1, | ||||
|                      -1, -1,  0,  1,  1, | ||||
|                      -1,  0,  1,  1,  1, | ||||
|                       0,  1,  1,  1,  1), | ||||
|                     # fmt: on | ||||
|                     0.3, | ||||
| def test_consistency_5x5(): | ||||
|     with Image.open("Tests/images/hopper.bmp") as source: | ||||
|         with Image.open("Tests/images/hopper_emboss_more.bmp") as reference: | ||||
|             kernel = ImageFilter.Kernel(  # noqa: E127 | ||||
|                 (5, 5), | ||||
|                 # fmt: off | ||||
|                 (-1, -1, -1, -1,  0, | ||||
|                  -1, -1, -1,  0,  1, | ||||
|                  -1, -1,  0,  1,  1, | ||||
|                  -1,  0,  1,  1,  1, | ||||
|                   0,  1,  1,  1,  1), | ||||
|                 # fmt: on | ||||
|                 0.3, | ||||
|             ) | ||||
|             source = source.split() * 2 | ||||
|             reference = reference.split() * 2 | ||||
| 
 | ||||
|             for mode in ["L", "LA", "RGB", "CMYK"]: | ||||
|                 assert_image_equal( | ||||
|                     Image.merge(mode, source[: len(mode)]).filter(kernel), | ||||
|                     Image.merge(mode, reference[: len(mode)]), | ||||
|                 ) | ||||
|                 source = source.split() * 2 | ||||
|                 reference = reference.split() * 2 | ||||
| 
 | ||||
|                 for mode in ["L", "LA", "RGB", "CMYK"]: | ||||
|                     assert_image_equal( | ||||
|                         Image.merge(mode, source[: len(mode)]).filter(kernel), | ||||
|                         Image.merge(mode, reference[: len(mode)]), | ||||
|                     ) | ||||
|  |  | |||
|  | @ -1,14 +1,16 @@ | |||
| import pytest | ||||
| from PIL import Image | ||||
| 
 | ||||
| from .helper import PillowTestCase, assert_image_equal, hopper | ||||
| from .helper import assert_image_equal, hopper | ||||
| 
 | ||||
| 
 | ||||
| class TestImageFromBytes(PillowTestCase): | ||||
|     def test_sanity(self): | ||||
|         im1 = hopper() | ||||
|         im2 = Image.frombytes(im1.mode, im1.size, im1.tobytes()) | ||||
| def test_sanity(): | ||||
|     im1 = hopper() | ||||
|     im2 = Image.frombytes(im1.mode, im1.size, im1.tobytes()) | ||||
| 
 | ||||
|         assert_image_equal(im1, im2) | ||||
|     assert_image_equal(im1, im2) | ||||
| 
 | ||||
|     def test_not_implemented(self): | ||||
|         self.assertRaises(NotImplementedError, Image.fromstring) | ||||
| 
 | ||||
| def test_not_implemented(): | ||||
|     with pytest.raises(NotImplementedError): | ||||
|         Image.fromstring() | ||||
|  |  | |||
|  | @ -1,39 +1,48 @@ | |||
| from .helper import PillowTestCase, assert_image_equal, hopper | ||||
| import pytest | ||||
| 
 | ||||
| from .helper import assert_image_equal, hopper | ||||
| 
 | ||||
| 
 | ||||
| class TestImagePoint(PillowTestCase): | ||||
|     def test_sanity(self): | ||||
|         im = hopper() | ||||
| def test_sanity(): | ||||
|     im = hopper() | ||||
| 
 | ||||
|         self.assertRaises(ValueError, im.point, list(range(256))) | ||||
|         im.point(list(range(256)) * 3) | ||||
|         im.point(lambda x: x) | ||||
|     with pytest.raises(ValueError): | ||||
|         im.point(list(range(256))) | ||||
|     im.point(list(range(256)) * 3) | ||||
|     im.point(lambda x: x) | ||||
| 
 | ||||
|         im = im.convert("I") | ||||
|         self.assertRaises(ValueError, im.point, list(range(256))) | ||||
|         im.point(lambda x: x * 1) | ||||
|         im.point(lambda x: x + 1) | ||||
|         im.point(lambda x: x * 1 + 1) | ||||
|         self.assertRaises(TypeError, im.point, lambda x: x - 1) | ||||
|         self.assertRaises(TypeError, im.point, lambda x: x / 1) | ||||
|     im = im.convert("I") | ||||
|     with pytest.raises(ValueError): | ||||
|         im.point(list(range(256))) | ||||
|     im.point(lambda x: x * 1) | ||||
|     im.point(lambda x: x + 1) | ||||
|     im.point(lambda x: x * 1 + 1) | ||||
|     with pytest.raises(TypeError): | ||||
|         im.point(lambda x: x - 1) | ||||
|     with pytest.raises(TypeError): | ||||
|         im.point(lambda x: x / 1) | ||||
| 
 | ||||
|     def test_16bit_lut(self): | ||||
|         """ Tests for 16 bit -> 8 bit lut for converting I->L images | ||||
|             see https://github.com/python-pillow/Pillow/issues/440 | ||||
|             """ | ||||
|         im = hopper("I") | ||||
|         im.point(list(range(256)) * 256, "L") | ||||
| 
 | ||||
|     def test_f_lut(self): | ||||
|         """ Tests for floating point lut of 8bit gray image """ | ||||
|         im = hopper("L") | ||||
|         lut = [0.5 * float(x) for x in range(256)] | ||||
| def test_16bit_lut(): | ||||
|     """ Tests for 16 bit -> 8 bit lut for converting I->L images | ||||
|         see https://github.com/python-pillow/Pillow/issues/440 | ||||
|         """ | ||||
|     im = hopper("I") | ||||
|     im.point(list(range(256)) * 256, "L") | ||||
| 
 | ||||
|         out = im.point(lut, "F") | ||||
| 
 | ||||
|         int_lut = [x // 2 for x in range(256)] | ||||
|         assert_image_equal(out.convert("L"), im.point(int_lut, "L")) | ||||
| def test_f_lut(): | ||||
|     """ Tests for floating point lut of 8bit gray image """ | ||||
|     im = hopper("L") | ||||
|     lut = [0.5 * float(x) for x in range(256)] | ||||
| 
 | ||||
|     def test_f_mode(self): | ||||
|         im = hopper("F") | ||||
|         self.assertRaises(ValueError, im.point, None) | ||||
|     out = im.point(lut, "F") | ||||
| 
 | ||||
|     int_lut = [x // 2 for x in range(256)] | ||||
|     assert_image_equal(out.convert("L"), im.point(int_lut, "L")) | ||||
| 
 | ||||
| 
 | ||||
| def test_f_mode(): | ||||
|     im = hopper("F") | ||||
|     with pytest.raises(ValueError): | ||||
|         im.point(None) | ||||
|  |  | |||
|  | @ -3,83 +3,87 @@ from array import array | |||
| 
 | ||||
| from PIL import Image | ||||
| 
 | ||||
| from .helper import PillowTestCase, assert_image_equal, hopper | ||||
| from .helper import assert_image_equal, hopper | ||||
| 
 | ||||
| 
 | ||||
| class TestImagePutData(PillowTestCase): | ||||
|     def test_sanity(self): | ||||
| def test_sanity(): | ||||
|     im1 = hopper() | ||||
| 
 | ||||
|         im1 = hopper() | ||||
|     data = list(im1.getdata()) | ||||
| 
 | ||||
|         data = list(im1.getdata()) | ||||
|     im2 = Image.new(im1.mode, im1.size, 0) | ||||
|     im2.putdata(data) | ||||
| 
 | ||||
|         im2 = Image.new(im1.mode, im1.size, 0) | ||||
|         im2.putdata(data) | ||||
|     assert_image_equal(im1, im2) | ||||
| 
 | ||||
|         assert_image_equal(im1, im2) | ||||
|     # readonly | ||||
|     im2 = Image.new(im1.mode, im2.size, 0) | ||||
|     im2.readonly = 1 | ||||
|     im2.putdata(data) | ||||
| 
 | ||||
|         # readonly | ||||
|         im2 = Image.new(im1.mode, im2.size, 0) | ||||
|         im2.readonly = 1 | ||||
|         im2.putdata(data) | ||||
|     assert not im2.readonly | ||||
|     assert_image_equal(im1, im2) | ||||
| 
 | ||||
|         self.assertFalse(im2.readonly) | ||||
|         assert_image_equal(im1, im2) | ||||
| 
 | ||||
|     def test_long_integers(self): | ||||
|         # see bug-200802-systemerror | ||||
|         def put(value): | ||||
|             im = Image.new("RGBA", (1, 1)) | ||||
|             im.putdata([value]) | ||||
|             return im.getpixel((0, 0)) | ||||
| def test_long_integers(): | ||||
|     # see bug-200802-systemerror | ||||
|     def put(value): | ||||
|         im = Image.new("RGBA", (1, 1)) | ||||
|         im.putdata([value]) | ||||
|         return im.getpixel((0, 0)) | ||||
| 
 | ||||
|         self.assertEqual(put(0xFFFFFFFF), (255, 255, 255, 255)) | ||||
|         self.assertEqual(put(0xFFFFFFFF), (255, 255, 255, 255)) | ||||
|         self.assertEqual(put(-1), (255, 255, 255, 255)) | ||||
|         self.assertEqual(put(-1), (255, 255, 255, 255)) | ||||
|         if sys.maxsize > 2 ** 32: | ||||
|             self.assertEqual(put(sys.maxsize), (255, 255, 255, 255)) | ||||
|         else: | ||||
|             self.assertEqual(put(sys.maxsize), (255, 255, 255, 127)) | ||||
|     assert put(0xFFFFFFFF) == (255, 255, 255, 255) | ||||
|     assert put(0xFFFFFFFF) == (255, 255, 255, 255) | ||||
|     assert put(-1) == (255, 255, 255, 255) | ||||
|     assert put(-1) == (255, 255, 255, 255) | ||||
|     if sys.maxsize > 2 ** 32: | ||||
|         assert put(sys.maxsize) == (255, 255, 255, 255) | ||||
|     else: | ||||
|         assert put(sys.maxsize) == (255, 255, 255, 127) | ||||
| 
 | ||||
|     def test_pypy_performance(self): | ||||
|         im = Image.new("L", (256, 256)) | ||||
|         im.putdata(list(range(256)) * 256) | ||||
| 
 | ||||
|     def test_mode_i(self): | ||||
|         src = hopper("L") | ||||
|         data = list(src.getdata()) | ||||
|         im = Image.new("I", src.size, 0) | ||||
|         im.putdata(data, 2, 256) | ||||
| def test_pypy_performance(): | ||||
|     im = Image.new("L", (256, 256)) | ||||
|     im.putdata(list(range(256)) * 256) | ||||
| 
 | ||||
|         target = [2 * elt + 256 for elt in data] | ||||
|         self.assertEqual(list(im.getdata()), target) | ||||
| 
 | ||||
|     def test_mode_F(self): | ||||
|         src = hopper("L") | ||||
|         data = list(src.getdata()) | ||||
|         im = Image.new("F", src.size, 0) | ||||
|         im.putdata(data, 2.0, 256.0) | ||||
| def test_mode_i(): | ||||
|     src = hopper("L") | ||||
|     data = list(src.getdata()) | ||||
|     im = Image.new("I", src.size, 0) | ||||
|     im.putdata(data, 2, 256) | ||||
| 
 | ||||
|         target = [2.0 * float(elt) + 256.0 for elt in data] | ||||
|         self.assertEqual(list(im.getdata()), target) | ||||
|     target = [2 * elt + 256 for elt in data] | ||||
|     assert list(im.getdata()) == target | ||||
| 
 | ||||
|     def test_array_B(self): | ||||
|         # shouldn't segfault | ||||
|         # see https://github.com/python-pillow/Pillow/issues/1008 | ||||
| 
 | ||||
|         arr = array("B", [0]) * 15000 | ||||
|         im = Image.new("L", (150, 100)) | ||||
|         im.putdata(arr) | ||||
| def test_mode_F(): | ||||
|     src = hopper("L") | ||||
|     data = list(src.getdata()) | ||||
|     im = Image.new("F", src.size, 0) | ||||
|     im.putdata(data, 2.0, 256.0) | ||||
| 
 | ||||
|         self.assertEqual(len(im.getdata()), len(arr)) | ||||
|     target = [2.0 * float(elt) + 256.0 for elt in data] | ||||
|     assert list(im.getdata()) == target | ||||
| 
 | ||||
|     def test_array_F(self): | ||||
|         # shouldn't segfault | ||||
|         # see https://github.com/python-pillow/Pillow/issues/1008 | ||||
| 
 | ||||
|         im = Image.new("F", (150, 100)) | ||||
|         arr = array("f", [0.0]) * 15000 | ||||
|         im.putdata(arr) | ||||
| def test_array_B(): | ||||
|     # shouldn't segfault | ||||
|     # see https://github.com/python-pillow/Pillow/issues/1008 | ||||
| 
 | ||||
|         self.assertEqual(len(im.getdata()), len(arr)) | ||||
|     arr = array("B", [0]) * 15000 | ||||
|     im = Image.new("L", (150, 100)) | ||||
|     im.putdata(arr) | ||||
| 
 | ||||
|     assert len(im.getdata()) == len(arr) | ||||
| 
 | ||||
| 
 | ||||
| def test_array_F(): | ||||
|     # shouldn't segfault | ||||
|     # see https://github.com/python-pillow/Pillow/issues/1008 | ||||
| 
 | ||||
|     im = Image.new("F", (150, 100)) | ||||
|     arr = array("f", [0.0]) * 15000 | ||||
|     im.putdata(arr) | ||||
| 
 | ||||
|     assert len(im.getdata()) == len(arr) | ||||
|  |  | |||
|  | @ -1,67 +1,74 @@ | |||
| import pytest | ||||
| from PIL import Image | ||||
| 
 | ||||
| from .helper import PillowTestCase, assert_image, assert_image_similar, hopper | ||||
| from .helper import assert_image, assert_image_similar, hopper | ||||
| 
 | ||||
| 
 | ||||
| class TestImageQuantize(PillowTestCase): | ||||
|     def test_sanity(self): | ||||
|         image = hopper() | ||||
|         converted = image.quantize() | ||||
|         assert_image(converted, "P", converted.size) | ||||
|         assert_image_similar(converted.convert("RGB"), image, 10) | ||||
| def test_sanity(): | ||||
|     image = hopper() | ||||
|     converted = image.quantize() | ||||
|     assert_image(converted, "P", converted.size) | ||||
|     assert_image_similar(converted.convert("RGB"), image, 10) | ||||
| 
 | ||||
|         image = hopper() | ||||
|         converted = image.quantize(palette=hopper("P")) | ||||
|         assert_image(converted, "P", converted.size) | ||||
|         assert_image_similar(converted.convert("RGB"), image, 60) | ||||
|     image = hopper() | ||||
|     converted = image.quantize(palette=hopper("P")) | ||||
|     assert_image(converted, "P", converted.size) | ||||
|     assert_image_similar(converted.convert("RGB"), image, 60) | ||||
| 
 | ||||
|     def test_libimagequant_quantize(self): | ||||
|         image = hopper() | ||||
|         try: | ||||
|             converted = image.quantize(100, Image.LIBIMAGEQUANT) | ||||
|         except ValueError as ex: | ||||
|             if "dependency" in str(ex).lower(): | ||||
|                 self.skipTest("libimagequant support not available") | ||||
|             else: | ||||
|                 raise | ||||
|         assert_image(converted, "P", converted.size) | ||||
|         assert_image_similar(converted.convert("RGB"), image, 15) | ||||
|         self.assertEqual(len(converted.getcolors()), 100) | ||||
| 
 | ||||
|     def test_octree_quantize(self): | ||||
|         image = hopper() | ||||
|         converted = image.quantize(100, Image.FASTOCTREE) | ||||
|         assert_image(converted, "P", converted.size) | ||||
|         assert_image_similar(converted.convert("RGB"), image, 20) | ||||
|         self.assertEqual(len(converted.getcolors()), 100) | ||||
| def test_libimagequant_quantize(): | ||||
|     image = hopper() | ||||
|     try: | ||||
|         converted = image.quantize(100, Image.LIBIMAGEQUANT) | ||||
|     except ValueError as ex: | ||||
|         if "dependency" in str(ex).lower(): | ||||
|             pytest.skip("libimagequant support not available") | ||||
|         else: | ||||
|             raise | ||||
|     assert_image(converted, "P", converted.size) | ||||
|     assert_image_similar(converted.convert("RGB"), image, 15) | ||||
|     assert len(converted.getcolors()) == 100 | ||||
| 
 | ||||
|     def test_rgba_quantize(self): | ||||
|         image = hopper("RGBA") | ||||
|         self.assertRaises(ValueError, image.quantize, method=0) | ||||
| 
 | ||||
|         self.assertEqual(image.quantize().convert().mode, "RGBA") | ||||
| def test_octree_quantize(): | ||||
|     image = hopper() | ||||
|     converted = image.quantize(100, Image.FASTOCTREE) | ||||
|     assert_image(converted, "P", converted.size) | ||||
|     assert_image_similar(converted.convert("RGB"), image, 20) | ||||
|     assert len(converted.getcolors()) == 100 | ||||
| 
 | ||||
|     def test_quantize(self): | ||||
|         with Image.open("Tests/images/caption_6_33_22.png") as image: | ||||
|             image = image.convert("RGB") | ||||
|         converted = image.quantize() | ||||
|         assert_image(converted, "P", converted.size) | ||||
|         assert_image_similar(converted.convert("RGB"), image, 1) | ||||
| 
 | ||||
|     def test_quantize_no_dither(self): | ||||
|         image = hopper() | ||||
|         with Image.open("Tests/images/caption_6_33_22.png") as palette: | ||||
|             palette = palette.convert("P") | ||||
| def test_rgba_quantize(): | ||||
|     image = hopper("RGBA") | ||||
|     with pytest.raises(ValueError): | ||||
|         image.quantize(method=0) | ||||
| 
 | ||||
|         converted = image.quantize(dither=0, palette=palette) | ||||
|         assert_image(converted, "P", converted.size) | ||||
|     assert image.quantize().convert().mode == "RGBA" | ||||
| 
 | ||||
|     def test_quantize_dither_diff(self): | ||||
|         image = hopper() | ||||
|         with Image.open("Tests/images/caption_6_33_22.png") as palette: | ||||
|             palette = palette.convert("P") | ||||
| 
 | ||||
|         dither = image.quantize(dither=1, palette=palette) | ||||
|         nodither = image.quantize(dither=0, palette=palette) | ||||
| def test_quantize(): | ||||
|     with Image.open("Tests/images/caption_6_33_22.png") as image: | ||||
|         image = image.convert("RGB") | ||||
|     converted = image.quantize() | ||||
|     assert_image(converted, "P", converted.size) | ||||
|     assert_image_similar(converted.convert("RGB"), image, 1) | ||||
| 
 | ||||
|         self.assertNotEqual(dither.tobytes(), nodither.tobytes()) | ||||
| 
 | ||||
| def test_quantize_no_dither(): | ||||
|     image = hopper() | ||||
|     with Image.open("Tests/images/caption_6_33_22.png") as palette: | ||||
|         palette = palette.convert("P") | ||||
| 
 | ||||
|     converted = image.quantize(dither=0, palette=palette) | ||||
|     assert_image(converted, "P", converted.size) | ||||
| 
 | ||||
| 
 | ||||
| def test_quantize_dither_diff(): | ||||
|     image = hopper() | ||||
|     with Image.open("Tests/images/caption_6_33_22.png") as palette: | ||||
|         palette = palette.convert("P") | ||||
| 
 | ||||
|     dither = image.quantize(dither=1, palette=palette) | ||||
|     nodither = image.quantize(dither=0, palette=palette) | ||||
| 
 | ||||
|     assert dither.tobytes() != nodither.tobytes() | ||||
|  |  | |||
|  | @ -1,127 +1,140 @@ | |||
| from PIL import Image | ||||
| 
 | ||||
| from .helper import PillowTestCase, assert_image_equal, assert_image_similar, hopper | ||||
| from .helper import assert_image_equal, assert_image_similar, hopper | ||||
| 
 | ||||
| 
 | ||||
| class TestImageRotate(PillowTestCase): | ||||
|     def rotate(self, im, mode, angle, center=None, translate=None): | ||||
|         out = im.rotate(angle, center=center, translate=translate) | ||||
|         self.assertEqual(out.mode, mode) | ||||
|         self.assertEqual(out.size, im.size)  # default rotate clips output | ||||
|         out = im.rotate(angle, center=center, translate=translate, expand=1) | ||||
|         self.assertEqual(out.mode, mode) | ||||
|         if angle % 180 == 0: | ||||
|             self.assertEqual(out.size, im.size) | ||||
|         elif im.size == (0, 0): | ||||
|             self.assertEqual(out.size, im.size) | ||||
|         else: | ||||
|             self.assertNotEqual(out.size, im.size) | ||||
| def rotate(im, mode, angle, center=None, translate=None): | ||||
|     out = im.rotate(angle, center=center, translate=translate) | ||||
|     assert out.mode == mode | ||||
|     assert out.size == im.size  # default rotate clips output | ||||
|     out = im.rotate(angle, center=center, translate=translate, expand=1) | ||||
|     assert out.mode == mode | ||||
|     if angle % 180 == 0: | ||||
|         assert out.size == im.size | ||||
|     elif im.size == (0, 0): | ||||
|         assert out.size == im.size | ||||
|     else: | ||||
|         assert out.size != im.size | ||||
| 
 | ||||
|     def test_mode(self): | ||||
|         for mode in ("1", "P", "L", "RGB", "I", "F"): | ||||
|             im = hopper(mode) | ||||
|             self.rotate(im, mode, 45) | ||||
| 
 | ||||
|     def test_angle(self): | ||||
|         for angle in (0, 90, 180, 270): | ||||
|             with Image.open("Tests/images/test-card.png") as im: | ||||
|                 self.rotate(im, im.mode, angle) | ||||
| def test_mode(): | ||||
|     for mode in ("1", "P", "L", "RGB", "I", "F"): | ||||
|         im = hopper(mode) | ||||
|         rotate(im, mode, 45) | ||||
| 
 | ||||
|     def test_zero(self): | ||||
|         for angle in (0, 45, 90, 180, 270): | ||||
|             im = Image.new("RGB", (0, 0)) | ||||
|             self.rotate(im, im.mode, angle) | ||||
| 
 | ||||
|     def test_resample(self): | ||||
|         # Target image creation, inspected by eye. | ||||
|         # >>> im = Image.open('Tests/images/hopper.ppm') | ||||
|         # >>> im = im.rotate(45, resample=Image.BICUBIC, expand=True) | ||||
|         # >>> im.save('Tests/images/hopper_45.png') | ||||
| def test_angle(): | ||||
|     for angle in (0, 90, 180, 270): | ||||
|         with Image.open("Tests/images/test-card.png") as im: | ||||
|             rotate(im, im.mode, angle) | ||||
| 
 | ||||
|         with Image.open("Tests/images/hopper_45.png") as target: | ||||
|             for (resample, epsilon) in ( | ||||
|                 (Image.NEAREST, 10), | ||||
|                 (Image.BILINEAR, 5), | ||||
|                 (Image.BICUBIC, 0), | ||||
|             ): | ||||
|                 im = hopper() | ||||
|                 im = im.rotate(45, resample=resample, expand=True) | ||||
|                 assert_image_similar(im, target, epsilon) | ||||
| 
 | ||||
|     def test_center_0(self): | ||||
|         im = hopper() | ||||
|         im = im.rotate(45, center=(0, 0), resample=Image.BICUBIC) | ||||
| def test_zero(): | ||||
|     for angle in (0, 45, 90, 180, 270): | ||||
|         im = Image.new("RGB", (0, 0)) | ||||
|         rotate(im, im.mode, angle) | ||||
| 
 | ||||
|         with Image.open("Tests/images/hopper_45.png") as target: | ||||
|             target_origin = target.size[1] / 2 | ||||
|             target = target.crop((0, target_origin, 128, target_origin + 128)) | ||||
| 
 | ||||
|         assert_image_similar(im, target, 15) | ||||
| def test_resample(): | ||||
|     # Target image creation, inspected by eye. | ||||
|     # >>> im = Image.open('Tests/images/hopper.ppm') | ||||
|     # >>> im = im.rotate(45, resample=Image.BICUBIC, expand=True) | ||||
|     # >>> im.save('Tests/images/hopper_45.png') | ||||
| 
 | ||||
|     def test_center_14(self): | ||||
|         im = hopper() | ||||
|         im = im.rotate(45, center=(14, 14), resample=Image.BICUBIC) | ||||
|     with Image.open("Tests/images/hopper_45.png") as target: | ||||
|         for (resample, epsilon) in ( | ||||
|             (Image.NEAREST, 10), | ||||
|             (Image.BILINEAR, 5), | ||||
|             (Image.BICUBIC, 0), | ||||
|         ): | ||||
|             im = hopper() | ||||
|             im = im.rotate(45, resample=resample, expand=True) | ||||
|             assert_image_similar(im, target, epsilon) | ||||
| 
 | ||||
|         with Image.open("Tests/images/hopper_45.png") as target: | ||||
|             target_origin = target.size[1] / 2 - 14 | ||||
|             target = target.crop((6, target_origin, 128 + 6, target_origin + 128)) | ||||
| 
 | ||||
|             assert_image_similar(im, target, 10) | ||||
| def test_center_0(): | ||||
|     im = hopper() | ||||
|     im = im.rotate(45, center=(0, 0), resample=Image.BICUBIC) | ||||
| 
 | ||||
|     def test_translate(self): | ||||
|         im = hopper() | ||||
|         with Image.open("Tests/images/hopper_45.png") as target: | ||||
|             target_origin = (target.size[1] / 2 - 64) - 5 | ||||
|             target = target.crop( | ||||
|                 (target_origin, target_origin, target_origin + 128, target_origin + 128) | ||||
|             ) | ||||
|     with Image.open("Tests/images/hopper_45.png") as target: | ||||
|         target_origin = target.size[1] / 2 | ||||
|         target = target.crop((0, target_origin, 128, target_origin + 128)) | ||||
| 
 | ||||
|         im = im.rotate(45, translate=(5, 5), resample=Image.BICUBIC) | ||||
|     assert_image_similar(im, target, 15) | ||||
| 
 | ||||
|         assert_image_similar(im, target, 1) | ||||
| 
 | ||||
|     def test_fastpath_center(self): | ||||
|         # if the center is -1,-1 and we rotate by 90<=x<=270 the | ||||
|         # resulting image should be black | ||||
|         for angle in (90, 180, 270): | ||||
|             im = hopper().rotate(angle, center=(-1, -1)) | ||||
|             assert_image_equal(im, Image.new("RGB", im.size, "black")) | ||||
| def test_center_14(): | ||||
|     im = hopper() | ||||
|     im = im.rotate(45, center=(14, 14), resample=Image.BICUBIC) | ||||
| 
 | ||||
|     def test_fastpath_translate(self): | ||||
|         # if we post-translate by -128 | ||||
|         # resulting image should be black | ||||
|         for angle in (0, 90, 180, 270): | ||||
|             im = hopper().rotate(angle, translate=(-128, -128)) | ||||
|             assert_image_equal(im, Image.new("RGB", im.size, "black")) | ||||
|     with Image.open("Tests/images/hopper_45.png") as target: | ||||
|         target_origin = target.size[1] / 2 - 14 | ||||
|         target = target.crop((6, target_origin, 128 + 6, target_origin + 128)) | ||||
| 
 | ||||
|     def test_center(self): | ||||
|         im = hopper() | ||||
|         self.rotate(im, im.mode, 45, center=(0, 0)) | ||||
|         self.rotate(im, im.mode, 45, translate=(im.size[0] / 2, 0)) | ||||
|         self.rotate(im, im.mode, 45, center=(0, 0), translate=(im.size[0] / 2, 0)) | ||||
|         assert_image_similar(im, target, 10) | ||||
| 
 | ||||
|     def test_rotate_no_fill(self): | ||||
|         im = Image.new("RGB", (100, 100), "green") | ||||
|         im = im.rotate(45) | ||||
|         with Image.open("Tests/images/rotate_45_no_fill.png") as target: | ||||
|             assert_image_equal(im, target) | ||||
| 
 | ||||
|     def test_rotate_with_fill(self): | ||||
|         im = Image.new("RGB", (100, 100), "green") | ||||
|         im = im.rotate(45, fillcolor="white") | ||||
|         with Image.open("Tests/images/rotate_45_with_fill.png") as target: | ||||
|             assert_image_equal(im, target) | ||||
| def test_translate(): | ||||
|     im = hopper() | ||||
|     with Image.open("Tests/images/hopper_45.png") as target: | ||||
|         target_origin = (target.size[1] / 2 - 64) - 5 | ||||
|         target = target.crop( | ||||
|             (target_origin, target_origin, target_origin + 128, target_origin + 128) | ||||
|         ) | ||||
| 
 | ||||
|     def test_alpha_rotate_no_fill(self): | ||||
|         # Alpha images are handled differently internally | ||||
|         im = Image.new("RGBA", (10, 10), "green") | ||||
|         im = im.rotate(45, expand=1) | ||||
|         corner = im.getpixel((0, 0)) | ||||
|         self.assertEqual(corner, (0, 0, 0, 0)) | ||||
|     im = im.rotate(45, translate=(5, 5), resample=Image.BICUBIC) | ||||
| 
 | ||||
|     def test_alpha_rotate_with_fill(self): | ||||
|         # Alpha images are handled differently internally | ||||
|         im = Image.new("RGBA", (10, 10), "green") | ||||
|         im = im.rotate(45, expand=1, fillcolor=(255, 0, 0, 255)) | ||||
|         corner = im.getpixel((0, 0)) | ||||
|         self.assertEqual(corner, (255, 0, 0, 255)) | ||||
|     assert_image_similar(im, target, 1) | ||||
| 
 | ||||
| 
 | ||||
| def test_fastpath_center(): | ||||
|     # if the center is -1,-1 and we rotate by 90<=x<=270 the | ||||
|     # resulting image should be black | ||||
|     for angle in (90, 180, 270): | ||||
|         im = hopper().rotate(angle, center=(-1, -1)) | ||||
|         assert_image_equal(im, Image.new("RGB", im.size, "black")) | ||||
| 
 | ||||
| 
 | ||||
| def test_fastpath_translate(): | ||||
|     # if we post-translate by -128 | ||||
|     # resulting image should be black | ||||
|     for angle in (0, 90, 180, 270): | ||||
|         im = hopper().rotate(angle, translate=(-128, -128)) | ||||
|         assert_image_equal(im, Image.new("RGB", im.size, "black")) | ||||
| 
 | ||||
| 
 | ||||
| def test_center(): | ||||
|     im = hopper() | ||||
|     rotate(im, im.mode, 45, center=(0, 0)) | ||||
|     rotate(im, im.mode, 45, translate=(im.size[0] / 2, 0)) | ||||
|     rotate(im, im.mode, 45, center=(0, 0), translate=(im.size[0] / 2, 0)) | ||||
| 
 | ||||
| 
 | ||||
| def test_rotate_no_fill(): | ||||
|     im = Image.new("RGB", (100, 100), "green") | ||||
|     im = im.rotate(45) | ||||
|     with Image.open("Tests/images/rotate_45_no_fill.png") as target: | ||||
|         assert_image_equal(im, target) | ||||
| 
 | ||||
| 
 | ||||
| def test_rotate_with_fill(): | ||||
|     im = Image.new("RGB", (100, 100), "green") | ||||
|     im = im.rotate(45, fillcolor="white") | ||||
|     with Image.open("Tests/images/rotate_45_with_fill.png") as target: | ||||
|         assert_image_equal(im, target) | ||||
| 
 | ||||
| 
 | ||||
| def test_alpha_rotate_no_fill(): | ||||
|     # Alpha images are handled differently internally | ||||
|     im = Image.new("RGBA", (10, 10), "green") | ||||
|     im = im.rotate(45, expand=1) | ||||
|     corner = im.getpixel((0, 0)) | ||||
|     assert corner == (0, 0, 0, 0) | ||||
| 
 | ||||
| 
 | ||||
| def test_alpha_rotate_with_fill(): | ||||
|     # Alpha images are handled differently internally | ||||
|     im = Image.new("RGBA", (10, 10), "green") | ||||
|     im = im.rotate(45, expand=1, fillcolor=(255, 0, 0, 255)) | ||||
|     corner = im.getpixel((0, 0)) | ||||
|     assert corner == (255, 0, 0, 255) | ||||
|  |  | |||
|  | @ -1,7 +1,7 @@ | |||
| import pytest | ||||
| from PIL import Image | ||||
| 
 | ||||
| from .helper import ( | ||||
|     PillowTestCase, | ||||
|     assert_image_equal, | ||||
|     assert_image_similar, | ||||
|     fromstring, | ||||
|  | @ -10,98 +10,103 @@ from .helper import ( | |||
| ) | ||||
| 
 | ||||
| 
 | ||||
| class TestImageThumbnail(PillowTestCase): | ||||
|     def test_sanity(self): | ||||
|         im = hopper() | ||||
|         self.assertIsNone(im.thumbnail((100, 100))) | ||||
| def test_sanity(): | ||||
|     im = hopper() | ||||
|     assert im.thumbnail((100, 100)) is None | ||||
| 
 | ||||
|         self.assertEqual(im.size, (100, 100)) | ||||
|     assert im.size == (100, 100) | ||||
| 
 | ||||
|     def test_aspect(self): | ||||
|         im = Image.new("L", (128, 128)) | ||||
|         im.thumbnail((100, 100)) | ||||
|         self.assertEqual(im.size, (100, 100)) | ||||
| 
 | ||||
|         im = Image.new("L", (128, 256)) | ||||
|         im.thumbnail((100, 100)) | ||||
|         self.assertEqual(im.size, (50, 100)) | ||||
| def test_aspect(): | ||||
|     im = Image.new("L", (128, 128)) | ||||
|     im.thumbnail((100, 100)) | ||||
|     assert im.size == (100, 100) | ||||
| 
 | ||||
|         im = Image.new("L", (128, 256)) | ||||
|         im.thumbnail((50, 100)) | ||||
|         self.assertEqual(im.size, (50, 100)) | ||||
|     im = Image.new("L", (128, 256)) | ||||
|     im.thumbnail((100, 100)) | ||||
|     assert im.size == (50, 100) | ||||
| 
 | ||||
|         im = Image.new("L", (256, 128)) | ||||
|         im.thumbnail((100, 100)) | ||||
|         self.assertEqual(im.size, (100, 50)) | ||||
|     im = Image.new("L", (128, 256)) | ||||
|     im.thumbnail((50, 100)) | ||||
|     assert im.size == (50, 100) | ||||
| 
 | ||||
|         im = Image.new("L", (256, 128)) | ||||
|         im.thumbnail((100, 50)) | ||||
|         self.assertEqual(im.size, (100, 50)) | ||||
|     im = Image.new("L", (256, 128)) | ||||
|     im.thumbnail((100, 100)) | ||||
|     assert im.size == (100, 50) | ||||
| 
 | ||||
|         im = Image.new("L", (128, 128)) | ||||
|         im.thumbnail((100, 100)) | ||||
|         self.assertEqual(im.size, (100, 100)) | ||||
|     im = Image.new("L", (256, 128)) | ||||
|     im.thumbnail((100, 50)) | ||||
|     assert im.size == (100, 50) | ||||
| 
 | ||||
|         im = Image.new("L", (256, 162))  # ratio is 1.5802469136 | ||||
|         im.thumbnail((33, 33)) | ||||
|         self.assertEqual(im.size, (33, 21))  # ratio is 1.5714285714 | ||||
|     im = Image.new("L", (128, 128)) | ||||
|     im.thumbnail((100, 100)) | ||||
|     assert im.size == (100, 100) | ||||
| 
 | ||||
|         im = Image.new("L", (162, 256))  # ratio is 0.6328125 | ||||
|         im.thumbnail((33, 33)) | ||||
|         self.assertEqual(im.size, (21, 33))  # ratio is 0.6363636364 | ||||
|     im = Image.new("L", (256, 162))  # ratio is 1.5802469136 | ||||
|     im.thumbnail((33, 33)) | ||||
|     assert im.size == (33, 21)  # ratio is 1.5714285714 | ||||
| 
 | ||||
|     def test_float(self): | ||||
|         im = Image.new("L", (128, 128)) | ||||
|         im.thumbnail((99.9, 99.9)) | ||||
|         self.assertEqual(im.size, (100, 100)) | ||||
|     im = Image.new("L", (162, 256))  # ratio is 0.6328125 | ||||
|     im.thumbnail((33, 33)) | ||||
|     assert im.size == (21, 33)  # ratio is 0.6363636364 | ||||
| 
 | ||||
|     def test_no_resize(self): | ||||
|         # Check that draft() can resize the image to the destination size | ||||
|         with Image.open("Tests/images/hopper.jpg") as im: | ||||
|             im.draft(None, (64, 64)) | ||||
|             self.assertEqual(im.size, (64, 64)) | ||||
| 
 | ||||
|         # Test thumbnail(), where only draft() is necessary to resize the image | ||||
|         with Image.open("Tests/images/hopper.jpg") as im: | ||||
|             im.thumbnail((64, 64)) | ||||
|             self.assertEqual(im.size, (64, 64)) | ||||
| def test_float(): | ||||
|     im = Image.new("L", (128, 128)) | ||||
|     im.thumbnail((99.9, 99.9)) | ||||
|     assert im.size == (100, 100) | ||||
| 
 | ||||
|     def test_DCT_scaling_edges(self): | ||||
|         # Make an image with red borders and size (N * 8) + 1 to cross DCT grid | ||||
|         im = Image.new("RGB", (257, 257), "red") | ||||
|         im.paste(Image.new("RGB", (235, 235)), (11, 11)) | ||||
| 
 | ||||
|         thumb = fromstring(tostring(im, "JPEG", quality=99, subsampling=0)) | ||||
|         # small reducing_gap to amplify the effect | ||||
|         thumb.thumbnail((32, 32), Image.BICUBIC, reducing_gap=1.0) | ||||
| def test_no_resize(): | ||||
|     # Check that draft() can resize the image to the destination size | ||||
|     with Image.open("Tests/images/hopper.jpg") as im: | ||||
|         im.draft(None, (64, 64)) | ||||
|         assert im.size == (64, 64) | ||||
| 
 | ||||
|         ref = im.resize((32, 32), Image.BICUBIC) | ||||
|         # This is still JPEG, some error is present. Without the fix it is 11.5 | ||||
|         assert_image_similar(thumb, ref, 1.5) | ||||
|     # Test thumbnail(), where only draft() is necessary to resize the image | ||||
|     with Image.open("Tests/images/hopper.jpg") as im: | ||||
|         im.thumbnail((64, 64)) | ||||
|         assert im.size == (64, 64) | ||||
| 
 | ||||
|     def test_reducing_gap_values(self): | ||||
|         im = hopper() | ||||
|         im.thumbnail((18, 18), Image.BICUBIC) | ||||
| 
 | ||||
|         ref = hopper() | ||||
|         ref.thumbnail((18, 18), Image.BICUBIC, reducing_gap=2.0) | ||||
|         # reducing_gap=2.0 should be the default | ||||
| def test_DCT_scaling_edges(): | ||||
|     # Make an image with red borders and size (N * 8) + 1 to cross DCT grid | ||||
|     im = Image.new("RGB", (257, 257), "red") | ||||
|     im.paste(Image.new("RGB", (235, 235)), (11, 11)) | ||||
| 
 | ||||
|     thumb = fromstring(tostring(im, "JPEG", quality=99, subsampling=0)) | ||||
|     # small reducing_gap to amplify the effect | ||||
|     thumb.thumbnail((32, 32), Image.BICUBIC, reducing_gap=1.0) | ||||
| 
 | ||||
|     ref = im.resize((32, 32), Image.BICUBIC) | ||||
|     # This is still JPEG, some error is present. Without the fix it is 11.5 | ||||
|     assert_image_similar(thumb, ref, 1.5) | ||||
| 
 | ||||
| 
 | ||||
| def test_reducing_gap_values(): | ||||
|     im = hopper() | ||||
|     im.thumbnail((18, 18), Image.BICUBIC) | ||||
| 
 | ||||
|     ref = hopper() | ||||
|     ref.thumbnail((18, 18), Image.BICUBIC, reducing_gap=2.0) | ||||
|     # reducing_gap=2.0 should be the default | ||||
|     assert_image_equal(ref, im) | ||||
| 
 | ||||
|     ref = hopper() | ||||
|     ref.thumbnail((18, 18), Image.BICUBIC, reducing_gap=None) | ||||
|     with pytest.raises(AssertionError): | ||||
|         assert_image_equal(ref, im) | ||||
| 
 | ||||
|         ref = hopper() | ||||
|         ref.thumbnail((18, 18), Image.BICUBIC, reducing_gap=None) | ||||
|         with self.assertRaises(AssertionError): | ||||
|     assert_image_similar(ref, im, 3.5) | ||||
| 
 | ||||
| 
 | ||||
| def test_reducing_gap_for_DCT_scaling(): | ||||
|     with Image.open("Tests/images/hopper.jpg") as ref: | ||||
|         # thumbnail should call draft with reducing_gap scale | ||||
|         ref.draft(None, (18 * 3, 18 * 3)) | ||||
|         ref = ref.resize((18, 18), Image.BICUBIC) | ||||
| 
 | ||||
|         with Image.open("Tests/images/hopper.jpg") as im: | ||||
|             im.thumbnail((18, 18), Image.BICUBIC, reducing_gap=3.0) | ||||
| 
 | ||||
|             assert_image_equal(ref, im) | ||||
| 
 | ||||
|         assert_image_similar(ref, im, 3.5) | ||||
| 
 | ||||
|     def test_reducing_gap_for_DCT_scaling(self): | ||||
|         with Image.open("Tests/images/hopper.jpg") as ref: | ||||
|             # thumbnail should call draft with reducing_gap scale | ||||
|             ref.draft(None, (18 * 3, 18 * 3)) | ||||
|             ref = ref.resize((18, 18), Image.BICUBIC) | ||||
| 
 | ||||
|             with Image.open("Tests/images/hopper.jpg") as im: | ||||
|                 im.thumbnail((18, 18), Image.BICUBIC, reducing_gap=3.0) | ||||
| 
 | ||||
|                 assert_image_equal(ref, im) | ||||
|  |  | |||
|  | @ -1,14 +1,16 @@ | |||
| from .helper import PillowTestCase, assert_image_equal, fromstring, hopper | ||||
| import pytest | ||||
| 
 | ||||
| from .helper import assert_image_equal, fromstring, hopper | ||||
| 
 | ||||
| 
 | ||||
| class TestImageToBitmap(PillowTestCase): | ||||
|     def test_sanity(self): | ||||
| def test_sanity(): | ||||
| 
 | ||||
|         self.assertRaises(ValueError, lambda: hopper().tobitmap()) | ||||
|     with pytest.raises(ValueError): | ||||
|         hopper().tobitmap() | ||||
| 
 | ||||
|         im1 = hopper().convert("1") | ||||
|     im1 = hopper().convert("1") | ||||
| 
 | ||||
|         bitmap = im1.tobitmap() | ||||
|     bitmap = im1.tobitmap() | ||||
| 
 | ||||
|         self.assertIsInstance(bitmap, bytes) | ||||
|         assert_image_equal(im1, fromstring(bitmap)) | ||||
|     assert isinstance(bitmap, bytes) | ||||
|     assert_image_equal(im1, fromstring(bitmap)) | ||||
|  |  | |||
|  | @ -9,151 +9,154 @@ from PIL.Image import ( | |||
| ) | ||||
| 
 | ||||
| from . import helper | ||||
| from .helper import PillowTestCase, assert_image_equal | ||||
| from .helper import assert_image_equal | ||||
| 
 | ||||
| HOPPER = { | ||||
|     mode: helper.hopper(mode).crop((0, 0, 121, 127)).copy() | ||||
|     for mode in ["L", "RGB", "I;16", "I;16L", "I;16B"] | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| class TestImageTranspose(PillowTestCase): | ||||
| def test_flip_left_right(): | ||||
|     def transpose(mode): | ||||
|         im = HOPPER[mode] | ||||
|         out = im.transpose(FLIP_LEFT_RIGHT) | ||||
|         assert out.mode == mode | ||||
|         assert out.size == im.size | ||||
| 
 | ||||
|     hopper = { | ||||
|         mode: helper.hopper(mode).crop((0, 0, 121, 127)).copy() | ||||
|         for mode in ["L", "RGB", "I;16", "I;16L", "I;16B"] | ||||
|     } | ||||
|         x, y = im.size | ||||
|         assert im.getpixel((1, 1)) == out.getpixel((x - 2, 1)) | ||||
|         assert im.getpixel((x - 2, 1)) == out.getpixel((1, 1)) | ||||
|         assert im.getpixel((1, y - 2)) == out.getpixel((x - 2, y - 2)) | ||||
|         assert im.getpixel((x - 2, y - 2)) == out.getpixel((1, y - 2)) | ||||
| 
 | ||||
|     def test_flip_left_right(self): | ||||
|         def transpose(mode): | ||||
|             im = self.hopper[mode] | ||||
|             out = im.transpose(FLIP_LEFT_RIGHT) | ||||
|             self.assertEqual(out.mode, mode) | ||||
|             self.assertEqual(out.size, im.size) | ||||
|     for mode in HOPPER: | ||||
|         transpose(mode) | ||||
| 
 | ||||
|             x, y = im.size | ||||
|             self.assertEqual(im.getpixel((1, 1)), out.getpixel((x - 2, 1))) | ||||
|             self.assertEqual(im.getpixel((x - 2, 1)), out.getpixel((1, 1))) | ||||
|             self.assertEqual(im.getpixel((1, y - 2)), out.getpixel((x - 2, y - 2))) | ||||
|             self.assertEqual(im.getpixel((x - 2, y - 2)), out.getpixel((1, y - 2))) | ||||
| 
 | ||||
|         for mode in self.hopper: | ||||
|             transpose(mode) | ||||
| def test_flip_top_bottom(): | ||||
|     def transpose(mode): | ||||
|         im = HOPPER[mode] | ||||
|         out = im.transpose(FLIP_TOP_BOTTOM) | ||||
|         assert out.mode == mode | ||||
|         assert out.size == im.size | ||||
| 
 | ||||
|     def test_flip_top_bottom(self): | ||||
|         def transpose(mode): | ||||
|             im = self.hopper[mode] | ||||
|             out = im.transpose(FLIP_TOP_BOTTOM) | ||||
|             self.assertEqual(out.mode, mode) | ||||
|             self.assertEqual(out.size, im.size) | ||||
|         x, y = im.size | ||||
|         assert im.getpixel((1, 1)) == out.getpixel((1, y - 2)) | ||||
|         assert im.getpixel((x - 2, 1)) == out.getpixel((x - 2, y - 2)) | ||||
|         assert im.getpixel((1, y - 2)) == out.getpixel((1, 1)) | ||||
|         assert im.getpixel((x - 2, y - 2)) == out.getpixel((x - 2, 1)) | ||||
| 
 | ||||
|             x, y = im.size | ||||
|             self.assertEqual(im.getpixel((1, 1)), out.getpixel((1, y - 2))) | ||||
|             self.assertEqual(im.getpixel((x - 2, 1)), out.getpixel((x - 2, y - 2))) | ||||
|             self.assertEqual(im.getpixel((1, y - 2)), out.getpixel((1, 1))) | ||||
|             self.assertEqual(im.getpixel((x - 2, y - 2)), out.getpixel((x - 2, 1))) | ||||
|     for mode in HOPPER: | ||||
|         transpose(mode) | ||||
| 
 | ||||
|         for mode in self.hopper: | ||||
|             transpose(mode) | ||||
| 
 | ||||
|     def test_rotate_90(self): | ||||
|         def transpose(mode): | ||||
|             im = self.hopper[mode] | ||||
|             out = im.transpose(ROTATE_90) | ||||
|             self.assertEqual(out.mode, mode) | ||||
|             self.assertEqual(out.size, im.size[::-1]) | ||||
| def test_rotate_90(): | ||||
|     def transpose(mode): | ||||
|         im = HOPPER[mode] | ||||
|         out = im.transpose(ROTATE_90) | ||||
|         assert out.mode == mode | ||||
|         assert out.size == im.size[::-1] | ||||
| 
 | ||||
|             x, y = im.size | ||||
|             self.assertEqual(im.getpixel((1, 1)), out.getpixel((1, x - 2))) | ||||
|             self.assertEqual(im.getpixel((x - 2, 1)), out.getpixel((1, 1))) | ||||
|             self.assertEqual(im.getpixel((1, y - 2)), out.getpixel((y - 2, x - 2))) | ||||
|             self.assertEqual(im.getpixel((x - 2, y - 2)), out.getpixel((y - 2, 1))) | ||||
|         x, y = im.size | ||||
|         assert im.getpixel((1, 1)) == out.getpixel((1, x - 2)) | ||||
|         assert im.getpixel((x - 2, 1)) == out.getpixel((1, 1)) | ||||
|         assert im.getpixel((1, y - 2)) == out.getpixel((y - 2, x - 2)) | ||||
|         assert im.getpixel((x - 2, y - 2)) == out.getpixel((y - 2, 1)) | ||||
| 
 | ||||
|         for mode in self.hopper: | ||||
|             transpose(mode) | ||||
|     for mode in HOPPER: | ||||
|         transpose(mode) | ||||
| 
 | ||||
|     def test_rotate_180(self): | ||||
|         def transpose(mode): | ||||
|             im = self.hopper[mode] | ||||
|             out = im.transpose(ROTATE_180) | ||||
|             self.assertEqual(out.mode, mode) | ||||
|             self.assertEqual(out.size, im.size) | ||||
| 
 | ||||
|             x, y = im.size | ||||
|             self.assertEqual(im.getpixel((1, 1)), out.getpixel((x - 2, y - 2))) | ||||
|             self.assertEqual(im.getpixel((x - 2, 1)), out.getpixel((1, y - 2))) | ||||
|             self.assertEqual(im.getpixel((1, y - 2)), out.getpixel((x - 2, 1))) | ||||
|             self.assertEqual(im.getpixel((x - 2, y - 2)), out.getpixel((1, 1))) | ||||
| def test_rotate_180(): | ||||
|     def transpose(mode): | ||||
|         im = HOPPER[mode] | ||||
|         out = im.transpose(ROTATE_180) | ||||
|         assert out.mode == mode | ||||
|         assert out.size == im.size | ||||
| 
 | ||||
|         for mode in self.hopper: | ||||
|             transpose(mode) | ||||
|         x, y = im.size | ||||
|         assert im.getpixel((1, 1)) == out.getpixel((x - 2, y - 2)) | ||||
|         assert im.getpixel((x - 2, 1)) == out.getpixel((1, y - 2)) | ||||
|         assert im.getpixel((1, y - 2)) == out.getpixel((x - 2, 1)) | ||||
|         assert im.getpixel((x - 2, y - 2)) == out.getpixel((1, 1)) | ||||
| 
 | ||||
|     def test_rotate_270(self): | ||||
|         def transpose(mode): | ||||
|             im = self.hopper[mode] | ||||
|             out = im.transpose(ROTATE_270) | ||||
|             self.assertEqual(out.mode, mode) | ||||
|             self.assertEqual(out.size, im.size[::-1]) | ||||
|     for mode in HOPPER: | ||||
|         transpose(mode) | ||||
| 
 | ||||
|             x, y = im.size | ||||
|             self.assertEqual(im.getpixel((1, 1)), out.getpixel((y - 2, 1))) | ||||
|             self.assertEqual(im.getpixel((x - 2, 1)), out.getpixel((y - 2, x - 2))) | ||||
|             self.assertEqual(im.getpixel((1, y - 2)), out.getpixel((1, 1))) | ||||
|             self.assertEqual(im.getpixel((x - 2, y - 2)), out.getpixel((1, x - 2))) | ||||
| 
 | ||||
|         for mode in self.hopper: | ||||
|             transpose(mode) | ||||
| def test_rotate_270(): | ||||
|     def transpose(mode): | ||||
|         im = HOPPER[mode] | ||||
|         out = im.transpose(ROTATE_270) | ||||
|         assert out.mode == mode | ||||
|         assert out.size == im.size[::-1] | ||||
| 
 | ||||
|     def test_transpose(self): | ||||
|         def transpose(mode): | ||||
|             im = self.hopper[mode] | ||||
|             out = im.transpose(TRANSPOSE) | ||||
|             self.assertEqual(out.mode, mode) | ||||
|             self.assertEqual(out.size, im.size[::-1]) | ||||
|         x, y = im.size | ||||
|         assert im.getpixel((1, 1)) == out.getpixel((y - 2, 1)) | ||||
|         assert im.getpixel((x - 2, 1)) == out.getpixel((y - 2, x - 2)) | ||||
|         assert im.getpixel((1, y - 2)) == out.getpixel((1, 1)) | ||||
|         assert im.getpixel((x - 2, y - 2)) == out.getpixel((1, x - 2)) | ||||
| 
 | ||||
|             x, y = im.size | ||||
|             self.assertEqual(im.getpixel((1, 1)), out.getpixel((1, 1))) | ||||
|             self.assertEqual(im.getpixel((x - 2, 1)), out.getpixel((1, x - 2))) | ||||
|             self.assertEqual(im.getpixel((1, y - 2)), out.getpixel((y - 2, 1))) | ||||
|             self.assertEqual(im.getpixel((x - 2, y - 2)), out.getpixel((y - 2, x - 2))) | ||||
|     for mode in HOPPER: | ||||
|         transpose(mode) | ||||
| 
 | ||||
|         for mode in self.hopper: | ||||
|             transpose(mode) | ||||
| 
 | ||||
|     def test_tranverse(self): | ||||
|         def transpose(mode): | ||||
|             im = self.hopper[mode] | ||||
|             out = im.transpose(TRANSVERSE) | ||||
|             self.assertEqual(out.mode, mode) | ||||
|             self.assertEqual(out.size, im.size[::-1]) | ||||
| def test_transpose(): | ||||
|     def transpose(mode): | ||||
|         im = HOPPER[mode] | ||||
|         out = im.transpose(TRANSPOSE) | ||||
|         assert out.mode == mode | ||||
|         assert out.size == im.size[::-1] | ||||
| 
 | ||||
|             x, y = im.size | ||||
|             self.assertEqual(im.getpixel((1, 1)), out.getpixel((y - 2, x - 2))) | ||||
|             self.assertEqual(im.getpixel((x - 2, 1)), out.getpixel((y - 2, 1))) | ||||
|             self.assertEqual(im.getpixel((1, y - 2)), out.getpixel((1, x - 2))) | ||||
|             self.assertEqual(im.getpixel((x - 2, y - 2)), out.getpixel((1, 1))) | ||||
|         x, y = im.size | ||||
|         assert im.getpixel((1, 1)) == out.getpixel((1, 1)) | ||||
|         assert im.getpixel((x - 2, 1)) == out.getpixel((1, x - 2)) | ||||
|         assert im.getpixel((1, y - 2)) == out.getpixel((y - 2, 1)) | ||||
|         assert im.getpixel((x - 2, y - 2)) == out.getpixel((y - 2, x - 2)) | ||||
| 
 | ||||
|         for mode in self.hopper: | ||||
|             transpose(mode) | ||||
|     for mode in HOPPER: | ||||
|         transpose(mode) | ||||
| 
 | ||||
|     def test_roundtrip(self): | ||||
|         for mode in self.hopper: | ||||
|             im = self.hopper[mode] | ||||
| 
 | ||||
|             def transpose(first, second): | ||||
|                 return im.transpose(first).transpose(second) | ||||
| def test_tranverse(): | ||||
|     def transpose(mode): | ||||
|         im = HOPPER[mode] | ||||
|         out = im.transpose(TRANSVERSE) | ||||
|         assert out.mode == mode | ||||
|         assert out.size == im.size[::-1] | ||||
| 
 | ||||
|             assert_image_equal(im, transpose(FLIP_LEFT_RIGHT, FLIP_LEFT_RIGHT)) | ||||
|             assert_image_equal(im, transpose(FLIP_TOP_BOTTOM, FLIP_TOP_BOTTOM)) | ||||
|             assert_image_equal(im, transpose(ROTATE_90, ROTATE_270)) | ||||
|             assert_image_equal(im, transpose(ROTATE_180, ROTATE_180)) | ||||
|             assert_image_equal( | ||||
|                 im.transpose(TRANSPOSE), transpose(ROTATE_90, FLIP_TOP_BOTTOM) | ||||
|             ) | ||||
|             assert_image_equal( | ||||
|                 im.transpose(TRANSPOSE), transpose(ROTATE_270, FLIP_LEFT_RIGHT) | ||||
|             ) | ||||
|             assert_image_equal( | ||||
|                 im.transpose(TRANSVERSE), transpose(ROTATE_90, FLIP_LEFT_RIGHT) | ||||
|             ) | ||||
|             assert_image_equal( | ||||
|                 im.transpose(TRANSVERSE), transpose(ROTATE_270, FLIP_TOP_BOTTOM) | ||||
|             ) | ||||
|             assert_image_equal( | ||||
|                 im.transpose(TRANSVERSE), transpose(ROTATE_180, TRANSPOSE) | ||||
|             ) | ||||
|         x, y = im.size | ||||
|         assert im.getpixel((1, 1)) == out.getpixel((y - 2, x - 2)) | ||||
|         assert im.getpixel((x - 2, 1)) == out.getpixel((y - 2, 1)) | ||||
|         assert im.getpixel((1, y - 2)) == out.getpixel((1, x - 2)) | ||||
|         assert im.getpixel((x - 2, y - 2)) == out.getpixel((1, 1)) | ||||
| 
 | ||||
|     for mode in HOPPER: | ||||
|         transpose(mode) | ||||
| 
 | ||||
| 
 | ||||
| def test_roundtrip(): | ||||
|     for mode in HOPPER: | ||||
|         im = HOPPER[mode] | ||||
| 
 | ||||
|         def transpose(first, second): | ||||
|             return im.transpose(first).transpose(second) | ||||
| 
 | ||||
|         assert_image_equal(im, transpose(FLIP_LEFT_RIGHT, FLIP_LEFT_RIGHT)) | ||||
|         assert_image_equal(im, transpose(FLIP_TOP_BOTTOM, FLIP_TOP_BOTTOM)) | ||||
|         assert_image_equal(im, transpose(ROTATE_90, ROTATE_270)) | ||||
|         assert_image_equal(im, transpose(ROTATE_180, ROTATE_180)) | ||||
|         assert_image_equal( | ||||
|             im.transpose(TRANSPOSE), transpose(ROTATE_90, FLIP_TOP_BOTTOM) | ||||
|         ) | ||||
|         assert_image_equal( | ||||
|             im.transpose(TRANSPOSE), transpose(ROTATE_270, FLIP_LEFT_RIGHT) | ||||
|         ) | ||||
|         assert_image_equal( | ||||
|             im.transpose(TRANSVERSE), transpose(ROTATE_90, FLIP_LEFT_RIGHT) | ||||
|         ) | ||||
|         assert_image_equal( | ||||
|             im.transpose(TRANSVERSE), transpose(ROTATE_270, FLIP_TOP_BOTTOM) | ||||
|         ) | ||||
|         assert_image_equal(im.transpose(TRANSVERSE), transpose(ROTATE_180, TRANSPOSE)) | ||||
|  |  | |||
|  | @ -1,6 +1,6 @@ | |||
| from PIL import Image, ImageChops | ||||
| 
 | ||||
| from .helper import PillowTestCase, assert_image_equal, hopper | ||||
| from .helper import assert_image_equal, hopper | ||||
| 
 | ||||
| BLACK = (0, 0, 0) | ||||
| BROWN = (127, 64, 0) | ||||
|  | @ -13,352 +13,373 @@ WHITE = (255, 255, 255) | |||
| GREY = 128 | ||||
| 
 | ||||
| 
 | ||||
| class TestImageChops(PillowTestCase): | ||||
|     def test_sanity(self): | ||||
| def test_sanity(): | ||||
|     im = hopper("L") | ||||
| 
 | ||||
|         im = hopper("L") | ||||
|     ImageChops.constant(im, 128) | ||||
|     ImageChops.duplicate(im) | ||||
|     ImageChops.invert(im) | ||||
|     ImageChops.lighter(im, im) | ||||
|     ImageChops.darker(im, im) | ||||
|     ImageChops.difference(im, im) | ||||
|     ImageChops.multiply(im, im) | ||||
|     ImageChops.screen(im, im) | ||||
| 
 | ||||
|         ImageChops.constant(im, 128) | ||||
|         ImageChops.duplicate(im) | ||||
|         ImageChops.invert(im) | ||||
|         ImageChops.lighter(im, im) | ||||
|         ImageChops.darker(im, im) | ||||
|         ImageChops.difference(im, im) | ||||
|         ImageChops.multiply(im, im) | ||||
|         ImageChops.screen(im, im) | ||||
|     ImageChops.add(im, im) | ||||
|     ImageChops.add(im, im, 2.0) | ||||
|     ImageChops.add(im, im, 2.0, 128) | ||||
|     ImageChops.subtract(im, im) | ||||
|     ImageChops.subtract(im, im, 2.0) | ||||
|     ImageChops.subtract(im, im, 2.0, 128) | ||||
| 
 | ||||
|         ImageChops.add(im, im) | ||||
|         ImageChops.add(im, im, 2.0) | ||||
|         ImageChops.add(im, im, 2.0, 128) | ||||
|         ImageChops.subtract(im, im) | ||||
|         ImageChops.subtract(im, im, 2.0) | ||||
|         ImageChops.subtract(im, im, 2.0, 128) | ||||
|     ImageChops.add_modulo(im, im) | ||||
|     ImageChops.subtract_modulo(im, im) | ||||
| 
 | ||||
|         ImageChops.add_modulo(im, im) | ||||
|         ImageChops.subtract_modulo(im, im) | ||||
|     ImageChops.blend(im, im, 0.5) | ||||
|     ImageChops.composite(im, im, im) | ||||
| 
 | ||||
|         ImageChops.blend(im, im, 0.5) | ||||
|         ImageChops.composite(im, im, im) | ||||
|     ImageChops.offset(im, 10) | ||||
|     ImageChops.offset(im, 10, 20) | ||||
| 
 | ||||
|         ImageChops.offset(im, 10) | ||||
|         ImageChops.offset(im, 10, 20) | ||||
| 
 | ||||
|     def test_add(self): | ||||
|         # Arrange | ||||
|         with Image.open("Tests/images/imagedraw_ellipse_RGB.png") as im1: | ||||
|             with Image.open("Tests/images/imagedraw_floodfill_RGB.png") as im2: | ||||
| def test_add(): | ||||
|     # Arrange | ||||
|     with Image.open("Tests/images/imagedraw_ellipse_RGB.png") as im1: | ||||
|         with Image.open("Tests/images/imagedraw_floodfill_RGB.png") as im2: | ||||
| 
 | ||||
|                 # Act | ||||
|                 new = ImageChops.add(im1, im2) | ||||
|             # Act | ||||
|             new = ImageChops.add(im1, im2) | ||||
| 
 | ||||
|         # Assert | ||||
|         self.assertEqual(new.getbbox(), (25, 25, 76, 76)) | ||||
|         self.assertEqual(new.getpixel((50, 50)), ORANGE) | ||||
|     # Assert | ||||
|     assert new.getbbox() == (25, 25, 76, 76) | ||||
|     assert new.getpixel((50, 50)) == ORANGE | ||||
| 
 | ||||
|     def test_add_scale_offset(self): | ||||
|         # Arrange | ||||
|         with Image.open("Tests/images/imagedraw_ellipse_RGB.png") as im1: | ||||
|             with Image.open("Tests/images/imagedraw_floodfill_RGB.png") as im2: | ||||
| 
 | ||||
|                 # Act | ||||
|                 new = ImageChops.add(im1, im2, scale=2.5, offset=100) | ||||
| def test_add_scale_offset(): | ||||
|     # Arrange | ||||
|     with Image.open("Tests/images/imagedraw_ellipse_RGB.png") as im1: | ||||
|         with Image.open("Tests/images/imagedraw_floodfill_RGB.png") as im2: | ||||
| 
 | ||||
|         # Assert | ||||
|         self.assertEqual(new.getbbox(), (0, 0, 100, 100)) | ||||
|         self.assertEqual(new.getpixel((50, 50)), (202, 151, 100)) | ||||
|             # Act | ||||
|             new = ImageChops.add(im1, im2, scale=2.5, offset=100) | ||||
| 
 | ||||
|     def test_add_clip(self): | ||||
|         # Arrange | ||||
|         im = hopper() | ||||
|     # Assert | ||||
|     assert new.getbbox() == (0, 0, 100, 100) | ||||
|     assert new.getpixel((50, 50)) == (202, 151, 100) | ||||
| 
 | ||||
|         # Act | ||||
|         new = ImageChops.add(im, im) | ||||
| 
 | ||||
|         # Assert | ||||
|         self.assertEqual(new.getpixel((50, 50)), (255, 255, 254)) | ||||
| def test_add_clip(): | ||||
|     # Arrange | ||||
|     im = hopper() | ||||
| 
 | ||||
|     def test_add_modulo(self): | ||||
|         # Arrange | ||||
|         with Image.open("Tests/images/imagedraw_ellipse_RGB.png") as im1: | ||||
|             with Image.open("Tests/images/imagedraw_floodfill_RGB.png") as im2: | ||||
|     # Act | ||||
|     new = ImageChops.add(im, im) | ||||
| 
 | ||||
|                 # Act | ||||
|                 new = ImageChops.add_modulo(im1, im2) | ||||
|     # Assert | ||||
|     assert new.getpixel((50, 50)) == (255, 255, 254) | ||||
| 
 | ||||
|         # Assert | ||||
|         self.assertEqual(new.getbbox(), (25, 25, 76, 76)) | ||||
|         self.assertEqual(new.getpixel((50, 50)), ORANGE) | ||||
| 
 | ||||
|     def test_add_modulo_no_clip(self): | ||||
|         # Arrange | ||||
|         im = hopper() | ||||
| def test_add_modulo(): | ||||
|     # Arrange | ||||
|     with Image.open("Tests/images/imagedraw_ellipse_RGB.png") as im1: | ||||
|         with Image.open("Tests/images/imagedraw_floodfill_RGB.png") as im2: | ||||
| 
 | ||||
|         # Act | ||||
|         new = ImageChops.add_modulo(im, im) | ||||
|             # Act | ||||
|             new = ImageChops.add_modulo(im1, im2) | ||||
| 
 | ||||
|         # Assert | ||||
|         self.assertEqual(new.getpixel((50, 50)), (224, 76, 254)) | ||||
|     # Assert | ||||
|     assert new.getbbox() == (25, 25, 76, 76) | ||||
|     assert new.getpixel((50, 50)) == ORANGE | ||||
| 
 | ||||
|     def test_blend(self): | ||||
|         # Arrange | ||||
|         with Image.open("Tests/images/imagedraw_ellipse_RGB.png") as im1: | ||||
|             with Image.open("Tests/images/imagedraw_floodfill_RGB.png") as im2: | ||||
| 
 | ||||
|                 # Act | ||||
|                 new = ImageChops.blend(im1, im2, 0.5) | ||||
| def test_add_modulo_no_clip(): | ||||
|     # Arrange | ||||
|     im = hopper() | ||||
| 
 | ||||
|         # Assert | ||||
|         self.assertEqual(new.getbbox(), (25, 25, 76, 76)) | ||||
|         self.assertEqual(new.getpixel((50, 50)), BROWN) | ||||
|     # Act | ||||
|     new = ImageChops.add_modulo(im, im) | ||||
| 
 | ||||
|     def test_constant(self): | ||||
|         # Arrange | ||||
|         im = Image.new("RGB", (20, 10)) | ||||
|     # Assert | ||||
|     assert new.getpixel((50, 50)) == (224, 76, 254) | ||||
| 
 | ||||
|         # Act | ||||
|         new = ImageChops.constant(im, GREY) | ||||
| 
 | ||||
|         # Assert | ||||
|         self.assertEqual(new.size, im.size) | ||||
|         self.assertEqual(new.getpixel((0, 0)), GREY) | ||||
|         self.assertEqual(new.getpixel((19, 9)), GREY) | ||||
| def test_blend(): | ||||
|     # Arrange | ||||
|     with Image.open("Tests/images/imagedraw_ellipse_RGB.png") as im1: | ||||
|         with Image.open("Tests/images/imagedraw_floodfill_RGB.png") as im2: | ||||
| 
 | ||||
|     def test_darker_image(self): | ||||
|         # Arrange | ||||
|         with Image.open("Tests/images/imagedraw_chord_RGB.png") as im1: | ||||
|             with Image.open("Tests/images/imagedraw_outline_chord_RGB.png") as im2: | ||||
|             # Act | ||||
|             new = ImageChops.blend(im1, im2, 0.5) | ||||
| 
 | ||||
|                 # Act | ||||
|                 new = ImageChops.darker(im1, im2) | ||||
|     # Assert | ||||
|     assert new.getbbox() == (25, 25, 76, 76) | ||||
|     assert new.getpixel((50, 50)) == BROWN | ||||
| 
 | ||||
|                 # Assert | ||||
|                 assert_image_equal(new, im2) | ||||
| 
 | ||||
|     def test_darker_pixel(self): | ||||
|         # Arrange | ||||
|         im1 = hopper() | ||||
|         with Image.open("Tests/images/imagedraw_chord_RGB.png") as im2: | ||||
| def test_constant(): | ||||
|     # Arrange | ||||
|     im = Image.new("RGB", (20, 10)) | ||||
| 
 | ||||
|     # Act | ||||
|     new = ImageChops.constant(im, GREY) | ||||
| 
 | ||||
|     # Assert | ||||
|     assert new.size == im.size | ||||
|     assert new.getpixel((0, 0)) == GREY | ||||
|     assert new.getpixel((19, 9)) == GREY | ||||
| 
 | ||||
| 
 | ||||
| def test_darker_image(): | ||||
|     # Arrange | ||||
|     with Image.open("Tests/images/imagedraw_chord_RGB.png") as im1: | ||||
|         with Image.open("Tests/images/imagedraw_outline_chord_RGB.png") as im2: | ||||
| 
 | ||||
|             # Act | ||||
|             new = ImageChops.darker(im1, im2) | ||||
| 
 | ||||
|         # Assert | ||||
|         self.assertEqual(new.getpixel((50, 50)), (240, 166, 0)) | ||||
|             # Assert | ||||
|             assert_image_equal(new, im2) | ||||
| 
 | ||||
|     def test_difference(self): | ||||
|         # Arrange | ||||
|         with Image.open("Tests/images/imagedraw_arc_end_le_start.png") as im1: | ||||
|             with Image.open("Tests/images/imagedraw_arc_no_loops.png") as im2: | ||||
| 
 | ||||
|                 # Act | ||||
|                 new = ImageChops.difference(im1, im2) | ||||
| def test_darker_pixel(): | ||||
|     # Arrange | ||||
|     im1 = hopper() | ||||
|     with Image.open("Tests/images/imagedraw_chord_RGB.png") as im2: | ||||
| 
 | ||||
|         # Assert | ||||
|         self.assertEqual(new.getbbox(), (25, 25, 76, 76)) | ||||
|         # Act | ||||
|         new = ImageChops.darker(im1, im2) | ||||
| 
 | ||||
|     def test_difference_pixel(self): | ||||
|         # Arrange | ||||
|         im1 = hopper() | ||||
|         with Image.open("Tests/images/imagedraw_polygon_kite_RGB.png") as im2: | ||||
|     # Assert | ||||
|     assert new.getpixel((50, 50)) == (240, 166, 0) | ||||
| 
 | ||||
| 
 | ||||
| def test_difference(): | ||||
|     # Arrange | ||||
|     with Image.open("Tests/images/imagedraw_arc_end_le_start.png") as im1: | ||||
|         with Image.open("Tests/images/imagedraw_arc_no_loops.png") as im2: | ||||
| 
 | ||||
|             # Act | ||||
|             new = ImageChops.difference(im1, im2) | ||||
| 
 | ||||
|         # Assert | ||||
|         self.assertEqual(new.getpixel((50, 50)), (240, 166, 128)) | ||||
|     # Assert | ||||
|     assert new.getbbox() == (25, 25, 76, 76) | ||||
| 
 | ||||
|     def test_duplicate(self): | ||||
|         # Arrange | ||||
|         im = hopper() | ||||
| 
 | ||||
| def test_difference_pixel(): | ||||
|     # Arrange | ||||
|     im1 = hopper() | ||||
|     with Image.open("Tests/images/imagedraw_polygon_kite_RGB.png") as im2: | ||||
| 
 | ||||
|         # Act | ||||
|         new = ImageChops.duplicate(im) | ||||
|         new = ImageChops.difference(im1, im2) | ||||
| 
 | ||||
|         # Assert | ||||
|         assert_image_equal(new, im) | ||||
|     # Assert | ||||
|     assert new.getpixel((50, 50)) == (240, 166, 128) | ||||
| 
 | ||||
|     def test_invert(self): | ||||
|         # Arrange | ||||
|         with Image.open("Tests/images/imagedraw_floodfill_RGB.png") as im: | ||||
| 
 | ||||
|             # Act | ||||
|             new = ImageChops.invert(im) | ||||
| def test_duplicate(): | ||||
|     # Arrange | ||||
|     im = hopper() | ||||
| 
 | ||||
|         # Assert | ||||
|         self.assertEqual(new.getbbox(), (0, 0, 100, 100)) | ||||
|         self.assertEqual(new.getpixel((0, 0)), WHITE) | ||||
|         self.assertEqual(new.getpixel((50, 50)), CYAN) | ||||
|     # Act | ||||
|     new = ImageChops.duplicate(im) | ||||
| 
 | ||||
|     def test_lighter_image(self): | ||||
|         # Arrange | ||||
|         with Image.open("Tests/images/imagedraw_chord_RGB.png") as im1: | ||||
|             with Image.open("Tests/images/imagedraw_outline_chord_RGB.png") as im2: | ||||
|     # Assert | ||||
|     assert_image_equal(new, im) | ||||
| 
 | ||||
|                 # Act | ||||
|                 new = ImageChops.lighter(im1, im2) | ||||
| 
 | ||||
|         # Assert | ||||
|         assert_image_equal(new, im1) | ||||
| def test_invert(): | ||||
|     # Arrange | ||||
|     with Image.open("Tests/images/imagedraw_floodfill_RGB.png") as im: | ||||
| 
 | ||||
|     def test_lighter_pixel(self): | ||||
|         # Arrange | ||||
|         im1 = hopper() | ||||
|         with Image.open("Tests/images/imagedraw_chord_RGB.png") as im2: | ||||
|         # Act | ||||
|         new = ImageChops.invert(im) | ||||
| 
 | ||||
|     # Assert | ||||
|     assert new.getbbox() == (0, 0, 100, 100) | ||||
|     assert new.getpixel((0, 0)) == WHITE | ||||
|     assert new.getpixel((50, 50)) == CYAN | ||||
| 
 | ||||
| 
 | ||||
| def test_lighter_image(): | ||||
|     # Arrange | ||||
|     with Image.open("Tests/images/imagedraw_chord_RGB.png") as im1: | ||||
|         with Image.open("Tests/images/imagedraw_outline_chord_RGB.png") as im2: | ||||
| 
 | ||||
|             # Act | ||||
|             new = ImageChops.lighter(im1, im2) | ||||
| 
 | ||||
|         # Assert | ||||
|         self.assertEqual(new.getpixel((50, 50)), (255, 255, 127)) | ||||
|     # Assert | ||||
|     assert_image_equal(new, im1) | ||||
| 
 | ||||
|     def test_multiply_black(self): | ||||
|         """If you multiply an image with a solid black image, | ||||
|         the result is black.""" | ||||
|         # Arrange | ||||
|         im1 = hopper() | ||||
|         black = Image.new("RGB", im1.size, "black") | ||||
| 
 | ||||
| def test_lighter_pixel(): | ||||
|     # Arrange | ||||
|     im1 = hopper() | ||||
|     with Image.open("Tests/images/imagedraw_chord_RGB.png") as im2: | ||||
| 
 | ||||
|         # Act | ||||
|         new = ImageChops.multiply(im1, black) | ||||
|         new = ImageChops.lighter(im1, im2) | ||||
| 
 | ||||
|         # Assert | ||||
|         assert_image_equal(new, black) | ||||
|     # Assert | ||||
|     assert new.getpixel((50, 50)) == (255, 255, 127) | ||||
| 
 | ||||
|     def test_multiply_green(self): | ||||
|         # Arrange | ||||
|         with Image.open("Tests/images/imagedraw_floodfill_RGB.png") as im: | ||||
|             green = Image.new("RGB", im.size, "green") | ||||
| 
 | ||||
|             # Act | ||||
|             new = ImageChops.multiply(im, green) | ||||
| def test_multiply_black(): | ||||
|     """If you multiply an image with a solid black image, | ||||
|     the result is black.""" | ||||
|     # Arrange | ||||
|     im1 = hopper() | ||||
|     black = Image.new("RGB", im1.size, "black") | ||||
| 
 | ||||
|         # Assert | ||||
|         self.assertEqual(new.getbbox(), (25, 25, 76, 76)) | ||||
|         self.assertEqual(new.getpixel((25, 25)), DARK_GREEN) | ||||
|         self.assertEqual(new.getpixel((50, 50)), BLACK) | ||||
|     # Act | ||||
|     new = ImageChops.multiply(im1, black) | ||||
| 
 | ||||
|     def test_multiply_white(self): | ||||
|         """If you multiply with a solid white image, | ||||
|         the image is unaffected.""" | ||||
|         # Arrange | ||||
|         im1 = hopper() | ||||
|         white = Image.new("RGB", im1.size, "white") | ||||
|     # Assert | ||||
|     assert_image_equal(new, black) | ||||
| 
 | ||||
| 
 | ||||
| def test_multiply_green(): | ||||
|     # Arrange | ||||
|     with Image.open("Tests/images/imagedraw_floodfill_RGB.png") as im: | ||||
|         green = Image.new("RGB", im.size, "green") | ||||
| 
 | ||||
|         # Act | ||||
|         new = ImageChops.multiply(im1, white) | ||||
|         new = ImageChops.multiply(im, green) | ||||
| 
 | ||||
|         # Assert | ||||
|         assert_image_equal(new, im1) | ||||
|     # Assert | ||||
|     assert new.getbbox() == (25, 25, 76, 76) | ||||
|     assert new.getpixel((25, 25)) == DARK_GREEN | ||||
|     assert new.getpixel((50, 50)) == BLACK | ||||
| 
 | ||||
|     def test_offset(self): | ||||
|         # Arrange | ||||
|         xoffset = 45 | ||||
|         yoffset = 20 | ||||
|         with Image.open("Tests/images/imagedraw_ellipse_RGB.png") as im: | ||||
| 
 | ||||
| def test_multiply_white(): | ||||
|     """If you multiply with a solid white image, the image is unaffected.""" | ||||
|     # Arrange | ||||
|     im1 = hopper() | ||||
|     white = Image.new("RGB", im1.size, "white") | ||||
| 
 | ||||
|     # Act | ||||
|     new = ImageChops.multiply(im1, white) | ||||
| 
 | ||||
|     # Assert | ||||
|     assert_image_equal(new, im1) | ||||
| 
 | ||||
| 
 | ||||
| def test_offset(): | ||||
|     # Arrange | ||||
|     xoffset = 45 | ||||
|     yoffset = 20 | ||||
|     with Image.open("Tests/images/imagedraw_ellipse_RGB.png") as im: | ||||
| 
 | ||||
|         # Act | ||||
|         new = ImageChops.offset(im, xoffset, yoffset) | ||||
| 
 | ||||
|     # Assert | ||||
|     assert new.getbbox() == (0, 45, 100, 96) | ||||
|     assert new.getpixel((50, 50)) == BLACK | ||||
|     assert new.getpixel((50 + xoffset, 50 + yoffset)) == DARK_GREEN | ||||
| 
 | ||||
|     # Test no yoffset | ||||
|     assert ImageChops.offset(im, xoffset) == ImageChops.offset(im, xoffset, xoffset) | ||||
| 
 | ||||
| 
 | ||||
| def test_screen(): | ||||
|     # Arrange | ||||
|     with Image.open("Tests/images/imagedraw_ellipse_RGB.png") as im1: | ||||
|         with Image.open("Tests/images/imagedraw_floodfill_RGB.png") as im2: | ||||
| 
 | ||||
|             # Act | ||||
|             new = ImageChops.offset(im, xoffset, yoffset) | ||||
|             new = ImageChops.screen(im1, im2) | ||||
| 
 | ||||
|         # Assert | ||||
|         self.assertEqual(new.getbbox(), (0, 45, 100, 96)) | ||||
|         self.assertEqual(new.getpixel((50, 50)), BLACK) | ||||
|         self.assertEqual(new.getpixel((50 + xoffset, 50 + yoffset)), DARK_GREEN) | ||||
|     # Assert | ||||
|     assert new.getbbox() == (25, 25, 76, 76) | ||||
|     assert new.getpixel((50, 50)) == ORANGE | ||||
| 
 | ||||
|         # Test no yoffset | ||||
|         self.assertEqual( | ||||
|             ImageChops.offset(im, xoffset), ImageChops.offset(im, xoffset, xoffset) | ||||
|         ) | ||||
| 
 | ||||
|     def test_screen(self): | ||||
|         # Arrange | ||||
|         with Image.open("Tests/images/imagedraw_ellipse_RGB.png") as im1: | ||||
|             with Image.open("Tests/images/imagedraw_floodfill_RGB.png") as im2: | ||||
| 
 | ||||
|                 # Act | ||||
|                 new = ImageChops.screen(im1, im2) | ||||
| 
 | ||||
|         # Assert | ||||
|         self.assertEqual(new.getbbox(), (25, 25, 76, 76)) | ||||
|         self.assertEqual(new.getpixel((50, 50)), ORANGE) | ||||
| 
 | ||||
|     def test_subtract(self): | ||||
|         # Arrange | ||||
|         with Image.open("Tests/images/imagedraw_chord_RGB.png") as im1: | ||||
|             with Image.open("Tests/images/imagedraw_outline_chord_RGB.png") as im2: | ||||
| 
 | ||||
|                 # Act | ||||
|                 new = ImageChops.subtract(im1, im2) | ||||
| 
 | ||||
|         # Assert | ||||
|         self.assertEqual(new.getbbox(), (25, 50, 76, 76)) | ||||
|         self.assertEqual(new.getpixel((50, 50)), GREEN) | ||||
|         self.assertEqual(new.getpixel((50, 51)), BLACK) | ||||
| 
 | ||||
|     def test_subtract_scale_offset(self): | ||||
|         # Arrange | ||||
|         with Image.open("Tests/images/imagedraw_chord_RGB.png") as im1: | ||||
|             with Image.open("Tests/images/imagedraw_outline_chord_RGB.png") as im2: | ||||
| 
 | ||||
|                 # Act | ||||
|                 new = ImageChops.subtract(im1, im2, scale=2.5, offset=100) | ||||
| 
 | ||||
|         # Assert | ||||
|         self.assertEqual(new.getbbox(), (0, 0, 100, 100)) | ||||
|         self.assertEqual(new.getpixel((50, 50)), (100, 202, 100)) | ||||
| 
 | ||||
|     def test_subtract_clip(self): | ||||
|         # Arrange | ||||
|         im1 = hopper() | ||||
|         with Image.open("Tests/images/imagedraw_chord_RGB.png") as im2: | ||||
| def test_subtract(): | ||||
|     # Arrange | ||||
|     with Image.open("Tests/images/imagedraw_chord_RGB.png") as im1: | ||||
|         with Image.open("Tests/images/imagedraw_outline_chord_RGB.png") as im2: | ||||
| 
 | ||||
|             # Act | ||||
|             new = ImageChops.subtract(im1, im2) | ||||
| 
 | ||||
|         # Assert | ||||
|         self.assertEqual(new.getpixel((50, 50)), (0, 0, 127)) | ||||
|     # Assert | ||||
|     assert new.getbbox() == (25, 50, 76, 76) | ||||
|     assert new.getpixel((50, 50)) == GREEN | ||||
|     assert new.getpixel((50, 51)) == BLACK | ||||
| 
 | ||||
|     def test_subtract_modulo(self): | ||||
|         # Arrange | ||||
|         with Image.open("Tests/images/imagedraw_chord_RGB.png") as im1: | ||||
|             with Image.open("Tests/images/imagedraw_outline_chord_RGB.png") as im2: | ||||
| 
 | ||||
|                 # Act | ||||
|                 new = ImageChops.subtract_modulo(im1, im2) | ||||
| def test_subtract_scale_offset(): | ||||
|     # Arrange | ||||
|     with Image.open("Tests/images/imagedraw_chord_RGB.png") as im1: | ||||
|         with Image.open("Tests/images/imagedraw_outline_chord_RGB.png") as im2: | ||||
| 
 | ||||
|         # Assert | ||||
|         self.assertEqual(new.getbbox(), (25, 50, 76, 76)) | ||||
|         self.assertEqual(new.getpixel((50, 50)), GREEN) | ||||
|         self.assertEqual(new.getpixel((50, 51)), BLACK) | ||||
|             # Act | ||||
|             new = ImageChops.subtract(im1, im2, scale=2.5, offset=100) | ||||
| 
 | ||||
|     def test_subtract_modulo_no_clip(self): | ||||
|         # Arrange | ||||
|         im1 = hopper() | ||||
|         with Image.open("Tests/images/imagedraw_chord_RGB.png") as im2: | ||||
|     # Assert | ||||
|     assert new.getbbox() == (0, 0, 100, 100) | ||||
|     assert new.getpixel((50, 50)) == (100, 202, 100) | ||||
| 
 | ||||
| 
 | ||||
| def test_subtract_clip(): | ||||
|     # Arrange | ||||
|     im1 = hopper() | ||||
|     with Image.open("Tests/images/imagedraw_chord_RGB.png") as im2: | ||||
| 
 | ||||
|         # Act | ||||
|         new = ImageChops.subtract(im1, im2) | ||||
| 
 | ||||
|     # Assert | ||||
|     assert new.getpixel((50, 50)) == (0, 0, 127) | ||||
| 
 | ||||
| 
 | ||||
| def test_subtract_modulo(): | ||||
|     # Arrange | ||||
|     with Image.open("Tests/images/imagedraw_chord_RGB.png") as im1: | ||||
|         with Image.open("Tests/images/imagedraw_outline_chord_RGB.png") as im2: | ||||
| 
 | ||||
|             # Act | ||||
|             new = ImageChops.subtract_modulo(im1, im2) | ||||
| 
 | ||||
|         # Assert | ||||
|         self.assertEqual(new.getpixel((50, 50)), (241, 167, 127)) | ||||
|     # Assert | ||||
|     assert new.getbbox() == (25, 50, 76, 76) | ||||
|     assert new.getpixel((50, 50)) == GREEN | ||||
|     assert new.getpixel((50, 51)) == BLACK | ||||
| 
 | ||||
|     def test_logical(self): | ||||
|         def table(op, a, b): | ||||
|             out = [] | ||||
|             for x in (a, b): | ||||
|                 imx = Image.new("1", (1, 1), x) | ||||
|                 for y in (a, b): | ||||
|                     imy = Image.new("1", (1, 1), y) | ||||
|                     out.append(op(imx, imy).getpixel((0, 0))) | ||||
|             return tuple(out) | ||||
| 
 | ||||
|         self.assertEqual(table(ImageChops.logical_and, 0, 1), (0, 0, 0, 255)) | ||||
|         self.assertEqual(table(ImageChops.logical_or, 0, 1), (0, 255, 255, 255)) | ||||
|         self.assertEqual(table(ImageChops.logical_xor, 0, 1), (0, 255, 255, 0)) | ||||
| def test_subtract_modulo_no_clip(): | ||||
|     # Arrange | ||||
|     im1 = hopper() | ||||
|     with Image.open("Tests/images/imagedraw_chord_RGB.png") as im2: | ||||
| 
 | ||||
|         self.assertEqual(table(ImageChops.logical_and, 0, 128), (0, 0, 0, 255)) | ||||
|         self.assertEqual(table(ImageChops.logical_or, 0, 128), (0, 255, 255, 255)) | ||||
|         self.assertEqual(table(ImageChops.logical_xor, 0, 128), (0, 255, 255, 0)) | ||||
|         # Act | ||||
|         new = ImageChops.subtract_modulo(im1, im2) | ||||
| 
 | ||||
|         self.assertEqual(table(ImageChops.logical_and, 0, 255), (0, 0, 0, 255)) | ||||
|         self.assertEqual(table(ImageChops.logical_or, 0, 255), (0, 255, 255, 255)) | ||||
|         self.assertEqual(table(ImageChops.logical_xor, 0, 255), (0, 255, 255, 0)) | ||||
|     # Assert | ||||
|     assert new.getpixel((50, 50)) == (241, 167, 127) | ||||
| 
 | ||||
| 
 | ||||
| def test_logical(): | ||||
|     def table(op, a, b): | ||||
|         out = [] | ||||
|         for x in (a, b): | ||||
|             imx = Image.new("1", (1, 1), x) | ||||
|             for y in (a, b): | ||||
|                 imy = Image.new("1", (1, 1), y) | ||||
|                 out.append(op(imx, imy).getpixel((0, 0))) | ||||
|         return tuple(out) | ||||
| 
 | ||||
|     assert table(ImageChops.logical_and, 0, 1) == (0, 0, 0, 255) | ||||
|     assert table(ImageChops.logical_or, 0, 1) == (0, 255, 255, 255) | ||||
|     assert table(ImageChops.logical_xor, 0, 1) == (0, 255, 255, 0) | ||||
| 
 | ||||
|     assert table(ImageChops.logical_and, 0, 128) == (0, 0, 0, 255) | ||||
|     assert table(ImageChops.logical_or, 0, 128) == (0, 255, 255, 255) | ||||
|     assert table(ImageChops.logical_xor, 0, 128) == (0, 255, 255, 0) | ||||
| 
 | ||||
|     assert table(ImageChops.logical_and, 0, 255) == (0, 0, 0, 255) | ||||
|     assert table(ImageChops.logical_or, 0, 255) == (0, 255, 255, 255) | ||||
|     assert table(ImageChops.logical_xor, 0, 255) == (0, 255, 255, 0) | ||||
|  |  | |||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							|  | @ -1,9 +1,9 @@ | |||
| import os.path | ||||
| import unittest | ||||
| 
 | ||||
| import pytest | ||||
| from PIL import Image, ImageDraw2, features | ||||
| 
 | ||||
| from .helper import PillowTestCase, assert_image_equal, assert_image_similar, hopper | ||||
| from .helper import assert_image_equal, assert_image_similar, hopper | ||||
| 
 | ||||
| BLACK = (0, 0, 0) | ||||
| WHITE = (255, 255, 255) | ||||
|  | @ -34,190 +34,206 @@ HAS_FREETYPE = features.check("freetype2") | |||
| FONT_PATH = "Tests/fonts/FreeMono.ttf" | ||||
| 
 | ||||
| 
 | ||||
| class TestImageDraw(PillowTestCase): | ||||
|     def test_sanity(self): | ||||
|         im = hopper("RGB").copy() | ||||
| def test_sanity(): | ||||
|     im = hopper("RGB").copy() | ||||
| 
 | ||||
|         draw = ImageDraw2.Draw(im) | ||||
|         pen = ImageDraw2.Pen("blue", width=7) | ||||
|         draw.line(list(range(10)), pen) | ||||
|     draw = ImageDraw2.Draw(im) | ||||
|     pen = ImageDraw2.Pen("blue", width=7) | ||||
|     draw.line(list(range(10)), pen) | ||||
| 
 | ||||
|         from PIL import ImageDraw | ||||
|     from PIL import ImageDraw | ||||
| 
 | ||||
|         draw, handler = ImageDraw.getdraw(im) | ||||
|         pen = ImageDraw2.Pen("blue", width=7) | ||||
|         draw.line(list(range(10)), pen) | ||||
|     draw, handler = ImageDraw.getdraw(im) | ||||
|     pen = ImageDraw2.Pen("blue", width=7) | ||||
|     draw.line(list(range(10)), pen) | ||||
| 
 | ||||
|     def helper_ellipse(self, mode, bbox): | ||||
|         # Arrange | ||||
|         im = Image.new("RGB", (W, H)) | ||||
|         draw = ImageDraw2.Draw(im) | ||||
|         pen = ImageDraw2.Pen("blue", width=2) | ||||
|         brush = ImageDraw2.Brush("green") | ||||
|         expected = "Tests/images/imagedraw_ellipse_{}.png".format(mode) | ||||
| 
 | ||||
|         # Act | ||||
|         draw.ellipse(bbox, pen, brush) | ||||
| def helper_ellipse(mode, bbox): | ||||
|     # Arrange | ||||
|     im = Image.new("RGB", (W, H)) | ||||
|     draw = ImageDraw2.Draw(im) | ||||
|     pen = ImageDraw2.Pen("blue", width=2) | ||||
|     brush = ImageDraw2.Brush("green") | ||||
|     expected = "Tests/images/imagedraw_ellipse_{}.png".format(mode) | ||||
| 
 | ||||
|         # Assert | ||||
|         assert_image_similar(im, Image.open(expected), 1) | ||||
|     # Act | ||||
|     draw.ellipse(bbox, pen, brush) | ||||
| 
 | ||||
|     def test_ellipse1(self): | ||||
|         self.helper_ellipse("RGB", BBOX1) | ||||
|     # Assert | ||||
|     assert_image_similar(im, Image.open(expected), 1) | ||||
| 
 | ||||
|     def test_ellipse2(self): | ||||
|         self.helper_ellipse("RGB", BBOX2) | ||||
| 
 | ||||
|     def test_ellipse_edge(self): | ||||
|         # Arrange | ||||
|         im = Image.new("RGB", (W, H)) | ||||
|         draw = ImageDraw2.Draw(im) | ||||
|         brush = ImageDraw2.Brush("white") | ||||
| def test_ellipse1(): | ||||
|     helper_ellipse("RGB", BBOX1) | ||||
| 
 | ||||
|         # Act | ||||
|         draw.ellipse(((0, 0), (W - 1, H)), brush) | ||||
| 
 | ||||
|         # Assert | ||||
|         assert_image_similar( | ||||
|             im, Image.open("Tests/images/imagedraw_ellipse_edge.png"), 1 | ||||
|         ) | ||||
| def test_ellipse2(): | ||||
|     helper_ellipse("RGB", BBOX2) | ||||
| 
 | ||||
|     def helper_line(self, points): | ||||
|         # Arrange | ||||
|         im = Image.new("RGB", (W, H)) | ||||
|         draw = ImageDraw2.Draw(im) | ||||
|         pen = ImageDraw2.Pen("yellow", width=2) | ||||
| 
 | ||||
|         # Act | ||||
|         draw.line(points, pen) | ||||
| def test_ellipse_edge(): | ||||
|     # Arrange | ||||
|     im = Image.new("RGB", (W, H)) | ||||
|     draw = ImageDraw2.Draw(im) | ||||
|     brush = ImageDraw2.Brush("white") | ||||
| 
 | ||||
|         # Assert | ||||
|         assert_image_equal(im, Image.open("Tests/images/imagedraw_line.png")) | ||||
|     # Act | ||||
|     draw.ellipse(((0, 0), (W - 1, H)), brush) | ||||
| 
 | ||||
|     def test_line1_pen(self): | ||||
|         self.helper_line(POINTS1) | ||||
|     # Assert | ||||
|     assert_image_similar(im, Image.open("Tests/images/imagedraw_ellipse_edge.png"), 1) | ||||
| 
 | ||||
|     def test_line2_pen(self): | ||||
|         self.helper_line(POINTS2) | ||||
| 
 | ||||
|     def test_line_pen_as_brush(self): | ||||
|         # Arrange | ||||
|         im = Image.new("RGB", (W, H)) | ||||
|         draw = ImageDraw2.Draw(im) | ||||
|         pen = None | ||||
|         brush = ImageDraw2.Pen("yellow", width=2) | ||||
| def helper_line(points): | ||||
|     # Arrange | ||||
|     im = Image.new("RGB", (W, H)) | ||||
|     draw = ImageDraw2.Draw(im) | ||||
|     pen = ImageDraw2.Pen("yellow", width=2) | ||||
| 
 | ||||
|         # Act | ||||
|         # Pass in the pen as the brush parameter | ||||
|         draw.line(POINTS1, pen, brush) | ||||
|     # Act | ||||
|     draw.line(points, pen) | ||||
| 
 | ||||
|         # Assert | ||||
|         assert_image_equal(im, Image.open("Tests/images/imagedraw_line.png")) | ||||
|     # Assert | ||||
|     assert_image_equal(im, Image.open("Tests/images/imagedraw_line.png")) | ||||
| 
 | ||||
|     def helper_polygon(self, points): | ||||
|         # Arrange | ||||
|         im = Image.new("RGB", (W, H)) | ||||
|         draw = ImageDraw2.Draw(im) | ||||
|         pen = ImageDraw2.Pen("blue", width=2) | ||||
|         brush = ImageDraw2.Brush("red") | ||||
| 
 | ||||
|         # Act | ||||
|         draw.polygon(points, pen, brush) | ||||
| def test_line1_pen(): | ||||
|     helper_line(POINTS1) | ||||
| 
 | ||||
|         # Assert | ||||
|         assert_image_equal(im, Image.open("Tests/images/imagedraw_polygon.png")) | ||||
| 
 | ||||
|     def test_polygon1(self): | ||||
|         self.helper_polygon(POINTS1) | ||||
| def test_line2_pen(): | ||||
|     helper_line(POINTS2) | ||||
| 
 | ||||
|     def test_polygon2(self): | ||||
|         self.helper_polygon(POINTS2) | ||||
| 
 | ||||
|     def helper_rectangle(self, bbox): | ||||
|         # Arrange | ||||
|         im = Image.new("RGB", (W, H)) | ||||
|         draw = ImageDraw2.Draw(im) | ||||
|         pen = ImageDraw2.Pen("green", width=2) | ||||
|         brush = ImageDraw2.Brush("black") | ||||
| def test_line_pen_as_brush(): | ||||
|     # Arrange | ||||
|     im = Image.new("RGB", (W, H)) | ||||
|     draw = ImageDraw2.Draw(im) | ||||
|     pen = None | ||||
|     brush = ImageDraw2.Pen("yellow", width=2) | ||||
| 
 | ||||
|         # Act | ||||
|         draw.rectangle(bbox, pen, brush) | ||||
|     # Act | ||||
|     # Pass in the pen as the brush parameter | ||||
|     draw.line(POINTS1, pen, brush) | ||||
| 
 | ||||
|         # Assert | ||||
|         assert_image_equal(im, Image.open("Tests/images/imagedraw_rectangle.png")) | ||||
|     # Assert | ||||
|     assert_image_equal(im, Image.open("Tests/images/imagedraw_line.png")) | ||||
| 
 | ||||
|     def test_rectangle1(self): | ||||
|         self.helper_rectangle(BBOX1) | ||||
| 
 | ||||
|     def test_rectangle2(self): | ||||
|         self.helper_rectangle(BBOX2) | ||||
| def helper_polygon(points): | ||||
|     # Arrange | ||||
|     im = Image.new("RGB", (W, H)) | ||||
|     draw = ImageDraw2.Draw(im) | ||||
|     pen = ImageDraw2.Pen("blue", width=2) | ||||
|     brush = ImageDraw2.Brush("red") | ||||
| 
 | ||||
|     def test_big_rectangle(self): | ||||
|         # Test drawing a rectangle bigger than the image | ||||
|         # Arrange | ||||
|         im = Image.new("RGB", (W, H)) | ||||
|         bbox = [(-1, -1), (W + 1, H + 1)] | ||||
|         brush = ImageDraw2.Brush("orange") | ||||
|         draw = ImageDraw2.Draw(im) | ||||
|         expected = "Tests/images/imagedraw_big_rectangle.png" | ||||
|     # Act | ||||
|     draw.polygon(points, pen, brush) | ||||
| 
 | ||||
|         # Act | ||||
|         draw.rectangle(bbox, brush) | ||||
|     # Assert | ||||
|     assert_image_equal(im, Image.open("Tests/images/imagedraw_polygon.png")) | ||||
| 
 | ||||
|         # Assert | ||||
|         assert_image_similar(im, Image.open(expected), 1) | ||||
| 
 | ||||
|     @unittest.skipUnless(HAS_FREETYPE, "ImageFont not available") | ||||
|     def test_text(self): | ||||
|         # Arrange | ||||
|         im = Image.new("RGB", (W, H)) | ||||
|         draw = ImageDraw2.Draw(im) | ||||
|         font = ImageDraw2.Font("white", FONT_PATH) | ||||
|         expected = "Tests/images/imagedraw2_text.png" | ||||
| def test_polygon1(): | ||||
|     helper_polygon(POINTS1) | ||||
| 
 | ||||
|         # Act | ||||
|         draw.text((5, 5), "ImageDraw2", font) | ||||
| 
 | ||||
|         # Assert | ||||
|         assert_image_similar(im, Image.open(expected), 13) | ||||
| def test_polygon2(): | ||||
|     helper_polygon(POINTS2) | ||||
| 
 | ||||
|     @unittest.skipUnless(HAS_FREETYPE, "ImageFont not available") | ||||
|     def test_textsize(self): | ||||
|         # Arrange | ||||
|         im = Image.new("RGB", (W, H)) | ||||
|         draw = ImageDraw2.Draw(im) | ||||
|         font = ImageDraw2.Font("white", FONT_PATH) | ||||
| 
 | ||||
|         # Act | ||||
|         size = draw.textsize("ImageDraw2", font) | ||||
| def helper_rectangle(bbox): | ||||
|     # Arrange | ||||
|     im = Image.new("RGB", (W, H)) | ||||
|     draw = ImageDraw2.Draw(im) | ||||
|     pen = ImageDraw2.Pen("green", width=2) | ||||
|     brush = ImageDraw2.Brush("black") | ||||
| 
 | ||||
|         # Assert | ||||
|         self.assertEqual(size[1], 12) | ||||
|     # Act | ||||
|     draw.rectangle(bbox, pen, brush) | ||||
| 
 | ||||
|     @unittest.skipUnless(HAS_FREETYPE, "ImageFont not available") | ||||
|     def test_textsize_empty_string(self): | ||||
|         # Arrange | ||||
|         im = Image.new("RGB", (W, H)) | ||||
|         draw = ImageDraw2.Draw(im) | ||||
|         font = ImageDraw2.Font("white", FONT_PATH) | ||||
|     # Assert | ||||
|     assert_image_equal(im, Image.open("Tests/images/imagedraw_rectangle.png")) | ||||
| 
 | ||||
|         # Act | ||||
|         # Should not cause 'SystemError: <built-in method getsize of | ||||
|         # ImagingFont object at 0x...> returned NULL without setting an error' | ||||
|         draw.textsize("", font) | ||||
|         draw.textsize("\n", font) | ||||
|         draw.textsize("test\n", font) | ||||
| 
 | ||||
|     @unittest.skipUnless(HAS_FREETYPE, "ImageFont not available") | ||||
|     def test_flush(self): | ||||
|         # Arrange | ||||
|         im = Image.new("RGB", (W, H)) | ||||
|         draw = ImageDraw2.Draw(im) | ||||
|         font = ImageDraw2.Font("white", FONT_PATH) | ||||
| def test_rectangle1(): | ||||
|     helper_rectangle(BBOX1) | ||||
| 
 | ||||
|         # Act | ||||
|         draw.text((5, 5), "ImageDraw2", font) | ||||
|         im2 = draw.flush() | ||||
| 
 | ||||
|         # Assert | ||||
|         assert_image_equal(im, im2) | ||||
| def test_rectangle2(): | ||||
|     helper_rectangle(BBOX2) | ||||
| 
 | ||||
| 
 | ||||
| def test_big_rectangle(): | ||||
|     # Test drawing a rectangle bigger than the image | ||||
|     # Arrange | ||||
|     im = Image.new("RGB", (W, H)) | ||||
|     bbox = [(-1, -1), (W + 1, H + 1)] | ||||
|     brush = ImageDraw2.Brush("orange") | ||||
|     draw = ImageDraw2.Draw(im) | ||||
|     expected = "Tests/images/imagedraw_big_rectangle.png" | ||||
| 
 | ||||
|     # Act | ||||
|     draw.rectangle(bbox, brush) | ||||
| 
 | ||||
|     # Assert | ||||
|     assert_image_similar(im, Image.open(expected), 1) | ||||
| 
 | ||||
| 
 | ||||
| @pytest.mark.skipif(not HAS_FREETYPE, reason="ImageFont not available") | ||||
| def test_text(): | ||||
|     # Arrange | ||||
|     im = Image.new("RGB", (W, H)) | ||||
|     draw = ImageDraw2.Draw(im) | ||||
|     font = ImageDraw2.Font("white", FONT_PATH) | ||||
|     expected = "Tests/images/imagedraw2_text.png" | ||||
| 
 | ||||
|     # Act | ||||
|     draw.text((5, 5), "ImageDraw2", font) | ||||
| 
 | ||||
|     # Assert | ||||
|     assert_image_similar(im, Image.open(expected), 13) | ||||
| 
 | ||||
| 
 | ||||
| @pytest.mark.skipif(not HAS_FREETYPE, reason="ImageFont not available") | ||||
| def test_textsize(): | ||||
|     # Arrange | ||||
|     im = Image.new("RGB", (W, H)) | ||||
|     draw = ImageDraw2.Draw(im) | ||||
|     font = ImageDraw2.Font("white", FONT_PATH) | ||||
| 
 | ||||
|     # Act | ||||
|     size = draw.textsize("ImageDraw2", font) | ||||
| 
 | ||||
|     # Assert | ||||
|     assert size[1] == 12 | ||||
| 
 | ||||
| 
 | ||||
| @pytest.mark.skipif(not HAS_FREETYPE, reason="ImageFont not available") | ||||
| def test_textsize_empty_string(): | ||||
|     # Arrange | ||||
|     im = Image.new("RGB", (W, H)) | ||||
|     draw = ImageDraw2.Draw(im) | ||||
|     font = ImageDraw2.Font("white", FONT_PATH) | ||||
| 
 | ||||
|     # Act | ||||
|     # Should not cause 'SystemError: <built-in method getsize of | ||||
|     # ImagingFont object at 0x...> returned NULL without setting an error' | ||||
|     draw.textsize("", font) | ||||
|     draw.textsize("\n", font) | ||||
|     draw.textsize("test\n", font) | ||||
| 
 | ||||
| 
 | ||||
| @pytest.mark.skipif(not HAS_FREETYPE, reason="ImageFont not available") | ||||
| def test_flush(): | ||||
|     # Arrange | ||||
|     im = Image.new("RGB", (W, H)) | ||||
|     draw = ImageDraw2.Draw(im) | ||||
|     font = ImageDraw2.Font("white", FONT_PATH) | ||||
| 
 | ||||
|     # Act | ||||
|     draw.text((5, 5), "ImageDraw2", font) | ||||
|     im2 = draw.flush() | ||||
| 
 | ||||
|     # Assert | ||||
|     assert_image_equal(im, im2) | ||||
|  |  | |||
|  | @ -1,54 +1,55 @@ | |||
| from PIL import Image, ImageEnhance | ||||
| 
 | ||||
| from .helper import PillowTestCase, assert_image_equal, hopper | ||||
| from .helper import assert_image_equal, hopper | ||||
| 
 | ||||
| 
 | ||||
| class TestImageEnhance(PillowTestCase): | ||||
|     def test_sanity(self): | ||||
| def test_sanity(): | ||||
|     # FIXME: assert_image | ||||
|     # Implicit asserts no exception: | ||||
|     ImageEnhance.Color(hopper()).enhance(0.5) | ||||
|     ImageEnhance.Contrast(hopper()).enhance(0.5) | ||||
|     ImageEnhance.Brightness(hopper()).enhance(0.5) | ||||
|     ImageEnhance.Sharpness(hopper()).enhance(0.5) | ||||
| 
 | ||||
|         # FIXME: assert_image | ||||
|         # Implicit asserts no exception: | ||||
|         ImageEnhance.Color(hopper()).enhance(0.5) | ||||
|         ImageEnhance.Contrast(hopper()).enhance(0.5) | ||||
|         ImageEnhance.Brightness(hopper()).enhance(0.5) | ||||
|         ImageEnhance.Sharpness(hopper()).enhance(0.5) | ||||
| 
 | ||||
|     def test_crash(self): | ||||
| def test_crash(): | ||||
|     # crashes on small images | ||||
|     im = Image.new("RGB", (1, 1)) | ||||
|     ImageEnhance.Sharpness(im).enhance(0.5) | ||||
| 
 | ||||
|         # crashes on small images | ||||
|         im = Image.new("RGB", (1, 1)) | ||||
|         ImageEnhance.Sharpness(im).enhance(0.5) | ||||
| 
 | ||||
|     def _half_transparent_image(self): | ||||
|         # returns an image, half transparent, half solid | ||||
|         im = hopper("RGB") | ||||
| def _half_transparent_image(): | ||||
|     # returns an image, half transparent, half solid | ||||
|     im = hopper("RGB") | ||||
| 
 | ||||
|         transparent = Image.new("L", im.size, 0) | ||||
|         solid = Image.new("L", (im.size[0] // 2, im.size[1]), 255) | ||||
|         transparent.paste(solid, (0, 0)) | ||||
|         im.putalpha(transparent) | ||||
|     transparent = Image.new("L", im.size, 0) | ||||
|     solid = Image.new("L", (im.size[0] // 2, im.size[1]), 255) | ||||
|     transparent.paste(solid, (0, 0)) | ||||
|     im.putalpha(transparent) | ||||
| 
 | ||||
|         return im | ||||
|     return im | ||||
| 
 | ||||
|     def _check_alpha(self, im, original, op, amount): | ||||
|         self.assertEqual(im.getbands(), original.getbands()) | ||||
|         assert_image_equal( | ||||
|             im.getchannel("A"), | ||||
|             original.getchannel("A"), | ||||
|             "Diff on {}: {}".format(op, amount), | ||||
|         ) | ||||
| 
 | ||||
|     def test_alpha(self): | ||||
|         # Issue https://github.com/python-pillow/Pillow/issues/899 | ||||
|         # Is alpha preserved through image enhancement? | ||||
| def _check_alpha(im, original, op, amount): | ||||
|     assert im.getbands() == original.getbands() | ||||
|     assert_image_equal( | ||||
|         im.getchannel("A"), | ||||
|         original.getchannel("A"), | ||||
|         "Diff on {}: {}".format(op, amount), | ||||
|     ) | ||||
| 
 | ||||
|         original = self._half_transparent_image() | ||||
| 
 | ||||
|         for op in ["Color", "Brightness", "Contrast", "Sharpness"]: | ||||
|             for amount in [0, 0.5, 1.0]: | ||||
|                 self._check_alpha( | ||||
|                     getattr(ImageEnhance, op)(original).enhance(amount), | ||||
|                     original, | ||||
|                     op, | ||||
|                     amount, | ||||
|                 ) | ||||
| def test_alpha(): | ||||
|     # Issue https://github.com/python-pillow/Pillow/issues/899 | ||||
|     # Is alpha preserved through image enhancement? | ||||
| 
 | ||||
|     original = _half_transparent_image() | ||||
| 
 | ||||
|     for op in ["Color", "Brightness", "Contrast", "Sharpness"]: | ||||
|         for amount in [0, 0.5, 1.0]: | ||||
|             _check_alpha( | ||||
|                 getattr(ImageEnhance, op)(original).enhance(amount), | ||||
|                 original, | ||||
|                 op, | ||||
|                 amount, | ||||
|             ) | ||||
|  |  | |||
|  | @ -1,7 +1,7 @@ | |||
| import pytest | ||||
| from PIL import Image, ImageOps | ||||
| 
 | ||||
| from .helper import ( | ||||
|     PillowTestCase, | ||||
|     assert_image_equal, | ||||
|     assert_image_similar, | ||||
|     assert_tuple_approx_equal, | ||||
|  | @ -16,287 +16,294 @@ except ImportError: | |||
|     HAVE_WEBP = False | ||||
| 
 | ||||
| 
 | ||||
| class TestImageOps(PillowTestCase): | ||||
|     class Deformer: | ||||
|         def getmesh(self, im): | ||||
|             x, y = im.size | ||||
|             return [((0, 0, x, y), (0, 0, x, 0, x, y, y, 0))] | ||||
| class Deformer: | ||||
|     def getmesh(self, im): | ||||
|         x, y = im.size | ||||
|         return [((0, 0, x, y), (0, 0, x, 0, x, y, y, 0))] | ||||
| 
 | ||||
|     deformer = Deformer() | ||||
| 
 | ||||
|     def test_sanity(self): | ||||
| deformer = Deformer() | ||||
| 
 | ||||
|         ImageOps.autocontrast(hopper("L")) | ||||
|         ImageOps.autocontrast(hopper("RGB")) | ||||
| 
 | ||||
|         ImageOps.autocontrast(hopper("L"), cutoff=10) | ||||
|         ImageOps.autocontrast(hopper("L"), ignore=[0, 255]) | ||||
| def test_sanity(): | ||||
| 
 | ||||
|         ImageOps.colorize(hopper("L"), (0, 0, 0), (255, 255, 255)) | ||||
|         ImageOps.colorize(hopper("L"), "black", "white") | ||||
|     ImageOps.autocontrast(hopper("L")) | ||||
|     ImageOps.autocontrast(hopper("RGB")) | ||||
| 
 | ||||
|         ImageOps.pad(hopper("L"), (128, 128)) | ||||
|         ImageOps.pad(hopper("RGB"), (128, 128)) | ||||
|     ImageOps.autocontrast(hopper("L"), cutoff=10) | ||||
|     ImageOps.autocontrast(hopper("L"), ignore=[0, 255]) | ||||
| 
 | ||||
|         ImageOps.crop(hopper("L"), 1) | ||||
|         ImageOps.crop(hopper("RGB"), 1) | ||||
|     ImageOps.colorize(hopper("L"), (0, 0, 0), (255, 255, 255)) | ||||
|     ImageOps.colorize(hopper("L"), "black", "white") | ||||
| 
 | ||||
|         ImageOps.deform(hopper("L"), self.deformer) | ||||
|         ImageOps.deform(hopper("RGB"), self.deformer) | ||||
|     ImageOps.pad(hopper("L"), (128, 128)) | ||||
|     ImageOps.pad(hopper("RGB"), (128, 128)) | ||||
| 
 | ||||
|         ImageOps.equalize(hopper("L")) | ||||
|         ImageOps.equalize(hopper("RGB")) | ||||
|     ImageOps.crop(hopper("L"), 1) | ||||
|     ImageOps.crop(hopper("RGB"), 1) | ||||
| 
 | ||||
|         ImageOps.expand(hopper("L"), 1) | ||||
|         ImageOps.expand(hopper("RGB"), 1) | ||||
|         ImageOps.expand(hopper("L"), 2, "blue") | ||||
|         ImageOps.expand(hopper("RGB"), 2, "blue") | ||||
|     ImageOps.deform(hopper("L"), deformer) | ||||
|     ImageOps.deform(hopper("RGB"), deformer) | ||||
| 
 | ||||
|         ImageOps.fit(hopper("L"), (128, 128)) | ||||
|         ImageOps.fit(hopper("RGB"), (128, 128)) | ||||
|     ImageOps.equalize(hopper("L")) | ||||
|     ImageOps.equalize(hopper("RGB")) | ||||
| 
 | ||||
|         ImageOps.flip(hopper("L")) | ||||
|         ImageOps.flip(hopper("RGB")) | ||||
|     ImageOps.expand(hopper("L"), 1) | ||||
|     ImageOps.expand(hopper("RGB"), 1) | ||||
|     ImageOps.expand(hopper("L"), 2, "blue") | ||||
|     ImageOps.expand(hopper("RGB"), 2, "blue") | ||||
| 
 | ||||
|         ImageOps.grayscale(hopper("L")) | ||||
|         ImageOps.grayscale(hopper("RGB")) | ||||
|     ImageOps.fit(hopper("L"), (128, 128)) | ||||
|     ImageOps.fit(hopper("RGB"), (128, 128)) | ||||
| 
 | ||||
|         ImageOps.invert(hopper("L")) | ||||
|         ImageOps.invert(hopper("RGB")) | ||||
|     ImageOps.flip(hopper("L")) | ||||
|     ImageOps.flip(hopper("RGB")) | ||||
| 
 | ||||
|         ImageOps.mirror(hopper("L")) | ||||
|         ImageOps.mirror(hopper("RGB")) | ||||
|     ImageOps.grayscale(hopper("L")) | ||||
|     ImageOps.grayscale(hopper("RGB")) | ||||
| 
 | ||||
|         ImageOps.posterize(hopper("L"), 4) | ||||
|         ImageOps.posterize(hopper("RGB"), 4) | ||||
|     ImageOps.invert(hopper("L")) | ||||
|     ImageOps.invert(hopper("RGB")) | ||||
| 
 | ||||
|         ImageOps.solarize(hopper("L")) | ||||
|         ImageOps.solarize(hopper("RGB")) | ||||
|     ImageOps.mirror(hopper("L")) | ||||
|     ImageOps.mirror(hopper("RGB")) | ||||
| 
 | ||||
|         ImageOps.exif_transpose(hopper("L")) | ||||
|         ImageOps.exif_transpose(hopper("RGB")) | ||||
|     ImageOps.posterize(hopper("L"), 4) | ||||
|     ImageOps.posterize(hopper("RGB"), 4) | ||||
| 
 | ||||
|     def test_1pxfit(self): | ||||
|         # Division by zero in equalize if image is 1 pixel high | ||||
|         newimg = ImageOps.fit(hopper("RGB").resize((1, 1)), (35, 35)) | ||||
|         self.assertEqual(newimg.size, (35, 35)) | ||||
|     ImageOps.solarize(hopper("L")) | ||||
|     ImageOps.solarize(hopper("RGB")) | ||||
| 
 | ||||
|         newimg = ImageOps.fit(hopper("RGB").resize((1, 100)), (35, 35)) | ||||
|         self.assertEqual(newimg.size, (35, 35)) | ||||
|     ImageOps.exif_transpose(hopper("L")) | ||||
|     ImageOps.exif_transpose(hopper("RGB")) | ||||
| 
 | ||||
|         newimg = ImageOps.fit(hopper("RGB").resize((100, 1)), (35, 35)) | ||||
|         self.assertEqual(newimg.size, (35, 35)) | ||||
| 
 | ||||
|     def test_fit_same_ratio(self): | ||||
|         # The ratio for this image is 1000.0 / 755 = 1.3245033112582782 | ||||
|         # If the ratios are not acknowledged to be the same, | ||||
|         # and Pillow attempts to adjust the width to | ||||
|         # 1.3245033112582782 * 755 = 1000.0000000000001 | ||||
|         # then centering this greater width causes a negative x offset when cropping | ||||
|         with Image.new("RGB", (1000, 755)) as im: | ||||
|             new_im = ImageOps.fit(im, (1000, 755)) | ||||
|             self.assertEqual(new_im.size, (1000, 755)) | ||||
| def test_1pxfit(): | ||||
|     # Division by zero in equalize if image is 1 pixel high | ||||
|     newimg = ImageOps.fit(hopper("RGB").resize((1, 1)), (35, 35)) | ||||
|     assert newimg.size == (35, 35) | ||||
| 
 | ||||
|     def test_pad(self): | ||||
|         # Same ratio | ||||
|         im = hopper() | ||||
|         new_size = (im.width * 2, im.height * 2) | ||||
|         new_im = ImageOps.pad(im, new_size) | ||||
|         self.assertEqual(new_im.size, new_size) | ||||
|     newimg = ImageOps.fit(hopper("RGB").resize((1, 100)), (35, 35)) | ||||
|     assert newimg.size == (35, 35) | ||||
| 
 | ||||
|         for label, color, new_size in [ | ||||
|             ("h", None, (im.width * 4, im.height * 2)), | ||||
|             ("v", "#f00", (im.width * 2, im.height * 4)), | ||||
|         ]: | ||||
|             for i, centering in enumerate([(0, 0), (0.5, 0.5), (1, 1)]): | ||||
|                 new_im = ImageOps.pad(im, new_size, color=color, centering=centering) | ||||
|                 self.assertEqual(new_im.size, new_size) | ||||
|     newimg = ImageOps.fit(hopper("RGB").resize((100, 1)), (35, 35)) | ||||
|     assert newimg.size == (35, 35) | ||||
| 
 | ||||
| 
 | ||||
| def test_fit_same_ratio(): | ||||
|     # The ratio for this image is 1000.0 / 755 = 1.3245033112582782 | ||||
|     # If the ratios are not acknowledged to be the same, | ||||
|     # and Pillow attempts to adjust the width to | ||||
|     # 1.3245033112582782 * 755 = 1000.0000000000001 | ||||
|     # then centering this greater width causes a negative x offset when cropping | ||||
|     with Image.new("RGB", (1000, 755)) as im: | ||||
|         new_im = ImageOps.fit(im, (1000, 755)) | ||||
|         assert new_im.size == (1000, 755) | ||||
| 
 | ||||
| 
 | ||||
| def test_pad(): | ||||
|     # Same ratio | ||||
|     im = hopper() | ||||
|     new_size = (im.width * 2, im.height * 2) | ||||
|     new_im = ImageOps.pad(im, new_size) | ||||
|     assert new_im.size == new_size | ||||
| 
 | ||||
|     for label, color, new_size in [ | ||||
|         ("h", None, (im.width * 4, im.height * 2)), | ||||
|         ("v", "#f00", (im.width * 2, im.height * 4)), | ||||
|     ]: | ||||
|         for i, centering in enumerate([(0, 0), (0.5, 0.5), (1, 1)]): | ||||
|             new_im = ImageOps.pad(im, new_size, color=color, centering=centering) | ||||
|             assert new_im.size == new_size | ||||
| 
 | ||||
|             with Image.open( | ||||
|                 "Tests/images/imageops_pad_" + label + "_" + str(i) + ".jpg" | ||||
|             ) as target: | ||||
|                 assert_image_similar(new_im, target, 6) | ||||
| 
 | ||||
| 
 | ||||
| def test_pil163(): | ||||
|     # Division by zero in equalize if < 255 pixels in image (@PIL163) | ||||
| 
 | ||||
|     i = hopper("RGB").resize((15, 16)) | ||||
| 
 | ||||
|     ImageOps.equalize(i.convert("L")) | ||||
|     ImageOps.equalize(i.convert("P")) | ||||
|     ImageOps.equalize(i.convert("RGB")) | ||||
| 
 | ||||
| 
 | ||||
| def test_scale(): | ||||
|     # Test the scaling function | ||||
|     i = hopper("L").resize((50, 50)) | ||||
| 
 | ||||
|     with pytest.raises(ValueError): | ||||
|         ImageOps.scale(i, -1) | ||||
| 
 | ||||
|     newimg = ImageOps.scale(i, 1) | ||||
|     assert newimg.size == (50, 50) | ||||
| 
 | ||||
|     newimg = ImageOps.scale(i, 2) | ||||
|     assert newimg.size == (100, 100) | ||||
| 
 | ||||
|     newimg = ImageOps.scale(i, 0.5) | ||||
|     assert newimg.size == (25, 25) | ||||
| 
 | ||||
| 
 | ||||
| def test_colorize_2color(): | ||||
|     # Test the colorizing function with 2-color functionality | ||||
| 
 | ||||
|     # Open test image (256px by 10px, black to white) | ||||
|     with Image.open("Tests/images/bw_gradient.png") as im: | ||||
|         im = im.convert("L") | ||||
| 
 | ||||
|     # Create image with original 2-color functionality | ||||
|     im_test = ImageOps.colorize(im, "red", "green") | ||||
| 
 | ||||
|     # Test output image (2-color) | ||||
|     left = (0, 1) | ||||
|     middle = (127, 1) | ||||
|     right = (255, 1) | ||||
|     assert_tuple_approx_equal( | ||||
|         im_test.getpixel(left), | ||||
|         (255, 0, 0), | ||||
|         threshold=1, | ||||
|         msg="black test pixel incorrect", | ||||
|     ) | ||||
|     assert_tuple_approx_equal( | ||||
|         im_test.getpixel(middle), | ||||
|         (127, 63, 0), | ||||
|         threshold=1, | ||||
|         msg="mid test pixel incorrect", | ||||
|     ) | ||||
|     assert_tuple_approx_equal( | ||||
|         im_test.getpixel(right), | ||||
|         (0, 127, 0), | ||||
|         threshold=1, | ||||
|         msg="white test pixel incorrect", | ||||
|     ) | ||||
| 
 | ||||
| 
 | ||||
| def test_colorize_2color_offset(): | ||||
|     # Test the colorizing function with 2-color functionality and offset | ||||
| 
 | ||||
|     # Open test image (256px by 10px, black to white) | ||||
|     with Image.open("Tests/images/bw_gradient.png") as im: | ||||
|         im = im.convert("L") | ||||
| 
 | ||||
|     # Create image with original 2-color functionality with offsets | ||||
|     im_test = ImageOps.colorize( | ||||
|         im, black="red", white="green", blackpoint=50, whitepoint=100 | ||||
|     ) | ||||
| 
 | ||||
|     # Test output image (2-color) with offsets | ||||
|     left = (25, 1) | ||||
|     middle = (75, 1) | ||||
|     right = (125, 1) | ||||
|     assert_tuple_approx_equal( | ||||
|         im_test.getpixel(left), | ||||
|         (255, 0, 0), | ||||
|         threshold=1, | ||||
|         msg="black test pixel incorrect", | ||||
|     ) | ||||
|     assert_tuple_approx_equal( | ||||
|         im_test.getpixel(middle), | ||||
|         (127, 63, 0), | ||||
|         threshold=1, | ||||
|         msg="mid test pixel incorrect", | ||||
|     ) | ||||
|     assert_tuple_approx_equal( | ||||
|         im_test.getpixel(right), | ||||
|         (0, 127, 0), | ||||
|         threshold=1, | ||||
|         msg="white test pixel incorrect", | ||||
|     ) | ||||
| 
 | ||||
| 
 | ||||
| def test_colorize_3color_offset(): | ||||
|     # Test the colorizing function with 3-color functionality and offset | ||||
| 
 | ||||
|     # Open test image (256px by 10px, black to white) | ||||
|     with Image.open("Tests/images/bw_gradient.png") as im: | ||||
|         im = im.convert("L") | ||||
| 
 | ||||
|     # Create image with new three color functionality with offsets | ||||
|     im_test = ImageOps.colorize( | ||||
|         im, | ||||
|         black="red", | ||||
|         white="green", | ||||
|         mid="blue", | ||||
|         blackpoint=50, | ||||
|         whitepoint=200, | ||||
|         midpoint=100, | ||||
|     ) | ||||
| 
 | ||||
|     # Test output image (3-color) with offsets | ||||
|     left = (25, 1) | ||||
|     left_middle = (75, 1) | ||||
|     middle = (100, 1) | ||||
|     right_middle = (150, 1) | ||||
|     right = (225, 1) | ||||
|     assert_tuple_approx_equal( | ||||
|         im_test.getpixel(left), | ||||
|         (255, 0, 0), | ||||
|         threshold=1, | ||||
|         msg="black test pixel incorrect", | ||||
|     ) | ||||
|     assert_tuple_approx_equal( | ||||
|         im_test.getpixel(left_middle), | ||||
|         (127, 0, 127), | ||||
|         threshold=1, | ||||
|         msg="low-mid test pixel incorrect", | ||||
|     ) | ||||
|     assert_tuple_approx_equal( | ||||
|         im_test.getpixel(middle), (0, 0, 255), threshold=1, msg="mid incorrect" | ||||
|     ) | ||||
|     assert_tuple_approx_equal( | ||||
|         im_test.getpixel(right_middle), | ||||
|         (0, 63, 127), | ||||
|         threshold=1, | ||||
|         msg="high-mid test pixel incorrect", | ||||
|     ) | ||||
|     assert_tuple_approx_equal( | ||||
|         im_test.getpixel(right), | ||||
|         (0, 127, 0), | ||||
|         threshold=1, | ||||
|         msg="white test pixel incorrect", | ||||
|     ) | ||||
| 
 | ||||
| 
 | ||||
| def test_exif_transpose(): | ||||
|     exts = [".jpg"] | ||||
|     if HAVE_WEBP and _webp.HAVE_WEBPANIM: | ||||
|         exts.append(".webp") | ||||
|     for ext in exts: | ||||
|         with Image.open("Tests/images/hopper" + ext) as base_im: | ||||
| 
 | ||||
|             def check(orientation_im): | ||||
|                 for im in [ | ||||
|                     orientation_im, | ||||
|                     orientation_im.copy(), | ||||
|                 ]:  # ImageFile  # Image | ||||
|                     if orientation_im is base_im: | ||||
|                         assert "exif" not in im.info | ||||
|                     else: | ||||
|                         original_exif = im.info["exif"] | ||||
|                     transposed_im = ImageOps.exif_transpose(im) | ||||
|                     assert_image_similar(base_im, transposed_im, 17) | ||||
|                     if orientation_im is base_im: | ||||
|                         assert "exif" not in im.info | ||||
|                     else: | ||||
|                         assert transposed_im.info["exif"] != original_exif | ||||
| 
 | ||||
|                         assert 0x0112 not in transposed_im.getexif() | ||||
| 
 | ||||
|                     # Repeat the operation to test that it does not keep transposing | ||||
|                     transposed_im2 = ImageOps.exif_transpose(transposed_im) | ||||
|                     assert_image_equal(transposed_im2, transposed_im) | ||||
| 
 | ||||
|             check(base_im) | ||||
|             for i in range(2, 9): | ||||
|                 with Image.open( | ||||
|                     "Tests/images/imageops_pad_" + label + "_" + str(i) + ".jpg" | ||||
|                 ) as target: | ||||
|                     assert_image_similar(new_im, target, 6) | ||||
| 
 | ||||
|     def test_pil163(self): | ||||
|         # Division by zero in equalize if < 255 pixels in image (@PIL163) | ||||
| 
 | ||||
|         i = hopper("RGB").resize((15, 16)) | ||||
| 
 | ||||
|         ImageOps.equalize(i.convert("L")) | ||||
|         ImageOps.equalize(i.convert("P")) | ||||
|         ImageOps.equalize(i.convert("RGB")) | ||||
| 
 | ||||
|     def test_scale(self): | ||||
|         # Test the scaling function | ||||
|         i = hopper("L").resize((50, 50)) | ||||
| 
 | ||||
|         with self.assertRaises(ValueError): | ||||
|             ImageOps.scale(i, -1) | ||||
| 
 | ||||
|         newimg = ImageOps.scale(i, 1) | ||||
|         self.assertEqual(newimg.size, (50, 50)) | ||||
| 
 | ||||
|         newimg = ImageOps.scale(i, 2) | ||||
|         self.assertEqual(newimg.size, (100, 100)) | ||||
| 
 | ||||
|         newimg = ImageOps.scale(i, 0.5) | ||||
|         self.assertEqual(newimg.size, (25, 25)) | ||||
| 
 | ||||
|     def test_colorize_2color(self): | ||||
|         # Test the colorizing function with 2-color functionality | ||||
| 
 | ||||
|         # Open test image (256px by 10px, black to white) | ||||
|         with Image.open("Tests/images/bw_gradient.png") as im: | ||||
|             im = im.convert("L") | ||||
| 
 | ||||
|         # Create image with original 2-color functionality | ||||
|         im_test = ImageOps.colorize(im, "red", "green") | ||||
| 
 | ||||
|         # Test output image (2-color) | ||||
|         left = (0, 1) | ||||
|         middle = (127, 1) | ||||
|         right = (255, 1) | ||||
|         assert_tuple_approx_equal( | ||||
|             im_test.getpixel(left), | ||||
|             (255, 0, 0), | ||||
|             threshold=1, | ||||
|             msg="black test pixel incorrect", | ||||
|         ) | ||||
|         assert_tuple_approx_equal( | ||||
|             im_test.getpixel(middle), | ||||
|             (127, 63, 0), | ||||
|             threshold=1, | ||||
|             msg="mid test pixel incorrect", | ||||
|         ) | ||||
|         assert_tuple_approx_equal( | ||||
|             im_test.getpixel(right), | ||||
|             (0, 127, 0), | ||||
|             threshold=1, | ||||
|             msg="white test pixel incorrect", | ||||
|         ) | ||||
| 
 | ||||
|     def test_colorize_2color_offset(self): | ||||
|         # Test the colorizing function with 2-color functionality and offset | ||||
| 
 | ||||
|         # Open test image (256px by 10px, black to white) | ||||
|         with Image.open("Tests/images/bw_gradient.png") as im: | ||||
|             im = im.convert("L") | ||||
| 
 | ||||
|         # Create image with original 2-color functionality with offsets | ||||
|         im_test = ImageOps.colorize( | ||||
|             im, black="red", white="green", blackpoint=50, whitepoint=100 | ||||
|         ) | ||||
| 
 | ||||
|         # Test output image (2-color) with offsets | ||||
|         left = (25, 1) | ||||
|         middle = (75, 1) | ||||
|         right = (125, 1) | ||||
|         assert_tuple_approx_equal( | ||||
|             im_test.getpixel(left), | ||||
|             (255, 0, 0), | ||||
|             threshold=1, | ||||
|             msg="black test pixel incorrect", | ||||
|         ) | ||||
|         assert_tuple_approx_equal( | ||||
|             im_test.getpixel(middle), | ||||
|             (127, 63, 0), | ||||
|             threshold=1, | ||||
|             msg="mid test pixel incorrect", | ||||
|         ) | ||||
|         assert_tuple_approx_equal( | ||||
|             im_test.getpixel(right), | ||||
|             (0, 127, 0), | ||||
|             threshold=1, | ||||
|             msg="white test pixel incorrect", | ||||
|         ) | ||||
| 
 | ||||
|     def test_colorize_3color_offset(self): | ||||
|         # Test the colorizing function with 3-color functionality and offset | ||||
| 
 | ||||
|         # Open test image (256px by 10px, black to white) | ||||
|         with Image.open("Tests/images/bw_gradient.png") as im: | ||||
|             im = im.convert("L") | ||||
| 
 | ||||
|         # Create image with new three color functionality with offsets | ||||
|         im_test = ImageOps.colorize( | ||||
|             im, | ||||
|             black="red", | ||||
|             white="green", | ||||
|             mid="blue", | ||||
|             blackpoint=50, | ||||
|             whitepoint=200, | ||||
|             midpoint=100, | ||||
|         ) | ||||
| 
 | ||||
|         # Test output image (3-color) with offsets | ||||
|         left = (25, 1) | ||||
|         left_middle = (75, 1) | ||||
|         middle = (100, 1) | ||||
|         right_middle = (150, 1) | ||||
|         right = (225, 1) | ||||
|         assert_tuple_approx_equal( | ||||
|             im_test.getpixel(left), | ||||
|             (255, 0, 0), | ||||
|             threshold=1, | ||||
|             msg="black test pixel incorrect", | ||||
|         ) | ||||
|         assert_tuple_approx_equal( | ||||
|             im_test.getpixel(left_middle), | ||||
|             (127, 0, 127), | ||||
|             threshold=1, | ||||
|             msg="low-mid test pixel incorrect", | ||||
|         ) | ||||
|         assert_tuple_approx_equal( | ||||
|             im_test.getpixel(middle), (0, 0, 255), threshold=1, msg="mid incorrect" | ||||
|         ) | ||||
|         assert_tuple_approx_equal( | ||||
|             im_test.getpixel(right_middle), | ||||
|             (0, 63, 127), | ||||
|             threshold=1, | ||||
|             msg="high-mid test pixel incorrect", | ||||
|         ) | ||||
|         assert_tuple_approx_equal( | ||||
|             im_test.getpixel(right), | ||||
|             (0, 127, 0), | ||||
|             threshold=1, | ||||
|             msg="white test pixel incorrect", | ||||
|         ) | ||||
| 
 | ||||
|     def test_exif_transpose(self): | ||||
|         exts = [".jpg"] | ||||
|         if HAVE_WEBP and _webp.HAVE_WEBPANIM: | ||||
|             exts.append(".webp") | ||||
|         for ext in exts: | ||||
|             with Image.open("Tests/images/hopper" + ext) as base_im: | ||||
| 
 | ||||
|                 def check(orientation_im): | ||||
|                     for im in [ | ||||
|                         orientation_im, | ||||
|                         orientation_im.copy(), | ||||
|                     ]:  # ImageFile  # Image | ||||
|                         if orientation_im is base_im: | ||||
|                             self.assertNotIn("exif", im.info) | ||||
|                         else: | ||||
|                             original_exif = im.info["exif"] | ||||
|                         transposed_im = ImageOps.exif_transpose(im) | ||||
|                         assert_image_similar(base_im, transposed_im, 17) | ||||
|                         if orientation_im is base_im: | ||||
|                             self.assertNotIn("exif", im.info) | ||||
|                         else: | ||||
|                             self.assertNotEqual( | ||||
|                                 transposed_im.info["exif"], original_exif | ||||
|                             ) | ||||
| 
 | ||||
|                             self.assertNotIn(0x0112, transposed_im.getexif()) | ||||
| 
 | ||||
|                         # Repeat the operation | ||||
|                         # to test that it does not keep transposing | ||||
|                         transposed_im2 = ImageOps.exif_transpose(transposed_im) | ||||
|                         assert_image_equal(transposed_im2, transposed_im) | ||||
| 
 | ||||
|                 check(base_im) | ||||
|                 for i in range(2, 9): | ||||
|                     with Image.open( | ||||
|                         "Tests/images/hopper_orientation_" + str(i) + ext | ||||
|                     ) as orientation_im: | ||||
|                         check(orientation_im) | ||||
|                     "Tests/images/hopper_orientation_" + str(i) + ext | ||||
|                 ) as orientation_im: | ||||
|                     check(orientation_im) | ||||
|  |  | |||
|  | @ -1,8 +1,7 @@ | |||
| import unittest | ||||
| 
 | ||||
| import pytest | ||||
| from PIL import Image | ||||
| 
 | ||||
| from .helper import PillowTestCase, assert_image_equal, hopper | ||||
| from .helper import assert_image_equal, hopper | ||||
| 
 | ||||
| try: | ||||
|     from PIL import ImageTk | ||||
|  | @ -12,76 +11,81 @@ try: | |||
|     dir(ImageTk) | ||||
|     HAS_TK = True | ||||
| except (OSError, ImportError): | ||||
|     # Skipped via setUp() | ||||
|     # Skipped via pytestmark | ||||
|     HAS_TK = False | ||||
| 
 | ||||
| TK_MODES = ("1", "L", "P", "RGB", "RGBA") | ||||
| 
 | ||||
| 
 | ||||
| @unittest.skipUnless(HAS_TK, "Tk not installed") | ||||
| class TestImageTk(PillowTestCase): | ||||
|     def setUp(self): | ||||
|         try: | ||||
|             # setup tk | ||||
|             tk.Frame() | ||||
|             # root = tk.Tk() | ||||
|         except tk.TclError as v: | ||||
|             self.skipTest("TCL Error: %s" % v) | ||||
| pytestmark = pytest.mark.skipif(not HAS_TK, reason="Tk not installed") | ||||
| 
 | ||||
|     def test_kw(self): | ||||
|         TEST_JPG = "Tests/images/hopper.jpg" | ||||
|         TEST_PNG = "Tests/images/hopper.png" | ||||
|         with Image.open(TEST_JPG) as im1: | ||||
|             with Image.open(TEST_PNG) as im2: | ||||
|                 with open(TEST_PNG, "rb") as fp: | ||||
|                     data = fp.read() | ||||
|                 kw = {"file": TEST_JPG, "data": data} | ||||
| 
 | ||||
|                 # Test "file" | ||||
|                 im = ImageTk._get_image_from_kw(kw) | ||||
|                 assert_image_equal(im, im1) | ||||
| def setup_module(): | ||||
|     try: | ||||
|         # setup tk | ||||
|         tk.Frame() | ||||
|         # root = tk.Tk() | ||||
|     except tk.TclError as v: | ||||
|         pytest.skip("TCL Error: %s" % v) | ||||
| 
 | ||||
|                 # Test "data" | ||||
|                 im = ImageTk._get_image_from_kw(kw) | ||||
|                 assert_image_equal(im, im2) | ||||
| 
 | ||||
|         # Test no relevant entry | ||||
|         im = ImageTk._get_image_from_kw(kw) | ||||
|         self.assertIsNone(im) | ||||
| def test_kw(): | ||||
|     TEST_JPG = "Tests/images/hopper.jpg" | ||||
|     TEST_PNG = "Tests/images/hopper.png" | ||||
|     with Image.open(TEST_JPG) as im1: | ||||
|         with Image.open(TEST_PNG) as im2: | ||||
|             with open(TEST_PNG, "rb") as fp: | ||||
|                 data = fp.read() | ||||
|             kw = {"file": TEST_JPG, "data": data} | ||||
| 
 | ||||
|     def test_photoimage(self): | ||||
|         for mode in TK_MODES: | ||||
|             # test as image: | ||||
|             im = hopper(mode) | ||||
|             # Test "file" | ||||
|             im = ImageTk._get_image_from_kw(kw) | ||||
|             assert_image_equal(im, im1) | ||||
| 
 | ||||
|             # this should not crash | ||||
|             im_tk = ImageTk.PhotoImage(im) | ||||
|             # Test "data" | ||||
|             im = ImageTk._get_image_from_kw(kw) | ||||
|             assert_image_equal(im, im2) | ||||
| 
 | ||||
|             self.assertEqual(im_tk.width(), im.width) | ||||
|             self.assertEqual(im_tk.height(), im.height) | ||||
|     # Test no relevant entry | ||||
|     im = ImageTk._get_image_from_kw(kw) | ||||
|     assert im is None | ||||
| 
 | ||||
|             reloaded = ImageTk.getimage(im_tk) | ||||
|             assert_image_equal(reloaded, im.convert("RGBA")) | ||||
| 
 | ||||
|     def test_photoimage_blank(self): | ||||
|         # test a image using mode/size: | ||||
|         for mode in TK_MODES: | ||||
|             im_tk = ImageTk.PhotoImage(mode, (100, 100)) | ||||
| 
 | ||||
|             self.assertEqual(im_tk.width(), 100) | ||||
|             self.assertEqual(im_tk.height(), 100) | ||||
| 
 | ||||
|             # reloaded = ImageTk.getimage(im_tk) | ||||
|             # assert_image_equal(reloaded, im) | ||||
| 
 | ||||
|     def test_bitmapimage(self): | ||||
|         im = hopper("1") | ||||
| def test_photoimage(): | ||||
|     for mode in TK_MODES: | ||||
|         # test as image: | ||||
|         im = hopper(mode) | ||||
| 
 | ||||
|         # this should not crash | ||||
|         im_tk = ImageTk.BitmapImage(im) | ||||
|         im_tk = ImageTk.PhotoImage(im) | ||||
| 
 | ||||
|         self.assertEqual(im_tk.width(), im.width) | ||||
|         self.assertEqual(im_tk.height(), im.height) | ||||
|         assert im_tk.width() == im.width | ||||
|         assert im_tk.height() == im.height | ||||
| 
 | ||||
|         reloaded = ImageTk.getimage(im_tk) | ||||
|         assert_image_equal(reloaded, im.convert("RGBA")) | ||||
| 
 | ||||
| 
 | ||||
| def test_photoimage_blank(): | ||||
|     # test a image using mode/size: | ||||
|     for mode in TK_MODES: | ||||
|         im_tk = ImageTk.PhotoImage(mode, (100, 100)) | ||||
| 
 | ||||
|         assert im_tk.width() == 100 | ||||
|         assert im_tk.height() == 100 | ||||
| 
 | ||||
|         # reloaded = ImageTk.getimage(im_tk) | ||||
|         # assert_image_equal(reloaded, im) | ||||
| 
 | ||||
| 
 | ||||
| def test_bitmapimage(): | ||||
|     im = hopper("1") | ||||
| 
 | ||||
|     # this should not crash | ||||
|     im_tk = ImageTk.BitmapImage(im) | ||||
| 
 | ||||
|     assert im_tk.width() == im.width | ||||
|     assert im_tk.height() == im.height | ||||
| 
 | ||||
|     # reloaded = ImageTk.getimage(im_tk) | ||||
|     # assert_image_equal(reloaded, im) | ||||
|  |  | |||
|  | @ -1,38 +1,39 @@ | |||
| import sys | ||||
| import unittest | ||||
| 
 | ||||
| import pytest | ||||
| from PIL import Image | ||||
| 
 | ||||
| from .helper import PillowTestCase, is_win32 | ||||
| from .helper import is_win32 | ||||
| 
 | ||||
| try: | ||||
|     import numpy | ||||
| except ImportError: | ||||
|     numpy = None | ||||
| 
 | ||||
| pytestmark = pytest.mark.skipif(is_win32(), reason="Win32 does not call map_buffer") | ||||
| 
 | ||||
| @unittest.skipIf(is_win32(), "Win32 does not call map_buffer") | ||||
| class TestMap(PillowTestCase): | ||||
|     def test_overflow(self): | ||||
|         # There is the potential to overflow comparisons in map.c | ||||
|         # if there are > SIZE_MAX bytes in the image or if | ||||
|         # the file encodes an offset that makes | ||||
|         # (offset + size(bytes)) > SIZE_MAX | ||||
| 
 | ||||
|         # Note that this image triggers the decompression bomb warning: | ||||
|         max_pixels = Image.MAX_IMAGE_PIXELS | ||||
|         Image.MAX_IMAGE_PIXELS = None | ||||
| def test_overflow(): | ||||
|     # There is the potential to overflow comparisons in map.c | ||||
|     # if there are > SIZE_MAX bytes in the image or if | ||||
|     # the file encodes an offset that makes | ||||
|     # (offset + size(bytes)) > SIZE_MAX | ||||
| 
 | ||||
|         # This image hits the offset test. | ||||
|         with Image.open("Tests/images/l2rgb_read.bmp") as im: | ||||
|             with self.assertRaises((ValueError, MemoryError, IOError)): | ||||
|                 im.load() | ||||
|     # Note that this image triggers the decompression bomb warning: | ||||
|     max_pixels = Image.MAX_IMAGE_PIXELS | ||||
|     Image.MAX_IMAGE_PIXELS = None | ||||
| 
 | ||||
|         Image.MAX_IMAGE_PIXELS = max_pixels | ||||
|     # This image hits the offset test. | ||||
|     with Image.open("Tests/images/l2rgb_read.bmp") as im: | ||||
|         with pytest.raises((ValueError, MemoryError, IOError)): | ||||
|             im.load() | ||||
| 
 | ||||
|     @unittest.skipIf(sys.maxsize <= 2 ** 32, "requires 64-bit system") | ||||
|     @unittest.skipIf(numpy is None, "Numpy is not installed") | ||||
|     def test_ysize(self): | ||||
|         # Should not raise 'Integer overflow in ysize' | ||||
|         arr = numpy.zeros((46341, 46341), dtype=numpy.uint8) | ||||
|         Image.fromarray(arr) | ||||
|     Image.MAX_IMAGE_PIXELS = max_pixels | ||||
| 
 | ||||
| 
 | ||||
| @pytest.mark.skipif(sys.maxsize <= 2 ** 32, reason="Requires 64-bit system") | ||||
| @pytest.mark.skipif(numpy is None, reason="NumPy is not installed") | ||||
| def test_ysize(): | ||||
|     # Should not raise 'Integer overflow in ysize' | ||||
|     arr = numpy.zeros((46341, 46341), dtype=numpy.uint8) | ||||
|     Image.fromarray(arr) | ||||
|  |  | |||
|  | @ -1,9 +1,7 @@ | |||
| import unittest | ||||
| 
 | ||||
| import pytest | ||||
| from PIL import Image | ||||
| 
 | ||||
| from .helper import PillowTestCase, assert_deep_equal, assert_image, hopper | ||||
| from .helper import assert_deep_equal, assert_image, hopper | ||||
| 
 | ||||
| try: | ||||
|     import numpy | ||||
|  | @ -14,211 +12,227 @@ except ImportError: | |||
| TEST_IMAGE_SIZE = (10, 10) | ||||
| 
 | ||||
| 
 | ||||
| @unittest.skipIf(numpy is None, "Numpy is not installed") | ||||
| class TestNumpy(PillowTestCase): | ||||
|     def test_numpy_to_image(self): | ||||
|         def to_image(dtype, bands=1, boolean=0): | ||||
|             if bands == 1: | ||||
|                 if boolean: | ||||
|                     data = [0, 255] * 50 | ||||
|                 else: | ||||
|                     data = list(range(100)) | ||||
|                 a = numpy.array(data, dtype=dtype) | ||||
|                 a.shape = TEST_IMAGE_SIZE | ||||
|                 i = Image.fromarray(a) | ||||
|                 if list(i.getdata()) != data: | ||||
|                     print("data mismatch for", dtype) | ||||
| pytestmark = pytest.mark.skipif(numpy is None, reason="NumPy is not installed") | ||||
| 
 | ||||
| 
 | ||||
| def test_numpy_to_image(): | ||||
|     def to_image(dtype, bands=1, boolean=0): | ||||
|         if bands == 1: | ||||
|             if boolean: | ||||
|                 data = [0, 255] * 50 | ||||
|             else: | ||||
|                 data = list(range(100)) | ||||
|                 a = numpy.array([[x] * bands for x in data], dtype=dtype) | ||||
|                 a.shape = TEST_IMAGE_SIZE[0], TEST_IMAGE_SIZE[1], bands | ||||
|                 i = Image.fromarray(a) | ||||
|                 if list(i.getchannel(0).getdata()) != list(range(100)): | ||||
|                     print("data mismatch for", dtype) | ||||
|             return i | ||||
| 
 | ||||
|         # Check supported 1-bit integer formats | ||||
|         assert_image(to_image(numpy.bool, 1, 1), "1", TEST_IMAGE_SIZE) | ||||
|         assert_image(to_image(numpy.bool8, 1, 1), "1", TEST_IMAGE_SIZE) | ||||
| 
 | ||||
|         # Check supported 8-bit integer formats | ||||
|         assert_image(to_image(numpy.uint8), "L", TEST_IMAGE_SIZE) | ||||
|         assert_image(to_image(numpy.uint8, 3), "RGB", TEST_IMAGE_SIZE) | ||||
|         assert_image(to_image(numpy.uint8, 4), "RGBA", TEST_IMAGE_SIZE) | ||||
|         assert_image(to_image(numpy.int8), "I", TEST_IMAGE_SIZE) | ||||
| 
 | ||||
|         # Check non-fixed-size integer types | ||||
|         # These may fail, depending on the platform, since we have no native | ||||
|         # 64 bit int image types. | ||||
|         # assert_image(to_image(numpy.uint), "I", TEST_IMAGE_SIZE) | ||||
|         # assert_image(to_image(numpy.int), "I", TEST_IMAGE_SIZE) | ||||
| 
 | ||||
|         # Check 16-bit integer formats | ||||
|         if Image._ENDIAN == "<": | ||||
|             assert_image(to_image(numpy.uint16), "I;16", TEST_IMAGE_SIZE) | ||||
|             a = numpy.array(data, dtype=dtype) | ||||
|             a.shape = TEST_IMAGE_SIZE | ||||
|             i = Image.fromarray(a) | ||||
|             if list(i.getdata()) != data: | ||||
|                 print("data mismatch for", dtype) | ||||
|         else: | ||||
|             assert_image(to_image(numpy.uint16), "I;16B", TEST_IMAGE_SIZE) | ||||
|             data = list(range(100)) | ||||
|             a = numpy.array([[x] * bands for x in data], dtype=dtype) | ||||
|             a.shape = TEST_IMAGE_SIZE[0], TEST_IMAGE_SIZE[1], bands | ||||
|             i = Image.fromarray(a) | ||||
|             if list(i.getchannel(0).getdata()) != list(range(100)): | ||||
|                 print("data mismatch for", dtype) | ||||
|         return i | ||||
| 
 | ||||
|         assert_image(to_image(numpy.int16), "I", TEST_IMAGE_SIZE) | ||||
|     # Check supported 1-bit integer formats | ||||
|     assert_image(to_image(numpy.bool, 1, 1), "1", TEST_IMAGE_SIZE) | ||||
|     assert_image(to_image(numpy.bool8, 1, 1), "1", TEST_IMAGE_SIZE) | ||||
| 
 | ||||
|         # Check 32-bit integer formats | ||||
|         assert_image(to_image(numpy.uint32), "I", TEST_IMAGE_SIZE) | ||||
|         assert_image(to_image(numpy.int32), "I", TEST_IMAGE_SIZE) | ||||
|     # Check supported 8-bit integer formats | ||||
|     assert_image(to_image(numpy.uint8), "L", TEST_IMAGE_SIZE) | ||||
|     assert_image(to_image(numpy.uint8, 3), "RGB", TEST_IMAGE_SIZE) | ||||
|     assert_image(to_image(numpy.uint8, 4), "RGBA", TEST_IMAGE_SIZE) | ||||
|     assert_image(to_image(numpy.int8), "I", TEST_IMAGE_SIZE) | ||||
| 
 | ||||
|         # Check 64-bit integer formats | ||||
|         self.assertRaises(TypeError, to_image, numpy.uint64) | ||||
|         self.assertRaises(TypeError, to_image, numpy.int64) | ||||
|     # Check non-fixed-size integer types | ||||
|     # These may fail, depending on the platform, since we have no native | ||||
|     # 64-bit int image types. | ||||
|     # assert_image(to_image(numpy.uint), "I", TEST_IMAGE_SIZE) | ||||
|     # assert_image(to_image(numpy.int), "I", TEST_IMAGE_SIZE) | ||||
| 
 | ||||
|         # Check floating-point formats | ||||
|         assert_image(to_image(numpy.float), "F", TEST_IMAGE_SIZE) | ||||
|         self.assertRaises(TypeError, to_image, numpy.float16) | ||||
|         assert_image(to_image(numpy.float32), "F", TEST_IMAGE_SIZE) | ||||
|         assert_image(to_image(numpy.float64), "F", TEST_IMAGE_SIZE) | ||||
|     # Check 16-bit integer formats | ||||
|     if Image._ENDIAN == "<": | ||||
|         assert_image(to_image(numpy.uint16), "I;16", TEST_IMAGE_SIZE) | ||||
|     else: | ||||
|         assert_image(to_image(numpy.uint16), "I;16B", TEST_IMAGE_SIZE) | ||||
| 
 | ||||
|         assert_image(to_image(numpy.uint8, 2), "LA", (10, 10)) | ||||
|         assert_image(to_image(numpy.uint8, 3), "RGB", (10, 10)) | ||||
|         assert_image(to_image(numpy.uint8, 4), "RGBA", (10, 10)) | ||||
|     assert_image(to_image(numpy.int16), "I", TEST_IMAGE_SIZE) | ||||
| 
 | ||||
|     # based on an erring example at | ||||
|     # https://stackoverflow.com/questions/10854903/what-is-causing-dimension-dependent-attributeerror-in-pil-fromarray-function | ||||
|     def test_3d_array(self): | ||||
|         size = (5, TEST_IMAGE_SIZE[0], TEST_IMAGE_SIZE[1]) | ||||
|         a = numpy.ones(size, dtype=numpy.uint8) | ||||
|         assert_image(Image.fromarray(a[1, :, :]), "L", TEST_IMAGE_SIZE) | ||||
|         size = (TEST_IMAGE_SIZE[0], 5, TEST_IMAGE_SIZE[1]) | ||||
|         a = numpy.ones(size, dtype=numpy.uint8) | ||||
|         assert_image(Image.fromarray(a[:, 1, :]), "L", TEST_IMAGE_SIZE) | ||||
|         size = (TEST_IMAGE_SIZE[0], TEST_IMAGE_SIZE[1], 5) | ||||
|         a = numpy.ones(size, dtype=numpy.uint8) | ||||
|         assert_image(Image.fromarray(a[:, :, 1]), "L", TEST_IMAGE_SIZE) | ||||
|     # Check 32-bit integer formats | ||||
|     assert_image(to_image(numpy.uint32), "I", TEST_IMAGE_SIZE) | ||||
|     assert_image(to_image(numpy.int32), "I", TEST_IMAGE_SIZE) | ||||
| 
 | ||||
|     def _test_img_equals_nparray(self, img, np): | ||||
|         self.assertGreaterEqual(len(np.shape), 2) | ||||
|         np_size = np.shape[1], np.shape[0] | ||||
|         self.assertEqual(img.size, np_size) | ||||
|         px = img.load() | ||||
|         for x in range(0, img.size[0], int(img.size[0] / 10)): | ||||
|             for y in range(0, img.size[1], int(img.size[1] / 10)): | ||||
|                 assert_deep_equal(px[x, y], np[y, x]) | ||||
|     # Check 64-bit integer formats | ||||
|     with pytest.raises(TypeError): | ||||
|         to_image(numpy.uint64) | ||||
|     with pytest.raises(TypeError): | ||||
|         to_image(numpy.int64) | ||||
| 
 | ||||
|     def test_16bit(self): | ||||
|         with Image.open("Tests/images/16bit.cropped.tif") as img: | ||||
|             np_img = numpy.array(img) | ||||
|             self._test_img_equals_nparray(img, np_img) | ||||
|         self.assertEqual(np_img.dtype, numpy.dtype("<u2")) | ||||
|     # Check floating-point formats | ||||
|     assert_image(to_image(numpy.float), "F", TEST_IMAGE_SIZE) | ||||
|     with pytest.raises(TypeError): | ||||
|         to_image(numpy.float16) | ||||
|     assert_image(to_image(numpy.float32), "F", TEST_IMAGE_SIZE) | ||||
|     assert_image(to_image(numpy.float64), "F", TEST_IMAGE_SIZE) | ||||
| 
 | ||||
|     def test_1bit(self): | ||||
|         # Test that 1-bit arrays convert to numpy and back | ||||
|         # See: https://github.com/python-pillow/Pillow/issues/350 | ||||
|         arr = numpy.array([[1, 0, 0, 1, 0], [0, 1, 0, 0, 0]], "u1") | ||||
|         img = Image.fromarray(arr * 255).convert("1") | ||||
|         self.assertEqual(img.mode, "1") | ||||
|         arr_back = numpy.array(img) | ||||
|         numpy.testing.assert_array_equal(arr, arr_back) | ||||
|     assert_image(to_image(numpy.uint8, 2), "LA", (10, 10)) | ||||
|     assert_image(to_image(numpy.uint8, 3), "RGB", (10, 10)) | ||||
|     assert_image(to_image(numpy.uint8, 4), "RGBA", (10, 10)) | ||||
| 
 | ||||
|     def test_save_tiff_uint16(self): | ||||
|         # Tests that we're getting the pixel value in the right byte order. | ||||
|         pixel_value = 0x1234 | ||||
|         a = numpy.array( | ||||
|             [pixel_value] * TEST_IMAGE_SIZE[0] * TEST_IMAGE_SIZE[1], dtype=numpy.uint16 | ||||
|         ) | ||||
|         a.shape = TEST_IMAGE_SIZE | ||||
|         img = Image.fromarray(a) | ||||
| 
 | ||||
|         img_px = img.load() | ||||
|         self.assertEqual(img_px[0, 0], pixel_value) | ||||
| # Based on an erring example at | ||||
| # https://stackoverflow.com/questions/10854903/what-is-causing-dimension-dependent-attributeerror-in-pil-fromarray-function | ||||
| def test_3d_array(): | ||||
|     size = (5, TEST_IMAGE_SIZE[0], TEST_IMAGE_SIZE[1]) | ||||
|     a = numpy.ones(size, dtype=numpy.uint8) | ||||
|     assert_image(Image.fromarray(a[1, :, :]), "L", TEST_IMAGE_SIZE) | ||||
|     size = (TEST_IMAGE_SIZE[0], 5, TEST_IMAGE_SIZE[1]) | ||||
|     a = numpy.ones(size, dtype=numpy.uint8) | ||||
|     assert_image(Image.fromarray(a[:, 1, :]), "L", TEST_IMAGE_SIZE) | ||||
|     size = (TEST_IMAGE_SIZE[0], TEST_IMAGE_SIZE[1], 5) | ||||
|     a = numpy.ones(size, dtype=numpy.uint8) | ||||
|     assert_image(Image.fromarray(a[:, :, 1]), "L", TEST_IMAGE_SIZE) | ||||
| 
 | ||||
|     def test_to_array(self): | ||||
|         def _to_array(mode, dtype): | ||||
|             img = hopper(mode) | ||||
| 
 | ||||
|             # Resize to non-square | ||||
|             img = img.crop((3, 0, 124, 127)) | ||||
|             self.assertEqual(img.size, (121, 127)) | ||||
| def _test_img_equals_nparray(img, np): | ||||
|     assert len(np.shape) >= 2 | ||||
|     np_size = np.shape[1], np.shape[0] | ||||
|     assert img.size == np_size | ||||
|     px = img.load() | ||||
|     for x in range(0, img.size[0], int(img.size[0] / 10)): | ||||
|         for y in range(0, img.size[1], int(img.size[1] / 10)): | ||||
|             assert_deep_equal(px[x, y], np[y, x]) | ||||
| 
 | ||||
|             np_img = numpy.array(img) | ||||
|             self._test_img_equals_nparray(img, np_img) | ||||
|             self.assertEqual(np_img.dtype, dtype) | ||||
| 
 | ||||
|         modes = [ | ||||
|             ("L", numpy.uint8), | ||||
|             ("I", numpy.int32), | ||||
|             ("F", numpy.float32), | ||||
|             ("LA", numpy.uint8), | ||||
|             ("RGB", numpy.uint8), | ||||
|             ("RGBA", numpy.uint8), | ||||
|             ("RGBX", numpy.uint8), | ||||
|             ("CMYK", numpy.uint8), | ||||
|             ("YCbCr", numpy.uint8), | ||||
|             ("I;16", "<u2"), | ||||
|             ("I;16B", ">u2"), | ||||
|             ("I;16L", "<u2"), | ||||
|             ("HSV", numpy.uint8), | ||||
|         ] | ||||
| def test_16bit(): | ||||
|     with Image.open("Tests/images/16bit.cropped.tif") as img: | ||||
|         np_img = numpy.array(img) | ||||
|         _test_img_equals_nparray(img, np_img) | ||||
|     assert np_img.dtype == numpy.dtype("<u2") | ||||
| 
 | ||||
|         for mode in modes: | ||||
|             _to_array(*mode) | ||||
| 
 | ||||
|     def test_point_lut(self): | ||||
|         # see https://github.com/python-pillow/Pillow/issues/439 | ||||
| def test_1bit(): | ||||
|     # Test that 1-bit arrays convert to numpy and back | ||||
|     # See: https://github.com/python-pillow/Pillow/issues/350 | ||||
|     arr = numpy.array([[1, 0, 0, 1, 0], [0, 1, 0, 0, 0]], "u1") | ||||
|     img = Image.fromarray(arr * 255).convert("1") | ||||
|     assert img.mode == "1" | ||||
|     arr_back = numpy.array(img) | ||||
|     numpy.testing.assert_array_equal(arr, arr_back) | ||||
| 
 | ||||
|         data = list(range(256)) * 3 | ||||
|         lut = numpy.array(data, dtype=numpy.uint8) | ||||
| 
 | ||||
|         im = hopper() | ||||
| def test_save_tiff_uint16(): | ||||
|     # Tests that we're getting the pixel value in the right byte order. | ||||
|     pixel_value = 0x1234 | ||||
|     a = numpy.array( | ||||
|         [pixel_value] * TEST_IMAGE_SIZE[0] * TEST_IMAGE_SIZE[1], dtype=numpy.uint16 | ||||
|     ) | ||||
|     a.shape = TEST_IMAGE_SIZE | ||||
|     img = Image.fromarray(a) | ||||
| 
 | ||||
|         im.point(lut) | ||||
|     img_px = img.load() | ||||
|     assert img_px[0, 0] == pixel_value | ||||
| 
 | ||||
|     def test_putdata(self): | ||||
|         # shouldn't segfault | ||||
|         # see https://github.com/python-pillow/Pillow/issues/1008 | ||||
| 
 | ||||
|         im = Image.new("F", (150, 100)) | ||||
|         arr = numpy.zeros((15000,), numpy.float32) | ||||
|         im.putdata(arr) | ||||
| def test_to_array(): | ||||
|     def _to_array(mode, dtype): | ||||
|         img = hopper(mode) | ||||
| 
 | ||||
|         self.assertEqual(len(im.getdata()), len(arr)) | ||||
|         # Resize to non-square | ||||
|         img = img.crop((3, 0, 124, 127)) | ||||
|         assert img.size == (121, 127) | ||||
| 
 | ||||
|     def test_roundtrip_eye(self): | ||||
|         for dtype in ( | ||||
|             numpy.bool, | ||||
|             numpy.bool8, | ||||
|             numpy.int8, | ||||
|             numpy.int16, | ||||
|             numpy.int32, | ||||
|             numpy.uint8, | ||||
|             numpy.uint16, | ||||
|             numpy.uint32, | ||||
|             numpy.float, | ||||
|             numpy.float32, | ||||
|             numpy.float64, | ||||
|         ): | ||||
|             arr = numpy.eye(10, dtype=dtype) | ||||
|             numpy.testing.assert_array_equal(arr, numpy.array(Image.fromarray(arr))) | ||||
|         np_img = numpy.array(img) | ||||
|         _test_img_equals_nparray(img, np_img) | ||||
|         assert np_img.dtype == dtype | ||||
| 
 | ||||
|     def test_zero_size(self): | ||||
|         # Shouldn't cause floating point exception | ||||
|         # See https://github.com/python-pillow/Pillow/issues/2259 | ||||
|     modes = [ | ||||
|         ("L", numpy.uint8), | ||||
|         ("I", numpy.int32), | ||||
|         ("F", numpy.float32), | ||||
|         ("LA", numpy.uint8), | ||||
|         ("RGB", numpy.uint8), | ||||
|         ("RGBA", numpy.uint8), | ||||
|         ("RGBX", numpy.uint8), | ||||
|         ("CMYK", numpy.uint8), | ||||
|         ("YCbCr", numpy.uint8), | ||||
|         ("I;16", "<u2"), | ||||
|         ("I;16B", ">u2"), | ||||
|         ("I;16L", "<u2"), | ||||
|         ("HSV", numpy.uint8), | ||||
|     ] | ||||
| 
 | ||||
|         im = Image.fromarray(numpy.empty((0, 0), dtype=numpy.uint8)) | ||||
|     for mode in modes: | ||||
|         _to_array(*mode) | ||||
| 
 | ||||
|         self.assertEqual(im.size, (0, 0)) | ||||
| 
 | ||||
|     def test_bool(self): | ||||
|         # https://github.com/python-pillow/Pillow/issues/2044 | ||||
|         a = numpy.zeros((10, 2), dtype=numpy.bool) | ||||
|         a[0][0] = True | ||||
| def test_point_lut(): | ||||
|     # See https://github.com/python-pillow/Pillow/issues/439 | ||||
| 
 | ||||
|         im2 = Image.fromarray(a) | ||||
|         self.assertEqual(im2.getdata()[0], 255) | ||||
|     data = list(range(256)) * 3 | ||||
|     lut = numpy.array(data, dtype=numpy.uint8) | ||||
| 
 | ||||
|     def test_no_resource_warning_for_numpy_array(self): | ||||
|         # https://github.com/python-pillow/Pillow/issues/835 | ||||
|         # Arrange | ||||
|         from numpy import array | ||||
|     im = hopper() | ||||
| 
 | ||||
|         test_file = "Tests/images/hopper.png" | ||||
|         with Image.open(test_file) as im: | ||||
|     im.point(lut) | ||||
| 
 | ||||
|             # Act/Assert | ||||
|             pytest.warns(None, lambda: array(im)) | ||||
| 
 | ||||
| def test_putdata(): | ||||
|     # Shouldn't segfault | ||||
|     # See https://github.com/python-pillow/Pillow/issues/1008 | ||||
| 
 | ||||
|     im = Image.new("F", (150, 100)) | ||||
|     arr = numpy.zeros((15000,), numpy.float32) | ||||
|     im.putdata(arr) | ||||
| 
 | ||||
|     assert len(im.getdata()) == len(arr) | ||||
| 
 | ||||
| 
 | ||||
| def test_roundtrip_eye(): | ||||
|     for dtype in ( | ||||
|         numpy.bool, | ||||
|         numpy.bool8, | ||||
|         numpy.int8, | ||||
|         numpy.int16, | ||||
|         numpy.int32, | ||||
|         numpy.uint8, | ||||
|         numpy.uint16, | ||||
|         numpy.uint32, | ||||
|         numpy.float, | ||||
|         numpy.float32, | ||||
|         numpy.float64, | ||||
|     ): | ||||
|         arr = numpy.eye(10, dtype=dtype) | ||||
|         numpy.testing.assert_array_equal(arr, numpy.array(Image.fromarray(arr))) | ||||
| 
 | ||||
| 
 | ||||
| def test_zero_size(): | ||||
|     # Shouldn't cause floating point exception | ||||
|     # See https://github.com/python-pillow/Pillow/issues/2259 | ||||
| 
 | ||||
|     im = Image.fromarray(numpy.empty((0, 0), dtype=numpy.uint8)) | ||||
| 
 | ||||
|     assert im.size == (0, 0) | ||||
| 
 | ||||
| 
 | ||||
| def test_bool(): | ||||
|     # https://github.com/python-pillow/Pillow/issues/2044 | ||||
|     a = numpy.zeros((10, 2), dtype=numpy.bool) | ||||
|     a[0][0] = True | ||||
| 
 | ||||
|     im2 = Image.fromarray(a) | ||||
|     assert im2.getdata()[0] == 255 | ||||
| 
 | ||||
| 
 | ||||
| def test_no_resource_warning_for_numpy_array(): | ||||
|     # https://github.com/python-pillow/Pillow/issues/835 | ||||
|     # Arrange | ||||
|     from numpy import array | ||||
| 
 | ||||
|     test_file = "Tests/images/hopper.png" | ||||
|     with Image.open(test_file) as im: | ||||
| 
 | ||||
|         # Act/Assert | ||||
|         pytest.warns(None, lambda: array(im)) | ||||
|  |  | |||
|  | @ -1,5 +1,6 @@ | |||
| import time | ||||
| 
 | ||||
| import pytest | ||||
| from PIL.PdfParser import ( | ||||
|     IndirectObjectDef, | ||||
|     IndirectReference, | ||||
|  | @ -14,127 +15,105 @@ from PIL.PdfParser import ( | |||
|     pdf_repr, | ||||
| ) | ||||
| 
 | ||||
| from .helper import PillowTestCase | ||||
| 
 | ||||
| def test_text_encode_decode(): | ||||
|     assert encode_text("abc") == b"\xFE\xFF\x00a\x00b\x00c" | ||||
|     assert decode_text(b"\xFE\xFF\x00a\x00b\x00c") == "abc" | ||||
|     assert decode_text(b"abc") == "abc" | ||||
|     assert decode_text(b"\x1B a \x1C") == "\u02D9 a \u02DD" | ||||
| 
 | ||||
| 
 | ||||
| class TestPdfParser(PillowTestCase): | ||||
|     def test_text_encode_decode(self): | ||||
|         self.assertEqual(encode_text("abc"), b"\xFE\xFF\x00a\x00b\x00c") | ||||
|         self.assertEqual(decode_text(b"\xFE\xFF\x00a\x00b\x00c"), "abc") | ||||
|         self.assertEqual(decode_text(b"abc"), "abc") | ||||
|         self.assertEqual(decode_text(b"\x1B a \x1C"), "\u02D9 a \u02DD") | ||||
| def test_indirect_refs(): | ||||
|     assert IndirectReference(1, 2) == IndirectReference(1, 2) | ||||
|     assert IndirectReference(1, 2) != IndirectReference(1, 3) | ||||
|     assert IndirectReference(1, 2) != IndirectObjectDef(1, 2) | ||||
|     assert IndirectReference(1, 2) != (1, 2) | ||||
|     assert IndirectObjectDef(1, 2) == IndirectObjectDef(1, 2) | ||||
|     assert IndirectObjectDef(1, 2) != IndirectObjectDef(1, 3) | ||||
|     assert IndirectObjectDef(1, 2) != IndirectReference(1, 2) | ||||
|     assert IndirectObjectDef(1, 2) != (1, 2) | ||||
| 
 | ||||
|     def test_indirect_refs(self): | ||||
|         self.assertEqual(IndirectReference(1, 2), IndirectReference(1, 2)) | ||||
|         self.assertNotEqual(IndirectReference(1, 2), IndirectReference(1, 3)) | ||||
|         self.assertNotEqual(IndirectReference(1, 2), IndirectObjectDef(1, 2)) | ||||
|         self.assertNotEqual(IndirectReference(1, 2), (1, 2)) | ||||
|         self.assertEqual(IndirectObjectDef(1, 2), IndirectObjectDef(1, 2)) | ||||
|         self.assertNotEqual(IndirectObjectDef(1, 2), IndirectObjectDef(1, 3)) | ||||
|         self.assertNotEqual(IndirectObjectDef(1, 2), IndirectReference(1, 2)) | ||||
|         self.assertNotEqual(IndirectObjectDef(1, 2), (1, 2)) | ||||
| 
 | ||||
|     def test_parsing(self): | ||||
|         self.assertEqual(PdfParser.interpret_name(b"Name#23Hash"), b"Name#Hash") | ||||
|         self.assertEqual( | ||||
|             PdfParser.interpret_name(b"Name#23Hash", as_text=True), "Name#Hash" | ||||
|         ) | ||||
|         self.assertEqual( | ||||
|             PdfParser.get_value(b"1 2 R ", 0), (IndirectReference(1, 2), 5) | ||||
|         ) | ||||
|         self.assertEqual(PdfParser.get_value(b"true[", 0), (True, 4)) | ||||
|         self.assertEqual(PdfParser.get_value(b"false%", 0), (False, 5)) | ||||
|         self.assertEqual(PdfParser.get_value(b"null<", 0), (None, 4)) | ||||
|         self.assertEqual(PdfParser.get_value(b"%cmt\n %cmt\n 123\n", 0), (123, 15)) | ||||
|         self.assertEqual(PdfParser.get_value(b"<901FA3>", 0), (b"\x90\x1F\xA3", 8)) | ||||
|         self.assertEqual( | ||||
|             PdfParser.get_value(b"asd < 9 0 1 f A > qwe", 3), (b"\x90\x1F\xA0", 17) | ||||
|         ) | ||||
|         self.assertEqual(PdfParser.get_value(b"(asd)", 0), (b"asd", 5)) | ||||
|         self.assertEqual( | ||||
|             PdfParser.get_value(b"(asd(qwe)zxc)zzz(aaa)", 0), (b"asd(qwe)zxc", 13) | ||||
|         ) | ||||
|         self.assertEqual( | ||||
|             PdfParser.get_value(b"(Two \\\nwords.)", 0), (b"Two words.", 14) | ||||
|         ) | ||||
|         self.assertEqual(PdfParser.get_value(b"(Two\nlines.)", 0), (b"Two\nlines.", 12)) | ||||
|         self.assertEqual( | ||||
|             PdfParser.get_value(b"(Two\r\nlines.)", 0), (b"Two\nlines.", 13) | ||||
|         ) | ||||
|         self.assertEqual( | ||||
|             PdfParser.get_value(b"(Two\\nlines.)", 0), (b"Two\nlines.", 13) | ||||
|         ) | ||||
|         self.assertEqual(PdfParser.get_value(b"(One\\(paren).", 0), (b"One(paren", 12)) | ||||
|         self.assertEqual(PdfParser.get_value(b"(One\\)paren).", 0), (b"One)paren", 12)) | ||||
|         self.assertEqual(PdfParser.get_value(b"(\\0053)", 0), (b"\x053", 7)) | ||||
|         self.assertEqual(PdfParser.get_value(b"(\\053)", 0), (b"\x2B", 6)) | ||||
|         self.assertEqual(PdfParser.get_value(b"(\\53)", 0), (b"\x2B", 5)) | ||||
|         self.assertEqual(PdfParser.get_value(b"(\\53a)", 0), (b"\x2Ba", 6)) | ||||
|         self.assertEqual(PdfParser.get_value(b"(\\1111)", 0), (b"\x491", 7)) | ||||
|         self.assertEqual(PdfParser.get_value(b" 123 (", 0), (123, 4)) | ||||
|         self.assertAlmostEqual(PdfParser.get_value(b" 123.4 %", 0)[0], 123.4) | ||||
|         self.assertEqual(PdfParser.get_value(b" 123.4 %", 0)[1], 6) | ||||
|         self.assertRaises(PdfFormatError, PdfParser.get_value, b"]", 0) | ||||
|         d = PdfParser.get_value(b"<</Name (value) /N /V>>", 0)[0] | ||||
|         self.assertIsInstance(d, PdfDict) | ||||
|         self.assertEqual(len(d), 2) | ||||
|         self.assertEqual(d.Name, "value") | ||||
|         self.assertEqual(d[b"Name"], b"value") | ||||
|         self.assertEqual(d.N, PdfName("V")) | ||||
|         a = PdfParser.get_value(b"[/Name (value) /N /V]", 0)[0] | ||||
|         self.assertIsInstance(a, list) | ||||
|         self.assertEqual(len(a), 4) | ||||
|         self.assertEqual(a[0], PdfName("Name")) | ||||
|         s = PdfParser.get_value( | ||||
|             b"<</Name (value) /Length 5>>\nstream\nabcde\nendstream<<...", 0 | ||||
|         )[0] | ||||
|         self.assertIsInstance(s, PdfStream) | ||||
|         self.assertEqual(s.dictionary.Name, "value") | ||||
|         self.assertEqual(s.decode(), b"abcde") | ||||
|         for name in ["CreationDate", "ModDate"]: | ||||
|             for date, value in { | ||||
|                 b"20180729214124": "20180729214124", | ||||
|                 b"D:20180729214124": "20180729214124", | ||||
|                 b"D:2018072921": "20180729210000", | ||||
|                 b"D:20180729214124Z": "20180729214124", | ||||
|                 b"D:20180729214124+08'00'": "20180729134124", | ||||
|                 b"D:20180729214124-05'00'": "20180730024124", | ||||
|             }.items(): | ||||
|                 d = PdfParser.get_value( | ||||
|                     b"<</" + name.encode() + b" (" + date + b")>>", 0 | ||||
|                 )[0] | ||||
|                 self.assertEqual(time.strftime("%Y%m%d%H%M%S", getattr(d, name)), value) | ||||
| def test_parsing(): | ||||
|     assert PdfParser.interpret_name(b"Name#23Hash") == b"Name#Hash" | ||||
|     assert PdfParser.interpret_name(b"Name#23Hash", as_text=True) == "Name#Hash" | ||||
|     assert PdfParser.get_value(b"1 2 R ", 0) == (IndirectReference(1, 2), 5) | ||||
|     assert PdfParser.get_value(b"true[", 0) == (True, 4) | ||||
|     assert PdfParser.get_value(b"false%", 0) == (False, 5) | ||||
|     assert PdfParser.get_value(b"null<", 0) == (None, 4) | ||||
|     assert PdfParser.get_value(b"%cmt\n %cmt\n 123\n", 0) == (123, 15) | ||||
|     assert PdfParser.get_value(b"<901FA3>", 0) == (b"\x90\x1F\xA3", 8) | ||||
|     assert PdfParser.get_value(b"asd < 9 0 1 f A > qwe", 3) == (b"\x90\x1F\xA0", 17) | ||||
|     assert PdfParser.get_value(b"(asd)", 0) == (b"asd", 5) | ||||
|     assert PdfParser.get_value(b"(asd(qwe)zxc)zzz(aaa)", 0) == (b"asd(qwe)zxc", 13) | ||||
|     assert PdfParser.get_value(b"(Two \\\nwords.)", 0) == (b"Two words.", 14) | ||||
|     assert PdfParser.get_value(b"(Two\nlines.)", 0) == (b"Two\nlines.", 12) | ||||
|     assert PdfParser.get_value(b"(Two\r\nlines.)", 0) == (b"Two\nlines.", 13) | ||||
|     assert PdfParser.get_value(b"(Two\\nlines.)", 0) == (b"Two\nlines.", 13) | ||||
|     assert PdfParser.get_value(b"(One\\(paren).", 0) == (b"One(paren", 12) | ||||
|     assert PdfParser.get_value(b"(One\\)paren).", 0) == (b"One)paren", 12) | ||||
|     assert PdfParser.get_value(b"(\\0053)", 0) == (b"\x053", 7) | ||||
|     assert PdfParser.get_value(b"(\\053)", 0) == (b"\x2B", 6) | ||||
|     assert PdfParser.get_value(b"(\\53)", 0) == (b"\x2B", 5) | ||||
|     assert PdfParser.get_value(b"(\\53a)", 0) == (b"\x2Ba", 6) | ||||
|     assert PdfParser.get_value(b"(\\1111)", 0) == (b"\x491", 7) | ||||
|     assert PdfParser.get_value(b" 123 (", 0) == (123, 4) | ||||
|     assert round(abs(PdfParser.get_value(b" 123.4 %", 0)[0] - 123.4), 7) == 0 | ||||
|     assert PdfParser.get_value(b" 123.4 %", 0)[1] == 6 | ||||
|     with pytest.raises(PdfFormatError): | ||||
|         PdfParser.get_value(b"]", 0) | ||||
|     d = PdfParser.get_value(b"<</Name (value) /N /V>>", 0)[0] | ||||
|     assert isinstance(d, PdfDict) | ||||
|     assert len(d) == 2 | ||||
|     assert d.Name == "value" | ||||
|     assert d[b"Name"] == b"value" | ||||
|     assert d.N == PdfName("V") | ||||
|     a = PdfParser.get_value(b"[/Name (value) /N /V]", 0)[0] | ||||
|     assert isinstance(a, list) | ||||
|     assert len(a) == 4 | ||||
|     assert a[0] == PdfName("Name") | ||||
|     s = PdfParser.get_value( | ||||
|         b"<</Name (value) /Length 5>>\nstream\nabcde\nendstream<<...", 0 | ||||
|     )[0] | ||||
|     assert isinstance(s, PdfStream) | ||||
|     assert s.dictionary.Name == "value" | ||||
|     assert s.decode() == b"abcde" | ||||
|     for name in ["CreationDate", "ModDate"]: | ||||
|         for date, value in { | ||||
|             b"20180729214124": "20180729214124", | ||||
|             b"D:20180729214124": "20180729214124", | ||||
|             b"D:2018072921": "20180729210000", | ||||
|             b"D:20180729214124Z": "20180729214124", | ||||
|             b"D:20180729214124+08'00'": "20180729134124", | ||||
|             b"D:20180729214124-05'00'": "20180730024124", | ||||
|         }.items(): | ||||
|             d = PdfParser.get_value(b"<</" + name.encode() + b" (" + date + b")>>", 0)[ | ||||
|                 0 | ||||
|             ] | ||||
|             assert time.strftime("%Y%m%d%H%M%S", getattr(d, name)) == value | ||||
| 
 | ||||
|     def test_pdf_repr(self): | ||||
|         self.assertEqual(bytes(IndirectReference(1, 2)), b"1 2 R") | ||||
|         self.assertEqual(bytes(IndirectObjectDef(*IndirectReference(1, 2))), b"1 2 obj") | ||||
|         self.assertEqual(bytes(PdfName(b"Name#Hash")), b"/Name#23Hash") | ||||
|         self.assertEqual(bytes(PdfName("Name#Hash")), b"/Name#23Hash") | ||||
|         self.assertEqual( | ||||
|             bytes(PdfDict({b"Name": IndirectReference(1, 2)})), b"<<\n/Name 1 2 R\n>>" | ||||
|         ) | ||||
|         self.assertEqual( | ||||
|             bytes(PdfDict({"Name": IndirectReference(1, 2)})), b"<<\n/Name 1 2 R\n>>" | ||||
|         ) | ||||
|         self.assertEqual(pdf_repr(IndirectReference(1, 2)), b"1 2 R") | ||||
|         self.assertEqual( | ||||
|             pdf_repr(IndirectObjectDef(*IndirectReference(1, 2))), b"1 2 obj" | ||||
|         ) | ||||
|         self.assertEqual(pdf_repr(PdfName(b"Name#Hash")), b"/Name#23Hash") | ||||
|         self.assertEqual(pdf_repr(PdfName("Name#Hash")), b"/Name#23Hash") | ||||
|         self.assertEqual( | ||||
|             pdf_repr(PdfDict({b"Name": IndirectReference(1, 2)})), | ||||
|             b"<<\n/Name 1 2 R\n>>", | ||||
|         ) | ||||
|         self.assertEqual( | ||||
|             pdf_repr(PdfDict({"Name": IndirectReference(1, 2)})), b"<<\n/Name 1 2 R\n>>" | ||||
|         ) | ||||
|         self.assertEqual(pdf_repr(123), b"123") | ||||
|         self.assertEqual(pdf_repr(True), b"true") | ||||
|         self.assertEqual(pdf_repr(False), b"false") | ||||
|         self.assertEqual(pdf_repr(None), b"null") | ||||
|         self.assertEqual(pdf_repr(b"a)/b\\(c"), br"(a\)/b\\\(c)") | ||||
|         self.assertEqual( | ||||
|             pdf_repr([123, True, {"a": PdfName(b"b")}]), b"[ 123 true <<\n/a /b\n>> ]" | ||||
|         ) | ||||
|         self.assertEqual(pdf_repr(PdfBinary(b"\x90\x1F\xA0")), b"<901FA0>") | ||||
| 
 | ||||
| def test_pdf_repr(): | ||||
|     assert bytes(IndirectReference(1, 2)) == b"1 2 R" | ||||
|     assert bytes(IndirectObjectDef(*IndirectReference(1, 2))) == b"1 2 obj" | ||||
|     assert bytes(PdfName(b"Name#Hash")) == b"/Name#23Hash" | ||||
|     assert bytes(PdfName("Name#Hash")) == b"/Name#23Hash" | ||||
|     assert bytes(PdfDict({b"Name": IndirectReference(1, 2)})) == b"<<\n/Name 1 2 R\n>>" | ||||
|     assert bytes(PdfDict({"Name": IndirectReference(1, 2)})) == b"<<\n/Name 1 2 R\n>>" | ||||
|     assert pdf_repr(IndirectReference(1, 2)) == b"1 2 R" | ||||
|     assert pdf_repr(IndirectObjectDef(*IndirectReference(1, 2))) == b"1 2 obj" | ||||
|     assert pdf_repr(PdfName(b"Name#Hash")) == b"/Name#23Hash" | ||||
|     assert pdf_repr(PdfName("Name#Hash")) == b"/Name#23Hash" | ||||
|     assert ( | ||||
|         pdf_repr(PdfDict({b"Name": IndirectReference(1, 2)})) == b"<<\n/Name 1 2 R\n>>" | ||||
|     ) | ||||
|     assert ( | ||||
|         pdf_repr(PdfDict({"Name": IndirectReference(1, 2)})) == b"<<\n/Name 1 2 R\n>>" | ||||
|     ) | ||||
|     assert pdf_repr(123) == b"123" | ||||
|     assert pdf_repr(True) == b"true" | ||||
|     assert pdf_repr(False) == b"false" | ||||
|     assert pdf_repr(None) == b"null" | ||||
|     assert pdf_repr(b"a)/b\\(c") == br"(a\)/b\\\(c)" | ||||
|     assert pdf_repr([123, True, {"a": PdfName(b"b")}]) == b"[ 123 true <<\n/a /b\n>> ]" | ||||
|     assert pdf_repr(PdfBinary(b"\x90\x1F\xA0")) == b"<901FA0>" | ||||
|  |  | |||
		Loading…
	
		Reference in New Issue
	
	Block a user