mirror of
				https://github.com/python-pillow/Pillow.git
				synced 2025-11-04 01:47:47 +03:00 
			
		
		
		
	Autotype tests (#7756)
* autotyping: --none-return * autotyping: --scalar-return * autotyping: --int-param * autotyping: --float-param * autotyping: --str-param * autotyping: --annotate-named-param tmp_path:pathlib.Path
This commit is contained in:
		
							parent
							
								
									db437386eb
								
							
						
					
					
						commit
						4a4b90c365
					
				| 
						 | 
					@ -9,21 +9,21 @@ from .helper import hopper
 | 
				
			||||||
# Not running this test by default. No DOS against CI.
 | 
					# Not running this test by default. No DOS against CI.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def iterate_get(size, access):
 | 
					def iterate_get(size, access) -> None:
 | 
				
			||||||
    (w, h) = size
 | 
					    (w, h) = size
 | 
				
			||||||
    for x in range(w):
 | 
					    for x in range(w):
 | 
				
			||||||
        for y in range(h):
 | 
					        for y in range(h):
 | 
				
			||||||
            access[(x, y)]
 | 
					            access[(x, y)]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def iterate_set(size, access):
 | 
					def iterate_set(size, access) -> None:
 | 
				
			||||||
    (w, h) = size
 | 
					    (w, h) = size
 | 
				
			||||||
    for x in range(w):
 | 
					    for x in range(w):
 | 
				
			||||||
        for y in range(h):
 | 
					        for y in range(h):
 | 
				
			||||||
            access[(x, y)] = (x % 256, y % 256, 0)
 | 
					            access[(x, y)] = (x % 256, y % 256, 0)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def timer(func, label, *args):
 | 
					def timer(func, label, *args) -> None:
 | 
				
			||||||
    iterations = 5000
 | 
					    iterations = 5000
 | 
				
			||||||
    starttime = time.time()
 | 
					    starttime = time.time()
 | 
				
			||||||
    for x in range(iterations):
 | 
					    for x in range(iterations):
 | 
				
			||||||
| 
						 | 
					@ -38,7 +38,7 @@ def timer(func, label, *args):
 | 
				
			||||||
    )
 | 
					    )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_direct():
 | 
					def test_direct() -> None:
 | 
				
			||||||
    im = hopper()
 | 
					    im = hopper()
 | 
				
			||||||
    im.load()
 | 
					    im.load()
 | 
				
			||||||
    # im = Image.new("RGB", (2000, 2000), (1, 3, 2))
 | 
					    # im = Image.new("RGB", (2000, 2000), (1, 3, 2))
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -10,13 +10,13 @@ from .helper import assert_image_similar
 | 
				
			||||||
base = os.path.join("Tests", "images", "bmp")
 | 
					base = os.path.join("Tests", "images", "bmp")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def get_files(d, ext=".bmp"):
 | 
					def get_files(d, ext: str = ".bmp"):
 | 
				
			||||||
    return [
 | 
					    return [
 | 
				
			||||||
        os.path.join(base, d, f) for f in os.listdir(os.path.join(base, d)) if ext in f
 | 
					        os.path.join(base, d, f) for f in os.listdir(os.path.join(base, d)) if ext in f
 | 
				
			||||||
    ]
 | 
					    ]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_bad():
 | 
					def test_bad() -> None:
 | 
				
			||||||
    """These shouldn't crash/dos, but they shouldn't return anything
 | 
					    """These shouldn't crash/dos, but they shouldn't return anything
 | 
				
			||||||
    either"""
 | 
					    either"""
 | 
				
			||||||
    for f in get_files("b"):
 | 
					    for f in get_files("b"):
 | 
				
			||||||
| 
						 | 
					@ -56,7 +56,7 @@ def test_questionable():
 | 
				
			||||||
                raise
 | 
					                raise
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_good():
 | 
					def test_good() -> None:
 | 
				
			||||||
    """These should all work. There's a set of target files in the
 | 
					    """These should all work. There's a set of target files in the
 | 
				
			||||||
    html directory that we can compare against."""
 | 
					    html directory that we can compare against."""
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -16,18 +16,18 @@ sample.putdata(sum([
 | 
				
			||||||
# fmt: on
 | 
					# fmt: on
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_imageops_box_blur():
 | 
					def test_imageops_box_blur() -> None:
 | 
				
			||||||
    i = sample.filter(ImageFilter.BoxBlur(1))
 | 
					    i = sample.filter(ImageFilter.BoxBlur(1))
 | 
				
			||||||
    assert i.mode == sample.mode
 | 
					    assert i.mode == sample.mode
 | 
				
			||||||
    assert i.size == sample.size
 | 
					    assert i.size == sample.size
 | 
				
			||||||
    assert isinstance(i, Image.Image)
 | 
					    assert isinstance(i, Image.Image)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def box_blur(image, radius=1, n=1):
 | 
					def box_blur(image, radius: int = 1, n: int = 1):
 | 
				
			||||||
    return image._new(image.im.box_blur((radius, radius), n))
 | 
					    return image._new(image.im.box_blur((radius, radius), n))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def assert_image(im, data, delta=0):
 | 
					def assert_image(im, data, delta: int = 0) -> None:
 | 
				
			||||||
    it = iter(im.getdata())
 | 
					    it = iter(im.getdata())
 | 
				
			||||||
    for data_row in data:
 | 
					    for data_row in data:
 | 
				
			||||||
        im_row = [next(it) for _ in range(im.size[0])]
 | 
					        im_row = [next(it) for _ in range(im.size[0])]
 | 
				
			||||||
| 
						 | 
					@ -37,7 +37,7 @@ def assert_image(im, data, delta=0):
 | 
				
			||||||
        next(it)
 | 
					        next(it)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def assert_blur(im, radius, data, passes=1, delta=0):
 | 
					def assert_blur(im, radius, data, passes: int = 1, delta: int = 0) -> None:
 | 
				
			||||||
    # check grayscale image
 | 
					    # check grayscale image
 | 
				
			||||||
    assert_image(box_blur(im, radius, passes), data, delta)
 | 
					    assert_image(box_blur(im, radius, passes), data, delta)
 | 
				
			||||||
    rgba = Image.merge("RGBA", (im, im, im, im))
 | 
					    rgba = Image.merge("RGBA", (im, im, im, im))
 | 
				
			||||||
| 
						 | 
					@ -45,7 +45,7 @@ def assert_blur(im, radius, data, passes=1, delta=0):
 | 
				
			||||||
        assert_image(band, data, delta)
 | 
					        assert_image(band, data, delta)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_color_modes():
 | 
					def test_color_modes() -> None:
 | 
				
			||||||
    with pytest.raises(ValueError):
 | 
					    with pytest.raises(ValueError):
 | 
				
			||||||
        box_blur(sample.convert("1"))
 | 
					        box_blur(sample.convert("1"))
 | 
				
			||||||
    with pytest.raises(ValueError):
 | 
					    with pytest.raises(ValueError):
 | 
				
			||||||
| 
						 | 
					@ -65,7 +65,7 @@ def test_color_modes():
 | 
				
			||||||
        box_blur(sample.convert("YCbCr"))
 | 
					        box_blur(sample.convert("YCbCr"))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_radius_0():
 | 
					def test_radius_0() -> None:
 | 
				
			||||||
    assert_blur(
 | 
					    assert_blur(
 | 
				
			||||||
        sample,
 | 
					        sample,
 | 
				
			||||||
        0,
 | 
					        0,
 | 
				
			||||||
| 
						 | 
					@ -81,7 +81,7 @@ def test_radius_0():
 | 
				
			||||||
    )
 | 
					    )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_radius_0_02():
 | 
					def test_radius_0_02() -> None:
 | 
				
			||||||
    assert_blur(
 | 
					    assert_blur(
 | 
				
			||||||
        sample,
 | 
					        sample,
 | 
				
			||||||
        0.02,
 | 
					        0.02,
 | 
				
			||||||
| 
						 | 
					@ -98,7 +98,7 @@ def test_radius_0_02():
 | 
				
			||||||
    )
 | 
					    )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_radius_0_05():
 | 
					def test_radius_0_05() -> None:
 | 
				
			||||||
    assert_blur(
 | 
					    assert_blur(
 | 
				
			||||||
        sample,
 | 
					        sample,
 | 
				
			||||||
        0.05,
 | 
					        0.05,
 | 
				
			||||||
| 
						 | 
					@ -115,7 +115,7 @@ def test_radius_0_05():
 | 
				
			||||||
    )
 | 
					    )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_radius_0_1():
 | 
					def test_radius_0_1() -> None:
 | 
				
			||||||
    assert_blur(
 | 
					    assert_blur(
 | 
				
			||||||
        sample,
 | 
					        sample,
 | 
				
			||||||
        0.1,
 | 
					        0.1,
 | 
				
			||||||
| 
						 | 
					@ -132,7 +132,7 @@ def test_radius_0_1():
 | 
				
			||||||
    )
 | 
					    )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_radius_0_5():
 | 
					def test_radius_0_5() -> None:
 | 
				
			||||||
    assert_blur(
 | 
					    assert_blur(
 | 
				
			||||||
        sample,
 | 
					        sample,
 | 
				
			||||||
        0.5,
 | 
					        0.5,
 | 
				
			||||||
| 
						 | 
					@ -149,7 +149,7 @@ def test_radius_0_5():
 | 
				
			||||||
    )
 | 
					    )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_radius_1():
 | 
					def test_radius_1() -> None:
 | 
				
			||||||
    assert_blur(
 | 
					    assert_blur(
 | 
				
			||||||
        sample,
 | 
					        sample,
 | 
				
			||||||
        1,
 | 
					        1,
 | 
				
			||||||
| 
						 | 
					@ -166,7 +166,7 @@ def test_radius_1():
 | 
				
			||||||
    )
 | 
					    )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_radius_1_5():
 | 
					def test_radius_1_5() -> None:
 | 
				
			||||||
    assert_blur(
 | 
					    assert_blur(
 | 
				
			||||||
        sample,
 | 
					        sample,
 | 
				
			||||||
        1.5,
 | 
					        1.5,
 | 
				
			||||||
| 
						 | 
					@ -183,7 +183,7 @@ def test_radius_1_5():
 | 
				
			||||||
    )
 | 
					    )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_radius_bigger_then_half():
 | 
					def test_radius_bigger_then_half() -> None:
 | 
				
			||||||
    assert_blur(
 | 
					    assert_blur(
 | 
				
			||||||
        sample,
 | 
					        sample,
 | 
				
			||||||
        3,
 | 
					        3,
 | 
				
			||||||
| 
						 | 
					@ -200,7 +200,7 @@ def test_radius_bigger_then_half():
 | 
				
			||||||
    )
 | 
					    )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_radius_bigger_then_width():
 | 
					def test_radius_bigger_then_width() -> None:
 | 
				
			||||||
    assert_blur(
 | 
					    assert_blur(
 | 
				
			||||||
        sample,
 | 
					        sample,
 | 
				
			||||||
        10,
 | 
					        10,
 | 
				
			||||||
| 
						 | 
					@ -215,7 +215,7 @@ def test_radius_bigger_then_width():
 | 
				
			||||||
    )
 | 
					    )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_extreme_large_radius():
 | 
					def test_extreme_large_radius() -> None:
 | 
				
			||||||
    assert_blur(
 | 
					    assert_blur(
 | 
				
			||||||
        sample,
 | 
					        sample,
 | 
				
			||||||
        600,
 | 
					        600,
 | 
				
			||||||
| 
						 | 
					@ -230,7 +230,7 @@ def test_extreme_large_radius():
 | 
				
			||||||
    )
 | 
					    )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_two_passes():
 | 
					def test_two_passes() -> None:
 | 
				
			||||||
    assert_blur(
 | 
					    assert_blur(
 | 
				
			||||||
        sample,
 | 
					        sample,
 | 
				
			||||||
        1,
 | 
					        1,
 | 
				
			||||||
| 
						 | 
					@ -248,7 +248,7 @@ def test_two_passes():
 | 
				
			||||||
    )
 | 
					    )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_three_passes():
 | 
					def test_three_passes() -> None:
 | 
				
			||||||
    assert_blur(
 | 
					    assert_blur(
 | 
				
			||||||
        sample,
 | 
					        sample,
 | 
				
			||||||
        1,
 | 
					        1,
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -41,7 +41,7 @@ class TestColorLut3DCoreAPI:
 | 
				
			||||||
            [item for sublist in table for item in sublist],
 | 
					            [item for sublist in table for item in sublist],
 | 
				
			||||||
        )
 | 
					        )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_wrong_args(self):
 | 
					    def test_wrong_args(self) -> None:
 | 
				
			||||||
        im = Image.new("RGB", (10, 10), 0)
 | 
					        im = Image.new("RGB", (10, 10), 0)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        with pytest.raises(ValueError, match="filter"):
 | 
					        with pytest.raises(ValueError, match="filter"):
 | 
				
			||||||
| 
						 | 
					@ -101,7 +101,7 @@ class TestColorLut3DCoreAPI:
 | 
				
			||||||
        with pytest.raises(TypeError):
 | 
					        with pytest.raises(TypeError):
 | 
				
			||||||
            im.im.color_lut_3d("RGB", Image.Resampling.BILINEAR, 3, 2, 2, 2, 16)
 | 
					            im.im.color_lut_3d("RGB", Image.Resampling.BILINEAR, 3, 2, 2, 2, 16)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_correct_args(self):
 | 
					    def test_correct_args(self) -> None:
 | 
				
			||||||
        im = Image.new("RGB", (10, 10), 0)
 | 
					        im = Image.new("RGB", (10, 10), 0)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        im.im.color_lut_3d(
 | 
					        im.im.color_lut_3d(
 | 
				
			||||||
| 
						 | 
					@ -136,7 +136,7 @@ class TestColorLut3DCoreAPI:
 | 
				
			||||||
            *self.generate_identity_table(3, (3, 3, 65)),
 | 
					            *self.generate_identity_table(3, (3, 3, 65)),
 | 
				
			||||||
        )
 | 
					        )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_wrong_mode(self):
 | 
					    def test_wrong_mode(self) -> None:
 | 
				
			||||||
        with pytest.raises(ValueError, match="wrong mode"):
 | 
					        with pytest.raises(ValueError, match="wrong mode"):
 | 
				
			||||||
            im = Image.new("L", (10, 10), 0)
 | 
					            im = Image.new("L", (10, 10), 0)
 | 
				
			||||||
            im.im.color_lut_3d(
 | 
					            im.im.color_lut_3d(
 | 
				
			||||||
| 
						 | 
					@ -167,7 +167,7 @@ class TestColorLut3DCoreAPI:
 | 
				
			||||||
                "RGB", Image.Resampling.BILINEAR, *self.generate_identity_table(4, 3)
 | 
					                "RGB", Image.Resampling.BILINEAR, *self.generate_identity_table(4, 3)
 | 
				
			||||||
            )
 | 
					            )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_correct_mode(self):
 | 
					    def test_correct_mode(self) -> None:
 | 
				
			||||||
        im = Image.new("RGBA", (10, 10), 0)
 | 
					        im = Image.new("RGBA", (10, 10), 0)
 | 
				
			||||||
        im.im.color_lut_3d(
 | 
					        im.im.color_lut_3d(
 | 
				
			||||||
            "RGBA", Image.Resampling.BILINEAR, *self.generate_identity_table(3, 3)
 | 
					            "RGBA", Image.Resampling.BILINEAR, *self.generate_identity_table(3, 3)
 | 
				
			||||||
| 
						 | 
					@ -188,7 +188,7 @@ class TestColorLut3DCoreAPI:
 | 
				
			||||||
            "RGBA", Image.Resampling.BILINEAR, *self.generate_identity_table(4, 3)
 | 
					            "RGBA", Image.Resampling.BILINEAR, *self.generate_identity_table(4, 3)
 | 
				
			||||||
        )
 | 
					        )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_identities(self):
 | 
					    def test_identities(self) -> None:
 | 
				
			||||||
        g = Image.linear_gradient("L")
 | 
					        g = Image.linear_gradient("L")
 | 
				
			||||||
        im = Image.merge(
 | 
					        im = Image.merge(
 | 
				
			||||||
            "RGB",
 | 
					            "RGB",
 | 
				
			||||||
| 
						 | 
					@ -224,7 +224,7 @@ class TestColorLut3DCoreAPI:
 | 
				
			||||||
            ),
 | 
					            ),
 | 
				
			||||||
        )
 | 
					        )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_identities_4_channels(self):
 | 
					    def test_identities_4_channels(self) -> None:
 | 
				
			||||||
        g = Image.linear_gradient("L")
 | 
					        g = Image.linear_gradient("L")
 | 
				
			||||||
        im = Image.merge(
 | 
					        im = Image.merge(
 | 
				
			||||||
            "RGB",
 | 
					            "RGB",
 | 
				
			||||||
| 
						 | 
					@ -247,7 +247,7 @@ class TestColorLut3DCoreAPI:
 | 
				
			||||||
            ),
 | 
					            ),
 | 
				
			||||||
        )
 | 
					        )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_copy_alpha_channel(self):
 | 
					    def test_copy_alpha_channel(self) -> None:
 | 
				
			||||||
        g = Image.linear_gradient("L")
 | 
					        g = Image.linear_gradient("L")
 | 
				
			||||||
        im = Image.merge(
 | 
					        im = Image.merge(
 | 
				
			||||||
            "RGBA",
 | 
					            "RGBA",
 | 
				
			||||||
| 
						 | 
					@ -270,7 +270,7 @@ class TestColorLut3DCoreAPI:
 | 
				
			||||||
            ),
 | 
					            ),
 | 
				
			||||||
        )
 | 
					        )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_channels_order(self):
 | 
					    def test_channels_order(self) -> None:
 | 
				
			||||||
        g = Image.linear_gradient("L")
 | 
					        g = Image.linear_gradient("L")
 | 
				
			||||||
        im = Image.merge(
 | 
					        im = Image.merge(
 | 
				
			||||||
            "RGB",
 | 
					            "RGB",
 | 
				
			||||||
| 
						 | 
					@ -295,7 +295,7 @@ class TestColorLut3DCoreAPI:
 | 
				
			||||||
                    ])))
 | 
					                    ])))
 | 
				
			||||||
        # fmt: on
 | 
					        # fmt: on
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_overflow(self):
 | 
					    def test_overflow(self) -> None:
 | 
				
			||||||
        g = Image.linear_gradient("L")
 | 
					        g = Image.linear_gradient("L")
 | 
				
			||||||
        im = Image.merge(
 | 
					        im = Image.merge(
 | 
				
			||||||
            "RGB",
 | 
					            "RGB",
 | 
				
			||||||
| 
						 | 
					@ -348,7 +348,7 @@ class TestColorLut3DCoreAPI:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class TestColorLut3DFilter:
 | 
					class TestColorLut3DFilter:
 | 
				
			||||||
    def test_wrong_args(self):
 | 
					    def test_wrong_args(self) -> None:
 | 
				
			||||||
        with pytest.raises(ValueError, match="should be either an integer"):
 | 
					        with pytest.raises(ValueError, match="should be either an integer"):
 | 
				
			||||||
            ImageFilter.Color3DLUT("small", [1])
 | 
					            ImageFilter.Color3DLUT("small", [1])
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -376,7 +376,7 @@ class TestColorLut3DFilter:
 | 
				
			||||||
        with pytest.raises(ValueError, match="Only 3 or 4 output"):
 | 
					        with pytest.raises(ValueError, match="Only 3 or 4 output"):
 | 
				
			||||||
            ImageFilter.Color3DLUT((2, 2, 2), [[1, 1]] * 8, channels=2)
 | 
					            ImageFilter.Color3DLUT((2, 2, 2), [[1, 1]] * 8, channels=2)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_convert_table(self):
 | 
					    def test_convert_table(self) -> None:
 | 
				
			||||||
        lut = ImageFilter.Color3DLUT(2, [0, 1, 2] * 8)
 | 
					        lut = ImageFilter.Color3DLUT(2, [0, 1, 2] * 8)
 | 
				
			||||||
        assert tuple(lut.size) == (2, 2, 2)
 | 
					        assert tuple(lut.size) == (2, 2, 2)
 | 
				
			||||||
        assert lut.name == "Color 3D LUT"
 | 
					        assert lut.name == "Color 3D LUT"
 | 
				
			||||||
| 
						 | 
					@ -394,7 +394,7 @@ class TestColorLut3DFilter:
 | 
				
			||||||
        assert lut.table == list(range(4)) * 8
 | 
					        assert lut.table == list(range(4)) * 8
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    @pytest.mark.skipif(numpy is None, reason="NumPy not installed")
 | 
					    @pytest.mark.skipif(numpy is None, reason="NumPy not installed")
 | 
				
			||||||
    def test_numpy_sources(self):
 | 
					    def test_numpy_sources(self) -> None:
 | 
				
			||||||
        table = numpy.ones((5, 6, 7, 3), dtype=numpy.float16)
 | 
					        table = numpy.ones((5, 6, 7, 3), dtype=numpy.float16)
 | 
				
			||||||
        with pytest.raises(ValueError, match="should have either channels"):
 | 
					        with pytest.raises(ValueError, match="should have either channels"):
 | 
				
			||||||
            lut = ImageFilter.Color3DLUT((5, 6, 7), table)
 | 
					            lut = ImageFilter.Color3DLUT((5, 6, 7), table)
 | 
				
			||||||
| 
						 | 
					@ -427,7 +427,7 @@ class TestColorLut3DFilter:
 | 
				
			||||||
        assert lut.table[0] == 33
 | 
					        assert lut.table[0] == 33
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    @pytest.mark.skipif(numpy is None, reason="NumPy not installed")
 | 
					    @pytest.mark.skipif(numpy is None, reason="NumPy not installed")
 | 
				
			||||||
    def test_numpy_formats(self):
 | 
					    def test_numpy_formats(self) -> None:
 | 
				
			||||||
        g = Image.linear_gradient("L")
 | 
					        g = Image.linear_gradient("L")
 | 
				
			||||||
        im = Image.merge(
 | 
					        im = Image.merge(
 | 
				
			||||||
            "RGB",
 | 
					            "RGB",
 | 
				
			||||||
| 
						 | 
					@ -466,7 +466,7 @@ class TestColorLut3DFilter:
 | 
				
			||||||
        lut.table = numpy.array(lut.table, dtype=numpy.int8)
 | 
					        lut.table = numpy.array(lut.table, dtype=numpy.int8)
 | 
				
			||||||
        im.filter(lut)
 | 
					        im.filter(lut)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_repr(self):
 | 
					    def test_repr(self) -> None:
 | 
				
			||||||
        lut = ImageFilter.Color3DLUT(2, [0, 1, 2] * 8)
 | 
					        lut = ImageFilter.Color3DLUT(2, [0, 1, 2] * 8)
 | 
				
			||||||
        assert repr(lut) == "<Color3DLUT from list size=2x2x2 channels=3>"
 | 
					        assert repr(lut) == "<Color3DLUT from list size=2x2x2 channels=3>"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -484,7 +484,7 @@ class TestColorLut3DFilter:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class TestGenerateColorLut3D:
 | 
					class TestGenerateColorLut3D:
 | 
				
			||||||
    def test_wrong_channels_count(self):
 | 
					    def test_wrong_channels_count(self) -> None:
 | 
				
			||||||
        with pytest.raises(ValueError, match="3 or 4 output channels"):
 | 
					        with pytest.raises(ValueError, match="3 or 4 output channels"):
 | 
				
			||||||
            ImageFilter.Color3DLUT.generate(
 | 
					            ImageFilter.Color3DLUT.generate(
 | 
				
			||||||
                5, channels=2, callback=lambda r, g, b: (r, g, b)
 | 
					                5, channels=2, callback=lambda r, g, b: (r, g, b)
 | 
				
			||||||
| 
						 | 
					@ -498,7 +498,7 @@ class TestGenerateColorLut3D:
 | 
				
			||||||
                5, channels=4, callback=lambda r, g, b: (r, g, b)
 | 
					                5, channels=4, callback=lambda r, g, b: (r, g, b)
 | 
				
			||||||
            )
 | 
					            )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_3_channels(self):
 | 
					    def test_3_channels(self) -> None:
 | 
				
			||||||
        lut = ImageFilter.Color3DLUT.generate(5, lambda r, g, b: (r, g, b))
 | 
					        lut = ImageFilter.Color3DLUT.generate(5, lambda r, g, b: (r, g, b))
 | 
				
			||||||
        assert tuple(lut.size) == (5, 5, 5)
 | 
					        assert tuple(lut.size) == (5, 5, 5)
 | 
				
			||||||
        assert lut.name == "Color 3D LUT"
 | 
					        assert lut.name == "Color 3D LUT"
 | 
				
			||||||
| 
						 | 
					@ -508,7 +508,7 @@ class TestGenerateColorLut3D:
 | 
				
			||||||
            1.0, 0.0, 0.0,  0.0, 0.25, 0.0,  0.25, 0.25, 0.0,  0.5, 0.25, 0.0]
 | 
					            1.0, 0.0, 0.0,  0.0, 0.25, 0.0,  0.25, 0.25, 0.0,  0.5, 0.25, 0.0]
 | 
				
			||||||
        # fmt: on
 | 
					        # fmt: on
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_4_channels(self):
 | 
					    def test_4_channels(self) -> None:
 | 
				
			||||||
        lut = ImageFilter.Color3DLUT.generate(
 | 
					        lut = ImageFilter.Color3DLUT.generate(
 | 
				
			||||||
            5, channels=4, callback=lambda r, g, b: (b, r, g, (r + g + b) / 2)
 | 
					            5, channels=4, callback=lambda r, g, b: (b, r, g, (r + g + b) / 2)
 | 
				
			||||||
        )
 | 
					        )
 | 
				
			||||||
| 
						 | 
					@ -521,7 +521,7 @@ class TestGenerateColorLut3D:
 | 
				
			||||||
        ]
 | 
					        ]
 | 
				
			||||||
        # fmt: on
 | 
					        # fmt: on
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_apply(self):
 | 
					    def test_apply(self) -> None:
 | 
				
			||||||
        lut = ImageFilter.Color3DLUT.generate(5, lambda r, g, b: (r, g, b))
 | 
					        lut = ImageFilter.Color3DLUT.generate(5, lambda r, g, b: (r, g, b))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        g = Image.linear_gradient("L")
 | 
					        g = Image.linear_gradient("L")
 | 
				
			||||||
| 
						 | 
					@ -537,7 +537,7 @@ class TestGenerateColorLut3D:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class TestTransformColorLut3D:
 | 
					class TestTransformColorLut3D:
 | 
				
			||||||
    def test_wrong_args(self):
 | 
					    def test_wrong_args(self) -> None:
 | 
				
			||||||
        source = ImageFilter.Color3DLUT.generate(5, lambda r, g, b: (r, g, b))
 | 
					        source = ImageFilter.Color3DLUT.generate(5, lambda r, g, b: (r, g, b))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        with pytest.raises(ValueError, match="Only 3 or 4 output"):
 | 
					        with pytest.raises(ValueError, match="Only 3 or 4 output"):
 | 
				
			||||||
| 
						 | 
					@ -552,7 +552,7 @@ class TestTransformColorLut3D:
 | 
				
			||||||
        with pytest.raises(TypeError):
 | 
					        with pytest.raises(TypeError):
 | 
				
			||||||
            source.transform(lambda r, g, b, a: (r, g, b))
 | 
					            source.transform(lambda r, g, b, a: (r, g, b))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_target_mode(self):
 | 
					    def test_target_mode(self) -> None:
 | 
				
			||||||
        source = ImageFilter.Color3DLUT.generate(
 | 
					        source = ImageFilter.Color3DLUT.generate(
 | 
				
			||||||
            2, lambda r, g, b: (r, g, b), target_mode="HSV"
 | 
					            2, lambda r, g, b: (r, g, b), target_mode="HSV"
 | 
				
			||||||
        )
 | 
					        )
 | 
				
			||||||
| 
						 | 
					@ -563,7 +563,7 @@ class TestTransformColorLut3D:
 | 
				
			||||||
        lut = source.transform(lambda r, g, b: (r, g, b), target_mode="RGB")
 | 
					        lut = source.transform(lambda r, g, b: (r, g, b), target_mode="RGB")
 | 
				
			||||||
        assert lut.mode == "RGB"
 | 
					        assert lut.mode == "RGB"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_3_to_3_channels(self):
 | 
					    def test_3_to_3_channels(self) -> None:
 | 
				
			||||||
        source = ImageFilter.Color3DLUT.generate((3, 4, 5), lambda r, g, b: (r, g, b))
 | 
					        source = ImageFilter.Color3DLUT.generate((3, 4, 5), lambda r, g, b: (r, g, b))
 | 
				
			||||||
        lut = source.transform(lambda r, g, b: (r * r, g * g, b * b))
 | 
					        lut = source.transform(lambda r, g, b: (r * r, g * g, b * b))
 | 
				
			||||||
        assert tuple(lut.size) == tuple(source.size)
 | 
					        assert tuple(lut.size) == tuple(source.size)
 | 
				
			||||||
| 
						 | 
					@ -571,7 +571,7 @@ class TestTransformColorLut3D:
 | 
				
			||||||
        assert lut.table != source.table
 | 
					        assert lut.table != source.table
 | 
				
			||||||
        assert lut.table[:10] == [0.0, 0.0, 0.0, 0.25, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0]
 | 
					        assert lut.table[:10] == [0.0, 0.0, 0.0, 0.25, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_3_to_4_channels(self):
 | 
					    def test_3_to_4_channels(self) -> None:
 | 
				
			||||||
        source = ImageFilter.Color3DLUT.generate((6, 5, 4), lambda r, g, b: (r, g, b))
 | 
					        source = ImageFilter.Color3DLUT.generate((6, 5, 4), lambda r, g, b: (r, g, b))
 | 
				
			||||||
        lut = source.transform(lambda r, g, b: (r * r, g * g, b * b, 1), channels=4)
 | 
					        lut = source.transform(lambda r, g, b: (r * r, g * g, b * b, 1), channels=4)
 | 
				
			||||||
        assert tuple(lut.size) == tuple(source.size)
 | 
					        assert tuple(lut.size) == tuple(source.size)
 | 
				
			||||||
| 
						 | 
					@ -583,7 +583,7 @@ class TestTransformColorLut3D:
 | 
				
			||||||
            0.4**2, 0.0, 0.0, 1,  0.6**2, 0.0, 0.0, 1]
 | 
					            0.4**2, 0.0, 0.0, 1,  0.6**2, 0.0, 0.0, 1]
 | 
				
			||||||
        # fmt: on
 | 
					        # fmt: on
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_4_to_3_channels(self):
 | 
					    def test_4_to_3_channels(self) -> None:
 | 
				
			||||||
        source = ImageFilter.Color3DLUT.generate(
 | 
					        source = ImageFilter.Color3DLUT.generate(
 | 
				
			||||||
            (3, 6, 5), lambda r, g, b: (r, g, b, 1), channels=4
 | 
					            (3, 6, 5), lambda r, g, b: (r, g, b, 1), channels=4
 | 
				
			||||||
        )
 | 
					        )
 | 
				
			||||||
| 
						 | 
					@ -599,7 +599,7 @@ class TestTransformColorLut3D:
 | 
				
			||||||
            1.0, 0.96, 1.0,  0.75, 0.96, 1.0,  0.0, 0.96, 1.0]
 | 
					            1.0, 0.96, 1.0,  0.75, 0.96, 1.0,  0.0, 0.96, 1.0]
 | 
				
			||||||
        # fmt: on
 | 
					        # fmt: on
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_4_to_4_channels(self):
 | 
					    def test_4_to_4_channels(self) -> None:
 | 
				
			||||||
        source = ImageFilter.Color3DLUT.generate(
 | 
					        source = ImageFilter.Color3DLUT.generate(
 | 
				
			||||||
            (6, 5, 4), lambda r, g, b: (r, g, b, 1), channels=4
 | 
					            (6, 5, 4), lambda r, g, b: (r, g, b, 1), channels=4
 | 
				
			||||||
        )
 | 
					        )
 | 
				
			||||||
| 
						 | 
					@ -613,7 +613,7 @@ class TestTransformColorLut3D:
 | 
				
			||||||
            0.4**2, 0.0, 0.0, 0.5,  0.6**2, 0.0, 0.0, 0.5]
 | 
					            0.4**2, 0.0, 0.0, 0.5,  0.6**2, 0.0, 0.0, 0.5]
 | 
				
			||||||
        # fmt: on
 | 
					        # fmt: on
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_with_normals_3_channels(self):
 | 
					    def test_with_normals_3_channels(self) -> None:
 | 
				
			||||||
        source = ImageFilter.Color3DLUT.generate(
 | 
					        source = ImageFilter.Color3DLUT.generate(
 | 
				
			||||||
            (6, 5, 4), lambda r, g, b: (r * r, g * g, b * b)
 | 
					            (6, 5, 4), lambda r, g, b: (r * r, g * g, b * b)
 | 
				
			||||||
        )
 | 
					        )
 | 
				
			||||||
| 
						 | 
					@ -629,7 +629,7 @@ class TestTransformColorLut3D:
 | 
				
			||||||
            0.24, 0.0, 0.0,  0.8 - (0.8**2), 0, 0,  0, 0, 0]
 | 
					            0.24, 0.0, 0.0,  0.8 - (0.8**2), 0, 0,  0, 0, 0]
 | 
				
			||||||
        # fmt: on
 | 
					        # fmt: on
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_with_normals_4_channels(self):
 | 
					    def test_with_normals_4_channels(self) -> None:
 | 
				
			||||||
        source = ImageFilter.Color3DLUT.generate(
 | 
					        source = ImageFilter.Color3DLUT.generate(
 | 
				
			||||||
            (3, 6, 5), lambda r, g, b: (r * r, g * g, b * b, 1), channels=4
 | 
					            (3, 6, 5), lambda r, g, b: (r * r, g * g, b * b, 1), channels=4
 | 
				
			||||||
        )
 | 
					        )
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -9,7 +9,7 @@ from PIL import Image
 | 
				
			||||||
from .helper import is_pypy
 | 
					from .helper import is_pypy
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_get_stats():
 | 
					def test_get_stats() -> None:
 | 
				
			||||||
    # Create at least one image
 | 
					    # Create at least one image
 | 
				
			||||||
    Image.new("RGB", (10, 10))
 | 
					    Image.new("RGB", (10, 10))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -22,7 +22,7 @@ def test_get_stats():
 | 
				
			||||||
    assert "blocks_cached" in stats
 | 
					    assert "blocks_cached" in stats
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_reset_stats():
 | 
					def test_reset_stats() -> None:
 | 
				
			||||||
    Image.core.reset_stats()
 | 
					    Image.core.reset_stats()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    stats = Image.core.get_stats()
 | 
					    stats = Image.core.get_stats()
 | 
				
			||||||
| 
						 | 
					@ -35,19 +35,19 @@ def test_reset_stats():
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class TestCoreMemory:
 | 
					class TestCoreMemory:
 | 
				
			||||||
    def teardown_method(self):
 | 
					    def teardown_method(self) -> None:
 | 
				
			||||||
        # Restore default values
 | 
					        # Restore default values
 | 
				
			||||||
        Image.core.set_alignment(1)
 | 
					        Image.core.set_alignment(1)
 | 
				
			||||||
        Image.core.set_block_size(1024 * 1024)
 | 
					        Image.core.set_block_size(1024 * 1024)
 | 
				
			||||||
        Image.core.set_blocks_max(0)
 | 
					        Image.core.set_blocks_max(0)
 | 
				
			||||||
        Image.core.clear_cache()
 | 
					        Image.core.clear_cache()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_get_alignment(self):
 | 
					    def test_get_alignment(self) -> None:
 | 
				
			||||||
        alignment = Image.core.get_alignment()
 | 
					        alignment = Image.core.get_alignment()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        assert alignment > 0
 | 
					        assert alignment > 0
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_set_alignment(self):
 | 
					    def test_set_alignment(self) -> None:
 | 
				
			||||||
        for i in [1, 2, 4, 8, 16, 32]:
 | 
					        for i in [1, 2, 4, 8, 16, 32]:
 | 
				
			||||||
            Image.core.set_alignment(i)
 | 
					            Image.core.set_alignment(i)
 | 
				
			||||||
            alignment = Image.core.get_alignment()
 | 
					            alignment = Image.core.get_alignment()
 | 
				
			||||||
| 
						 | 
					@ -63,12 +63,12 @@ class TestCoreMemory:
 | 
				
			||||||
        with pytest.raises(ValueError):
 | 
					        with pytest.raises(ValueError):
 | 
				
			||||||
            Image.core.set_alignment(3)
 | 
					            Image.core.set_alignment(3)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_get_block_size(self):
 | 
					    def test_get_block_size(self) -> None:
 | 
				
			||||||
        block_size = Image.core.get_block_size()
 | 
					        block_size = Image.core.get_block_size()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        assert block_size >= 4096
 | 
					        assert block_size >= 4096
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_set_block_size(self):
 | 
					    def test_set_block_size(self) -> None:
 | 
				
			||||||
        for i in [4096, 2 * 4096, 3 * 4096]:
 | 
					        for i in [4096, 2 * 4096, 3 * 4096]:
 | 
				
			||||||
            Image.core.set_block_size(i)
 | 
					            Image.core.set_block_size(i)
 | 
				
			||||||
            block_size = Image.core.get_block_size()
 | 
					            block_size = Image.core.get_block_size()
 | 
				
			||||||
| 
						 | 
					@ -84,7 +84,7 @@ class TestCoreMemory:
 | 
				
			||||||
        with pytest.raises(ValueError):
 | 
					        with pytest.raises(ValueError):
 | 
				
			||||||
            Image.core.set_block_size(4000)
 | 
					            Image.core.set_block_size(4000)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_set_block_size_stats(self):
 | 
					    def test_set_block_size_stats(self) -> None:
 | 
				
			||||||
        Image.core.reset_stats()
 | 
					        Image.core.reset_stats()
 | 
				
			||||||
        Image.core.set_blocks_max(0)
 | 
					        Image.core.set_blocks_max(0)
 | 
				
			||||||
        Image.core.set_block_size(4096)
 | 
					        Image.core.set_block_size(4096)
 | 
				
			||||||
| 
						 | 
					@ -96,12 +96,12 @@ class TestCoreMemory:
 | 
				
			||||||
        if not is_pypy():
 | 
					        if not is_pypy():
 | 
				
			||||||
            assert stats["freed_blocks"] >= 64
 | 
					            assert stats["freed_blocks"] >= 64
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_get_blocks_max(self):
 | 
					    def test_get_blocks_max(self) -> None:
 | 
				
			||||||
        blocks_max = Image.core.get_blocks_max()
 | 
					        blocks_max = Image.core.get_blocks_max()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        assert blocks_max >= 0
 | 
					        assert blocks_max >= 0
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_set_blocks_max(self):
 | 
					    def test_set_blocks_max(self) -> None:
 | 
				
			||||||
        for i in [0, 1, 10]:
 | 
					        for i in [0, 1, 10]:
 | 
				
			||||||
            Image.core.set_blocks_max(i)
 | 
					            Image.core.set_blocks_max(i)
 | 
				
			||||||
            blocks_max = Image.core.get_blocks_max()
 | 
					            blocks_max = Image.core.get_blocks_max()
 | 
				
			||||||
| 
						 | 
					@ -117,7 +117,7 @@ class TestCoreMemory:
 | 
				
			||||||
                Image.core.set_blocks_max(2**29)
 | 
					                Image.core.set_blocks_max(2**29)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    @pytest.mark.skipif(is_pypy(), reason="Images not collected")
 | 
					    @pytest.mark.skipif(is_pypy(), reason="Images not collected")
 | 
				
			||||||
    def test_set_blocks_max_stats(self):
 | 
					    def test_set_blocks_max_stats(self) -> None:
 | 
				
			||||||
        Image.core.reset_stats()
 | 
					        Image.core.reset_stats()
 | 
				
			||||||
        Image.core.set_blocks_max(128)
 | 
					        Image.core.set_blocks_max(128)
 | 
				
			||||||
        Image.core.set_block_size(4096)
 | 
					        Image.core.set_block_size(4096)
 | 
				
			||||||
| 
						 | 
					@ -132,7 +132,7 @@ class TestCoreMemory:
 | 
				
			||||||
        assert stats["blocks_cached"] == 64
 | 
					        assert stats["blocks_cached"] == 64
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    @pytest.mark.skipif(is_pypy(), reason="Images not collected")
 | 
					    @pytest.mark.skipif(is_pypy(), reason="Images not collected")
 | 
				
			||||||
    def test_clear_cache_stats(self):
 | 
					    def test_clear_cache_stats(self) -> None:
 | 
				
			||||||
        Image.core.reset_stats()
 | 
					        Image.core.reset_stats()
 | 
				
			||||||
        Image.core.clear_cache()
 | 
					        Image.core.clear_cache()
 | 
				
			||||||
        Image.core.set_blocks_max(128)
 | 
					        Image.core.set_blocks_max(128)
 | 
				
			||||||
| 
						 | 
					@ -149,7 +149,7 @@ class TestCoreMemory:
 | 
				
			||||||
        assert stats["freed_blocks"] >= 48
 | 
					        assert stats["freed_blocks"] >= 48
 | 
				
			||||||
        assert stats["blocks_cached"] == 16
 | 
					        assert stats["blocks_cached"] == 16
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_large_images(self):
 | 
					    def test_large_images(self) -> None:
 | 
				
			||||||
        Image.core.reset_stats()
 | 
					        Image.core.reset_stats()
 | 
				
			||||||
        Image.core.set_blocks_max(0)
 | 
					        Image.core.set_blocks_max(0)
 | 
				
			||||||
        Image.core.set_block_size(4096)
 | 
					        Image.core.set_block_size(4096)
 | 
				
			||||||
| 
						 | 
					@ -166,14 +166,14 @@ class TestCoreMemory:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class TestEnvVars:
 | 
					class TestEnvVars:
 | 
				
			||||||
    def teardown_method(self):
 | 
					    def teardown_method(self) -> None:
 | 
				
			||||||
        # Restore default values
 | 
					        # Restore default values
 | 
				
			||||||
        Image.core.set_alignment(1)
 | 
					        Image.core.set_alignment(1)
 | 
				
			||||||
        Image.core.set_block_size(1024 * 1024)
 | 
					        Image.core.set_block_size(1024 * 1024)
 | 
				
			||||||
        Image.core.set_blocks_max(0)
 | 
					        Image.core.set_blocks_max(0)
 | 
				
			||||||
        Image.core.clear_cache()
 | 
					        Image.core.clear_cache()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_units(self):
 | 
					    def test_units(self) -> None:
 | 
				
			||||||
        Image._apply_env_variables({"PILLOW_BLOCKS_MAX": "2K"})
 | 
					        Image._apply_env_variables({"PILLOW_BLOCKS_MAX": "2K"})
 | 
				
			||||||
        assert Image.core.get_blocks_max() == 2 * 1024
 | 
					        assert Image.core.get_blocks_max() == 2 * 1024
 | 
				
			||||||
        Image._apply_env_variables({"PILLOW_BLOCK_SIZE": "2m"})
 | 
					        Image._apply_env_variables({"PILLOW_BLOCK_SIZE": "2m"})
 | 
				
			||||||
| 
						 | 
					@ -187,6 +187,6 @@ class TestEnvVars:
 | 
				
			||||||
            {"PILLOW_BLOCKS_MAX": "wat"},
 | 
					            {"PILLOW_BLOCKS_MAX": "wat"},
 | 
				
			||||||
        ),
 | 
					        ),
 | 
				
			||||||
    )
 | 
					    )
 | 
				
			||||||
    def test_warnings(self, var):
 | 
					    def test_warnings(self, var) -> None:
 | 
				
			||||||
        with pytest.warns(UserWarning):
 | 
					        with pytest.warns(UserWarning):
 | 
				
			||||||
            Image._apply_env_variables(var)
 | 
					            Image._apply_env_variables(var)
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -12,16 +12,16 @@ ORIGINAL_LIMIT = Image.MAX_IMAGE_PIXELS
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class TestDecompressionBomb:
 | 
					class TestDecompressionBomb:
 | 
				
			||||||
    def teardown_method(self, method):
 | 
					    def teardown_method(self, method) -> None:
 | 
				
			||||||
        Image.MAX_IMAGE_PIXELS = ORIGINAL_LIMIT
 | 
					        Image.MAX_IMAGE_PIXELS = ORIGINAL_LIMIT
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_no_warning_small_file(self):
 | 
					    def test_no_warning_small_file(self) -> None:
 | 
				
			||||||
        # Implicit assert: no warning.
 | 
					        # Implicit assert: no warning.
 | 
				
			||||||
        # A warning would cause a failure.
 | 
					        # A warning would cause a failure.
 | 
				
			||||||
        with Image.open(TEST_FILE):
 | 
					        with Image.open(TEST_FILE):
 | 
				
			||||||
            pass
 | 
					            pass
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_no_warning_no_limit(self):
 | 
					    def test_no_warning_no_limit(self) -> None:
 | 
				
			||||||
        # Arrange
 | 
					        # Arrange
 | 
				
			||||||
        # Turn limit off
 | 
					        # Turn limit off
 | 
				
			||||||
        Image.MAX_IMAGE_PIXELS = None
 | 
					        Image.MAX_IMAGE_PIXELS = None
 | 
				
			||||||
| 
						 | 
					@ -33,7 +33,7 @@ class TestDecompressionBomb:
 | 
				
			||||||
        with Image.open(TEST_FILE):
 | 
					        with Image.open(TEST_FILE):
 | 
				
			||||||
            pass
 | 
					            pass
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_warning(self):
 | 
					    def test_warning(self) -> None:
 | 
				
			||||||
        # Set limit to trigger warning on the test file
 | 
					        # Set limit to trigger warning on the test file
 | 
				
			||||||
        Image.MAX_IMAGE_PIXELS = 128 * 128 - 1
 | 
					        Image.MAX_IMAGE_PIXELS = 128 * 128 - 1
 | 
				
			||||||
        assert Image.MAX_IMAGE_PIXELS == 128 * 128 - 1
 | 
					        assert Image.MAX_IMAGE_PIXELS == 128 * 128 - 1
 | 
				
			||||||
| 
						 | 
					@ -42,7 +42,7 @@ class TestDecompressionBomb:
 | 
				
			||||||
            with Image.open(TEST_FILE):
 | 
					            with Image.open(TEST_FILE):
 | 
				
			||||||
                pass
 | 
					                pass
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_exception(self):
 | 
					    def test_exception(self) -> None:
 | 
				
			||||||
        # Set limit to trigger exception on the test file
 | 
					        # Set limit to trigger exception on the test file
 | 
				
			||||||
        Image.MAX_IMAGE_PIXELS = 64 * 128 - 1
 | 
					        Image.MAX_IMAGE_PIXELS = 64 * 128 - 1
 | 
				
			||||||
        assert Image.MAX_IMAGE_PIXELS == 64 * 128 - 1
 | 
					        assert Image.MAX_IMAGE_PIXELS == 64 * 128 - 1
 | 
				
			||||||
| 
						 | 
					@ -51,22 +51,22 @@ class TestDecompressionBomb:
 | 
				
			||||||
            with Image.open(TEST_FILE):
 | 
					            with Image.open(TEST_FILE):
 | 
				
			||||||
                pass
 | 
					                pass
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_exception_ico(self):
 | 
					    def test_exception_ico(self) -> None:
 | 
				
			||||||
        with pytest.raises(Image.DecompressionBombError):
 | 
					        with pytest.raises(Image.DecompressionBombError):
 | 
				
			||||||
            with Image.open("Tests/images/decompression_bomb.ico"):
 | 
					            with Image.open("Tests/images/decompression_bomb.ico"):
 | 
				
			||||||
                pass
 | 
					                pass
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_exception_gif(self):
 | 
					    def test_exception_gif(self) -> None:
 | 
				
			||||||
        with pytest.raises(Image.DecompressionBombError):
 | 
					        with pytest.raises(Image.DecompressionBombError):
 | 
				
			||||||
            with Image.open("Tests/images/decompression_bomb.gif"):
 | 
					            with Image.open("Tests/images/decompression_bomb.gif"):
 | 
				
			||||||
                pass
 | 
					                pass
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_exception_gif_extents(self):
 | 
					    def test_exception_gif_extents(self) -> None:
 | 
				
			||||||
        with Image.open("Tests/images/decompression_bomb_extents.gif") as im:
 | 
					        with Image.open("Tests/images/decompression_bomb_extents.gif") as im:
 | 
				
			||||||
            with pytest.raises(Image.DecompressionBombError):
 | 
					            with pytest.raises(Image.DecompressionBombError):
 | 
				
			||||||
                im.seek(1)
 | 
					                im.seek(1)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_exception_gif_zero_width(self):
 | 
					    def test_exception_gif_zero_width(self) -> None:
 | 
				
			||||||
        # Set limit to trigger exception on the test file
 | 
					        # Set limit to trigger exception on the test file
 | 
				
			||||||
        Image.MAX_IMAGE_PIXELS = 4 * 64 * 128
 | 
					        Image.MAX_IMAGE_PIXELS = 4 * 64 * 128
 | 
				
			||||||
        assert Image.MAX_IMAGE_PIXELS == 4 * 64 * 128
 | 
					        assert Image.MAX_IMAGE_PIXELS == 4 * 64 * 128
 | 
				
			||||||
| 
						 | 
					@ -75,7 +75,7 @@ class TestDecompressionBomb:
 | 
				
			||||||
            with Image.open("Tests/images/zero_width.gif"):
 | 
					            with Image.open("Tests/images/zero_width.gif"):
 | 
				
			||||||
                pass
 | 
					                pass
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_exception_bmp(self):
 | 
					    def test_exception_bmp(self) -> None:
 | 
				
			||||||
        with pytest.raises(Image.DecompressionBombError):
 | 
					        with pytest.raises(Image.DecompressionBombError):
 | 
				
			||||||
            with Image.open("Tests/images/bmp/b/reallybig.bmp"):
 | 
					            with Image.open("Tests/images/bmp/b/reallybig.bmp"):
 | 
				
			||||||
                pass
 | 
					                pass
 | 
				
			||||||
| 
						 | 
					@ -83,15 +83,15 @@ class TestDecompressionBomb:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class TestDecompressionCrop:
 | 
					class TestDecompressionCrop:
 | 
				
			||||||
    @classmethod
 | 
					    @classmethod
 | 
				
			||||||
    def setup_class(cls):
 | 
					    def setup_class(cls) -> None:
 | 
				
			||||||
        width, height = 128, 128
 | 
					        width, height = 128, 128
 | 
				
			||||||
        Image.MAX_IMAGE_PIXELS = height * width * 4 - 1
 | 
					        Image.MAX_IMAGE_PIXELS = height * width * 4 - 1
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    @classmethod
 | 
					    @classmethod
 | 
				
			||||||
    def teardown_class(cls):
 | 
					    def teardown_class(cls) -> None:
 | 
				
			||||||
        Image.MAX_IMAGE_PIXELS = ORIGINAL_LIMIT
 | 
					        Image.MAX_IMAGE_PIXELS = ORIGINAL_LIMIT
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_enlarge_crop(self):
 | 
					    def test_enlarge_crop(self) -> None:
 | 
				
			||||||
        # Crops can extend the extents, therefore we should have the
 | 
					        # Crops can extend the extents, therefore we should have the
 | 
				
			||||||
        # same decompression bomb warnings on them.
 | 
					        # same decompression bomb warnings on them.
 | 
				
			||||||
        with hopper() as src:
 | 
					        with hopper() as src:
 | 
				
			||||||
| 
						 | 
					@ -99,7 +99,7 @@ class TestDecompressionCrop:
 | 
				
			||||||
            with pytest.warns(Image.DecompressionBombWarning):
 | 
					            with pytest.warns(Image.DecompressionBombWarning):
 | 
				
			||||||
                src.crop(box)
 | 
					                src.crop(box)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_crop_decompression_checks(self):
 | 
					    def test_crop_decompression_checks(self) -> None:
 | 
				
			||||||
        im = Image.new("RGB", (100, 100))
 | 
					        im = Image.new("RGB", (100, 100))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        for value in ((-9999, -9999, -9990, -9990), (-999, -999, -990, -990)):
 | 
					        for value in ((-9999, -9999, -9990, -9990), (-999, -999, -990, -990)):
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -20,12 +20,12 @@ from PIL import _deprecate
 | 
				
			||||||
        ),
 | 
					        ),
 | 
				
			||||||
    ],
 | 
					    ],
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
def test_version(version, expected):
 | 
					def test_version(version, expected) -> None:
 | 
				
			||||||
    with pytest.warns(DeprecationWarning, match=expected):
 | 
					    with pytest.warns(DeprecationWarning, match=expected):
 | 
				
			||||||
        _deprecate.deprecate("Old thing", version, "new thing")
 | 
					        _deprecate.deprecate("Old thing", version, "new thing")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_unknown_version():
 | 
					def test_unknown_version() -> None:
 | 
				
			||||||
    expected = r"Unknown removal version: 12345. Update PIL\._deprecate\?"
 | 
					    expected = r"Unknown removal version: 12345. Update PIL\._deprecate\?"
 | 
				
			||||||
    with pytest.raises(ValueError, match=expected):
 | 
					    with pytest.raises(ValueError, match=expected):
 | 
				
			||||||
        _deprecate.deprecate("Old thing", 12345, "new thing")
 | 
					        _deprecate.deprecate("Old thing", 12345, "new thing")
 | 
				
			||||||
| 
						 | 
					@ -46,13 +46,13 @@ def test_unknown_version():
 | 
				
			||||||
        ),
 | 
					        ),
 | 
				
			||||||
    ],
 | 
					    ],
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
def test_old_version(deprecated, plural, expected):
 | 
					def test_old_version(deprecated, plural, expected) -> None:
 | 
				
			||||||
    expected = r""
 | 
					    expected = r""
 | 
				
			||||||
    with pytest.raises(RuntimeError, match=expected):
 | 
					    with pytest.raises(RuntimeError, match=expected):
 | 
				
			||||||
        _deprecate.deprecate(deprecated, 1, plural=plural)
 | 
					        _deprecate.deprecate(deprecated, 1, plural=plural)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_plural():
 | 
					def test_plural() -> None:
 | 
				
			||||||
    expected = (
 | 
					    expected = (
 | 
				
			||||||
        r"Old things are deprecated and will be removed in Pillow 11 \(2024-10-15\)\. "
 | 
					        r"Old things are deprecated and will be removed in Pillow 11 \(2024-10-15\)\. "
 | 
				
			||||||
        r"Use new thing instead\."
 | 
					        r"Use new thing instead\."
 | 
				
			||||||
| 
						 | 
					@ -61,7 +61,7 @@ def test_plural():
 | 
				
			||||||
        _deprecate.deprecate("Old things", 11, "new thing", plural=True)
 | 
					        _deprecate.deprecate("Old things", 11, "new thing", plural=True)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_replacement_and_action():
 | 
					def test_replacement_and_action() -> None:
 | 
				
			||||||
    expected = "Use only one of 'replacement' and 'action'"
 | 
					    expected = "Use only one of 'replacement' and 'action'"
 | 
				
			||||||
    with pytest.raises(ValueError, match=expected):
 | 
					    with pytest.raises(ValueError, match=expected):
 | 
				
			||||||
        _deprecate.deprecate(
 | 
					        _deprecate.deprecate(
 | 
				
			||||||
| 
						 | 
					@ -76,7 +76,7 @@ def test_replacement_and_action():
 | 
				
			||||||
        "Upgrade to new thing.",
 | 
					        "Upgrade to new thing.",
 | 
				
			||||||
    ],
 | 
					    ],
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
def test_action(action):
 | 
					def test_action(action) -> None:
 | 
				
			||||||
    expected = (
 | 
					    expected = (
 | 
				
			||||||
        r"Old thing is deprecated and will be removed in Pillow 11 \(2024-10-15\)\. "
 | 
					        r"Old thing is deprecated and will be removed in Pillow 11 \(2024-10-15\)\. "
 | 
				
			||||||
        r"Upgrade to new thing\."
 | 
					        r"Upgrade to new thing\."
 | 
				
			||||||
| 
						 | 
					@ -85,7 +85,7 @@ def test_action(action):
 | 
				
			||||||
        _deprecate.deprecate("Old thing", 11, action=action)
 | 
					        _deprecate.deprecate("Old thing", 11, action=action)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_no_replacement_or_action():
 | 
					def test_no_replacement_or_action() -> None:
 | 
				
			||||||
    expected = (
 | 
					    expected = (
 | 
				
			||||||
        r"Old thing is deprecated and will be removed in Pillow 11 \(2024-10-15\)"
 | 
					        r"Old thing is deprecated and will be removed in Pillow 11 \(2024-10-15\)"
 | 
				
			||||||
    )
 | 
					    )
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -15,7 +15,7 @@ except ImportError:
 | 
				
			||||||
    pass
 | 
					    pass
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_check():
 | 
					def test_check() -> None:
 | 
				
			||||||
    # Check the correctness of the convenience function
 | 
					    # Check the correctness of the convenience function
 | 
				
			||||||
    for module in features.modules:
 | 
					    for module in features.modules:
 | 
				
			||||||
        assert features.check_module(module) == features.check(module)
 | 
					        assert features.check_module(module) == features.check(module)
 | 
				
			||||||
| 
						 | 
					@ -25,11 +25,11 @@ def test_check():
 | 
				
			||||||
        assert features.check_feature(feature) == features.check(feature)
 | 
					        assert features.check_feature(feature) == features.check(feature)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_version():
 | 
					def test_version() -> None:
 | 
				
			||||||
    # Check the correctness of the convenience function
 | 
					    # Check the correctness of the convenience function
 | 
				
			||||||
    # and the format of version numbers
 | 
					    # and the format of version numbers
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test(name, function):
 | 
					    def test(name, function) -> None:
 | 
				
			||||||
        version = features.version(name)
 | 
					        version = features.version(name)
 | 
				
			||||||
        if not features.check(name):
 | 
					        if not features.check(name):
 | 
				
			||||||
            assert version is None
 | 
					            assert version is None
 | 
				
			||||||
| 
						 | 
					@ -47,56 +47,56 @@ def test_version():
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@skip_unless_feature("webp")
 | 
					@skip_unless_feature("webp")
 | 
				
			||||||
def test_webp_transparency():
 | 
					def test_webp_transparency() -> None:
 | 
				
			||||||
    assert features.check("transp_webp") != _webp.WebPDecoderBuggyAlpha()
 | 
					    assert features.check("transp_webp") != _webp.WebPDecoderBuggyAlpha()
 | 
				
			||||||
    assert features.check("transp_webp") == _webp.HAVE_TRANSPARENCY
 | 
					    assert features.check("transp_webp") == _webp.HAVE_TRANSPARENCY
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@skip_unless_feature("webp")
 | 
					@skip_unless_feature("webp")
 | 
				
			||||||
def test_webp_mux():
 | 
					def test_webp_mux() -> None:
 | 
				
			||||||
    assert features.check("webp_mux") == _webp.HAVE_WEBPMUX
 | 
					    assert features.check("webp_mux") == _webp.HAVE_WEBPMUX
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@skip_unless_feature("webp")
 | 
					@skip_unless_feature("webp")
 | 
				
			||||||
def test_webp_anim():
 | 
					def test_webp_anim() -> None:
 | 
				
			||||||
    assert features.check("webp_anim") == _webp.HAVE_WEBPANIM
 | 
					    assert features.check("webp_anim") == _webp.HAVE_WEBPANIM
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@skip_unless_feature("libjpeg_turbo")
 | 
					@skip_unless_feature("libjpeg_turbo")
 | 
				
			||||||
def test_libjpeg_turbo_version():
 | 
					def test_libjpeg_turbo_version() -> None:
 | 
				
			||||||
    assert re.search(r"\d+\.\d+\.\d+$", features.version("libjpeg_turbo"))
 | 
					    assert re.search(r"\d+\.\d+\.\d+$", features.version("libjpeg_turbo"))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@skip_unless_feature("libimagequant")
 | 
					@skip_unless_feature("libimagequant")
 | 
				
			||||||
def test_libimagequant_version():
 | 
					def test_libimagequant_version() -> None:
 | 
				
			||||||
    assert re.search(r"\d+\.\d+\.\d+$", features.version("libimagequant"))
 | 
					    assert re.search(r"\d+\.\d+\.\d+$", features.version("libimagequant"))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@pytest.mark.parametrize("feature", features.modules)
 | 
					@pytest.mark.parametrize("feature", features.modules)
 | 
				
			||||||
def test_check_modules(feature):
 | 
					def test_check_modules(feature) -> None:
 | 
				
			||||||
    assert features.check_module(feature) in [True, False]
 | 
					    assert features.check_module(feature) in [True, False]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@pytest.mark.parametrize("feature", features.codecs)
 | 
					@pytest.mark.parametrize("feature", features.codecs)
 | 
				
			||||||
def test_check_codecs(feature):
 | 
					def test_check_codecs(feature) -> None:
 | 
				
			||||||
    assert features.check_codec(feature) in [True, False]
 | 
					    assert features.check_codec(feature) in [True, False]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_check_warns_on_nonexistent():
 | 
					def test_check_warns_on_nonexistent() -> None:
 | 
				
			||||||
    with pytest.warns(UserWarning) as cm:
 | 
					    with pytest.warns(UserWarning) as cm:
 | 
				
			||||||
        has_feature = features.check("typo")
 | 
					        has_feature = features.check("typo")
 | 
				
			||||||
    assert has_feature is False
 | 
					    assert has_feature is False
 | 
				
			||||||
    assert str(cm[-1].message) == "Unknown feature 'typo'."
 | 
					    assert str(cm[-1].message) == "Unknown feature 'typo'."
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_supported_modules():
 | 
					def test_supported_modules() -> None:
 | 
				
			||||||
    assert isinstance(features.get_supported_modules(), list)
 | 
					    assert isinstance(features.get_supported_modules(), list)
 | 
				
			||||||
    assert isinstance(features.get_supported_codecs(), list)
 | 
					    assert isinstance(features.get_supported_codecs(), list)
 | 
				
			||||||
    assert isinstance(features.get_supported_features(), list)
 | 
					    assert isinstance(features.get_supported_features(), list)
 | 
				
			||||||
    assert isinstance(features.get_supported(), list)
 | 
					    assert isinstance(features.get_supported(), list)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_unsupported_codec():
 | 
					def test_unsupported_codec() -> None:
 | 
				
			||||||
    # Arrange
 | 
					    # Arrange
 | 
				
			||||||
    codec = "unsupported_codec"
 | 
					    codec = "unsupported_codec"
 | 
				
			||||||
    # Act / Assert
 | 
					    # Act / Assert
 | 
				
			||||||
| 
						 | 
					@ -106,7 +106,7 @@ def test_unsupported_codec():
 | 
				
			||||||
        features.version_codec(codec)
 | 
					        features.version_codec(codec)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_unsupported_module():
 | 
					def test_unsupported_module() -> None:
 | 
				
			||||||
    # Arrange
 | 
					    # Arrange
 | 
				
			||||||
    module = "unsupported_module"
 | 
					    module = "unsupported_module"
 | 
				
			||||||
    # Act / Assert
 | 
					    # Act / Assert
 | 
				
			||||||
| 
						 | 
					@ -116,7 +116,7 @@ def test_unsupported_module():
 | 
				
			||||||
        features.version_module(module)
 | 
					        features.version_module(module)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_pilinfo():
 | 
					def test_pilinfo() -> None:
 | 
				
			||||||
    buf = io.StringIO()
 | 
					    buf = io.StringIO()
 | 
				
			||||||
    features.pilinfo(buf)
 | 
					    features.pilinfo(buf)
 | 
				
			||||||
    out = buf.getvalue()
 | 
					    out = buf.getvalue()
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,5 +1,7 @@
 | 
				
			||||||
from __future__ import annotations
 | 
					from __future__ import annotations
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					from pathlib import Path
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import pytest
 | 
					import pytest
 | 
				
			||||||
 | 
					
 | 
				
			||||||
from PIL import Image, ImageSequence, PngImagePlugin
 | 
					from PIL import Image, ImageSequence, PngImagePlugin
 | 
				
			||||||
| 
						 | 
					@ -8,7 +10,7 @@ from PIL import Image, ImageSequence, PngImagePlugin
 | 
				
			||||||
# APNG browser support tests and fixtures via:
 | 
					# APNG browser support tests and fixtures via:
 | 
				
			||||||
# https://philip.html5.org/tests/apng/tests.html
 | 
					# https://philip.html5.org/tests/apng/tests.html
 | 
				
			||||||
# (referenced from https://wiki.mozilla.org/APNG_Specification)
 | 
					# (referenced from https://wiki.mozilla.org/APNG_Specification)
 | 
				
			||||||
def test_apng_basic():
 | 
					def test_apng_basic() -> None:
 | 
				
			||||||
    with Image.open("Tests/images/apng/single_frame.png") as im:
 | 
					    with Image.open("Tests/images/apng/single_frame.png") as im:
 | 
				
			||||||
        assert not im.is_animated
 | 
					        assert not im.is_animated
 | 
				
			||||||
        assert im.n_frames == 1
 | 
					        assert im.n_frames == 1
 | 
				
			||||||
| 
						 | 
					@ -45,14 +47,14 @@ def test_apng_basic():
 | 
				
			||||||
    "filename",
 | 
					    "filename",
 | 
				
			||||||
    ("Tests/images/apng/split_fdat.png", "Tests/images/apng/split_fdat_zero_chunk.png"),
 | 
					    ("Tests/images/apng/split_fdat.png", "Tests/images/apng/split_fdat_zero_chunk.png"),
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
def test_apng_fdat(filename):
 | 
					def test_apng_fdat(filename) -> None:
 | 
				
			||||||
    with Image.open(filename) as im:
 | 
					    with Image.open(filename) as im:
 | 
				
			||||||
        im.seek(im.n_frames - 1)
 | 
					        im.seek(im.n_frames - 1)
 | 
				
			||||||
        assert im.getpixel((0, 0)) == (0, 255, 0, 255)
 | 
					        assert im.getpixel((0, 0)) == (0, 255, 0, 255)
 | 
				
			||||||
        assert im.getpixel((64, 32)) == (0, 255, 0, 255)
 | 
					        assert im.getpixel((64, 32)) == (0, 255, 0, 255)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_apng_dispose():
 | 
					def test_apng_dispose() -> None:
 | 
				
			||||||
    with Image.open("Tests/images/apng/dispose_op_none.png") as im:
 | 
					    with Image.open("Tests/images/apng/dispose_op_none.png") as im:
 | 
				
			||||||
        im.seek(im.n_frames - 1)
 | 
					        im.seek(im.n_frames - 1)
 | 
				
			||||||
        assert im.getpixel((0, 0)) == (0, 255, 0, 255)
 | 
					        assert im.getpixel((0, 0)) == (0, 255, 0, 255)
 | 
				
			||||||
| 
						 | 
					@ -84,7 +86,7 @@ def test_apng_dispose():
 | 
				
			||||||
        assert im.getpixel((64, 32)) == (0, 0, 0, 0)
 | 
					        assert im.getpixel((64, 32)) == (0, 0, 0, 0)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_apng_dispose_region():
 | 
					def test_apng_dispose_region() -> None:
 | 
				
			||||||
    with Image.open("Tests/images/apng/dispose_op_none_region.png") as im:
 | 
					    with Image.open("Tests/images/apng/dispose_op_none_region.png") as im:
 | 
				
			||||||
        im.seek(im.n_frames - 1)
 | 
					        im.seek(im.n_frames - 1)
 | 
				
			||||||
        assert im.getpixel((0, 0)) == (0, 255, 0, 255)
 | 
					        assert im.getpixel((0, 0)) == (0, 255, 0, 255)
 | 
				
			||||||
| 
						 | 
					@ -106,7 +108,7 @@ def test_apng_dispose_region():
 | 
				
			||||||
        assert im.getpixel((64, 32)) == (0, 255, 0, 255)
 | 
					        assert im.getpixel((64, 32)) == (0, 255, 0, 255)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_apng_dispose_op_previous_frame():
 | 
					def test_apng_dispose_op_previous_frame() -> None:
 | 
				
			||||||
    # Test that the dispose settings being used are from the previous frame
 | 
					    # Test that the dispose settings being used are from the previous frame
 | 
				
			||||||
    #
 | 
					    #
 | 
				
			||||||
    # Image created with:
 | 
					    # Image created with:
 | 
				
			||||||
| 
						 | 
					@ -131,14 +133,14 @@ def test_apng_dispose_op_previous_frame():
 | 
				
			||||||
        assert im.getpixel((0, 0)) == (255, 0, 0, 255)
 | 
					        assert im.getpixel((0, 0)) == (255, 0, 0, 255)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_apng_dispose_op_background_p_mode():
 | 
					def test_apng_dispose_op_background_p_mode() -> None:
 | 
				
			||||||
    with Image.open("Tests/images/apng/dispose_op_background_p_mode.png") as im:
 | 
					    with Image.open("Tests/images/apng/dispose_op_background_p_mode.png") as im:
 | 
				
			||||||
        im.seek(1)
 | 
					        im.seek(1)
 | 
				
			||||||
        im.load()
 | 
					        im.load()
 | 
				
			||||||
        assert im.size == (128, 64)
 | 
					        assert im.size == (128, 64)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_apng_blend():
 | 
					def test_apng_blend() -> None:
 | 
				
			||||||
    with Image.open("Tests/images/apng/blend_op_source_solid.png") as im:
 | 
					    with Image.open("Tests/images/apng/blend_op_source_solid.png") as im:
 | 
				
			||||||
        im.seek(im.n_frames - 1)
 | 
					        im.seek(im.n_frames - 1)
 | 
				
			||||||
        assert im.getpixel((0, 0)) == (0, 255, 0, 255)
 | 
					        assert im.getpixel((0, 0)) == (0, 255, 0, 255)
 | 
				
			||||||
| 
						 | 
					@ -165,20 +167,20 @@ def test_apng_blend():
 | 
				
			||||||
        assert im.getpixel((64, 32)) == (0, 255, 0, 255)
 | 
					        assert im.getpixel((64, 32)) == (0, 255, 0, 255)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_apng_blend_transparency():
 | 
					def test_apng_blend_transparency() -> None:
 | 
				
			||||||
    with Image.open("Tests/images/blend_transparency.png") as im:
 | 
					    with Image.open("Tests/images/blend_transparency.png") as im:
 | 
				
			||||||
        im.seek(1)
 | 
					        im.seek(1)
 | 
				
			||||||
        assert im.getpixel((0, 0)) == (255, 0, 0)
 | 
					        assert im.getpixel((0, 0)) == (255, 0, 0)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_apng_chunk_order():
 | 
					def test_apng_chunk_order() -> None:
 | 
				
			||||||
    with Image.open("Tests/images/apng/fctl_actl.png") as im:
 | 
					    with Image.open("Tests/images/apng/fctl_actl.png") as im:
 | 
				
			||||||
        im.seek(im.n_frames - 1)
 | 
					        im.seek(im.n_frames - 1)
 | 
				
			||||||
        assert im.getpixel((0, 0)) == (0, 255, 0, 255)
 | 
					        assert im.getpixel((0, 0)) == (0, 255, 0, 255)
 | 
				
			||||||
        assert im.getpixel((64, 32)) == (0, 255, 0, 255)
 | 
					        assert im.getpixel((64, 32)) == (0, 255, 0, 255)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_apng_delay():
 | 
					def test_apng_delay() -> None:
 | 
				
			||||||
    with Image.open("Tests/images/apng/delay.png") as im:
 | 
					    with Image.open("Tests/images/apng/delay.png") as im:
 | 
				
			||||||
        im.seek(1)
 | 
					        im.seek(1)
 | 
				
			||||||
        assert im.info.get("duration") == 500.0
 | 
					        assert im.info.get("duration") == 500.0
 | 
				
			||||||
| 
						 | 
					@ -218,7 +220,7 @@ def test_apng_delay():
 | 
				
			||||||
        assert im.info.get("duration") == 1000.0
 | 
					        assert im.info.get("duration") == 1000.0
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_apng_num_plays():
 | 
					def test_apng_num_plays() -> None:
 | 
				
			||||||
    with Image.open("Tests/images/apng/num_plays.png") as im:
 | 
					    with Image.open("Tests/images/apng/num_plays.png") as im:
 | 
				
			||||||
        assert im.info.get("loop") == 0
 | 
					        assert im.info.get("loop") == 0
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -226,7 +228,7 @@ def test_apng_num_plays():
 | 
				
			||||||
        assert im.info.get("loop") == 1
 | 
					        assert im.info.get("loop") == 1
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_apng_mode():
 | 
					def test_apng_mode() -> None:
 | 
				
			||||||
    with Image.open("Tests/images/apng/mode_16bit.png") as im:
 | 
					    with Image.open("Tests/images/apng/mode_16bit.png") as im:
 | 
				
			||||||
        assert im.mode == "RGBA"
 | 
					        assert im.mode == "RGBA"
 | 
				
			||||||
        im.seek(im.n_frames - 1)
 | 
					        im.seek(im.n_frames - 1)
 | 
				
			||||||
| 
						 | 
					@ -267,7 +269,7 @@ def test_apng_mode():
 | 
				
			||||||
        assert im.getpixel((64, 32)) == (0, 0, 255, 128)
 | 
					        assert im.getpixel((64, 32)) == (0, 0, 255, 128)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_apng_chunk_errors():
 | 
					def test_apng_chunk_errors() -> None:
 | 
				
			||||||
    with Image.open("Tests/images/apng/chunk_no_actl.png") as im:
 | 
					    with Image.open("Tests/images/apng/chunk_no_actl.png") as im:
 | 
				
			||||||
        assert not im.is_animated
 | 
					        assert not im.is_animated
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -292,7 +294,7 @@ def test_apng_chunk_errors():
 | 
				
			||||||
            im.seek(im.n_frames - 1)
 | 
					            im.seek(im.n_frames - 1)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_apng_syntax_errors():
 | 
					def test_apng_syntax_errors() -> None:
 | 
				
			||||||
    with pytest.warns(UserWarning):
 | 
					    with pytest.warns(UserWarning):
 | 
				
			||||||
        with Image.open("Tests/images/apng/syntax_num_frames_zero.png") as im:
 | 
					        with Image.open("Tests/images/apng/syntax_num_frames_zero.png") as im:
 | 
				
			||||||
            assert not im.is_animated
 | 
					            assert not im.is_animated
 | 
				
			||||||
| 
						 | 
					@ -336,14 +338,14 @@ def test_apng_syntax_errors():
 | 
				
			||||||
        "sequence_fdat_fctl.png",
 | 
					        "sequence_fdat_fctl.png",
 | 
				
			||||||
    ),
 | 
					    ),
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
def test_apng_sequence_errors(test_file):
 | 
					def test_apng_sequence_errors(test_file) -> None:
 | 
				
			||||||
    with pytest.raises(SyntaxError):
 | 
					    with pytest.raises(SyntaxError):
 | 
				
			||||||
        with Image.open(f"Tests/images/apng/{test_file}") as im:
 | 
					        with Image.open(f"Tests/images/apng/{test_file}") as im:
 | 
				
			||||||
            im.seek(im.n_frames - 1)
 | 
					            im.seek(im.n_frames - 1)
 | 
				
			||||||
            im.load()
 | 
					            im.load()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_apng_save(tmp_path):
 | 
					def test_apng_save(tmp_path: Path) -> None:
 | 
				
			||||||
    with Image.open("Tests/images/apng/single_frame.png") as im:
 | 
					    with Image.open("Tests/images/apng/single_frame.png") as im:
 | 
				
			||||||
        test_file = str(tmp_path / "temp.png")
 | 
					        test_file = str(tmp_path / "temp.png")
 | 
				
			||||||
        im.save(test_file, save_all=True)
 | 
					        im.save(test_file, save_all=True)
 | 
				
			||||||
| 
						 | 
					@ -374,7 +376,7 @@ def test_apng_save(tmp_path):
 | 
				
			||||||
        assert im.getpixel((64, 32)) == (0, 255, 0, 255)
 | 
					        assert im.getpixel((64, 32)) == (0, 255, 0, 255)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_apng_save_alpha(tmp_path):
 | 
					def test_apng_save_alpha(tmp_path: Path) -> None:
 | 
				
			||||||
    test_file = str(tmp_path / "temp.png")
 | 
					    test_file = str(tmp_path / "temp.png")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    im = Image.new("RGBA", (1, 1), (255, 0, 0, 255))
 | 
					    im = Image.new("RGBA", (1, 1), (255, 0, 0, 255))
 | 
				
			||||||
| 
						 | 
					@ -388,7 +390,7 @@ def test_apng_save_alpha(tmp_path):
 | 
				
			||||||
        assert reloaded.getpixel((0, 0)) == (255, 0, 0, 127)
 | 
					        assert reloaded.getpixel((0, 0)) == (255, 0, 0, 127)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_apng_save_split_fdat(tmp_path):
 | 
					def test_apng_save_split_fdat(tmp_path: Path) -> None:
 | 
				
			||||||
    # test to make sure we do not generate sequence errors when writing
 | 
					    # test to make sure we do not generate sequence errors when writing
 | 
				
			||||||
    # frames with image data spanning multiple fdAT chunks (in this case
 | 
					    # frames with image data spanning multiple fdAT chunks (in this case
 | 
				
			||||||
    # both the default image and first animation frame will span multiple
 | 
					    # both the default image and first animation frame will span multiple
 | 
				
			||||||
| 
						 | 
					@ -412,7 +414,7 @@ def test_apng_save_split_fdat(tmp_path):
 | 
				
			||||||
        assert exception is None
 | 
					        assert exception is None
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_apng_save_duration_loop(tmp_path):
 | 
					def test_apng_save_duration_loop(tmp_path: Path) -> None:
 | 
				
			||||||
    test_file = str(tmp_path / "temp.png")
 | 
					    test_file = str(tmp_path / "temp.png")
 | 
				
			||||||
    with Image.open("Tests/images/apng/delay.png") as im:
 | 
					    with Image.open("Tests/images/apng/delay.png") as im:
 | 
				
			||||||
        frames = []
 | 
					        frames = []
 | 
				
			||||||
| 
						 | 
					@ -475,7 +477,7 @@ def test_apng_save_duration_loop(tmp_path):
 | 
				
			||||||
        assert im.info["duration"] == 600
 | 
					        assert im.info["duration"] == 600
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_apng_save_disposal(tmp_path):
 | 
					def test_apng_save_disposal(tmp_path: Path) -> None:
 | 
				
			||||||
    test_file = str(tmp_path / "temp.png")
 | 
					    test_file = str(tmp_path / "temp.png")
 | 
				
			||||||
    size = (128, 64)
 | 
					    size = (128, 64)
 | 
				
			||||||
    red = Image.new("RGBA", size, (255, 0, 0, 255))
 | 
					    red = Image.new("RGBA", size, (255, 0, 0, 255))
 | 
				
			||||||
| 
						 | 
					@ -576,7 +578,7 @@ def test_apng_save_disposal(tmp_path):
 | 
				
			||||||
        assert im.getpixel((64, 32)) == (0, 0, 0, 0)
 | 
					        assert im.getpixel((64, 32)) == (0, 0, 0, 0)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_apng_save_disposal_previous(tmp_path):
 | 
					def test_apng_save_disposal_previous(tmp_path: Path) -> None:
 | 
				
			||||||
    test_file = str(tmp_path / "temp.png")
 | 
					    test_file = str(tmp_path / "temp.png")
 | 
				
			||||||
    size = (128, 64)
 | 
					    size = (128, 64)
 | 
				
			||||||
    blue = Image.new("RGBA", size, (0, 0, 255, 255))
 | 
					    blue = Image.new("RGBA", size, (0, 0, 255, 255))
 | 
				
			||||||
| 
						 | 
					@ -598,7 +600,7 @@ def test_apng_save_disposal_previous(tmp_path):
 | 
				
			||||||
        assert im.getpixel((64, 32)) == (0, 255, 0, 255)
 | 
					        assert im.getpixel((64, 32)) == (0, 255, 0, 255)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_apng_save_blend(tmp_path):
 | 
					def test_apng_save_blend(tmp_path: Path) -> None:
 | 
				
			||||||
    test_file = str(tmp_path / "temp.png")
 | 
					    test_file = str(tmp_path / "temp.png")
 | 
				
			||||||
    size = (128, 64)
 | 
					    size = (128, 64)
 | 
				
			||||||
    red = Image.new("RGBA", size, (255, 0, 0, 255))
 | 
					    red = Image.new("RGBA", size, (255, 0, 0, 255))
 | 
				
			||||||
| 
						 | 
					@ -666,7 +668,7 @@ def test_apng_save_blend(tmp_path):
 | 
				
			||||||
        assert im.getpixel((0, 0)) == (0, 255, 0, 255)
 | 
					        assert im.getpixel((0, 0)) == (0, 255, 0, 255)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_seek_after_close():
 | 
					def test_seek_after_close() -> None:
 | 
				
			||||||
    im = Image.open("Tests/images/apng/delay.png")
 | 
					    im = Image.open("Tests/images/apng/delay.png")
 | 
				
			||||||
    im.seek(1)
 | 
					    im.seek(1)
 | 
				
			||||||
    im.close()
 | 
					    im.close()
 | 
				
			||||||
| 
						 | 
					@ -678,7 +680,9 @@ def test_seek_after_close():
 | 
				
			||||||
@pytest.mark.parametrize("mode", ("RGBA", "RGB", "P"))
 | 
					@pytest.mark.parametrize("mode", ("RGBA", "RGB", "P"))
 | 
				
			||||||
@pytest.mark.parametrize("default_image", (True, False))
 | 
					@pytest.mark.parametrize("default_image", (True, False))
 | 
				
			||||||
@pytest.mark.parametrize("duplicate", (True, False))
 | 
					@pytest.mark.parametrize("duplicate", (True, False))
 | 
				
			||||||
def test_different_modes_in_later_frames(mode, default_image, duplicate, tmp_path):
 | 
					def test_different_modes_in_later_frames(
 | 
				
			||||||
 | 
					    mode, default_image, duplicate, tmp_path: Path
 | 
				
			||||||
 | 
					) -> None:
 | 
				
			||||||
    test_file = str(tmp_path / "temp.png")
 | 
					    test_file = str(tmp_path / "temp.png")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    im = Image.new("L", (1, 1))
 | 
					    im = Image.new("L", (1, 1))
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,5 +1,7 @@
 | 
				
			||||||
from __future__ import annotations
 | 
					from __future__ import annotations
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					from pathlib import Path
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import pytest
 | 
					import pytest
 | 
				
			||||||
 | 
					
 | 
				
			||||||
from PIL import Image
 | 
					from PIL import Image
 | 
				
			||||||
| 
						 | 
					@ -12,7 +14,7 @@ from .helper import (
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_load_blp1():
 | 
					def test_load_blp1() -> None:
 | 
				
			||||||
    with Image.open("Tests/images/blp/blp1_jpeg.blp") as im:
 | 
					    with Image.open("Tests/images/blp/blp1_jpeg.blp") as im:
 | 
				
			||||||
        assert_image_equal_tofile(im, "Tests/images/blp/blp1_jpeg.png")
 | 
					        assert_image_equal_tofile(im, "Tests/images/blp/blp1_jpeg.png")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -20,22 +22,22 @@ def test_load_blp1():
 | 
				
			||||||
        im.load()
 | 
					        im.load()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_load_blp2_raw():
 | 
					def test_load_blp2_raw() -> None:
 | 
				
			||||||
    with Image.open("Tests/images/blp/blp2_raw.blp") as im:
 | 
					    with Image.open("Tests/images/blp/blp2_raw.blp") as im:
 | 
				
			||||||
        assert_image_equal_tofile(im, "Tests/images/blp/blp2_raw.png")
 | 
					        assert_image_equal_tofile(im, "Tests/images/blp/blp2_raw.png")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_load_blp2_dxt1():
 | 
					def test_load_blp2_dxt1() -> None:
 | 
				
			||||||
    with Image.open("Tests/images/blp/blp2_dxt1.blp") as im:
 | 
					    with Image.open("Tests/images/blp/blp2_dxt1.blp") as im:
 | 
				
			||||||
        assert_image_equal_tofile(im, "Tests/images/blp/blp2_dxt1.png")
 | 
					        assert_image_equal_tofile(im, "Tests/images/blp/blp2_dxt1.png")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_load_blp2_dxt1a():
 | 
					def test_load_blp2_dxt1a() -> None:
 | 
				
			||||||
    with Image.open("Tests/images/blp/blp2_dxt1a.blp") as im:
 | 
					    with Image.open("Tests/images/blp/blp2_dxt1a.blp") as im:
 | 
				
			||||||
        assert_image_equal_tofile(im, "Tests/images/blp/blp2_dxt1a.png")
 | 
					        assert_image_equal_tofile(im, "Tests/images/blp/blp2_dxt1a.png")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_save(tmp_path):
 | 
					def test_save(tmp_path: Path) -> None:
 | 
				
			||||||
    f = str(tmp_path / "temp.blp")
 | 
					    f = str(tmp_path / "temp.blp")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    for version in ("BLP1", "BLP2"):
 | 
					    for version in ("BLP1", "BLP2"):
 | 
				
			||||||
| 
						 | 
					@ -69,7 +71,7 @@ def test_save(tmp_path):
 | 
				
			||||||
        "Tests/images/timeout-ef9112a065e7183fa7faa2e18929b03e44ee16bf.blp",
 | 
					        "Tests/images/timeout-ef9112a065e7183fa7faa2e18929b03e44ee16bf.blp",
 | 
				
			||||||
    ],
 | 
					    ],
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
def test_crashes(test_file):
 | 
					def test_crashes(test_file) -> None:
 | 
				
			||||||
    with open(test_file, "rb") as f:
 | 
					    with open(test_file, "rb") as f:
 | 
				
			||||||
        with Image.open(f) as im:
 | 
					        with Image.open(f) as im:
 | 
				
			||||||
            with pytest.raises(OSError):
 | 
					            with pytest.raises(OSError):
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,6 +1,7 @@
 | 
				
			||||||
from __future__ import annotations
 | 
					from __future__ import annotations
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import io
 | 
					import io
 | 
				
			||||||
 | 
					from pathlib import Path
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import pytest
 | 
					import pytest
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -14,8 +15,8 @@ from .helper import (
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_sanity(tmp_path):
 | 
					def test_sanity(tmp_path: Path) -> None:
 | 
				
			||||||
    def roundtrip(im):
 | 
					    def roundtrip(im) -> None:
 | 
				
			||||||
        outfile = str(tmp_path / "temp.bmp")
 | 
					        outfile = str(tmp_path / "temp.bmp")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        im.save(outfile, "BMP")
 | 
					        im.save(outfile, "BMP")
 | 
				
			||||||
| 
						 | 
					@ -35,20 +36,20 @@ def test_sanity(tmp_path):
 | 
				
			||||||
    roundtrip(hopper("RGB"))
 | 
					    roundtrip(hopper("RGB"))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_invalid_file():
 | 
					def test_invalid_file() -> None:
 | 
				
			||||||
    with open("Tests/images/flower.jpg", "rb") as fp:
 | 
					    with open("Tests/images/flower.jpg", "rb") as fp:
 | 
				
			||||||
        with pytest.raises(SyntaxError):
 | 
					        with pytest.raises(SyntaxError):
 | 
				
			||||||
            BmpImagePlugin.BmpImageFile(fp)
 | 
					            BmpImagePlugin.BmpImageFile(fp)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_fallback_if_mmap_errors():
 | 
					def test_fallback_if_mmap_errors() -> None:
 | 
				
			||||||
    # This image has been truncated,
 | 
					    # This image has been truncated,
 | 
				
			||||||
    # so that the buffer is not large enough when using mmap
 | 
					    # so that the buffer is not large enough when using mmap
 | 
				
			||||||
    with Image.open("Tests/images/mmap_error.bmp") as im:
 | 
					    with Image.open("Tests/images/mmap_error.bmp") as im:
 | 
				
			||||||
        assert_image_equal_tofile(im, "Tests/images/pal8_offset.bmp")
 | 
					        assert_image_equal_tofile(im, "Tests/images/pal8_offset.bmp")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_save_to_bytes():
 | 
					def test_save_to_bytes() -> None:
 | 
				
			||||||
    output = io.BytesIO()
 | 
					    output = io.BytesIO()
 | 
				
			||||||
    im = hopper()
 | 
					    im = hopper()
 | 
				
			||||||
    im.save(output, "BMP")
 | 
					    im.save(output, "BMP")
 | 
				
			||||||
| 
						 | 
					@ -60,7 +61,7 @@ def test_save_to_bytes():
 | 
				
			||||||
        assert reloaded.format == "BMP"
 | 
					        assert reloaded.format == "BMP"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_small_palette(tmp_path):
 | 
					def test_small_palette(tmp_path: Path) -> None:
 | 
				
			||||||
    im = Image.new("P", (1, 1))
 | 
					    im = Image.new("P", (1, 1))
 | 
				
			||||||
    colors = [0, 0, 0, 125, 125, 125, 255, 255, 255]
 | 
					    colors = [0, 0, 0, 125, 125, 125, 255, 255, 255]
 | 
				
			||||||
    im.putpalette(colors)
 | 
					    im.putpalette(colors)
 | 
				
			||||||
| 
						 | 
					@ -72,7 +73,7 @@ def test_small_palette(tmp_path):
 | 
				
			||||||
        assert reloaded.getpalette() == colors
 | 
					        assert reloaded.getpalette() == colors
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_save_too_large(tmp_path):
 | 
					def test_save_too_large(tmp_path: Path) -> None:
 | 
				
			||||||
    outfile = str(tmp_path / "temp.bmp")
 | 
					    outfile = str(tmp_path / "temp.bmp")
 | 
				
			||||||
    with Image.new("RGB", (1, 1)) as im:
 | 
					    with Image.new("RGB", (1, 1)) as im:
 | 
				
			||||||
        im._size = (37838, 37838)
 | 
					        im._size = (37838, 37838)
 | 
				
			||||||
| 
						 | 
					@ -80,7 +81,7 @@ def test_save_too_large(tmp_path):
 | 
				
			||||||
            im.save(outfile)
 | 
					            im.save(outfile)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_dpi():
 | 
					def test_dpi() -> None:
 | 
				
			||||||
    dpi = (72, 72)
 | 
					    dpi = (72, 72)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    output = io.BytesIO()
 | 
					    output = io.BytesIO()
 | 
				
			||||||
| 
						 | 
					@ -92,7 +93,7 @@ def test_dpi():
 | 
				
			||||||
        assert reloaded.info["dpi"] == (72.008961115161, 72.008961115161)
 | 
					        assert reloaded.info["dpi"] == (72.008961115161, 72.008961115161)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_save_bmp_with_dpi(tmp_path):
 | 
					def test_save_bmp_with_dpi(tmp_path: Path) -> None:
 | 
				
			||||||
    # Test for #1301
 | 
					    # Test for #1301
 | 
				
			||||||
    # Arrange
 | 
					    # Arrange
 | 
				
			||||||
    outfile = str(tmp_path / "temp.jpg")
 | 
					    outfile = str(tmp_path / "temp.jpg")
 | 
				
			||||||
| 
						 | 
					@ -110,7 +111,7 @@ def test_save_bmp_with_dpi(tmp_path):
 | 
				
			||||||
            assert reloaded.format == "JPEG"
 | 
					            assert reloaded.format == "JPEG"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_save_float_dpi(tmp_path):
 | 
					def test_save_float_dpi(tmp_path: Path) -> None:
 | 
				
			||||||
    outfile = str(tmp_path / "temp.bmp")
 | 
					    outfile = str(tmp_path / "temp.bmp")
 | 
				
			||||||
    with Image.open("Tests/images/hopper.bmp") as im:
 | 
					    with Image.open("Tests/images/hopper.bmp") as im:
 | 
				
			||||||
        im.save(outfile, dpi=(72.21216100543306, 72.21216100543306))
 | 
					        im.save(outfile, dpi=(72.21216100543306, 72.21216100543306))
 | 
				
			||||||
| 
						 | 
					@ -118,7 +119,7 @@ def test_save_float_dpi(tmp_path):
 | 
				
			||||||
            assert reloaded.info["dpi"] == (72.21216100543306, 72.21216100543306)
 | 
					            assert reloaded.info["dpi"] == (72.21216100543306, 72.21216100543306)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_load_dib():
 | 
					def test_load_dib() -> None:
 | 
				
			||||||
    # test for #1293, Imagegrab returning Unsupported Bitfields Format
 | 
					    # test for #1293, Imagegrab returning Unsupported Bitfields Format
 | 
				
			||||||
    with Image.open("Tests/images/clipboard.dib") as im:
 | 
					    with Image.open("Tests/images/clipboard.dib") as im:
 | 
				
			||||||
        assert im.format == "DIB"
 | 
					        assert im.format == "DIB"
 | 
				
			||||||
| 
						 | 
					@ -127,7 +128,7 @@ def test_load_dib():
 | 
				
			||||||
        assert_image_equal_tofile(im, "Tests/images/clipboard_target.png")
 | 
					        assert_image_equal_tofile(im, "Tests/images/clipboard_target.png")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_save_dib(tmp_path):
 | 
					def test_save_dib(tmp_path: Path) -> None:
 | 
				
			||||||
    outfile = str(tmp_path / "temp.dib")
 | 
					    outfile = str(tmp_path / "temp.dib")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    with Image.open("Tests/images/clipboard.dib") as im:
 | 
					    with Image.open("Tests/images/clipboard.dib") as im:
 | 
				
			||||||
| 
						 | 
					@ -139,7 +140,7 @@ def test_save_dib(tmp_path):
 | 
				
			||||||
            assert_image_equal(im, reloaded)
 | 
					            assert_image_equal(im, reloaded)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_rgba_bitfields():
 | 
					def test_rgba_bitfields() -> None:
 | 
				
			||||||
    # This test image has been manually hexedited
 | 
					    # This test image has been manually hexedited
 | 
				
			||||||
    # to change the bitfield compression in the header from XBGR to RGBA
 | 
					    # to change the bitfield compression in the header from XBGR to RGBA
 | 
				
			||||||
    with Image.open("Tests/images/rgb32bf-rgba.bmp") as im:
 | 
					    with Image.open("Tests/images/rgb32bf-rgba.bmp") as im:
 | 
				
			||||||
| 
						 | 
					@ -157,7 +158,7 @@ def test_rgba_bitfields():
 | 
				
			||||||
        )
 | 
					        )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_rle8():
 | 
					def test_rle8() -> None:
 | 
				
			||||||
    with Image.open("Tests/images/hopper_rle8.bmp") as im:
 | 
					    with Image.open("Tests/images/hopper_rle8.bmp") as im:
 | 
				
			||||||
        assert_image_similar_tofile(im.convert("RGB"), "Tests/images/hopper.bmp", 12)
 | 
					        assert_image_similar_tofile(im.convert("RGB"), "Tests/images/hopper.bmp", 12)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -177,7 +178,7 @@ def test_rle8():
 | 
				
			||||||
                im.load()
 | 
					                im.load()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_rle4():
 | 
					def test_rle4() -> None:
 | 
				
			||||||
    with Image.open("Tests/images/bmp/g/pal4rle.bmp") as im:
 | 
					    with Image.open("Tests/images/bmp/g/pal4rle.bmp") as im:
 | 
				
			||||||
        assert_image_similar_tofile(im, "Tests/images/bmp/g/pal4.bmp", 12)
 | 
					        assert_image_similar_tofile(im, "Tests/images/bmp/g/pal4.bmp", 12)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -193,7 +194,7 @@ def test_rle4():
 | 
				
			||||||
        ("Tests/images/bmp/g/pal8rle.bmp", 1064),
 | 
					        ("Tests/images/bmp/g/pal8rle.bmp", 1064),
 | 
				
			||||||
    ),
 | 
					    ),
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
def test_rle8_eof(file_name, length):
 | 
					def test_rle8_eof(file_name, length) -> None:
 | 
				
			||||||
    with open(file_name, "rb") as fp:
 | 
					    with open(file_name, "rb") as fp:
 | 
				
			||||||
        data = fp.read(length)
 | 
					        data = fp.read(length)
 | 
				
			||||||
        with Image.open(io.BytesIO(data)) as im:
 | 
					        with Image.open(io.BytesIO(data)) as im:
 | 
				
			||||||
| 
						 | 
					@ -201,7 +202,7 @@ def test_rle8_eof(file_name, length):
 | 
				
			||||||
                im.load()
 | 
					                im.load()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_offset():
 | 
					def test_offset() -> None:
 | 
				
			||||||
    # This image has been hexedited
 | 
					    # This image has been hexedited
 | 
				
			||||||
    # to exclude the palette size from the pixel data offset
 | 
					    # to exclude the palette size from the pixel data offset
 | 
				
			||||||
    with Image.open("Tests/images/pal8_offset.bmp") as im:
 | 
					    with Image.open("Tests/images/pal8_offset.bmp") as im:
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,5 +1,7 @@
 | 
				
			||||||
from __future__ import annotations
 | 
					from __future__ import annotations
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					from pathlib import Path
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import pytest
 | 
					import pytest
 | 
				
			||||||
 | 
					
 | 
				
			||||||
from PIL import BufrStubImagePlugin, Image
 | 
					from PIL import BufrStubImagePlugin, Image
 | 
				
			||||||
| 
						 | 
					@ -9,7 +11,7 @@ from .helper import hopper
 | 
				
			||||||
TEST_FILE = "Tests/images/gfs.t06z.rassda.tm00.bufr_d"
 | 
					TEST_FILE = "Tests/images/gfs.t06z.rassda.tm00.bufr_d"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_open():
 | 
					def test_open() -> None:
 | 
				
			||||||
    # Act
 | 
					    # Act
 | 
				
			||||||
    with Image.open(TEST_FILE) as im:
 | 
					    with Image.open(TEST_FILE) as im:
 | 
				
			||||||
        # Assert
 | 
					        # Assert
 | 
				
			||||||
| 
						 | 
					@ -20,7 +22,7 @@ def test_open():
 | 
				
			||||||
        assert im.size == (1, 1)
 | 
					        assert im.size == (1, 1)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_invalid_file():
 | 
					def test_invalid_file() -> None:
 | 
				
			||||||
    # Arrange
 | 
					    # Arrange
 | 
				
			||||||
    invalid_file = "Tests/images/flower.jpg"
 | 
					    invalid_file = "Tests/images/flower.jpg"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -29,7 +31,7 @@ def test_invalid_file():
 | 
				
			||||||
        BufrStubImagePlugin.BufrStubImageFile(invalid_file)
 | 
					        BufrStubImagePlugin.BufrStubImageFile(invalid_file)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_load():
 | 
					def test_load() -> None:
 | 
				
			||||||
    # Arrange
 | 
					    # Arrange
 | 
				
			||||||
    with Image.open(TEST_FILE) as im:
 | 
					    with Image.open(TEST_FILE) as im:
 | 
				
			||||||
        # Act / Assert: stub cannot load without an implemented handler
 | 
					        # Act / Assert: stub cannot load without an implemented handler
 | 
				
			||||||
| 
						 | 
					@ -37,7 +39,7 @@ def test_load():
 | 
				
			||||||
            im.load()
 | 
					            im.load()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_save(tmp_path):
 | 
					def test_save(tmp_path: Path) -> None:
 | 
				
			||||||
    # Arrange
 | 
					    # Arrange
 | 
				
			||||||
    im = hopper()
 | 
					    im = hopper()
 | 
				
			||||||
    tmpfile = str(tmp_path / "temp.bufr")
 | 
					    tmpfile = str(tmp_path / "temp.bufr")
 | 
				
			||||||
| 
						 | 
					@ -47,13 +49,13 @@ def test_save(tmp_path):
 | 
				
			||||||
        im.save(tmpfile)
 | 
					        im.save(tmpfile)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_handler(tmp_path):
 | 
					def test_handler(tmp_path: Path) -> None:
 | 
				
			||||||
    class TestHandler:
 | 
					    class TestHandler:
 | 
				
			||||||
        opened = False
 | 
					        opened = False
 | 
				
			||||||
        loaded = False
 | 
					        loaded = False
 | 
				
			||||||
        saved = False
 | 
					        saved = False
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        def open(self, im):
 | 
					        def open(self, im) -> None:
 | 
				
			||||||
            self.opened = True
 | 
					            self.opened = True
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        def load(self, im):
 | 
					        def load(self, im):
 | 
				
			||||||
| 
						 | 
					@ -61,7 +63,7 @@ def test_handler(tmp_path):
 | 
				
			||||||
            im.fp.close()
 | 
					            im.fp.close()
 | 
				
			||||||
            return Image.new("RGB", (1, 1))
 | 
					            return Image.new("RGB", (1, 1))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        def save(self, im, fp, filename):
 | 
					        def save(self, im, fp, filename) -> None:
 | 
				
			||||||
            self.saved = True
 | 
					            self.saved = True
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    handler = TestHandler()
 | 
					    handler = TestHandler()
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -9,19 +9,19 @@ from .helper import hopper
 | 
				
			||||||
TEST_FILE = "Tests/images/dummy.container"
 | 
					TEST_FILE = "Tests/images/dummy.container"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_sanity():
 | 
					def test_sanity() -> None:
 | 
				
			||||||
    dir(Image)
 | 
					    dir(Image)
 | 
				
			||||||
    dir(ContainerIO)
 | 
					    dir(ContainerIO)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_isatty():
 | 
					def test_isatty() -> None:
 | 
				
			||||||
    with hopper() as im:
 | 
					    with hopper() as im:
 | 
				
			||||||
        container = ContainerIO.ContainerIO(im, 0, 0)
 | 
					        container = ContainerIO.ContainerIO(im, 0, 0)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    assert container.isatty() is False
 | 
					    assert container.isatty() is False
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_seek_mode_0():
 | 
					def test_seek_mode_0() -> None:
 | 
				
			||||||
    # Arrange
 | 
					    # Arrange
 | 
				
			||||||
    mode = 0
 | 
					    mode = 0
 | 
				
			||||||
    with open(TEST_FILE, "rb") as fh:
 | 
					    with open(TEST_FILE, "rb") as fh:
 | 
				
			||||||
| 
						 | 
					@ -35,7 +35,7 @@ def test_seek_mode_0():
 | 
				
			||||||
        assert container.tell() == 33
 | 
					        assert container.tell() == 33
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_seek_mode_1():
 | 
					def test_seek_mode_1() -> None:
 | 
				
			||||||
    # Arrange
 | 
					    # Arrange
 | 
				
			||||||
    mode = 1
 | 
					    mode = 1
 | 
				
			||||||
    with open(TEST_FILE, "rb") as fh:
 | 
					    with open(TEST_FILE, "rb") as fh:
 | 
				
			||||||
| 
						 | 
					@ -49,7 +49,7 @@ def test_seek_mode_1():
 | 
				
			||||||
        assert container.tell() == 66
 | 
					        assert container.tell() == 66
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_seek_mode_2():
 | 
					def test_seek_mode_2() -> None:
 | 
				
			||||||
    # Arrange
 | 
					    # Arrange
 | 
				
			||||||
    mode = 2
 | 
					    mode = 2
 | 
				
			||||||
    with open(TEST_FILE, "rb") as fh:
 | 
					    with open(TEST_FILE, "rb") as fh:
 | 
				
			||||||
| 
						 | 
					@ -64,7 +64,7 @@ def test_seek_mode_2():
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@pytest.mark.parametrize("bytesmode", (True, False))
 | 
					@pytest.mark.parametrize("bytesmode", (True, False))
 | 
				
			||||||
def test_read_n0(bytesmode):
 | 
					def test_read_n0(bytesmode) -> None:
 | 
				
			||||||
    # Arrange
 | 
					    # Arrange
 | 
				
			||||||
    with open(TEST_FILE, "rb" if bytesmode else "r") as fh:
 | 
					    with open(TEST_FILE, "rb" if bytesmode else "r") as fh:
 | 
				
			||||||
        container = ContainerIO.ContainerIO(fh, 22, 100)
 | 
					        container = ContainerIO.ContainerIO(fh, 22, 100)
 | 
				
			||||||
| 
						 | 
					@ -80,7 +80,7 @@ def test_read_n0(bytesmode):
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@pytest.mark.parametrize("bytesmode", (True, False))
 | 
					@pytest.mark.parametrize("bytesmode", (True, False))
 | 
				
			||||||
def test_read_n(bytesmode):
 | 
					def test_read_n(bytesmode) -> None:
 | 
				
			||||||
    # Arrange
 | 
					    # Arrange
 | 
				
			||||||
    with open(TEST_FILE, "rb" if bytesmode else "r") as fh:
 | 
					    with open(TEST_FILE, "rb" if bytesmode else "r") as fh:
 | 
				
			||||||
        container = ContainerIO.ContainerIO(fh, 22, 100)
 | 
					        container = ContainerIO.ContainerIO(fh, 22, 100)
 | 
				
			||||||
| 
						 | 
					@ -96,7 +96,7 @@ def test_read_n(bytesmode):
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@pytest.mark.parametrize("bytesmode", (True, False))
 | 
					@pytest.mark.parametrize("bytesmode", (True, False))
 | 
				
			||||||
def test_read_eof(bytesmode):
 | 
					def test_read_eof(bytesmode) -> None:
 | 
				
			||||||
    # Arrange
 | 
					    # Arrange
 | 
				
			||||||
    with open(TEST_FILE, "rb" if bytesmode else "r") as fh:
 | 
					    with open(TEST_FILE, "rb" if bytesmode else "r") as fh:
 | 
				
			||||||
        container = ContainerIO.ContainerIO(fh, 22, 100)
 | 
					        container = ContainerIO.ContainerIO(fh, 22, 100)
 | 
				
			||||||
| 
						 | 
					@ -112,7 +112,7 @@ def test_read_eof(bytesmode):
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@pytest.mark.parametrize("bytesmode", (True, False))
 | 
					@pytest.mark.parametrize("bytesmode", (True, False))
 | 
				
			||||||
def test_readline(bytesmode):
 | 
					def test_readline(bytesmode) -> None:
 | 
				
			||||||
    # Arrange
 | 
					    # Arrange
 | 
				
			||||||
    with open(TEST_FILE, "rb" if bytesmode else "r") as fh:
 | 
					    with open(TEST_FILE, "rb" if bytesmode else "r") as fh:
 | 
				
			||||||
        container = ContainerIO.ContainerIO(fh, 0, 120)
 | 
					        container = ContainerIO.ContainerIO(fh, 0, 120)
 | 
				
			||||||
| 
						 | 
					@ -127,7 +127,7 @@ def test_readline(bytesmode):
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@pytest.mark.parametrize("bytesmode", (True, False))
 | 
					@pytest.mark.parametrize("bytesmode", (True, False))
 | 
				
			||||||
def test_readlines(bytesmode):
 | 
					def test_readlines(bytesmode) -> None:
 | 
				
			||||||
    # Arrange
 | 
					    # Arrange
 | 
				
			||||||
    expected = [
 | 
					    expected = [
 | 
				
			||||||
        "This is line 1\n",
 | 
					        "This is line 1\n",
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -12,7 +12,7 @@ from .helper import assert_image_equal, hopper, is_pypy
 | 
				
			||||||
TEST_FILE = "Tests/images/hopper.dcx"
 | 
					TEST_FILE = "Tests/images/hopper.dcx"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_sanity():
 | 
					def test_sanity() -> None:
 | 
				
			||||||
    # Arrange
 | 
					    # Arrange
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    # Act
 | 
					    # Act
 | 
				
			||||||
| 
						 | 
					@ -25,8 +25,8 @@ def test_sanity():
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@pytest.mark.skipif(is_pypy(), reason="Requires CPython")
 | 
					@pytest.mark.skipif(is_pypy(), reason="Requires CPython")
 | 
				
			||||||
def test_unclosed_file():
 | 
					def test_unclosed_file() -> None:
 | 
				
			||||||
    def open():
 | 
					    def open() -> None:
 | 
				
			||||||
        im = Image.open(TEST_FILE)
 | 
					        im = Image.open(TEST_FILE)
 | 
				
			||||||
        im.load()
 | 
					        im.load()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -34,26 +34,26 @@ def test_unclosed_file():
 | 
				
			||||||
        open()
 | 
					        open()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_closed_file():
 | 
					def test_closed_file() -> None:
 | 
				
			||||||
    with warnings.catch_warnings():
 | 
					    with warnings.catch_warnings():
 | 
				
			||||||
        im = Image.open(TEST_FILE)
 | 
					        im = Image.open(TEST_FILE)
 | 
				
			||||||
        im.load()
 | 
					        im.load()
 | 
				
			||||||
        im.close()
 | 
					        im.close()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_context_manager():
 | 
					def test_context_manager() -> None:
 | 
				
			||||||
    with warnings.catch_warnings():
 | 
					    with warnings.catch_warnings():
 | 
				
			||||||
        with Image.open(TEST_FILE) as im:
 | 
					        with Image.open(TEST_FILE) as im:
 | 
				
			||||||
            im.load()
 | 
					            im.load()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_invalid_file():
 | 
					def test_invalid_file() -> None:
 | 
				
			||||||
    with open("Tests/images/flower.jpg", "rb") as fp:
 | 
					    with open("Tests/images/flower.jpg", "rb") as fp:
 | 
				
			||||||
        with pytest.raises(SyntaxError):
 | 
					        with pytest.raises(SyntaxError):
 | 
				
			||||||
            DcxImagePlugin.DcxImageFile(fp)
 | 
					            DcxImagePlugin.DcxImageFile(fp)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_tell():
 | 
					def test_tell() -> None:
 | 
				
			||||||
    # Arrange
 | 
					    # Arrange
 | 
				
			||||||
    with Image.open(TEST_FILE) as im:
 | 
					    with Image.open(TEST_FILE) as im:
 | 
				
			||||||
        # Act
 | 
					        # Act
 | 
				
			||||||
| 
						 | 
					@ -63,13 +63,13 @@ def test_tell():
 | 
				
			||||||
        assert frame == 0
 | 
					        assert frame == 0
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_n_frames():
 | 
					def test_n_frames() -> None:
 | 
				
			||||||
    with Image.open(TEST_FILE) as im:
 | 
					    with Image.open(TEST_FILE) as im:
 | 
				
			||||||
        assert im.n_frames == 1
 | 
					        assert im.n_frames == 1
 | 
				
			||||||
        assert not im.is_animated
 | 
					        assert not im.is_animated
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_eoferror():
 | 
					def test_eoferror() -> None:
 | 
				
			||||||
    with Image.open(TEST_FILE) as im:
 | 
					    with Image.open(TEST_FILE) as im:
 | 
				
			||||||
        n_frames = im.n_frames
 | 
					        n_frames = im.n_frames
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -82,7 +82,7 @@ def test_eoferror():
 | 
				
			||||||
        im.seek(n_frames - 1)
 | 
					        im.seek(n_frames - 1)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_seek_too_far():
 | 
					def test_seek_too_far() -> None:
 | 
				
			||||||
    # Arrange
 | 
					    # Arrange
 | 
				
			||||||
    with Image.open(TEST_FILE) as im:
 | 
					    with Image.open(TEST_FILE) as im:
 | 
				
			||||||
        frame = 999  # too big on purpose
 | 
					        frame = 999  # too big on purpose
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -2,6 +2,7 @@
 | 
				
			||||||
from __future__ import annotations
 | 
					from __future__ import annotations
 | 
				
			||||||
 | 
					
 | 
				
			||||||
from io import BytesIO
 | 
					from io import BytesIO
 | 
				
			||||||
 | 
					from pathlib import Path
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import pytest
 | 
					import pytest
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -46,7 +47,7 @@ TEST_FILE_UNCOMPRESSED_RGB_WITH_ALPHA = "Tests/images/uncompressed_rgb.dds"
 | 
				
			||||||
        TEST_FILE_DX10_BC1_TYPELESS,
 | 
					        TEST_FILE_DX10_BC1_TYPELESS,
 | 
				
			||||||
    ),
 | 
					    ),
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
def test_sanity_dxt1_bc1(image_path):
 | 
					def test_sanity_dxt1_bc1(image_path) -> None:
 | 
				
			||||||
    """Check DXT1 and BC1 images can be opened"""
 | 
					    """Check DXT1 and BC1 images can be opened"""
 | 
				
			||||||
    with Image.open(TEST_FILE_DXT1.replace(".dds", ".png")) as target:
 | 
					    with Image.open(TEST_FILE_DXT1.replace(".dds", ".png")) as target:
 | 
				
			||||||
        target = target.convert("RGBA")
 | 
					        target = target.convert("RGBA")
 | 
				
			||||||
| 
						 | 
					@ -60,7 +61,7 @@ def test_sanity_dxt1_bc1(image_path):
 | 
				
			||||||
        assert_image_equal(im, target)
 | 
					        assert_image_equal(im, target)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_sanity_dxt3():
 | 
					def test_sanity_dxt3() -> None:
 | 
				
			||||||
    """Check DXT3 images can be opened"""
 | 
					    """Check DXT3 images can be opened"""
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    with Image.open(TEST_FILE_DXT3) as im:
 | 
					    with Image.open(TEST_FILE_DXT3) as im:
 | 
				
			||||||
| 
						 | 
					@ -73,7 +74,7 @@ def test_sanity_dxt3():
 | 
				
			||||||
        assert_image_equal_tofile(im, TEST_FILE_DXT3.replace(".dds", ".png"))
 | 
					        assert_image_equal_tofile(im, TEST_FILE_DXT3.replace(".dds", ".png"))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_sanity_dxt5():
 | 
					def test_sanity_dxt5() -> None:
 | 
				
			||||||
    """Check DXT5 images can be opened"""
 | 
					    """Check DXT5 images can be opened"""
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    with Image.open(TEST_FILE_DXT5) as im:
 | 
					    with Image.open(TEST_FILE_DXT5) as im:
 | 
				
			||||||
| 
						 | 
					@ -94,7 +95,7 @@ def test_sanity_dxt5():
 | 
				
			||||||
        TEST_FILE_BC4U,
 | 
					        TEST_FILE_BC4U,
 | 
				
			||||||
    ),
 | 
					    ),
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
def test_sanity_ati1_bc4u(image_path):
 | 
					def test_sanity_ati1_bc4u(image_path) -> None:
 | 
				
			||||||
    """Check ATI1 and BC4U images can be opened"""
 | 
					    """Check ATI1 and BC4U images can be opened"""
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    with Image.open(image_path) as im:
 | 
					    with Image.open(image_path) as im:
 | 
				
			||||||
| 
						 | 
					@ -115,7 +116,7 @@ def test_sanity_ati1_bc4u(image_path):
 | 
				
			||||||
        TEST_FILE_DX10_BC4_TYPELESS,
 | 
					        TEST_FILE_DX10_BC4_TYPELESS,
 | 
				
			||||||
    ),
 | 
					    ),
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
def test_dx10_bc4(image_path):
 | 
					def test_dx10_bc4(image_path) -> None:
 | 
				
			||||||
    """Check DX10 BC4 images can be opened"""
 | 
					    """Check DX10 BC4 images can be opened"""
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    with Image.open(image_path) as im:
 | 
					    with Image.open(image_path) as im:
 | 
				
			||||||
| 
						 | 
					@ -136,7 +137,7 @@ def test_dx10_bc4(image_path):
 | 
				
			||||||
        TEST_FILE_BC5U,
 | 
					        TEST_FILE_BC5U,
 | 
				
			||||||
    ),
 | 
					    ),
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
def test_sanity_ati2_bc5u(image_path):
 | 
					def test_sanity_ati2_bc5u(image_path) -> None:
 | 
				
			||||||
    """Check ATI2 and BC5U images can be opened"""
 | 
					    """Check ATI2 and BC5U images can be opened"""
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    with Image.open(image_path) as im:
 | 
					    with Image.open(image_path) as im:
 | 
				
			||||||
| 
						 | 
					@ -160,7 +161,7 @@ def test_sanity_ati2_bc5u(image_path):
 | 
				
			||||||
        (TEST_FILE_BC5S, TEST_FILE_BC5S),
 | 
					        (TEST_FILE_BC5S, TEST_FILE_BC5S),
 | 
				
			||||||
    ),
 | 
					    ),
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
def test_dx10_bc5(image_path, expected_path):
 | 
					def test_dx10_bc5(image_path, expected_path) -> None:
 | 
				
			||||||
    """Check DX10 BC5 images can be opened"""
 | 
					    """Check DX10 BC5 images can be opened"""
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    with Image.open(image_path) as im:
 | 
					    with Image.open(image_path) as im:
 | 
				
			||||||
| 
						 | 
					@ -174,7 +175,7 @@ def test_dx10_bc5(image_path, expected_path):
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@pytest.mark.parametrize("image_path", (TEST_FILE_BC6H, TEST_FILE_BC6HS))
 | 
					@pytest.mark.parametrize("image_path", (TEST_FILE_BC6H, TEST_FILE_BC6HS))
 | 
				
			||||||
def test_dx10_bc6h(image_path):
 | 
					def test_dx10_bc6h(image_path) -> None:
 | 
				
			||||||
    """Check DX10 BC6H/BC6HS images can be opened"""
 | 
					    """Check DX10 BC6H/BC6HS images can be opened"""
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    with Image.open(image_path) as im:
 | 
					    with Image.open(image_path) as im:
 | 
				
			||||||
| 
						 | 
					@ -187,7 +188,7 @@ def test_dx10_bc6h(image_path):
 | 
				
			||||||
        assert_image_equal_tofile(im, image_path.replace(".dds", ".png"))
 | 
					        assert_image_equal_tofile(im, image_path.replace(".dds", ".png"))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_dx10_bc7():
 | 
					def test_dx10_bc7() -> None:
 | 
				
			||||||
    """Check DX10 images can be opened"""
 | 
					    """Check DX10 images can be opened"""
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    with Image.open(TEST_FILE_DX10_BC7) as im:
 | 
					    with Image.open(TEST_FILE_DX10_BC7) as im:
 | 
				
			||||||
| 
						 | 
					@ -200,7 +201,7 @@ def test_dx10_bc7():
 | 
				
			||||||
        assert_image_equal_tofile(im, TEST_FILE_DX10_BC7.replace(".dds", ".png"))
 | 
					        assert_image_equal_tofile(im, TEST_FILE_DX10_BC7.replace(".dds", ".png"))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_dx10_bc7_unorm_srgb():
 | 
					def test_dx10_bc7_unorm_srgb() -> None:
 | 
				
			||||||
    """Check DX10 unsigned normalized integer images can be opened"""
 | 
					    """Check DX10 unsigned normalized integer images can be opened"""
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    with Image.open(TEST_FILE_DX10_BC7_UNORM_SRGB) as im:
 | 
					    with Image.open(TEST_FILE_DX10_BC7_UNORM_SRGB) as im:
 | 
				
			||||||
| 
						 | 
					@ -216,7 +217,7 @@ def test_dx10_bc7_unorm_srgb():
 | 
				
			||||||
        )
 | 
					        )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_dx10_r8g8b8a8():
 | 
					def test_dx10_r8g8b8a8() -> None:
 | 
				
			||||||
    """Check DX10 images can be opened"""
 | 
					    """Check DX10 images can be opened"""
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    with Image.open(TEST_FILE_DX10_R8G8B8A8) as im:
 | 
					    with Image.open(TEST_FILE_DX10_R8G8B8A8) as im:
 | 
				
			||||||
| 
						 | 
					@ -229,7 +230,7 @@ def test_dx10_r8g8b8a8():
 | 
				
			||||||
        assert_image_equal_tofile(im, TEST_FILE_DX10_R8G8B8A8.replace(".dds", ".png"))
 | 
					        assert_image_equal_tofile(im, TEST_FILE_DX10_R8G8B8A8.replace(".dds", ".png"))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_dx10_r8g8b8a8_unorm_srgb():
 | 
					def test_dx10_r8g8b8a8_unorm_srgb() -> None:
 | 
				
			||||||
    """Check DX10 unsigned normalized integer images can be opened"""
 | 
					    """Check DX10 unsigned normalized integer images can be opened"""
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    with Image.open(TEST_FILE_DX10_R8G8B8A8_UNORM_SRGB) as im:
 | 
					    with Image.open(TEST_FILE_DX10_R8G8B8A8_UNORM_SRGB) as im:
 | 
				
			||||||
| 
						 | 
					@ -255,7 +256,7 @@ def test_dx10_r8g8b8a8_unorm_srgb():
 | 
				
			||||||
        ("RGBA", (800, 600), TEST_FILE_UNCOMPRESSED_RGB_WITH_ALPHA),
 | 
					        ("RGBA", (800, 600), TEST_FILE_UNCOMPRESSED_RGB_WITH_ALPHA),
 | 
				
			||||||
    ],
 | 
					    ],
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
def test_uncompressed(mode, size, test_file):
 | 
					def test_uncompressed(mode, size, test_file) -> None:
 | 
				
			||||||
    """Check uncompressed images can be opened"""
 | 
					    """Check uncompressed images can be opened"""
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    with Image.open(test_file) as im:
 | 
					    with Image.open(test_file) as im:
 | 
				
			||||||
| 
						 | 
					@ -266,7 +267,7 @@ def test_uncompressed(mode, size, test_file):
 | 
				
			||||||
        assert_image_equal_tofile(im, test_file.replace(".dds", ".png"))
 | 
					        assert_image_equal_tofile(im, test_file.replace(".dds", ".png"))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test__accept_true():
 | 
					def test__accept_true() -> None:
 | 
				
			||||||
    """Check valid prefix"""
 | 
					    """Check valid prefix"""
 | 
				
			||||||
    # Arrange
 | 
					    # Arrange
 | 
				
			||||||
    prefix = b"DDS etc"
 | 
					    prefix = b"DDS etc"
 | 
				
			||||||
| 
						 | 
					@ -278,7 +279,7 @@ def test__accept_true():
 | 
				
			||||||
    assert output
 | 
					    assert output
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test__accept_false():
 | 
					def test__accept_false() -> None:
 | 
				
			||||||
    """Check invalid prefix"""
 | 
					    """Check invalid prefix"""
 | 
				
			||||||
    # Arrange
 | 
					    # Arrange
 | 
				
			||||||
    prefix = b"something invalid"
 | 
					    prefix = b"something invalid"
 | 
				
			||||||
| 
						 | 
					@ -290,19 +291,19 @@ def test__accept_false():
 | 
				
			||||||
    assert not output
 | 
					    assert not output
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_invalid_file():
 | 
					def test_invalid_file() -> None:
 | 
				
			||||||
    invalid_file = "Tests/images/flower.jpg"
 | 
					    invalid_file = "Tests/images/flower.jpg"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    with pytest.raises(SyntaxError):
 | 
					    with pytest.raises(SyntaxError):
 | 
				
			||||||
        DdsImagePlugin.DdsImageFile(invalid_file)
 | 
					        DdsImagePlugin.DdsImageFile(invalid_file)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_short_header():
 | 
					def test_short_header() -> None:
 | 
				
			||||||
    """Check a short header"""
 | 
					    """Check a short header"""
 | 
				
			||||||
    with open(TEST_FILE_DXT5, "rb") as f:
 | 
					    with open(TEST_FILE_DXT5, "rb") as f:
 | 
				
			||||||
        img_file = f.read()
 | 
					        img_file = f.read()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def short_header():
 | 
					    def short_header() -> None:
 | 
				
			||||||
        with Image.open(BytesIO(img_file[:119])):
 | 
					        with Image.open(BytesIO(img_file[:119])):
 | 
				
			||||||
            pass  # pragma: no cover
 | 
					            pass  # pragma: no cover
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -310,13 +311,13 @@ def test_short_header():
 | 
				
			||||||
        short_header()
 | 
					        short_header()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_short_file():
 | 
					def test_short_file() -> None:
 | 
				
			||||||
    """Check that the appropriate error is thrown for a short file"""
 | 
					    """Check that the appropriate error is thrown for a short file"""
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    with open(TEST_FILE_DXT5, "rb") as f:
 | 
					    with open(TEST_FILE_DXT5, "rb") as f:
 | 
				
			||||||
        img_file = f.read()
 | 
					        img_file = f.read()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def short_file():
 | 
					    def short_file() -> None:
 | 
				
			||||||
        with Image.open(BytesIO(img_file[:-100])) as im:
 | 
					        with Image.open(BytesIO(img_file[:-100])) as im:
 | 
				
			||||||
            im.load()
 | 
					            im.load()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -324,7 +325,7 @@ def test_short_file():
 | 
				
			||||||
        short_file()
 | 
					        short_file()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_dxt5_colorblock_alpha_issue_4142():
 | 
					def test_dxt5_colorblock_alpha_issue_4142() -> None:
 | 
				
			||||||
    """Check that colorblocks are decoded correctly in DXT5"""
 | 
					    """Check that colorblocks are decoded correctly in DXT5"""
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    with Image.open("Tests/images/dxt5-colorblock-alpha-issue-4142.dds") as im:
 | 
					    with Image.open("Tests/images/dxt5-colorblock-alpha-issue-4142.dds") as im:
 | 
				
			||||||
| 
						 | 
					@ -339,12 +340,12 @@ def test_dxt5_colorblock_alpha_issue_4142():
 | 
				
			||||||
        assert px[2] != 0
 | 
					        assert px[2] != 0
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_palette():
 | 
					def test_palette() -> None:
 | 
				
			||||||
    with Image.open("Tests/images/palette.dds") as im:
 | 
					    with Image.open("Tests/images/palette.dds") as im:
 | 
				
			||||||
        assert_image_equal_tofile(im, "Tests/images/transparent.gif")
 | 
					        assert_image_equal_tofile(im, "Tests/images/transparent.gif")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_unsupported_bitcount():
 | 
					def test_unsupported_bitcount() -> None:
 | 
				
			||||||
    with pytest.raises(OSError):
 | 
					    with pytest.raises(OSError):
 | 
				
			||||||
        with Image.open("Tests/images/unsupported_bitcount.dds"):
 | 
					        with Image.open("Tests/images/unsupported_bitcount.dds"):
 | 
				
			||||||
            pass
 | 
					            pass
 | 
				
			||||||
| 
						 | 
					@ -357,13 +358,13 @@ def test_unsupported_bitcount():
 | 
				
			||||||
        "Tests/images/unimplemented_pfflags.dds",
 | 
					        "Tests/images/unimplemented_pfflags.dds",
 | 
				
			||||||
    ),
 | 
					    ),
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
def test_not_implemented(test_file):
 | 
					def test_not_implemented(test_file) -> None:
 | 
				
			||||||
    with pytest.raises(NotImplementedError):
 | 
					    with pytest.raises(NotImplementedError):
 | 
				
			||||||
        with Image.open(test_file):
 | 
					        with Image.open(test_file):
 | 
				
			||||||
            pass
 | 
					            pass
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_save_unsupported_mode(tmp_path):
 | 
					def test_save_unsupported_mode(tmp_path: Path) -> None:
 | 
				
			||||||
    out = str(tmp_path / "temp.dds")
 | 
					    out = str(tmp_path / "temp.dds")
 | 
				
			||||||
    im = hopper("HSV")
 | 
					    im = hopper("HSV")
 | 
				
			||||||
    with pytest.raises(OSError):
 | 
					    with pytest.raises(OSError):
 | 
				
			||||||
| 
						 | 
					@ -379,7 +380,7 @@ def test_save_unsupported_mode(tmp_path):
 | 
				
			||||||
        ("RGBA", "Tests/images/pil123rgba.png"),
 | 
					        ("RGBA", "Tests/images/pil123rgba.png"),
 | 
				
			||||||
    ],
 | 
					    ],
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
def test_save(mode, test_file, tmp_path):
 | 
					def test_save(mode, test_file, tmp_path: Path) -> None:
 | 
				
			||||||
    out = str(tmp_path / "temp.dds")
 | 
					    out = str(tmp_path / "temp.dds")
 | 
				
			||||||
    with Image.open(test_file) as im:
 | 
					    with Image.open(test_file) as im:
 | 
				
			||||||
        assert im.mode == mode
 | 
					        assert im.mode == mode
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,6 +1,7 @@
 | 
				
			||||||
from __future__ import annotations
 | 
					from __future__ import annotations
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import io
 | 
					import io
 | 
				
			||||||
 | 
					from pathlib import Path
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import pytest
 | 
					import pytest
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -83,7 +84,7 @@ simple_eps_file_with_long_binary_data = (
 | 
				
			||||||
    ("filename", "size"), ((FILE1, (460, 352)), (FILE2, (360, 252)))
 | 
					    ("filename", "size"), ((FILE1, (460, 352)), (FILE2, (360, 252)))
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
@pytest.mark.parametrize("scale", (1, 2))
 | 
					@pytest.mark.parametrize("scale", (1, 2))
 | 
				
			||||||
def test_sanity(filename, size, scale):
 | 
					def test_sanity(filename, size, scale) -> None:
 | 
				
			||||||
    expected_size = tuple(s * scale for s in size)
 | 
					    expected_size = tuple(s * scale for s in size)
 | 
				
			||||||
    with Image.open(filename) as image:
 | 
					    with Image.open(filename) as image:
 | 
				
			||||||
        image.load(scale=scale)
 | 
					        image.load(scale=scale)
 | 
				
			||||||
| 
						 | 
					@ -93,7 +94,7 @@ def test_sanity(filename, size, scale):
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@pytest.mark.skipif(not HAS_GHOSTSCRIPT, reason="Ghostscript not available")
 | 
					@pytest.mark.skipif(not HAS_GHOSTSCRIPT, reason="Ghostscript not available")
 | 
				
			||||||
def test_load():
 | 
					def test_load() -> None:
 | 
				
			||||||
    with Image.open(FILE1) as im:
 | 
					    with Image.open(FILE1) as im:
 | 
				
			||||||
        assert im.load()[0, 0] == (255, 255, 255)
 | 
					        assert im.load()[0, 0] == (255, 255, 255)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -101,7 +102,7 @@ def test_load():
 | 
				
			||||||
        assert im.load()[0, 0] == (255, 255, 255)
 | 
					        assert im.load()[0, 0] == (255, 255, 255)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_binary():
 | 
					def test_binary() -> None:
 | 
				
			||||||
    if HAS_GHOSTSCRIPT:
 | 
					    if HAS_GHOSTSCRIPT:
 | 
				
			||||||
        assert EpsImagePlugin.gs_binary is not None
 | 
					        assert EpsImagePlugin.gs_binary is not None
 | 
				
			||||||
    else:
 | 
					    else:
 | 
				
			||||||
| 
						 | 
					@ -115,41 +116,41 @@ def test_binary():
 | 
				
			||||||
        assert EpsImagePlugin.gs_windows_binary is not None
 | 
					        assert EpsImagePlugin.gs_windows_binary is not None
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_invalid_file():
 | 
					def test_invalid_file() -> None:
 | 
				
			||||||
    invalid_file = "Tests/images/flower.jpg"
 | 
					    invalid_file = "Tests/images/flower.jpg"
 | 
				
			||||||
    with pytest.raises(SyntaxError):
 | 
					    with pytest.raises(SyntaxError):
 | 
				
			||||||
        EpsImagePlugin.EpsImageFile(invalid_file)
 | 
					        EpsImagePlugin.EpsImageFile(invalid_file)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_binary_header_only():
 | 
					def test_binary_header_only() -> None:
 | 
				
			||||||
    data = io.BytesIO(simple_binary_header)
 | 
					    data = io.BytesIO(simple_binary_header)
 | 
				
			||||||
    with pytest.raises(SyntaxError, match='EPS header missing "%!PS-Adobe" comment'):
 | 
					    with pytest.raises(SyntaxError, match='EPS header missing "%!PS-Adobe" comment'):
 | 
				
			||||||
        EpsImagePlugin.EpsImageFile(data)
 | 
					        EpsImagePlugin.EpsImageFile(data)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@pytest.mark.parametrize("prefix", (b"", simple_binary_header))
 | 
					@pytest.mark.parametrize("prefix", (b"", simple_binary_header))
 | 
				
			||||||
def test_missing_version_comment(prefix):
 | 
					def test_missing_version_comment(prefix) -> None:
 | 
				
			||||||
    data = io.BytesIO(prefix + b"\n".join(simple_eps_file_without_version))
 | 
					    data = io.BytesIO(prefix + b"\n".join(simple_eps_file_without_version))
 | 
				
			||||||
    with pytest.raises(SyntaxError):
 | 
					    with pytest.raises(SyntaxError):
 | 
				
			||||||
        EpsImagePlugin.EpsImageFile(data)
 | 
					        EpsImagePlugin.EpsImageFile(data)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@pytest.mark.parametrize("prefix", (b"", simple_binary_header))
 | 
					@pytest.mark.parametrize("prefix", (b"", simple_binary_header))
 | 
				
			||||||
def test_missing_boundingbox_comment(prefix):
 | 
					def test_missing_boundingbox_comment(prefix) -> None:
 | 
				
			||||||
    data = io.BytesIO(prefix + b"\n".join(simple_eps_file_without_boundingbox))
 | 
					    data = io.BytesIO(prefix + b"\n".join(simple_eps_file_without_boundingbox))
 | 
				
			||||||
    with pytest.raises(SyntaxError, match='EPS header missing "%%BoundingBox" comment'):
 | 
					    with pytest.raises(SyntaxError, match='EPS header missing "%%BoundingBox" comment'):
 | 
				
			||||||
        EpsImagePlugin.EpsImageFile(data)
 | 
					        EpsImagePlugin.EpsImageFile(data)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@pytest.mark.parametrize("prefix", (b"", simple_binary_header))
 | 
					@pytest.mark.parametrize("prefix", (b"", simple_binary_header))
 | 
				
			||||||
def test_invalid_boundingbox_comment(prefix):
 | 
					def test_invalid_boundingbox_comment(prefix) -> None:
 | 
				
			||||||
    data = io.BytesIO(prefix + b"\n".join(simple_eps_file_with_invalid_boundingbox))
 | 
					    data = io.BytesIO(prefix + b"\n".join(simple_eps_file_with_invalid_boundingbox))
 | 
				
			||||||
    with pytest.raises(OSError, match="cannot determine EPS bounding box"):
 | 
					    with pytest.raises(OSError, match="cannot determine EPS bounding box"):
 | 
				
			||||||
        EpsImagePlugin.EpsImageFile(data)
 | 
					        EpsImagePlugin.EpsImageFile(data)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@pytest.mark.parametrize("prefix", (b"", simple_binary_header))
 | 
					@pytest.mark.parametrize("prefix", (b"", simple_binary_header))
 | 
				
			||||||
def test_invalid_boundingbox_comment_valid_imagedata_comment(prefix):
 | 
					def test_invalid_boundingbox_comment_valid_imagedata_comment(prefix) -> None:
 | 
				
			||||||
    data = io.BytesIO(
 | 
					    data = io.BytesIO(
 | 
				
			||||||
        prefix + b"\n".join(simple_eps_file_with_invalid_boundingbox_valid_imagedata)
 | 
					        prefix + b"\n".join(simple_eps_file_with_invalid_boundingbox_valid_imagedata)
 | 
				
			||||||
    )
 | 
					    )
 | 
				
			||||||
| 
						 | 
					@ -160,21 +161,21 @@ def test_invalid_boundingbox_comment_valid_imagedata_comment(prefix):
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@pytest.mark.parametrize("prefix", (b"", simple_binary_header))
 | 
					@pytest.mark.parametrize("prefix", (b"", simple_binary_header))
 | 
				
			||||||
def test_ascii_comment_too_long(prefix):
 | 
					def test_ascii_comment_too_long(prefix) -> None:
 | 
				
			||||||
    data = io.BytesIO(prefix + b"\n".join(simple_eps_file_with_long_ascii_comment))
 | 
					    data = io.BytesIO(prefix + b"\n".join(simple_eps_file_with_long_ascii_comment))
 | 
				
			||||||
    with pytest.raises(SyntaxError, match="not an EPS file"):
 | 
					    with pytest.raises(SyntaxError, match="not an EPS file"):
 | 
				
			||||||
        EpsImagePlugin.EpsImageFile(data)
 | 
					        EpsImagePlugin.EpsImageFile(data)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@pytest.mark.parametrize("prefix", (b"", simple_binary_header))
 | 
					@pytest.mark.parametrize("prefix", (b"", simple_binary_header))
 | 
				
			||||||
def test_long_binary_data(prefix):
 | 
					def test_long_binary_data(prefix) -> None:
 | 
				
			||||||
    data = io.BytesIO(prefix + b"\n".join(simple_eps_file_with_long_binary_data))
 | 
					    data = io.BytesIO(prefix + b"\n".join(simple_eps_file_with_long_binary_data))
 | 
				
			||||||
    EpsImagePlugin.EpsImageFile(data)
 | 
					    EpsImagePlugin.EpsImageFile(data)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@pytest.mark.skipif(not HAS_GHOSTSCRIPT, reason="Ghostscript not available")
 | 
					@pytest.mark.skipif(not HAS_GHOSTSCRIPT, reason="Ghostscript not available")
 | 
				
			||||||
@pytest.mark.parametrize("prefix", (b"", simple_binary_header))
 | 
					@pytest.mark.parametrize("prefix", (b"", simple_binary_header))
 | 
				
			||||||
def test_load_long_binary_data(prefix):
 | 
					def test_load_long_binary_data(prefix) -> None:
 | 
				
			||||||
    data = io.BytesIO(prefix + b"\n".join(simple_eps_file_with_long_binary_data))
 | 
					    data = io.BytesIO(prefix + b"\n".join(simple_eps_file_with_long_binary_data))
 | 
				
			||||||
    with Image.open(data) as img:
 | 
					    with Image.open(data) as img:
 | 
				
			||||||
        img.load()
 | 
					        img.load()
 | 
				
			||||||
| 
						 | 
					@ -187,7 +188,7 @@ def test_load_long_binary_data(prefix):
 | 
				
			||||||
    pytest.mark.valgrind_known_error, "libjpeg_turbo", "2.0", reason="Known Failing"
 | 
					    pytest.mark.valgrind_known_error, "libjpeg_turbo", "2.0", reason="Known Failing"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
@pytest.mark.skipif(not HAS_GHOSTSCRIPT, reason="Ghostscript not available")
 | 
					@pytest.mark.skipif(not HAS_GHOSTSCRIPT, reason="Ghostscript not available")
 | 
				
			||||||
def test_cmyk():
 | 
					def test_cmyk() -> None:
 | 
				
			||||||
    with Image.open("Tests/images/pil_sample_cmyk.eps") as cmyk_image:
 | 
					    with Image.open("Tests/images/pil_sample_cmyk.eps") as cmyk_image:
 | 
				
			||||||
        assert cmyk_image.mode == "CMYK"
 | 
					        assert cmyk_image.mode == "CMYK"
 | 
				
			||||||
        assert cmyk_image.size == (100, 100)
 | 
					        assert cmyk_image.size == (100, 100)
 | 
				
			||||||
| 
						 | 
					@ -203,7 +204,7 @@ def test_cmyk():
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@pytest.mark.skipif(not HAS_GHOSTSCRIPT, reason="Ghostscript not available")
 | 
					@pytest.mark.skipif(not HAS_GHOSTSCRIPT, reason="Ghostscript not available")
 | 
				
			||||||
def test_showpage():
 | 
					def test_showpage() -> None:
 | 
				
			||||||
    # See https://github.com/python-pillow/Pillow/issues/2615
 | 
					    # See https://github.com/python-pillow/Pillow/issues/2615
 | 
				
			||||||
    with Image.open("Tests/images/reqd_showpage.eps") as plot_image:
 | 
					    with Image.open("Tests/images/reqd_showpage.eps") as plot_image:
 | 
				
			||||||
        with Image.open("Tests/images/reqd_showpage.png") as target:
 | 
					        with Image.open("Tests/images/reqd_showpage.png") as target:
 | 
				
			||||||
| 
						 | 
					@ -214,7 +215,7 @@ def test_showpage():
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@pytest.mark.skipif(not HAS_GHOSTSCRIPT, reason="Ghostscript not available")
 | 
					@pytest.mark.skipif(not HAS_GHOSTSCRIPT, reason="Ghostscript not available")
 | 
				
			||||||
def test_transparency():
 | 
					def test_transparency() -> None:
 | 
				
			||||||
    with Image.open("Tests/images/reqd_showpage.eps") as plot_image:
 | 
					    with Image.open("Tests/images/reqd_showpage.eps") as plot_image:
 | 
				
			||||||
        plot_image.load(transparency=True)
 | 
					        plot_image.load(transparency=True)
 | 
				
			||||||
        assert plot_image.mode == "RGBA"
 | 
					        assert plot_image.mode == "RGBA"
 | 
				
			||||||
| 
						 | 
					@ -225,7 +226,7 @@ def test_transparency():
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@pytest.mark.skipif(not HAS_GHOSTSCRIPT, reason="Ghostscript not available")
 | 
					@pytest.mark.skipif(not HAS_GHOSTSCRIPT, reason="Ghostscript not available")
 | 
				
			||||||
def test_file_object(tmp_path):
 | 
					def test_file_object(tmp_path: Path) -> None:
 | 
				
			||||||
    # issue 479
 | 
					    # issue 479
 | 
				
			||||||
    with Image.open(FILE1) as image1:
 | 
					    with Image.open(FILE1) as image1:
 | 
				
			||||||
        with open(str(tmp_path / "temp.eps"), "wb") as fh:
 | 
					        with open(str(tmp_path / "temp.eps"), "wb") as fh:
 | 
				
			||||||
| 
						 | 
					@ -233,7 +234,7 @@ def test_file_object(tmp_path):
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@pytest.mark.skipif(not HAS_GHOSTSCRIPT, reason="Ghostscript not available")
 | 
					@pytest.mark.skipif(not HAS_GHOSTSCRIPT, reason="Ghostscript not available")
 | 
				
			||||||
def test_bytesio_object():
 | 
					def test_bytesio_object() -> None:
 | 
				
			||||||
    with open(FILE1, "rb") as f:
 | 
					    with open(FILE1, "rb") as f:
 | 
				
			||||||
        img_bytes = io.BytesIO(f.read())
 | 
					        img_bytes = io.BytesIO(f.read())
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -246,12 +247,12 @@ def test_bytesio_object():
 | 
				
			||||||
        assert_image_similar(img, image1_scale1_compare, 5)
 | 
					        assert_image_similar(img, image1_scale1_compare, 5)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_1_mode():
 | 
					def test_1_mode() -> None:
 | 
				
			||||||
    with Image.open("Tests/images/1.eps") as im:
 | 
					    with Image.open("Tests/images/1.eps") as im:
 | 
				
			||||||
        assert im.mode == "1"
 | 
					        assert im.mode == "1"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_image_mode_not_supported(tmp_path):
 | 
					def test_image_mode_not_supported(tmp_path: Path) -> None:
 | 
				
			||||||
    im = hopper("RGBA")
 | 
					    im = hopper("RGBA")
 | 
				
			||||||
    tmpfile = str(tmp_path / "temp.eps")
 | 
					    tmpfile = str(tmp_path / "temp.eps")
 | 
				
			||||||
    with pytest.raises(ValueError):
 | 
					    with pytest.raises(ValueError):
 | 
				
			||||||
| 
						 | 
					@ -260,7 +261,7 @@ def test_image_mode_not_supported(tmp_path):
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@pytest.mark.skipif(not HAS_GHOSTSCRIPT, reason="Ghostscript not available")
 | 
					@pytest.mark.skipif(not HAS_GHOSTSCRIPT, reason="Ghostscript not available")
 | 
				
			||||||
@skip_unless_feature("zlib")
 | 
					@skip_unless_feature("zlib")
 | 
				
			||||||
def test_render_scale1():
 | 
					def test_render_scale1() -> None:
 | 
				
			||||||
    # We need png support for these render test
 | 
					    # We need png support for these render test
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    # Zero bounding box
 | 
					    # Zero bounding box
 | 
				
			||||||
| 
						 | 
					@ -282,7 +283,7 @@ def test_render_scale1():
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@pytest.mark.skipif(not HAS_GHOSTSCRIPT, reason="Ghostscript not available")
 | 
					@pytest.mark.skipif(not HAS_GHOSTSCRIPT, reason="Ghostscript not available")
 | 
				
			||||||
@skip_unless_feature("zlib")
 | 
					@skip_unless_feature("zlib")
 | 
				
			||||||
def test_render_scale2():
 | 
					def test_render_scale2() -> None:
 | 
				
			||||||
    # We need png support for these render test
 | 
					    # We need png support for these render test
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    # Zero bounding box
 | 
					    # Zero bounding box
 | 
				
			||||||
| 
						 | 
					@ -304,7 +305,7 @@ def test_render_scale2():
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@pytest.mark.skipif(not HAS_GHOSTSCRIPT, reason="Ghostscript not available")
 | 
					@pytest.mark.skipif(not HAS_GHOSTSCRIPT, reason="Ghostscript not available")
 | 
				
			||||||
@pytest.mark.parametrize("filename", (FILE1, FILE2, "Tests/images/illu10_preview.eps"))
 | 
					@pytest.mark.parametrize("filename", (FILE1, FILE2, "Tests/images/illu10_preview.eps"))
 | 
				
			||||||
def test_resize(filename):
 | 
					def test_resize(filename) -> None:
 | 
				
			||||||
    with Image.open(filename) as im:
 | 
					    with Image.open(filename) as im:
 | 
				
			||||||
        new_size = (100, 100)
 | 
					        new_size = (100, 100)
 | 
				
			||||||
        im = im.resize(new_size)
 | 
					        im = im.resize(new_size)
 | 
				
			||||||
| 
						 | 
					@ -313,7 +314,7 @@ def test_resize(filename):
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@pytest.mark.skipif(not HAS_GHOSTSCRIPT, reason="Ghostscript not available")
 | 
					@pytest.mark.skipif(not HAS_GHOSTSCRIPT, reason="Ghostscript not available")
 | 
				
			||||||
@pytest.mark.parametrize("filename", (FILE1, FILE2))
 | 
					@pytest.mark.parametrize("filename", (FILE1, FILE2))
 | 
				
			||||||
def test_thumbnail(filename):
 | 
					def test_thumbnail(filename) -> None:
 | 
				
			||||||
    # Issue #619
 | 
					    # Issue #619
 | 
				
			||||||
    with Image.open(filename) as im:
 | 
					    with Image.open(filename) as im:
 | 
				
			||||||
        new_size = (100, 100)
 | 
					        new_size = (100, 100)
 | 
				
			||||||
| 
						 | 
					@ -321,20 +322,20 @@ def test_thumbnail(filename):
 | 
				
			||||||
        assert max(im.size) == max(new_size)
 | 
					        assert max(im.size) == max(new_size)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_read_binary_preview():
 | 
					def test_read_binary_preview() -> None:
 | 
				
			||||||
    # Issue 302
 | 
					    # Issue 302
 | 
				
			||||||
    # open image with binary preview
 | 
					    # open image with binary preview
 | 
				
			||||||
    with Image.open(FILE3):
 | 
					    with Image.open(FILE3):
 | 
				
			||||||
        pass
 | 
					        pass
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_readline_psfile(tmp_path):
 | 
					def test_readline_psfile(tmp_path: Path) -> None:
 | 
				
			||||||
    # check all the freaking line endings possible from the spec
 | 
					    # check all the freaking line endings possible from the spec
 | 
				
			||||||
    # test_string = u'something\r\nelse\n\rbaz\rbif\n'
 | 
					    # test_string = u'something\r\nelse\n\rbaz\rbif\n'
 | 
				
			||||||
    line_endings = ["\r\n", "\n", "\n\r", "\r"]
 | 
					    line_endings = ["\r\n", "\n", "\n\r", "\r"]
 | 
				
			||||||
    strings = ["something", "else", "baz", "bif"]
 | 
					    strings = ["something", "else", "baz", "bif"]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def _test_readline(t, ending):
 | 
					    def _test_readline(t, ending) -> None:
 | 
				
			||||||
        ending = "Failure with line ending: %s" % (
 | 
					        ending = "Failure with line ending: %s" % (
 | 
				
			||||||
            "".join("%s" % ord(s) for s in ending)
 | 
					            "".join("%s" % ord(s) for s in ending)
 | 
				
			||||||
        )
 | 
					        )
 | 
				
			||||||
| 
						 | 
					@ -343,13 +344,13 @@ def test_readline_psfile(tmp_path):
 | 
				
			||||||
        assert t.readline().strip("\r\n") == "baz", ending
 | 
					        assert t.readline().strip("\r\n") == "baz", ending
 | 
				
			||||||
        assert t.readline().strip("\r\n") == "bif", ending
 | 
					        assert t.readline().strip("\r\n") == "bif", ending
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def _test_readline_io_psfile(test_string, ending):
 | 
					    def _test_readline_io_psfile(test_string, ending) -> None:
 | 
				
			||||||
        f = io.BytesIO(test_string.encode("latin-1"))
 | 
					        f = io.BytesIO(test_string.encode("latin-1"))
 | 
				
			||||||
        with pytest.warns(DeprecationWarning):
 | 
					        with pytest.warns(DeprecationWarning):
 | 
				
			||||||
            t = EpsImagePlugin.PSFile(f)
 | 
					            t = EpsImagePlugin.PSFile(f)
 | 
				
			||||||
        _test_readline(t, ending)
 | 
					        _test_readline(t, ending)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def _test_readline_file_psfile(test_string, ending):
 | 
					    def _test_readline_file_psfile(test_string, ending) -> None:
 | 
				
			||||||
        f = str(tmp_path / "temp.txt")
 | 
					        f = str(tmp_path / "temp.txt")
 | 
				
			||||||
        with open(f, "wb") as w:
 | 
					        with open(f, "wb") as w:
 | 
				
			||||||
            w.write(test_string.encode("latin-1"))
 | 
					            w.write(test_string.encode("latin-1"))
 | 
				
			||||||
| 
						 | 
					@ -365,7 +366,7 @@ def test_readline_psfile(tmp_path):
 | 
				
			||||||
        _test_readline_file_psfile(s, ending)
 | 
					        _test_readline_file_psfile(s, ending)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_psfile_deprecation():
 | 
					def test_psfile_deprecation() -> None:
 | 
				
			||||||
    with pytest.warns(DeprecationWarning):
 | 
					    with pytest.warns(DeprecationWarning):
 | 
				
			||||||
        EpsImagePlugin.PSFile(None)
 | 
					        EpsImagePlugin.PSFile(None)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -375,7 +376,7 @@ def test_psfile_deprecation():
 | 
				
			||||||
    "line_ending",
 | 
					    "line_ending",
 | 
				
			||||||
    (b"\r\n", b"\n", b"\n\r", b"\r"),
 | 
					    (b"\r\n", b"\n", b"\n\r", b"\r"),
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
def test_readline(prefix, line_ending):
 | 
					def test_readline(prefix, line_ending) -> None:
 | 
				
			||||||
    simple_file = prefix + line_ending.join(simple_eps_file_with_comments)
 | 
					    simple_file = prefix + line_ending.join(simple_eps_file_with_comments)
 | 
				
			||||||
    data = io.BytesIO(simple_file)
 | 
					    data = io.BytesIO(simple_file)
 | 
				
			||||||
    test_file = EpsImagePlugin.EpsImageFile(data)
 | 
					    test_file = EpsImagePlugin.EpsImageFile(data)
 | 
				
			||||||
| 
						 | 
					@ -393,14 +394,14 @@ def test_readline(prefix, line_ending):
 | 
				
			||||||
        "Tests/images/illuCS6_preview.eps",
 | 
					        "Tests/images/illuCS6_preview.eps",
 | 
				
			||||||
    ),
 | 
					    ),
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
def test_open_eps(filename):
 | 
					def test_open_eps(filename) -> None:
 | 
				
			||||||
    # https://github.com/python-pillow/Pillow/issues/1104
 | 
					    # https://github.com/python-pillow/Pillow/issues/1104
 | 
				
			||||||
    with Image.open(filename) as img:
 | 
					    with Image.open(filename) as img:
 | 
				
			||||||
        assert img.mode == "RGB"
 | 
					        assert img.mode == "RGB"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@pytest.mark.skipif(not HAS_GHOSTSCRIPT, reason="Ghostscript not available")
 | 
					@pytest.mark.skipif(not HAS_GHOSTSCRIPT, reason="Ghostscript not available")
 | 
				
			||||||
def test_emptyline():
 | 
					def test_emptyline() -> None:
 | 
				
			||||||
    # Test file includes an empty line in the header data
 | 
					    # Test file includes an empty line in the header data
 | 
				
			||||||
    emptyline_file = "Tests/images/zero_bb_emptyline.eps"
 | 
					    emptyline_file = "Tests/images/zero_bb_emptyline.eps"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -416,14 +417,14 @@ def test_emptyline():
 | 
				
			||||||
    "test_file",
 | 
					    "test_file",
 | 
				
			||||||
    ["Tests/images/timeout-d675703545fee17acab56e5fec644c19979175de.eps"],
 | 
					    ["Tests/images/timeout-d675703545fee17acab56e5fec644c19979175de.eps"],
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
def test_timeout(test_file):
 | 
					def test_timeout(test_file) -> None:
 | 
				
			||||||
    with open(test_file, "rb") as f:
 | 
					    with open(test_file, "rb") as f:
 | 
				
			||||||
        with pytest.raises(Image.UnidentifiedImageError):
 | 
					        with pytest.raises(Image.UnidentifiedImageError):
 | 
				
			||||||
            with Image.open(f):
 | 
					            with Image.open(f):
 | 
				
			||||||
                pass
 | 
					                pass
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_bounding_box_in_trailer():
 | 
					def test_bounding_box_in_trailer() -> None:
 | 
				
			||||||
    # Check bounding boxes are parsed in the same way
 | 
					    # Check bounding boxes are parsed in the same way
 | 
				
			||||||
    # when specified in the header and the trailer
 | 
					    # when specified in the header and the trailer
 | 
				
			||||||
    with Image.open("Tests/images/zero_bb_trailer.eps") as trailer_image, Image.open(
 | 
					    with Image.open("Tests/images/zero_bb_trailer.eps") as trailer_image, Image.open(
 | 
				
			||||||
| 
						 | 
					@ -432,7 +433,7 @@ def test_bounding_box_in_trailer():
 | 
				
			||||||
        assert trailer_image.size == header_image.size
 | 
					        assert trailer_image.size == header_image.size
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_eof_before_bounding_box():
 | 
					def test_eof_before_bounding_box() -> None:
 | 
				
			||||||
    with pytest.raises(OSError):
 | 
					    with pytest.raises(OSError):
 | 
				
			||||||
        with Image.open("Tests/images/zero_bb_eof_before_boundingbox.eps"):
 | 
					        with Image.open("Tests/images/zero_bb_eof_before_boundingbox.eps"):
 | 
				
			||||||
            pass
 | 
					            pass
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -11,7 +11,7 @@ from .helper import assert_image_equal, hopper
 | 
				
			||||||
TEST_FILE = "Tests/images/hopper.fits"
 | 
					TEST_FILE = "Tests/images/hopper.fits"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_open():
 | 
					def test_open() -> None:
 | 
				
			||||||
    # Act
 | 
					    # Act
 | 
				
			||||||
    with Image.open(TEST_FILE) as im:
 | 
					    with Image.open(TEST_FILE) as im:
 | 
				
			||||||
        # Assert
 | 
					        # Assert
 | 
				
			||||||
| 
						 | 
					@ -22,7 +22,7 @@ def test_open():
 | 
				
			||||||
        assert_image_equal(im, hopper("L"))
 | 
					        assert_image_equal(im, hopper("L"))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_invalid_file():
 | 
					def test_invalid_file() -> None:
 | 
				
			||||||
    # Arrange
 | 
					    # Arrange
 | 
				
			||||||
    invalid_file = "Tests/images/flower.jpg"
 | 
					    invalid_file = "Tests/images/flower.jpg"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -31,14 +31,14 @@ def test_invalid_file():
 | 
				
			||||||
        FitsImagePlugin.FitsImageFile(invalid_file)
 | 
					        FitsImagePlugin.FitsImageFile(invalid_file)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_truncated_fits():
 | 
					def test_truncated_fits() -> None:
 | 
				
			||||||
    # No END to headers
 | 
					    # No END to headers
 | 
				
			||||||
    image_data = b"SIMPLE  =                    T" + b" " * 50 + b"TRUNCATE"
 | 
					    image_data = b"SIMPLE  =                    T" + b" " * 50 + b"TRUNCATE"
 | 
				
			||||||
    with pytest.raises(OSError):
 | 
					    with pytest.raises(OSError):
 | 
				
			||||||
        FitsImagePlugin.FitsImageFile(BytesIO(image_data))
 | 
					        FitsImagePlugin.FitsImageFile(BytesIO(image_data))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_naxis_zero():
 | 
					def test_naxis_zero() -> None:
 | 
				
			||||||
    # This test image has been manually hexedited
 | 
					    # This test image has been manually hexedited
 | 
				
			||||||
    # to set the number of data axes to zero
 | 
					    # to set the number of data axes to zero
 | 
				
			||||||
    with pytest.raises(ValueError):
 | 
					    with pytest.raises(ValueError):
 | 
				
			||||||
| 
						 | 
					@ -46,7 +46,7 @@ def test_naxis_zero():
 | 
				
			||||||
            pass
 | 
					            pass
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_comment():
 | 
					def test_comment() -> None:
 | 
				
			||||||
    image_data = b"SIMPLE  =                    T / comment string"
 | 
					    image_data = b"SIMPLE  =                    T / comment string"
 | 
				
			||||||
    with pytest.raises(OSError):
 | 
					    with pytest.raises(OSError):
 | 
				
			||||||
        FitsImagePlugin.FitsImageFile(BytesIO(image_data))
 | 
					        FitsImagePlugin.FitsImageFile(BytesIO(image_data))
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -16,7 +16,7 @@ static_test_file = "Tests/images/hopper.fli"
 | 
				
			||||||
animated_test_file = "Tests/images/a.fli"
 | 
					animated_test_file = "Tests/images/a.fli"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_sanity():
 | 
					def test_sanity() -> None:
 | 
				
			||||||
    with Image.open(static_test_file) as im:
 | 
					    with Image.open(static_test_file) as im:
 | 
				
			||||||
        im.load()
 | 
					        im.load()
 | 
				
			||||||
        assert im.mode == "P"
 | 
					        assert im.mode == "P"
 | 
				
			||||||
| 
						 | 
					@ -33,8 +33,8 @@ def test_sanity():
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@pytest.mark.skipif(is_pypy(), reason="Requires CPython")
 | 
					@pytest.mark.skipif(is_pypy(), reason="Requires CPython")
 | 
				
			||||||
def test_unclosed_file():
 | 
					def test_unclosed_file() -> None:
 | 
				
			||||||
    def open():
 | 
					    def open() -> None:
 | 
				
			||||||
        im = Image.open(static_test_file)
 | 
					        im = Image.open(static_test_file)
 | 
				
			||||||
        im.load()
 | 
					        im.load()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -42,14 +42,14 @@ def test_unclosed_file():
 | 
				
			||||||
        open()
 | 
					        open()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_closed_file():
 | 
					def test_closed_file() -> None:
 | 
				
			||||||
    with warnings.catch_warnings():
 | 
					    with warnings.catch_warnings():
 | 
				
			||||||
        im = Image.open(static_test_file)
 | 
					        im = Image.open(static_test_file)
 | 
				
			||||||
        im.load()
 | 
					        im.load()
 | 
				
			||||||
        im.close()
 | 
					        im.close()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_seek_after_close():
 | 
					def test_seek_after_close() -> None:
 | 
				
			||||||
    im = Image.open(animated_test_file)
 | 
					    im = Image.open(animated_test_file)
 | 
				
			||||||
    im.seek(1)
 | 
					    im.seek(1)
 | 
				
			||||||
    im.close()
 | 
					    im.close()
 | 
				
			||||||
| 
						 | 
					@ -58,13 +58,13 @@ def test_seek_after_close():
 | 
				
			||||||
        im.seek(0)
 | 
					        im.seek(0)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_context_manager():
 | 
					def test_context_manager() -> None:
 | 
				
			||||||
    with warnings.catch_warnings():
 | 
					    with warnings.catch_warnings():
 | 
				
			||||||
        with Image.open(static_test_file) as im:
 | 
					        with Image.open(static_test_file) as im:
 | 
				
			||||||
            im.load()
 | 
					            im.load()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_tell():
 | 
					def test_tell() -> None:
 | 
				
			||||||
    # Arrange
 | 
					    # Arrange
 | 
				
			||||||
    with Image.open(static_test_file) as im:
 | 
					    with Image.open(static_test_file) as im:
 | 
				
			||||||
        # Act
 | 
					        # Act
 | 
				
			||||||
| 
						 | 
					@ -74,20 +74,20 @@ def test_tell():
 | 
				
			||||||
        assert frame == 0
 | 
					        assert frame == 0
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_invalid_file():
 | 
					def test_invalid_file() -> None:
 | 
				
			||||||
    invalid_file = "Tests/images/flower.jpg"
 | 
					    invalid_file = "Tests/images/flower.jpg"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    with pytest.raises(SyntaxError):
 | 
					    with pytest.raises(SyntaxError):
 | 
				
			||||||
        FliImagePlugin.FliImageFile(invalid_file)
 | 
					        FliImagePlugin.FliImageFile(invalid_file)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_palette_chunk_second():
 | 
					def test_palette_chunk_second() -> None:
 | 
				
			||||||
    with Image.open("Tests/images/hopper_palette_chunk_second.fli") as im:
 | 
					    with Image.open("Tests/images/hopper_palette_chunk_second.fli") as im:
 | 
				
			||||||
        with Image.open(static_test_file) as expected:
 | 
					        with Image.open(static_test_file) as expected:
 | 
				
			||||||
            assert_image_equal(im.convert("RGB"), expected.convert("RGB"))
 | 
					            assert_image_equal(im.convert("RGB"), expected.convert("RGB"))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_n_frames():
 | 
					def test_n_frames() -> None:
 | 
				
			||||||
    with Image.open(static_test_file) as im:
 | 
					    with Image.open(static_test_file) as im:
 | 
				
			||||||
        assert im.n_frames == 1
 | 
					        assert im.n_frames == 1
 | 
				
			||||||
        assert not im.is_animated
 | 
					        assert not im.is_animated
 | 
				
			||||||
| 
						 | 
					@ -97,7 +97,7 @@ def test_n_frames():
 | 
				
			||||||
        assert im.is_animated
 | 
					        assert im.is_animated
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_eoferror():
 | 
					def test_eoferror() -> None:
 | 
				
			||||||
    with Image.open(animated_test_file) as im:
 | 
					    with Image.open(animated_test_file) as im:
 | 
				
			||||||
        n_frames = im.n_frames
 | 
					        n_frames = im.n_frames
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -110,7 +110,7 @@ def test_eoferror():
 | 
				
			||||||
        im.seek(n_frames - 1)
 | 
					        im.seek(n_frames - 1)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_seek_tell():
 | 
					def test_seek_tell() -> None:
 | 
				
			||||||
    with Image.open(animated_test_file) as im:
 | 
					    with Image.open(animated_test_file) as im:
 | 
				
			||||||
        layer_number = im.tell()
 | 
					        layer_number = im.tell()
 | 
				
			||||||
        assert layer_number == 0
 | 
					        assert layer_number == 0
 | 
				
			||||||
| 
						 | 
					@ -132,7 +132,7 @@ def test_seek_tell():
 | 
				
			||||||
        assert layer_number == 1
 | 
					        assert layer_number == 1
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_seek():
 | 
					def test_seek() -> None:
 | 
				
			||||||
    with Image.open(animated_test_file) as im:
 | 
					    with Image.open(animated_test_file) as im:
 | 
				
			||||||
        im.seek(50)
 | 
					        im.seek(50)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -147,7 +147,7 @@ def test_seek():
 | 
				
			||||||
    ],
 | 
					    ],
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
@pytest.mark.timeout(timeout=3)
 | 
					@pytest.mark.timeout(timeout=3)
 | 
				
			||||||
def test_timeouts(test_file):
 | 
					def test_timeouts(test_file) -> None:
 | 
				
			||||||
    with open(test_file, "rb") as f:
 | 
					    with open(test_file, "rb") as f:
 | 
				
			||||||
        with Image.open(f) as im:
 | 
					        with Image.open(f) as im:
 | 
				
			||||||
            with pytest.raises(OSError):
 | 
					            with pytest.raises(OSError):
 | 
				
			||||||
| 
						 | 
					@ -160,7 +160,7 @@ def test_timeouts(test_file):
 | 
				
			||||||
        "Tests/images/crash-5762152299364352.fli",
 | 
					        "Tests/images/crash-5762152299364352.fli",
 | 
				
			||||||
    ],
 | 
					    ],
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
def test_crash(test_file):
 | 
					def test_crash(test_file) -> None:
 | 
				
			||||||
    with open(test_file, "rb") as f:
 | 
					    with open(test_file, "rb") as f:
 | 
				
			||||||
        with Image.open(f) as im:
 | 
					        with Image.open(f) as im:
 | 
				
			||||||
            with pytest.raises(OSError):
 | 
					            with pytest.raises(OSError):
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -11,7 +11,7 @@ FpxImagePlugin = pytest.importorskip(
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_sanity():
 | 
					def test_sanity() -> None:
 | 
				
			||||||
    with Image.open("Tests/images/input_bw_one_band.fpx") as im:
 | 
					    with Image.open("Tests/images/input_bw_one_band.fpx") as im:
 | 
				
			||||||
        assert im.mode == "L"
 | 
					        assert im.mode == "L"
 | 
				
			||||||
        assert im.size == (70, 46)
 | 
					        assert im.size == (70, 46)
 | 
				
			||||||
| 
						 | 
					@ -20,7 +20,7 @@ def test_sanity():
 | 
				
			||||||
        assert_image_equal_tofile(im, "Tests/images/input_bw_one_band.png")
 | 
					        assert_image_equal_tofile(im, "Tests/images/input_bw_one_band.png")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_close():
 | 
					def test_close() -> None:
 | 
				
			||||||
    with Image.open("Tests/images/input_bw_one_band.fpx") as im:
 | 
					    with Image.open("Tests/images/input_bw_one_band.fpx") as im:
 | 
				
			||||||
        pass
 | 
					        pass
 | 
				
			||||||
    assert im.ole.fp.closed
 | 
					    assert im.ole.fp.closed
 | 
				
			||||||
| 
						 | 
					@ -30,7 +30,7 @@ def test_close():
 | 
				
			||||||
    assert im.ole.fp.closed
 | 
					    assert im.ole.fp.closed
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_invalid_file():
 | 
					def test_invalid_file() -> None:
 | 
				
			||||||
    # Test an invalid OLE file
 | 
					    # Test an invalid OLE file
 | 
				
			||||||
    invalid_file = "Tests/images/flower.jpg"
 | 
					    invalid_file = "Tests/images/flower.jpg"
 | 
				
			||||||
    with pytest.raises(SyntaxError):
 | 
					    with pytest.raises(SyntaxError):
 | 
				
			||||||
| 
						 | 
					@ -42,7 +42,7 @@ def test_invalid_file():
 | 
				
			||||||
        FpxImagePlugin.FpxImageFile(ole_file)
 | 
					        FpxImagePlugin.FpxImageFile(ole_file)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_fpx_invalid_number_of_bands():
 | 
					def test_fpx_invalid_number_of_bands() -> None:
 | 
				
			||||||
    with pytest.raises(OSError, match="Invalid number of bands"):
 | 
					    with pytest.raises(OSError, match="Invalid number of bands"):
 | 
				
			||||||
        with Image.open("Tests/images/input_bw_five_bands.fpx"):
 | 
					        with Image.open("Tests/images/input_bw_five_bands.fpx"):
 | 
				
			||||||
            pass
 | 
					            pass
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -2,6 +2,7 @@ from __future__ import annotations
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import warnings
 | 
					import warnings
 | 
				
			||||||
from io import BytesIO
 | 
					from io import BytesIO
 | 
				
			||||||
 | 
					from pathlib import Path
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import pytest
 | 
					import pytest
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -23,7 +24,7 @@ with open(TEST_GIF, "rb") as f:
 | 
				
			||||||
    data = f.read()
 | 
					    data = f.read()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_sanity():
 | 
					def test_sanity() -> None:
 | 
				
			||||||
    with Image.open(TEST_GIF) as im:
 | 
					    with Image.open(TEST_GIF) as im:
 | 
				
			||||||
        im.load()
 | 
					        im.load()
 | 
				
			||||||
        assert im.mode == "P"
 | 
					        assert im.mode == "P"
 | 
				
			||||||
| 
						 | 
					@ -33,8 +34,8 @@ def test_sanity():
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@pytest.mark.skipif(is_pypy(), reason="Requires CPython")
 | 
					@pytest.mark.skipif(is_pypy(), reason="Requires CPython")
 | 
				
			||||||
def test_unclosed_file():
 | 
					def test_unclosed_file() -> None:
 | 
				
			||||||
    def open():
 | 
					    def open() -> None:
 | 
				
			||||||
        im = Image.open(TEST_GIF)
 | 
					        im = Image.open(TEST_GIF)
 | 
				
			||||||
        im.load()
 | 
					        im.load()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -42,14 +43,14 @@ def test_unclosed_file():
 | 
				
			||||||
        open()
 | 
					        open()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_closed_file():
 | 
					def test_closed_file() -> None:
 | 
				
			||||||
    with warnings.catch_warnings():
 | 
					    with warnings.catch_warnings():
 | 
				
			||||||
        im = Image.open(TEST_GIF)
 | 
					        im = Image.open(TEST_GIF)
 | 
				
			||||||
        im.load()
 | 
					        im.load()
 | 
				
			||||||
        im.close()
 | 
					        im.close()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_seek_after_close():
 | 
					def test_seek_after_close() -> None:
 | 
				
			||||||
    im = Image.open("Tests/images/iss634.gif")
 | 
					    im = Image.open("Tests/images/iss634.gif")
 | 
				
			||||||
    im.load()
 | 
					    im.load()
 | 
				
			||||||
    im.close()
 | 
					    im.close()
 | 
				
			||||||
| 
						 | 
					@ -62,20 +63,20 @@ def test_seek_after_close():
 | 
				
			||||||
        im.seek(1)
 | 
					        im.seek(1)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_context_manager():
 | 
					def test_context_manager() -> None:
 | 
				
			||||||
    with warnings.catch_warnings():
 | 
					    with warnings.catch_warnings():
 | 
				
			||||||
        with Image.open(TEST_GIF) as im:
 | 
					        with Image.open(TEST_GIF) as im:
 | 
				
			||||||
            im.load()
 | 
					            im.load()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_invalid_file():
 | 
					def test_invalid_file() -> None:
 | 
				
			||||||
    invalid_file = "Tests/images/flower.jpg"
 | 
					    invalid_file = "Tests/images/flower.jpg"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    with pytest.raises(SyntaxError):
 | 
					    with pytest.raises(SyntaxError):
 | 
				
			||||||
        GifImagePlugin.GifImageFile(invalid_file)
 | 
					        GifImagePlugin.GifImageFile(invalid_file)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_l_mode_transparency():
 | 
					def test_l_mode_transparency() -> None:
 | 
				
			||||||
    with Image.open("Tests/images/no_palette_with_transparency.gif") as im:
 | 
					    with Image.open("Tests/images/no_palette_with_transparency.gif") as im:
 | 
				
			||||||
        assert im.mode == "L"
 | 
					        assert im.mode == "L"
 | 
				
			||||||
        assert im.load()[0, 0] == 128
 | 
					        assert im.load()[0, 0] == 128
 | 
				
			||||||
| 
						 | 
					@ -86,7 +87,7 @@ def test_l_mode_transparency():
 | 
				
			||||||
        assert im.load()[0, 0] == 128
 | 
					        assert im.load()[0, 0] == 128
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_l_mode_after_rgb():
 | 
					def test_l_mode_after_rgb() -> None:
 | 
				
			||||||
    with Image.open("Tests/images/no_palette_after_rgb.gif") as im:
 | 
					    with Image.open("Tests/images/no_palette_after_rgb.gif") as im:
 | 
				
			||||||
        im.seek(1)
 | 
					        im.seek(1)
 | 
				
			||||||
        assert im.mode == "RGB"
 | 
					        assert im.mode == "RGB"
 | 
				
			||||||
| 
						 | 
					@ -95,13 +96,13 @@ def test_l_mode_after_rgb():
 | 
				
			||||||
        assert im.mode == "RGB"
 | 
					        assert im.mode == "RGB"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_palette_not_needed_for_second_frame():
 | 
					def test_palette_not_needed_for_second_frame() -> None:
 | 
				
			||||||
    with Image.open("Tests/images/palette_not_needed_for_second_frame.gif") as im:
 | 
					    with Image.open("Tests/images/palette_not_needed_for_second_frame.gif") as im:
 | 
				
			||||||
        im.seek(1)
 | 
					        im.seek(1)
 | 
				
			||||||
        assert_image_similar(im, hopper("L").convert("RGB"), 8)
 | 
					        assert_image_similar(im, hopper("L").convert("RGB"), 8)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_strategy():
 | 
					def test_strategy() -> None:
 | 
				
			||||||
    with Image.open("Tests/images/iss634.gif") as im:
 | 
					    with Image.open("Tests/images/iss634.gif") as im:
 | 
				
			||||||
        expected_rgb_always = im.convert("RGB")
 | 
					        expected_rgb_always = im.convert("RGB")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -142,7 +143,7 @@ def test_strategy():
 | 
				
			||||||
        GifImagePlugin.LOADING_STRATEGY = GifImagePlugin.LoadingStrategy.RGB_AFTER_FIRST
 | 
					        GifImagePlugin.LOADING_STRATEGY = GifImagePlugin.LoadingStrategy.RGB_AFTER_FIRST
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_optimize():
 | 
					def test_optimize() -> None:
 | 
				
			||||||
    def test_grayscale(optimize):
 | 
					    def test_grayscale(optimize):
 | 
				
			||||||
        im = Image.new("L", (1, 1), 0)
 | 
					        im = Image.new("L", (1, 1), 0)
 | 
				
			||||||
        filename = BytesIO()
 | 
					        filename = BytesIO()
 | 
				
			||||||
| 
						 | 
					@ -177,7 +178,7 @@ def test_optimize():
 | 
				
			||||||
        (4, 513, 256),
 | 
					        (4, 513, 256),
 | 
				
			||||||
    ),
 | 
					    ),
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
def test_optimize_correctness(colors, size, expected_palette_length):
 | 
					def test_optimize_correctness(colors, size, expected_palette_length) -> None:
 | 
				
			||||||
    # 256 color Palette image, posterize to > 128 and < 128 levels.
 | 
					    # 256 color Palette image, posterize to > 128 and < 128 levels.
 | 
				
			||||||
    # Size bigger and smaller than 512x512.
 | 
					    # Size bigger and smaller than 512x512.
 | 
				
			||||||
    # Check the palette for number of colors allocated.
 | 
					    # Check the palette for number of colors allocated.
 | 
				
			||||||
| 
						 | 
					@ -199,14 +200,14 @@ def test_optimize_correctness(colors, size, expected_palette_length):
 | 
				
			||||||
        assert_image_equal(im.convert("RGB"), reloaded.convert("RGB"))
 | 
					        assert_image_equal(im.convert("RGB"), reloaded.convert("RGB"))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_optimize_full_l():
 | 
					def test_optimize_full_l() -> None:
 | 
				
			||||||
    im = Image.frombytes("L", (16, 16), bytes(range(256)))
 | 
					    im = Image.frombytes("L", (16, 16), bytes(range(256)))
 | 
				
			||||||
    test_file = BytesIO()
 | 
					    test_file = BytesIO()
 | 
				
			||||||
    im.save(test_file, "GIF", optimize=True)
 | 
					    im.save(test_file, "GIF", optimize=True)
 | 
				
			||||||
    assert im.mode == "L"
 | 
					    assert im.mode == "L"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_optimize_if_palette_can_be_reduced_by_half():
 | 
					def test_optimize_if_palette_can_be_reduced_by_half() -> None:
 | 
				
			||||||
    im = Image.new("P", (8, 1))
 | 
					    im = Image.new("P", (8, 1))
 | 
				
			||||||
    im.palette = ImagePalette.raw("RGB", bytes((0, 0, 0) * 150))
 | 
					    im.palette = ImagePalette.raw("RGB", bytes((0, 0, 0) * 150))
 | 
				
			||||||
    for i in range(8):
 | 
					    for i in range(8):
 | 
				
			||||||
| 
						 | 
					@ -219,7 +220,7 @@ def test_optimize_if_palette_can_be_reduced_by_half():
 | 
				
			||||||
            assert len(reloaded.palette.palette) // 3 == colors
 | 
					            assert len(reloaded.palette.palette) // 3 == colors
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_full_palette_second_frame(tmp_path):
 | 
					def test_full_palette_second_frame(tmp_path: Path) -> None:
 | 
				
			||||||
    out = str(tmp_path / "temp.gif")
 | 
					    out = str(tmp_path / "temp.gif")
 | 
				
			||||||
    im = Image.new("P", (1, 256))
 | 
					    im = Image.new("P", (1, 256))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -240,7 +241,7 @@ def test_full_palette_second_frame(tmp_path):
 | 
				
			||||||
            reloaded.getpixel((0, i)) == i
 | 
					            reloaded.getpixel((0, i)) == i
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_roundtrip(tmp_path):
 | 
					def test_roundtrip(tmp_path: Path) -> None:
 | 
				
			||||||
    out = str(tmp_path / "temp.gif")
 | 
					    out = str(tmp_path / "temp.gif")
 | 
				
			||||||
    im = hopper()
 | 
					    im = hopper()
 | 
				
			||||||
    im.save(out)
 | 
					    im.save(out)
 | 
				
			||||||
| 
						 | 
					@ -248,7 +249,7 @@ def test_roundtrip(tmp_path):
 | 
				
			||||||
        assert_image_similar(reread.convert("RGB"), im, 50)
 | 
					        assert_image_similar(reread.convert("RGB"), im, 50)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_roundtrip2(tmp_path):
 | 
					def test_roundtrip2(tmp_path: Path) -> None:
 | 
				
			||||||
    # see https://github.com/python-pillow/Pillow/issues/403
 | 
					    # see https://github.com/python-pillow/Pillow/issues/403
 | 
				
			||||||
    out = str(tmp_path / "temp.gif")
 | 
					    out = str(tmp_path / "temp.gif")
 | 
				
			||||||
    with Image.open(TEST_GIF) as im:
 | 
					    with Image.open(TEST_GIF) as im:
 | 
				
			||||||
| 
						 | 
					@ -258,7 +259,7 @@ def test_roundtrip2(tmp_path):
 | 
				
			||||||
        assert_image_similar(reread.convert("RGB"), hopper(), 50)
 | 
					        assert_image_similar(reread.convert("RGB"), hopper(), 50)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_roundtrip_save_all(tmp_path):
 | 
					def test_roundtrip_save_all(tmp_path: Path) -> None:
 | 
				
			||||||
    # Single frame image
 | 
					    # Single frame image
 | 
				
			||||||
    out = str(tmp_path / "temp.gif")
 | 
					    out = str(tmp_path / "temp.gif")
 | 
				
			||||||
    im = hopper()
 | 
					    im = hopper()
 | 
				
			||||||
| 
						 | 
					@ -275,7 +276,7 @@ def test_roundtrip_save_all(tmp_path):
 | 
				
			||||||
        assert reread.n_frames == 5
 | 
					        assert reread.n_frames == 5
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_roundtrip_save_all_1(tmp_path):
 | 
					def test_roundtrip_save_all_1(tmp_path: Path) -> None:
 | 
				
			||||||
    out = str(tmp_path / "temp.gif")
 | 
					    out = str(tmp_path / "temp.gif")
 | 
				
			||||||
    im = Image.new("1", (1, 1))
 | 
					    im = Image.new("1", (1, 1))
 | 
				
			||||||
    im2 = Image.new("1", (1, 1), 1)
 | 
					    im2 = Image.new("1", (1, 1), 1)
 | 
				
			||||||
| 
						 | 
					@ -296,7 +297,7 @@ def test_roundtrip_save_all_1(tmp_path):
 | 
				
			||||||
        ("Tests/images/dispose_bgnd_rgba.gif", "RGBA"),
 | 
					        ("Tests/images/dispose_bgnd_rgba.gif", "RGBA"),
 | 
				
			||||||
    ),
 | 
					    ),
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
def test_loading_multiple_palettes(path, mode):
 | 
					def test_loading_multiple_palettes(path, mode) -> None:
 | 
				
			||||||
    with Image.open(path) as im:
 | 
					    with Image.open(path) as im:
 | 
				
			||||||
        assert im.mode == "P"
 | 
					        assert im.mode == "P"
 | 
				
			||||||
        first_frame_colors = im.palette.colors.keys()
 | 
					        first_frame_colors = im.palette.colors.keys()
 | 
				
			||||||
| 
						 | 
					@ -314,7 +315,7 @@ def test_loading_multiple_palettes(path, mode):
 | 
				
			||||||
        assert im.load()[24, 24] not in first_frame_colors
 | 
					        assert im.load()[24, 24] not in first_frame_colors
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_headers_saving_for_animated_gifs(tmp_path):
 | 
					def test_headers_saving_for_animated_gifs(tmp_path: Path) -> None:
 | 
				
			||||||
    important_headers = ["background", "version", "duration", "loop"]
 | 
					    important_headers = ["background", "version", "duration", "loop"]
 | 
				
			||||||
    # Multiframe image
 | 
					    # Multiframe image
 | 
				
			||||||
    with Image.open("Tests/images/dispose_bgnd.gif") as im:
 | 
					    with Image.open("Tests/images/dispose_bgnd.gif") as im:
 | 
				
			||||||
| 
						 | 
					@ -327,7 +328,7 @@ def test_headers_saving_for_animated_gifs(tmp_path):
 | 
				
			||||||
            assert info[header] == reread.info[header]
 | 
					            assert info[header] == reread.info[header]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_palette_handling(tmp_path):
 | 
					def test_palette_handling(tmp_path: Path) -> None:
 | 
				
			||||||
    # see https://github.com/python-pillow/Pillow/issues/513
 | 
					    # see https://github.com/python-pillow/Pillow/issues/513
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    with Image.open(TEST_GIF) as im:
 | 
					    with Image.open(TEST_GIF) as im:
 | 
				
			||||||
| 
						 | 
					@ -343,7 +344,7 @@ def test_palette_handling(tmp_path):
 | 
				
			||||||
        assert_image_similar(im, reloaded.convert("RGB"), 10)
 | 
					        assert_image_similar(im, reloaded.convert("RGB"), 10)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_palette_434(tmp_path):
 | 
					def test_palette_434(tmp_path: Path) -> None:
 | 
				
			||||||
    # see https://github.com/python-pillow/Pillow/issues/434
 | 
					    # see https://github.com/python-pillow/Pillow/issues/434
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def roundtrip(im, *args, **kwargs):
 | 
					    def roundtrip(im, *args, **kwargs):
 | 
				
			||||||
| 
						 | 
					@ -368,7 +369,7 @@ def test_palette_434(tmp_path):
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@pytest.mark.skipif(not netpbm_available(), reason="Netpbm not available")
 | 
					@pytest.mark.skipif(not netpbm_available(), reason="Netpbm not available")
 | 
				
			||||||
def test_save_netpbm_bmp_mode(tmp_path):
 | 
					def test_save_netpbm_bmp_mode(tmp_path: Path) -> None:
 | 
				
			||||||
    with Image.open(TEST_GIF) as img:
 | 
					    with Image.open(TEST_GIF) as img:
 | 
				
			||||||
        img = img.convert("RGB")
 | 
					        img = img.convert("RGB")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -379,7 +380,7 @@ def test_save_netpbm_bmp_mode(tmp_path):
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@pytest.mark.skipif(not netpbm_available(), reason="Netpbm not available")
 | 
					@pytest.mark.skipif(not netpbm_available(), reason="Netpbm not available")
 | 
				
			||||||
def test_save_netpbm_l_mode(tmp_path):
 | 
					def test_save_netpbm_l_mode(tmp_path: Path) -> None:
 | 
				
			||||||
    with Image.open(TEST_GIF) as img:
 | 
					    with Image.open(TEST_GIF) as img:
 | 
				
			||||||
        img = img.convert("L")
 | 
					        img = img.convert("L")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -389,7 +390,7 @@ def test_save_netpbm_l_mode(tmp_path):
 | 
				
			||||||
            assert_image_similar(img, reloaded.convert("L"), 0)
 | 
					            assert_image_similar(img, reloaded.convert("L"), 0)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_seek():
 | 
					def test_seek() -> None:
 | 
				
			||||||
    with Image.open("Tests/images/dispose_none.gif") as img:
 | 
					    with Image.open("Tests/images/dispose_none.gif") as img:
 | 
				
			||||||
        frame_count = 0
 | 
					        frame_count = 0
 | 
				
			||||||
        try:
 | 
					        try:
 | 
				
			||||||
| 
						 | 
					@ -400,7 +401,7 @@ def test_seek():
 | 
				
			||||||
            assert frame_count == 5
 | 
					            assert frame_count == 5
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_seek_info():
 | 
					def test_seek_info() -> None:
 | 
				
			||||||
    with Image.open("Tests/images/iss634.gif") as im:
 | 
					    with Image.open("Tests/images/iss634.gif") as im:
 | 
				
			||||||
        info = im.info.copy()
 | 
					        info = im.info.copy()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -410,7 +411,7 @@ def test_seek_info():
 | 
				
			||||||
        assert im.info == info
 | 
					        assert im.info == info
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_seek_rewind():
 | 
					def test_seek_rewind() -> None:
 | 
				
			||||||
    with Image.open("Tests/images/iss634.gif") as im:
 | 
					    with Image.open("Tests/images/iss634.gif") as im:
 | 
				
			||||||
        im.seek(2)
 | 
					        im.seek(2)
 | 
				
			||||||
        im.seek(1)
 | 
					        im.seek(1)
 | 
				
			||||||
| 
						 | 
					@ -428,7 +429,7 @@ def test_seek_rewind():
 | 
				
			||||||
        ("Tests/images/iss634.gif", 42),
 | 
					        ("Tests/images/iss634.gif", 42),
 | 
				
			||||||
    ),
 | 
					    ),
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
def test_n_frames(path, n_frames):
 | 
					def test_n_frames(path, n_frames) -> None:
 | 
				
			||||||
    # Test is_animated before n_frames
 | 
					    # Test is_animated before n_frames
 | 
				
			||||||
    with Image.open(path) as im:
 | 
					    with Image.open(path) as im:
 | 
				
			||||||
        assert im.is_animated == (n_frames != 1)
 | 
					        assert im.is_animated == (n_frames != 1)
 | 
				
			||||||
| 
						 | 
					@ -439,7 +440,7 @@ def test_n_frames(path, n_frames):
 | 
				
			||||||
        assert im.is_animated == (n_frames != 1)
 | 
					        assert im.is_animated == (n_frames != 1)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_no_change():
 | 
					def test_no_change() -> None:
 | 
				
			||||||
    # Test n_frames does not change the image
 | 
					    # Test n_frames does not change the image
 | 
				
			||||||
    with Image.open("Tests/images/dispose_bgnd.gif") as im:
 | 
					    with Image.open("Tests/images/dispose_bgnd.gif") as im:
 | 
				
			||||||
        im.seek(1)
 | 
					        im.seek(1)
 | 
				
			||||||
| 
						 | 
					@ -460,7 +461,7 @@ def test_no_change():
 | 
				
			||||||
        assert_image_equal(im, expected)
 | 
					        assert_image_equal(im, expected)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_eoferror():
 | 
					def test_eoferror() -> None:
 | 
				
			||||||
    with Image.open(TEST_GIF) as im:
 | 
					    with Image.open(TEST_GIF) as im:
 | 
				
			||||||
        n_frames = im.n_frames
 | 
					        n_frames = im.n_frames
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -473,13 +474,13 @@ def test_eoferror():
 | 
				
			||||||
        im.seek(n_frames - 1)
 | 
					        im.seek(n_frames - 1)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_first_frame_transparency():
 | 
					def test_first_frame_transparency() -> None:
 | 
				
			||||||
    with Image.open("Tests/images/first_frame_transparency.gif") as im:
 | 
					    with Image.open("Tests/images/first_frame_transparency.gif") as im:
 | 
				
			||||||
        px = im.load()
 | 
					        px = im.load()
 | 
				
			||||||
        assert px[0, 0] == im.info["transparency"]
 | 
					        assert px[0, 0] == im.info["transparency"]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_dispose_none():
 | 
					def test_dispose_none() -> None:
 | 
				
			||||||
    with Image.open("Tests/images/dispose_none.gif") as img:
 | 
					    with Image.open("Tests/images/dispose_none.gif") as img:
 | 
				
			||||||
        try:
 | 
					        try:
 | 
				
			||||||
            while True:
 | 
					            while True:
 | 
				
			||||||
| 
						 | 
					@ -489,7 +490,7 @@ def test_dispose_none():
 | 
				
			||||||
            pass
 | 
					            pass
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_dispose_none_load_end():
 | 
					def test_dispose_none_load_end() -> None:
 | 
				
			||||||
    # Test image created with:
 | 
					    # Test image created with:
 | 
				
			||||||
    #
 | 
					    #
 | 
				
			||||||
    # im = Image.open("transparent.gif")
 | 
					    # im = Image.open("transparent.gif")
 | 
				
			||||||
| 
						 | 
					@ -502,7 +503,7 @@ def test_dispose_none_load_end():
 | 
				
			||||||
        assert_image_equal_tofile(img, "Tests/images/dispose_none_load_end_second.png")
 | 
					        assert_image_equal_tofile(img, "Tests/images/dispose_none_load_end_second.png")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_dispose_background():
 | 
					def test_dispose_background() -> None:
 | 
				
			||||||
    with Image.open("Tests/images/dispose_bgnd.gif") as img:
 | 
					    with Image.open("Tests/images/dispose_bgnd.gif") as img:
 | 
				
			||||||
        try:
 | 
					        try:
 | 
				
			||||||
            while True:
 | 
					            while True:
 | 
				
			||||||
| 
						 | 
					@ -512,7 +513,7 @@ def test_dispose_background():
 | 
				
			||||||
            pass
 | 
					            pass
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_dispose_background_transparency():
 | 
					def test_dispose_background_transparency() -> None:
 | 
				
			||||||
    with Image.open("Tests/images/dispose_bgnd_transparency.gif") as img:
 | 
					    with Image.open("Tests/images/dispose_bgnd_transparency.gif") as img:
 | 
				
			||||||
        img.seek(2)
 | 
					        img.seek(2)
 | 
				
			||||||
        px = img.load()
 | 
					        px = img.load()
 | 
				
			||||||
| 
						 | 
					@ -540,7 +541,7 @@ def test_dispose_background_transparency():
 | 
				
			||||||
        ),
 | 
					        ),
 | 
				
			||||||
    ),
 | 
					    ),
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
def test_transparent_dispose(loading_strategy, expected_colors):
 | 
					def test_transparent_dispose(loading_strategy, expected_colors) -> None:
 | 
				
			||||||
    GifImagePlugin.LOADING_STRATEGY = loading_strategy
 | 
					    GifImagePlugin.LOADING_STRATEGY = loading_strategy
 | 
				
			||||||
    try:
 | 
					    try:
 | 
				
			||||||
        with Image.open("Tests/images/transparent_dispose.gif") as img:
 | 
					        with Image.open("Tests/images/transparent_dispose.gif") as img:
 | 
				
			||||||
| 
						 | 
					@ -553,7 +554,7 @@ def test_transparent_dispose(loading_strategy, expected_colors):
 | 
				
			||||||
        GifImagePlugin.LOADING_STRATEGY = GifImagePlugin.LoadingStrategy.RGB_AFTER_FIRST
 | 
					        GifImagePlugin.LOADING_STRATEGY = GifImagePlugin.LoadingStrategy.RGB_AFTER_FIRST
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_dispose_previous():
 | 
					def test_dispose_previous() -> None:
 | 
				
			||||||
    with Image.open("Tests/images/dispose_prev.gif") as img:
 | 
					    with Image.open("Tests/images/dispose_prev.gif") as img:
 | 
				
			||||||
        try:
 | 
					        try:
 | 
				
			||||||
            while True:
 | 
					            while True:
 | 
				
			||||||
| 
						 | 
					@ -563,7 +564,7 @@ def test_dispose_previous():
 | 
				
			||||||
            pass
 | 
					            pass
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_dispose_previous_first_frame():
 | 
					def test_dispose_previous_first_frame() -> None:
 | 
				
			||||||
    with Image.open("Tests/images/dispose_prev_first_frame.gif") as im:
 | 
					    with Image.open("Tests/images/dispose_prev_first_frame.gif") as im:
 | 
				
			||||||
        im.seek(1)
 | 
					        im.seek(1)
 | 
				
			||||||
        assert_image_equal_tofile(
 | 
					        assert_image_equal_tofile(
 | 
				
			||||||
| 
						 | 
					@ -571,7 +572,7 @@ def test_dispose_previous_first_frame():
 | 
				
			||||||
        )
 | 
					        )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_previous_frame_loaded():
 | 
					def test_previous_frame_loaded() -> None:
 | 
				
			||||||
    with Image.open("Tests/images/dispose_none.gif") as img:
 | 
					    with Image.open("Tests/images/dispose_none.gif") as img:
 | 
				
			||||||
        img.load()
 | 
					        img.load()
 | 
				
			||||||
        img.seek(1)
 | 
					        img.seek(1)
 | 
				
			||||||
| 
						 | 
					@ -582,7 +583,7 @@ def test_previous_frame_loaded():
 | 
				
			||||||
            assert_image_equal(img_skipped, img)
 | 
					            assert_image_equal(img_skipped, img)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_save_dispose(tmp_path):
 | 
					def test_save_dispose(tmp_path: Path) -> None:
 | 
				
			||||||
    out = str(tmp_path / "temp.gif")
 | 
					    out = str(tmp_path / "temp.gif")
 | 
				
			||||||
    im_list = [
 | 
					    im_list = [
 | 
				
			||||||
        Image.new("L", (100, 100), "#000"),
 | 
					        Image.new("L", (100, 100), "#000"),
 | 
				
			||||||
| 
						 | 
					@ -610,7 +611,7 @@ def test_save_dispose(tmp_path):
 | 
				
			||||||
            assert img.disposal_method == i + 1
 | 
					            assert img.disposal_method == i + 1
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_dispose2_palette(tmp_path):
 | 
					def test_dispose2_palette(tmp_path: Path) -> None:
 | 
				
			||||||
    out = str(tmp_path / "temp.gif")
 | 
					    out = str(tmp_path / "temp.gif")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    # Four colors: white, gray, black, red
 | 
					    # Four colors: white, gray, black, red
 | 
				
			||||||
| 
						 | 
					@ -641,7 +642,7 @@ def test_dispose2_palette(tmp_path):
 | 
				
			||||||
            assert rgb_img.getpixel((50, 50)) == circle
 | 
					            assert rgb_img.getpixel((50, 50)) == circle
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_dispose2_diff(tmp_path):
 | 
					def test_dispose2_diff(tmp_path: Path) -> None:
 | 
				
			||||||
    out = str(tmp_path / "temp.gif")
 | 
					    out = str(tmp_path / "temp.gif")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    # 4 frames: red/blue, red/red, blue/blue, red/blue
 | 
					    # 4 frames: red/blue, red/red, blue/blue, red/blue
 | 
				
			||||||
| 
						 | 
					@ -683,7 +684,7 @@ def test_dispose2_diff(tmp_path):
 | 
				
			||||||
            assert rgb_img.getpixel((1, 1)) == (255, 255, 255, 0)
 | 
					            assert rgb_img.getpixel((1, 1)) == (255, 255, 255, 0)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_dispose2_background(tmp_path):
 | 
					def test_dispose2_background(tmp_path: Path) -> None:
 | 
				
			||||||
    out = str(tmp_path / "temp.gif")
 | 
					    out = str(tmp_path / "temp.gif")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    im_list = []
 | 
					    im_list = []
 | 
				
			||||||
| 
						 | 
					@ -709,7 +710,7 @@ def test_dispose2_background(tmp_path):
 | 
				
			||||||
        assert im.getpixel((0, 0)) == (255, 0, 0)
 | 
					        assert im.getpixel((0, 0)) == (255, 0, 0)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_dispose2_background_frame(tmp_path):
 | 
					def test_dispose2_background_frame(tmp_path: Path) -> None:
 | 
				
			||||||
    out = str(tmp_path / "temp.gif")
 | 
					    out = str(tmp_path / "temp.gif")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    im_list = [Image.new("RGBA", (1, 20))]
 | 
					    im_list = [Image.new("RGBA", (1, 20))]
 | 
				
			||||||
| 
						 | 
					@ -727,7 +728,7 @@ def test_dispose2_background_frame(tmp_path):
 | 
				
			||||||
        assert im.n_frames == 3
 | 
					        assert im.n_frames == 3
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_transparency_in_second_frame(tmp_path):
 | 
					def test_transparency_in_second_frame(tmp_path: Path) -> None:
 | 
				
			||||||
    out = str(tmp_path / "temp.gif")
 | 
					    out = str(tmp_path / "temp.gif")
 | 
				
			||||||
    with Image.open("Tests/images/different_transparency.gif") as im:
 | 
					    with Image.open("Tests/images/different_transparency.gif") as im:
 | 
				
			||||||
        assert im.info["transparency"] == 0
 | 
					        assert im.info["transparency"] == 0
 | 
				
			||||||
| 
						 | 
					@ -747,7 +748,7 @@ def test_transparency_in_second_frame(tmp_path):
 | 
				
			||||||
        )
 | 
					        )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_no_transparency_in_second_frame():
 | 
					def test_no_transparency_in_second_frame() -> None:
 | 
				
			||||||
    with Image.open("Tests/images/iss634.gif") as img:
 | 
					    with Image.open("Tests/images/iss634.gif") as img:
 | 
				
			||||||
        # Seek to the second frame
 | 
					        # Seek to the second frame
 | 
				
			||||||
        img.seek(img.tell() + 1)
 | 
					        img.seek(img.tell() + 1)
 | 
				
			||||||
| 
						 | 
					@ -757,7 +758,7 @@ def test_no_transparency_in_second_frame():
 | 
				
			||||||
        assert img.histogram()[255] == 0
 | 
					        assert img.histogram()[255] == 0
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_remapped_transparency(tmp_path):
 | 
					def test_remapped_transparency(tmp_path: Path) -> None:
 | 
				
			||||||
    out = str(tmp_path / "temp.gif")
 | 
					    out = str(tmp_path / "temp.gif")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    im = Image.new("P", (1, 2))
 | 
					    im = Image.new("P", (1, 2))
 | 
				
			||||||
| 
						 | 
					@ -773,7 +774,7 @@ def test_remapped_transparency(tmp_path):
 | 
				
			||||||
        assert reloaded.info["transparency"] == reloaded.getpixel((0, 1))
 | 
					        assert reloaded.info["transparency"] == reloaded.getpixel((0, 1))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_duration(tmp_path):
 | 
					def test_duration(tmp_path: Path) -> None:
 | 
				
			||||||
    duration = 1000
 | 
					    duration = 1000
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    out = str(tmp_path / "temp.gif")
 | 
					    out = str(tmp_path / "temp.gif")
 | 
				
			||||||
| 
						 | 
					@ -787,7 +788,7 @@ def test_duration(tmp_path):
 | 
				
			||||||
        assert reread.info["duration"] == duration
 | 
					        assert reread.info["duration"] == duration
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_multiple_duration(tmp_path):
 | 
					def test_multiple_duration(tmp_path: Path) -> None:
 | 
				
			||||||
    duration_list = [1000, 2000, 3000]
 | 
					    duration_list = [1000, 2000, 3000]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    out = str(tmp_path / "temp.gif")
 | 
					    out = str(tmp_path / "temp.gif")
 | 
				
			||||||
| 
						 | 
					@ -822,7 +823,7 @@ def test_multiple_duration(tmp_path):
 | 
				
			||||||
                pass
 | 
					                pass
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_roundtrip_info_duration(tmp_path):
 | 
					def test_roundtrip_info_duration(tmp_path: Path) -> None:
 | 
				
			||||||
    duration_list = [100, 500, 500]
 | 
					    duration_list = [100, 500, 500]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    out = str(tmp_path / "temp.gif")
 | 
					    out = str(tmp_path / "temp.gif")
 | 
				
			||||||
| 
						 | 
					@ -839,7 +840,7 @@ def test_roundtrip_info_duration(tmp_path):
 | 
				
			||||||
        ] == duration_list
 | 
					        ] == duration_list
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_roundtrip_info_duration_combined(tmp_path):
 | 
					def test_roundtrip_info_duration_combined(tmp_path: Path) -> None:
 | 
				
			||||||
    out = str(tmp_path / "temp.gif")
 | 
					    out = str(tmp_path / "temp.gif")
 | 
				
			||||||
    with Image.open("Tests/images/duplicate_frame.gif") as im:
 | 
					    with Image.open("Tests/images/duplicate_frame.gif") as im:
 | 
				
			||||||
        assert [frame.info["duration"] for frame in ImageSequence.Iterator(im)] == [
 | 
					        assert [frame.info["duration"] for frame in ImageSequence.Iterator(im)] == [
 | 
				
			||||||
| 
						 | 
					@ -855,7 +856,7 @@ def test_roundtrip_info_duration_combined(tmp_path):
 | 
				
			||||||
        ] == [1000, 2000]
 | 
					        ] == [1000, 2000]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_identical_frames(tmp_path):
 | 
					def test_identical_frames(tmp_path: Path) -> None:
 | 
				
			||||||
    duration_list = [1000, 1500, 2000, 4000]
 | 
					    duration_list = [1000, 1500, 2000, 4000]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    out = str(tmp_path / "temp.gif")
 | 
					    out = str(tmp_path / "temp.gif")
 | 
				
			||||||
| 
						 | 
					@ -888,7 +889,7 @@ def test_identical_frames(tmp_path):
 | 
				
			||||||
        1500,
 | 
					        1500,
 | 
				
			||||||
    ),
 | 
					    ),
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
def test_identical_frames_to_single_frame(duration, tmp_path):
 | 
					def test_identical_frames_to_single_frame(duration, tmp_path: Path) -> None:
 | 
				
			||||||
    out = str(tmp_path / "temp.gif")
 | 
					    out = str(tmp_path / "temp.gif")
 | 
				
			||||||
    im_list = [
 | 
					    im_list = [
 | 
				
			||||||
        Image.new("L", (100, 100), "#000"),
 | 
					        Image.new("L", (100, 100), "#000"),
 | 
				
			||||||
| 
						 | 
					@ -905,7 +906,7 @@ def test_identical_frames_to_single_frame(duration, tmp_path):
 | 
				
			||||||
        assert reread.info["duration"] == 4500
 | 
					        assert reread.info["duration"] == 4500
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_loop_none(tmp_path):
 | 
					def test_loop_none(tmp_path: Path) -> None:
 | 
				
			||||||
    out = str(tmp_path / "temp.gif")
 | 
					    out = str(tmp_path / "temp.gif")
 | 
				
			||||||
    im = Image.new("L", (100, 100), "#000")
 | 
					    im = Image.new("L", (100, 100), "#000")
 | 
				
			||||||
    im.save(out, loop=None)
 | 
					    im.save(out, loop=None)
 | 
				
			||||||
| 
						 | 
					@ -913,7 +914,7 @@ def test_loop_none(tmp_path):
 | 
				
			||||||
        assert "loop" not in reread.info
 | 
					        assert "loop" not in reread.info
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_number_of_loops(tmp_path):
 | 
					def test_number_of_loops(tmp_path: Path) -> None:
 | 
				
			||||||
    number_of_loops = 2
 | 
					    number_of_loops = 2
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    out = str(tmp_path / "temp.gif")
 | 
					    out = str(tmp_path / "temp.gif")
 | 
				
			||||||
| 
						 | 
					@ -931,7 +932,7 @@ def test_number_of_loops(tmp_path):
 | 
				
			||||||
        assert im.info["loop"] == 2
 | 
					        assert im.info["loop"] == 2
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_background(tmp_path):
 | 
					def test_background(tmp_path: Path) -> None:
 | 
				
			||||||
    out = str(tmp_path / "temp.gif")
 | 
					    out = str(tmp_path / "temp.gif")
 | 
				
			||||||
    im = Image.new("L", (100, 100), "#000")
 | 
					    im = Image.new("L", (100, 100), "#000")
 | 
				
			||||||
    im.info["background"] = 1
 | 
					    im.info["background"] = 1
 | 
				
			||||||
| 
						 | 
					@ -940,7 +941,7 @@ def test_background(tmp_path):
 | 
				
			||||||
        assert reread.info["background"] == im.info["background"]
 | 
					        assert reread.info["background"] == im.info["background"]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_webp_background(tmp_path):
 | 
					def test_webp_background(tmp_path: Path) -> None:
 | 
				
			||||||
    out = str(tmp_path / "temp.gif")
 | 
					    out = str(tmp_path / "temp.gif")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    # Test opaque WebP background
 | 
					    # Test opaque WebP background
 | 
				
			||||||
| 
						 | 
					@ -955,7 +956,7 @@ def test_webp_background(tmp_path):
 | 
				
			||||||
    im.save(out)
 | 
					    im.save(out)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_comment(tmp_path):
 | 
					def test_comment(tmp_path: Path) -> None:
 | 
				
			||||||
    with Image.open(TEST_GIF) as im:
 | 
					    with Image.open(TEST_GIF) as im:
 | 
				
			||||||
        assert im.info["comment"] == b"File written by Adobe Photoshop\xa8 4.0"
 | 
					        assert im.info["comment"] == b"File written by Adobe Photoshop\xa8 4.0"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -975,7 +976,7 @@ def test_comment(tmp_path):
 | 
				
			||||||
        assert reread.info["version"] == b"GIF89a"
 | 
					        assert reread.info["version"] == b"GIF89a"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_comment_over_255(tmp_path):
 | 
					def test_comment_over_255(tmp_path: Path) -> None:
 | 
				
			||||||
    out = str(tmp_path / "temp.gif")
 | 
					    out = str(tmp_path / "temp.gif")
 | 
				
			||||||
    im = Image.new("L", (100, 100), "#000")
 | 
					    im = Image.new("L", (100, 100), "#000")
 | 
				
			||||||
    comment = b"Test comment text"
 | 
					    comment = b"Test comment text"
 | 
				
			||||||
| 
						 | 
					@ -990,18 +991,18 @@ def test_comment_over_255(tmp_path):
 | 
				
			||||||
        assert reread.info["version"] == b"GIF89a"
 | 
					        assert reread.info["version"] == b"GIF89a"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_zero_comment_subblocks():
 | 
					def test_zero_comment_subblocks() -> None:
 | 
				
			||||||
    with Image.open("Tests/images/hopper_zero_comment_subblocks.gif") as im:
 | 
					    with Image.open("Tests/images/hopper_zero_comment_subblocks.gif") as im:
 | 
				
			||||||
        assert_image_equal_tofile(im, TEST_GIF)
 | 
					        assert_image_equal_tofile(im, TEST_GIF)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_read_multiple_comment_blocks():
 | 
					def test_read_multiple_comment_blocks() -> None:
 | 
				
			||||||
    with Image.open("Tests/images/multiple_comments.gif") as im:
 | 
					    with Image.open("Tests/images/multiple_comments.gif") as im:
 | 
				
			||||||
        # Multiple comment blocks in a frame are separated not concatenated
 | 
					        # Multiple comment blocks in a frame are separated not concatenated
 | 
				
			||||||
        assert im.info["comment"] == b"Test comment 1\nTest comment 2"
 | 
					        assert im.info["comment"] == b"Test comment 1\nTest comment 2"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_empty_string_comment(tmp_path):
 | 
					def test_empty_string_comment(tmp_path: Path) -> None:
 | 
				
			||||||
    out = str(tmp_path / "temp.gif")
 | 
					    out = str(tmp_path / "temp.gif")
 | 
				
			||||||
    with Image.open("Tests/images/chi.gif") as im:
 | 
					    with Image.open("Tests/images/chi.gif") as im:
 | 
				
			||||||
        assert "comment" in im.info
 | 
					        assert "comment" in im.info
 | 
				
			||||||
| 
						 | 
					@ -1014,7 +1015,7 @@ def test_empty_string_comment(tmp_path):
 | 
				
			||||||
            assert "comment" not in frame.info
 | 
					            assert "comment" not in frame.info
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_retain_comment_in_subsequent_frames(tmp_path):
 | 
					def test_retain_comment_in_subsequent_frames(tmp_path: Path) -> None:
 | 
				
			||||||
    # Test that a comment block at the beginning is kept
 | 
					    # Test that a comment block at the beginning is kept
 | 
				
			||||||
    with Image.open("Tests/images/chi.gif") as im:
 | 
					    with Image.open("Tests/images/chi.gif") as im:
 | 
				
			||||||
        for frame in ImageSequence.Iterator(im):
 | 
					        for frame in ImageSequence.Iterator(im):
 | 
				
			||||||
| 
						 | 
					@ -1045,10 +1046,10 @@ def test_retain_comment_in_subsequent_frames(tmp_path):
 | 
				
			||||||
            assert frame.info["comment"] == b"Test"
 | 
					            assert frame.info["comment"] == b"Test"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_version(tmp_path):
 | 
					def test_version(tmp_path: Path) -> None:
 | 
				
			||||||
    out = str(tmp_path / "temp.gif")
 | 
					    out = str(tmp_path / "temp.gif")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def assert_version_after_save(im, version):
 | 
					    def assert_version_after_save(im, version) -> None:
 | 
				
			||||||
        im.save(out)
 | 
					        im.save(out)
 | 
				
			||||||
        with Image.open(out) as reread:
 | 
					        with Image.open(out) as reread:
 | 
				
			||||||
            assert reread.info["version"] == version
 | 
					            assert reread.info["version"] == version
 | 
				
			||||||
| 
						 | 
					@ -1075,7 +1076,7 @@ def test_version(tmp_path):
 | 
				
			||||||
        assert_version_after_save(im, b"GIF87a")
 | 
					        assert_version_after_save(im, b"GIF87a")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_append_images(tmp_path):
 | 
					def test_append_images(tmp_path: Path) -> None:
 | 
				
			||||||
    out = str(tmp_path / "temp.gif")
 | 
					    out = str(tmp_path / "temp.gif")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    # Test appending single frame images
 | 
					    # Test appending single frame images
 | 
				
			||||||
| 
						 | 
					@ -1104,7 +1105,7 @@ def test_append_images(tmp_path):
 | 
				
			||||||
        assert reread.n_frames == 10
 | 
					        assert reread.n_frames == 10
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_transparent_optimize(tmp_path):
 | 
					def test_transparent_optimize(tmp_path: Path) -> None:
 | 
				
			||||||
    # From issue #2195, if the transparent color is incorrectly optimized out, GIF loses
 | 
					    # From issue #2195, if the transparent color is incorrectly optimized out, GIF loses
 | 
				
			||||||
    # transparency.
 | 
					    # transparency.
 | 
				
			||||||
    # Need a palette that isn't using the 0 color,
 | 
					    # Need a palette that isn't using the 0 color,
 | 
				
			||||||
| 
						 | 
					@ -1124,7 +1125,7 @@ def test_transparent_optimize(tmp_path):
 | 
				
			||||||
        assert reloaded.info["transparency"] == reloaded.getpixel((252, 0))
 | 
					        assert reloaded.info["transparency"] == reloaded.getpixel((252, 0))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_removed_transparency(tmp_path):
 | 
					def test_removed_transparency(tmp_path: Path) -> None:
 | 
				
			||||||
    out = str(tmp_path / "temp.gif")
 | 
					    out = str(tmp_path / "temp.gif")
 | 
				
			||||||
    im = Image.new("RGB", (256, 1))
 | 
					    im = Image.new("RGB", (256, 1))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1139,7 +1140,7 @@ def test_removed_transparency(tmp_path):
 | 
				
			||||||
        assert "transparency" not in reloaded.info
 | 
					        assert "transparency" not in reloaded.info
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_rgb_transparency(tmp_path):
 | 
					def test_rgb_transparency(tmp_path: Path) -> None:
 | 
				
			||||||
    out = str(tmp_path / "temp.gif")
 | 
					    out = str(tmp_path / "temp.gif")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    # Single frame
 | 
					    # Single frame
 | 
				
			||||||
| 
						 | 
					@ -1161,7 +1162,7 @@ def test_rgb_transparency(tmp_path):
 | 
				
			||||||
        assert "transparency" not in reloaded.info
 | 
					        assert "transparency" not in reloaded.info
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_rgba_transparency(tmp_path):
 | 
					def test_rgba_transparency(tmp_path: Path) -> None:
 | 
				
			||||||
    out = str(tmp_path / "temp.gif")
 | 
					    out = str(tmp_path / "temp.gif")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    im = hopper("P")
 | 
					    im = hopper("P")
 | 
				
			||||||
| 
						 | 
					@ -1172,13 +1173,13 @@ def test_rgba_transparency(tmp_path):
 | 
				
			||||||
        assert_image_equal(hopper("P").convert("RGB"), reloaded)
 | 
					        assert_image_equal(hopper("P").convert("RGB"), reloaded)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_background_outside_palettte(tmp_path):
 | 
					def test_background_outside_palettte(tmp_path: Path) -> None:
 | 
				
			||||||
    with Image.open("Tests/images/background_outside_palette.gif") as im:
 | 
					    with Image.open("Tests/images/background_outside_palette.gif") as im:
 | 
				
			||||||
        im.seek(1)
 | 
					        im.seek(1)
 | 
				
			||||||
        assert im.info["background"] == 255
 | 
					        assert im.info["background"] == 255
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_bbox(tmp_path):
 | 
					def test_bbox(tmp_path: Path) -> None:
 | 
				
			||||||
    out = str(tmp_path / "temp.gif")
 | 
					    out = str(tmp_path / "temp.gif")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    im = Image.new("RGB", (100, 100), "#fff")
 | 
					    im = Image.new("RGB", (100, 100), "#fff")
 | 
				
			||||||
| 
						 | 
					@ -1189,7 +1190,7 @@ def test_bbox(tmp_path):
 | 
				
			||||||
        assert reread.n_frames == 2
 | 
					        assert reread.n_frames == 2
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_bbox_alpha(tmp_path):
 | 
					def test_bbox_alpha(tmp_path: Path) -> None:
 | 
				
			||||||
    out = str(tmp_path / "temp.gif")
 | 
					    out = str(tmp_path / "temp.gif")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    im = Image.new("RGBA", (1, 2), (255, 0, 0, 255))
 | 
					    im = Image.new("RGBA", (1, 2), (255, 0, 0, 255))
 | 
				
			||||||
| 
						 | 
					@ -1201,7 +1202,7 @@ def test_bbox_alpha(tmp_path):
 | 
				
			||||||
        assert reread.n_frames == 2
 | 
					        assert reread.n_frames == 2
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_palette_save_L(tmp_path):
 | 
					def test_palette_save_L(tmp_path: Path) -> None:
 | 
				
			||||||
    # Generate an L mode image with a separate palette
 | 
					    # Generate an L mode image with a separate palette
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    im = hopper("P")
 | 
					    im = hopper("P")
 | 
				
			||||||
| 
						 | 
					@ -1215,7 +1216,7 @@ def test_palette_save_L(tmp_path):
 | 
				
			||||||
        assert_image_equal(reloaded.convert("RGB"), im.convert("RGB"))
 | 
					        assert_image_equal(reloaded.convert("RGB"), im.convert("RGB"))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_palette_save_P(tmp_path):
 | 
					def test_palette_save_P(tmp_path: Path) -> None:
 | 
				
			||||||
    im = Image.new("P", (1, 2))
 | 
					    im = Image.new("P", (1, 2))
 | 
				
			||||||
    im.putpixel((0, 1), 1)
 | 
					    im.putpixel((0, 1), 1)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1229,7 +1230,7 @@ def test_palette_save_P(tmp_path):
 | 
				
			||||||
        assert reloaded_rgb.getpixel((0, 1)) == (4, 5, 6)
 | 
					        assert reloaded_rgb.getpixel((0, 1)) == (4, 5, 6)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_palette_save_duplicate_entries(tmp_path):
 | 
					def test_palette_save_duplicate_entries(tmp_path: Path) -> None:
 | 
				
			||||||
    im = Image.new("P", (1, 2))
 | 
					    im = Image.new("P", (1, 2))
 | 
				
			||||||
    im.putpixel((0, 1), 1)
 | 
					    im.putpixel((0, 1), 1)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1242,7 +1243,7 @@ def test_palette_save_duplicate_entries(tmp_path):
 | 
				
			||||||
        assert reloaded.convert("RGB").getpixel((0, 1)) == (0, 0, 0)
 | 
					        assert reloaded.convert("RGB").getpixel((0, 1)) == (0, 0, 0)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_palette_save_all_P(tmp_path):
 | 
					def test_palette_save_all_P(tmp_path: Path) -> None:
 | 
				
			||||||
    frames = []
 | 
					    frames = []
 | 
				
			||||||
    colors = ((255, 0, 0), (0, 255, 0))
 | 
					    colors = ((255, 0, 0), (0, 255, 0))
 | 
				
			||||||
    for color in colors:
 | 
					    for color in colors:
 | 
				
			||||||
| 
						 | 
					@ -1265,7 +1266,7 @@ def test_palette_save_all_P(tmp_path):
 | 
				
			||||||
        assert im.palette.palette == im.global_palette.palette
 | 
					        assert im.palette.palette == im.global_palette.palette
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_palette_save_ImagePalette(tmp_path):
 | 
					def test_palette_save_ImagePalette(tmp_path: Path) -> None:
 | 
				
			||||||
    # Pass in a different palette, as an ImagePalette.ImagePalette
 | 
					    # Pass in a different palette, as an ImagePalette.ImagePalette
 | 
				
			||||||
    # effectively the same as test_palette_save_P
 | 
					    # effectively the same as test_palette_save_P
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1280,7 +1281,7 @@ def test_palette_save_ImagePalette(tmp_path):
 | 
				
			||||||
        assert_image_equal(reloaded.convert("RGB"), im.convert("RGB"))
 | 
					        assert_image_equal(reloaded.convert("RGB"), im.convert("RGB"))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_save_I(tmp_path):
 | 
					def test_save_I(tmp_path: Path) -> None:
 | 
				
			||||||
    # Test saving something that would trigger the auto-convert to 'L'
 | 
					    # Test saving something that would trigger the auto-convert to 'L'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    im = hopper("I")
 | 
					    im = hopper("I")
 | 
				
			||||||
| 
						 | 
					@ -1292,7 +1293,7 @@ def test_save_I(tmp_path):
 | 
				
			||||||
        assert_image_equal(reloaded.convert("L"), im.convert("L"))
 | 
					        assert_image_equal(reloaded.convert("L"), im.convert("L"))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_getdata():
 | 
					def test_getdata() -> None:
 | 
				
			||||||
    # Test getheader/getdata against legacy values.
 | 
					    # Test getheader/getdata against legacy values.
 | 
				
			||||||
    # Create a 'P' image with holes in the palette.
 | 
					    # Create a 'P' image with holes in the palette.
 | 
				
			||||||
    im = Image._wedge().resize((16, 16), Image.Resampling.NEAREST)
 | 
					    im = Image._wedge().resize((16, 16), Image.Resampling.NEAREST)
 | 
				
			||||||
| 
						 | 
					@ -1320,7 +1321,7 @@ def test_getdata():
 | 
				
			||||||
        GifImagePlugin._FORCE_OPTIMIZE = False
 | 
					        GifImagePlugin._FORCE_OPTIMIZE = False
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_lzw_bits():
 | 
					def test_lzw_bits() -> None:
 | 
				
			||||||
    # see https://github.com/python-pillow/Pillow/issues/2811
 | 
					    # see https://github.com/python-pillow/Pillow/issues/2811
 | 
				
			||||||
    with Image.open("Tests/images/issue_2811.gif") as im:
 | 
					    with Image.open("Tests/images/issue_2811.gif") as im:
 | 
				
			||||||
        assert im.tile[0][3][0] == 11  # LZW bits
 | 
					        assert im.tile[0][3][0] == 11  # LZW bits
 | 
				
			||||||
| 
						 | 
					@ -1328,7 +1329,7 @@ def test_lzw_bits():
 | 
				
			||||||
        im.load()
 | 
					        im.load()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_extents():
 | 
					def test_extents() -> None:
 | 
				
			||||||
    with Image.open("Tests/images/test_extents.gif") as im:
 | 
					    with Image.open("Tests/images/test_extents.gif") as im:
 | 
				
			||||||
        assert im.size == (100, 100)
 | 
					        assert im.size == (100, 100)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1340,7 +1341,7 @@ def test_extents():
 | 
				
			||||||
        assert im.size == (150, 150)
 | 
					        assert im.size == (150, 150)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_missing_background():
 | 
					def test_missing_background() -> None:
 | 
				
			||||||
    # The Global Color Table Flag isn't set, so there is no background color index,
 | 
					    # The Global Color Table Flag isn't set, so there is no background color index,
 | 
				
			||||||
    # but the disposal method is "Restore to background color"
 | 
					    # but the disposal method is "Restore to background color"
 | 
				
			||||||
    with Image.open("Tests/images/missing_background.gif") as im:
 | 
					    with Image.open("Tests/images/missing_background.gif") as im:
 | 
				
			||||||
| 
						 | 
					@ -1348,7 +1349,7 @@ def test_missing_background():
 | 
				
			||||||
        assert_image_equal_tofile(im, "Tests/images/missing_background_first_frame.png")
 | 
					        assert_image_equal_tofile(im, "Tests/images/missing_background_first_frame.png")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_saving_rgba(tmp_path):
 | 
					def test_saving_rgba(tmp_path: Path) -> None:
 | 
				
			||||||
    out = str(tmp_path / "temp.gif")
 | 
					    out = str(tmp_path / "temp.gif")
 | 
				
			||||||
    with Image.open("Tests/images/transparent.png") as im:
 | 
					    with Image.open("Tests/images/transparent.png") as im:
 | 
				
			||||||
        im.save(out)
 | 
					        im.save(out)
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -3,7 +3,7 @@ from __future__ import annotations
 | 
				
			||||||
from PIL import GimpGradientFile, ImagePalette
 | 
					from PIL import GimpGradientFile, ImagePalette
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_linear_pos_le_middle():
 | 
					def test_linear_pos_le_middle() -> None:
 | 
				
			||||||
    # Arrange
 | 
					    # Arrange
 | 
				
			||||||
    middle = 0.5
 | 
					    middle = 0.5
 | 
				
			||||||
    pos = 0.25
 | 
					    pos = 0.25
 | 
				
			||||||
| 
						 | 
					@ -15,7 +15,7 @@ def test_linear_pos_le_middle():
 | 
				
			||||||
    assert ret == 0.25
 | 
					    assert ret == 0.25
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_linear_pos_le_small_middle():
 | 
					def test_linear_pos_le_small_middle() -> None:
 | 
				
			||||||
    # Arrange
 | 
					    # Arrange
 | 
				
			||||||
    middle = 1e-11
 | 
					    middle = 1e-11
 | 
				
			||||||
    pos = 1e-12
 | 
					    pos = 1e-12
 | 
				
			||||||
| 
						 | 
					@ -27,7 +27,7 @@ def test_linear_pos_le_small_middle():
 | 
				
			||||||
    assert ret == 0.0
 | 
					    assert ret == 0.0
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_linear_pos_gt_middle():
 | 
					def test_linear_pos_gt_middle() -> None:
 | 
				
			||||||
    # Arrange
 | 
					    # Arrange
 | 
				
			||||||
    middle = 0.5
 | 
					    middle = 0.5
 | 
				
			||||||
    pos = 0.75
 | 
					    pos = 0.75
 | 
				
			||||||
| 
						 | 
					@ -39,7 +39,7 @@ def test_linear_pos_gt_middle():
 | 
				
			||||||
    assert ret == 0.75
 | 
					    assert ret == 0.75
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_linear_pos_gt_small_middle():
 | 
					def test_linear_pos_gt_small_middle() -> None:
 | 
				
			||||||
    # Arrange
 | 
					    # Arrange
 | 
				
			||||||
    middle = 1 - 1e-11
 | 
					    middle = 1 - 1e-11
 | 
				
			||||||
    pos = 1 - 1e-12
 | 
					    pos = 1 - 1e-12
 | 
				
			||||||
| 
						 | 
					@ -51,7 +51,7 @@ def test_linear_pos_gt_small_middle():
 | 
				
			||||||
    assert ret == 1.0
 | 
					    assert ret == 1.0
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_curved():
 | 
					def test_curved() -> None:
 | 
				
			||||||
    # Arrange
 | 
					    # Arrange
 | 
				
			||||||
    middle = 0.5
 | 
					    middle = 0.5
 | 
				
			||||||
    pos = 0.75
 | 
					    pos = 0.75
 | 
				
			||||||
| 
						 | 
					@ -63,7 +63,7 @@ def test_curved():
 | 
				
			||||||
    assert ret == 0.75
 | 
					    assert ret == 0.75
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_sine():
 | 
					def test_sine() -> None:
 | 
				
			||||||
    # Arrange
 | 
					    # Arrange
 | 
				
			||||||
    middle = 0.5
 | 
					    middle = 0.5
 | 
				
			||||||
    pos = 0.75
 | 
					    pos = 0.75
 | 
				
			||||||
| 
						 | 
					@ -75,7 +75,7 @@ def test_sine():
 | 
				
			||||||
    assert ret == 0.8535533905932737
 | 
					    assert ret == 0.8535533905932737
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_sphere_increasing():
 | 
					def test_sphere_increasing() -> None:
 | 
				
			||||||
    # Arrange
 | 
					    # Arrange
 | 
				
			||||||
    middle = 0.5
 | 
					    middle = 0.5
 | 
				
			||||||
    pos = 0.75
 | 
					    pos = 0.75
 | 
				
			||||||
| 
						 | 
					@ -87,7 +87,7 @@ def test_sphere_increasing():
 | 
				
			||||||
    assert round(abs(ret - 0.9682458365518543), 7) == 0
 | 
					    assert round(abs(ret - 0.9682458365518543), 7) == 0
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_sphere_decreasing():
 | 
					def test_sphere_decreasing() -> None:
 | 
				
			||||||
    # Arrange
 | 
					    # Arrange
 | 
				
			||||||
    middle = 0.5
 | 
					    middle = 0.5
 | 
				
			||||||
    pos = 0.75
 | 
					    pos = 0.75
 | 
				
			||||||
| 
						 | 
					@ -99,7 +99,7 @@ def test_sphere_decreasing():
 | 
				
			||||||
    assert ret == 0.3385621722338523
 | 
					    assert ret == 0.3385621722338523
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_load_via_imagepalette():
 | 
					def test_load_via_imagepalette() -> None:
 | 
				
			||||||
    # Arrange
 | 
					    # Arrange
 | 
				
			||||||
    test_file = "Tests/images/gimp_gradient.ggr"
 | 
					    test_file = "Tests/images/gimp_gradient.ggr"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -112,7 +112,7 @@ def test_load_via_imagepalette():
 | 
				
			||||||
    assert palette[1] == "RGBA"
 | 
					    assert palette[1] == "RGBA"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_load_1_3_via_imagepalette():
 | 
					def test_load_1_3_via_imagepalette() -> None:
 | 
				
			||||||
    # Arrange
 | 
					    # Arrange
 | 
				
			||||||
    # GIMP 1.3 gradient files contain a name field
 | 
					    # GIMP 1.3 gradient files contain a name field
 | 
				
			||||||
    test_file = "Tests/images/gimp_gradient_with_name.ggr"
 | 
					    test_file = "Tests/images/gimp_gradient_with_name.ggr"
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,5 +1,7 @@
 | 
				
			||||||
from __future__ import annotations
 | 
					from __future__ import annotations
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					from pathlib import Path
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import pytest
 | 
					import pytest
 | 
				
			||||||
 | 
					
 | 
				
			||||||
from PIL import GribStubImagePlugin, Image
 | 
					from PIL import GribStubImagePlugin, Image
 | 
				
			||||||
| 
						 | 
					@ -9,7 +11,7 @@ from .helper import hopper
 | 
				
			||||||
TEST_FILE = "Tests/images/WAlaska.wind.7days.grb"
 | 
					TEST_FILE = "Tests/images/WAlaska.wind.7days.grb"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_open():
 | 
					def test_open() -> None:
 | 
				
			||||||
    # Act
 | 
					    # Act
 | 
				
			||||||
    with Image.open(TEST_FILE) as im:
 | 
					    with Image.open(TEST_FILE) as im:
 | 
				
			||||||
        # Assert
 | 
					        # Assert
 | 
				
			||||||
| 
						 | 
					@ -20,7 +22,7 @@ def test_open():
 | 
				
			||||||
        assert im.size == (1, 1)
 | 
					        assert im.size == (1, 1)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_invalid_file():
 | 
					def test_invalid_file() -> None:
 | 
				
			||||||
    # Arrange
 | 
					    # Arrange
 | 
				
			||||||
    invalid_file = "Tests/images/flower.jpg"
 | 
					    invalid_file = "Tests/images/flower.jpg"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -29,7 +31,7 @@ def test_invalid_file():
 | 
				
			||||||
        GribStubImagePlugin.GribStubImageFile(invalid_file)
 | 
					        GribStubImagePlugin.GribStubImageFile(invalid_file)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_load():
 | 
					def test_load() -> None:
 | 
				
			||||||
    # Arrange
 | 
					    # Arrange
 | 
				
			||||||
    with Image.open(TEST_FILE) as im:
 | 
					    with Image.open(TEST_FILE) as im:
 | 
				
			||||||
        # Act / Assert: stub cannot load without an implemented handler
 | 
					        # Act / Assert: stub cannot load without an implemented handler
 | 
				
			||||||
| 
						 | 
					@ -37,7 +39,7 @@ def test_load():
 | 
				
			||||||
            im.load()
 | 
					            im.load()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_save(tmp_path):
 | 
					def test_save(tmp_path: Path) -> None:
 | 
				
			||||||
    # Arrange
 | 
					    # Arrange
 | 
				
			||||||
    im = hopper()
 | 
					    im = hopper()
 | 
				
			||||||
    tmpfile = str(tmp_path / "temp.grib")
 | 
					    tmpfile = str(tmp_path / "temp.grib")
 | 
				
			||||||
| 
						 | 
					@ -47,13 +49,13 @@ def test_save(tmp_path):
 | 
				
			||||||
        im.save(tmpfile)
 | 
					        im.save(tmpfile)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_handler(tmp_path):
 | 
					def test_handler(tmp_path: Path) -> None:
 | 
				
			||||||
    class TestHandler:
 | 
					    class TestHandler:
 | 
				
			||||||
        opened = False
 | 
					        opened = False
 | 
				
			||||||
        loaded = False
 | 
					        loaded = False
 | 
				
			||||||
        saved = False
 | 
					        saved = False
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        def open(self, im):
 | 
					        def open(self, im) -> None:
 | 
				
			||||||
            self.opened = True
 | 
					            self.opened = True
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        def load(self, im):
 | 
					        def load(self, im):
 | 
				
			||||||
| 
						 | 
					@ -61,7 +63,7 @@ def test_handler(tmp_path):
 | 
				
			||||||
            im.fp.close()
 | 
					            im.fp.close()
 | 
				
			||||||
            return Image.new("RGB", (1, 1))
 | 
					            return Image.new("RGB", (1, 1))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        def save(self, im, fp, filename):
 | 
					        def save(self, im, fp, filename) -> None:
 | 
				
			||||||
            self.saved = True
 | 
					            self.saved = True
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    handler = TestHandler()
 | 
					    handler = TestHandler()
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,5 +1,7 @@
 | 
				
			||||||
from __future__ import annotations
 | 
					from __future__ import annotations
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					from pathlib import Path
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import pytest
 | 
					import pytest
 | 
				
			||||||
 | 
					
 | 
				
			||||||
from PIL import Hdf5StubImagePlugin, Image
 | 
					from PIL import Hdf5StubImagePlugin, Image
 | 
				
			||||||
| 
						 | 
					@ -7,7 +9,7 @@ from PIL import Hdf5StubImagePlugin, Image
 | 
				
			||||||
TEST_FILE = "Tests/images/hdf5.h5"
 | 
					TEST_FILE = "Tests/images/hdf5.h5"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_open():
 | 
					def test_open() -> None:
 | 
				
			||||||
    # Act
 | 
					    # Act
 | 
				
			||||||
    with Image.open(TEST_FILE) as im:
 | 
					    with Image.open(TEST_FILE) as im:
 | 
				
			||||||
        # Assert
 | 
					        # Assert
 | 
				
			||||||
| 
						 | 
					@ -18,7 +20,7 @@ def test_open():
 | 
				
			||||||
        assert im.size == (1, 1)
 | 
					        assert im.size == (1, 1)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_invalid_file():
 | 
					def test_invalid_file() -> None:
 | 
				
			||||||
    # Arrange
 | 
					    # Arrange
 | 
				
			||||||
    invalid_file = "Tests/images/flower.jpg"
 | 
					    invalid_file = "Tests/images/flower.jpg"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -27,7 +29,7 @@ def test_invalid_file():
 | 
				
			||||||
        Hdf5StubImagePlugin.HDF5StubImageFile(invalid_file)
 | 
					        Hdf5StubImagePlugin.HDF5StubImageFile(invalid_file)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_load():
 | 
					def test_load() -> None:
 | 
				
			||||||
    # Arrange
 | 
					    # Arrange
 | 
				
			||||||
    with Image.open(TEST_FILE) as im:
 | 
					    with Image.open(TEST_FILE) as im:
 | 
				
			||||||
        # Act / Assert: stub cannot load without an implemented handler
 | 
					        # Act / Assert: stub cannot load without an implemented handler
 | 
				
			||||||
| 
						 | 
					@ -35,7 +37,7 @@ def test_load():
 | 
				
			||||||
            im.load()
 | 
					            im.load()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_save():
 | 
					def test_save() -> None:
 | 
				
			||||||
    # Arrange
 | 
					    # Arrange
 | 
				
			||||||
    with Image.open(TEST_FILE) as im:
 | 
					    with Image.open(TEST_FILE) as im:
 | 
				
			||||||
        dummy_fp = None
 | 
					        dummy_fp = None
 | 
				
			||||||
| 
						 | 
					@ -48,13 +50,13 @@ def test_save():
 | 
				
			||||||
            Hdf5StubImagePlugin._save(im, dummy_fp, dummy_filename)
 | 
					            Hdf5StubImagePlugin._save(im, dummy_fp, dummy_filename)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_handler(tmp_path):
 | 
					def test_handler(tmp_path: Path) -> None:
 | 
				
			||||||
    class TestHandler:
 | 
					    class TestHandler:
 | 
				
			||||||
        opened = False
 | 
					        opened = False
 | 
				
			||||||
        loaded = False
 | 
					        loaded = False
 | 
				
			||||||
        saved = False
 | 
					        saved = False
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        def open(self, im):
 | 
					        def open(self, im) -> None:
 | 
				
			||||||
            self.opened = True
 | 
					            self.opened = True
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        def load(self, im):
 | 
					        def load(self, im):
 | 
				
			||||||
| 
						 | 
					@ -62,7 +64,7 @@ def test_handler(tmp_path):
 | 
				
			||||||
            im.fp.close()
 | 
					            im.fp.close()
 | 
				
			||||||
            return Image.new("RGB", (1, 1))
 | 
					            return Image.new("RGB", (1, 1))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        def save(self, im, fp, filename):
 | 
					        def save(self, im, fp, filename) -> None:
 | 
				
			||||||
            self.saved = True
 | 
					            self.saved = True
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    handler = TestHandler()
 | 
					    handler = TestHandler()
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -3,6 +3,7 @@ from __future__ import annotations
 | 
				
			||||||
import io
 | 
					import io
 | 
				
			||||||
import os
 | 
					import os
 | 
				
			||||||
import warnings
 | 
					import warnings
 | 
				
			||||||
 | 
					from pathlib import Path
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import pytest
 | 
					import pytest
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -14,7 +15,7 @@ from .helper import assert_image_equal, assert_image_similar_tofile, skip_unless
 | 
				
			||||||
TEST_FILE = "Tests/images/pillow.icns"
 | 
					TEST_FILE = "Tests/images/pillow.icns"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_sanity():
 | 
					def test_sanity() -> None:
 | 
				
			||||||
    # Loading this icon by default should result in the largest size
 | 
					    # Loading this icon by default should result in the largest size
 | 
				
			||||||
    # (512x512@2x) being loaded
 | 
					    # (512x512@2x) being loaded
 | 
				
			||||||
    with Image.open(TEST_FILE) as im:
 | 
					    with Image.open(TEST_FILE) as im:
 | 
				
			||||||
| 
						 | 
					@ -27,7 +28,7 @@ def test_sanity():
 | 
				
			||||||
        assert im.format == "ICNS"
 | 
					        assert im.format == "ICNS"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_load():
 | 
					def test_load() -> None:
 | 
				
			||||||
    with Image.open(TEST_FILE) as im:
 | 
					    with Image.open(TEST_FILE) as im:
 | 
				
			||||||
        assert im.load()[0, 0] == (0, 0, 0, 0)
 | 
					        assert im.load()[0, 0] == (0, 0, 0, 0)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -35,7 +36,7 @@ def test_load():
 | 
				
			||||||
        assert im.load()[0, 0] == (0, 0, 0, 0)
 | 
					        assert im.load()[0, 0] == (0, 0, 0, 0)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_save(tmp_path):
 | 
					def test_save(tmp_path: Path) -> None:
 | 
				
			||||||
    temp_file = str(tmp_path / "temp.icns")
 | 
					    temp_file = str(tmp_path / "temp.icns")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    with Image.open(TEST_FILE) as im:
 | 
					    with Image.open(TEST_FILE) as im:
 | 
				
			||||||
| 
						 | 
					@ -52,7 +53,7 @@ def test_save(tmp_path):
 | 
				
			||||||
        assert _binary.i32be(fp.read(4)) == file_length
 | 
					        assert _binary.i32be(fp.read(4)) == file_length
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_save_append_images(tmp_path):
 | 
					def test_save_append_images(tmp_path: Path) -> None:
 | 
				
			||||||
    temp_file = str(tmp_path / "temp.icns")
 | 
					    temp_file = str(tmp_path / "temp.icns")
 | 
				
			||||||
    provided_im = Image.new("RGBA", (32, 32), (255, 0, 0, 128))
 | 
					    provided_im = Image.new("RGBA", (32, 32), (255, 0, 0, 128))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -67,7 +68,7 @@ def test_save_append_images(tmp_path):
 | 
				
			||||||
            assert_image_equal(reread, provided_im)
 | 
					            assert_image_equal(reread, provided_im)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_save_fp():
 | 
					def test_save_fp() -> None:
 | 
				
			||||||
    fp = io.BytesIO()
 | 
					    fp = io.BytesIO()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    with Image.open(TEST_FILE) as im:
 | 
					    with Image.open(TEST_FILE) as im:
 | 
				
			||||||
| 
						 | 
					@ -79,7 +80,7 @@ def test_save_fp():
 | 
				
			||||||
        assert reread.format == "ICNS"
 | 
					        assert reread.format == "ICNS"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_sizes():
 | 
					def test_sizes() -> None:
 | 
				
			||||||
    # Check that we can load all of the sizes, and that the final pixel
 | 
					    # Check that we can load all of the sizes, and that the final pixel
 | 
				
			||||||
    # dimensions are as expected
 | 
					    # dimensions are as expected
 | 
				
			||||||
    with Image.open(TEST_FILE) as im:
 | 
					    with Image.open(TEST_FILE) as im:
 | 
				
			||||||
| 
						 | 
					@ -96,7 +97,7 @@ def test_sizes():
 | 
				
			||||||
            im.size = (1, 1)
 | 
					            im.size = (1, 1)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_older_icon():
 | 
					def test_older_icon() -> None:
 | 
				
			||||||
    # This icon was made with Icon Composer rather than iconutil; it still
 | 
					    # This icon was made with Icon Composer rather than iconutil; it still
 | 
				
			||||||
    # uses PNG rather than JP2, however (since it was made on 10.9).
 | 
					    # uses PNG rather than JP2, however (since it was made on 10.9).
 | 
				
			||||||
    with Image.open("Tests/images/pillow2.icns") as im:
 | 
					    with Image.open("Tests/images/pillow2.icns") as im:
 | 
				
			||||||
| 
						 | 
					@ -111,7 +112,7 @@ def test_older_icon():
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@skip_unless_feature("jpg_2000")
 | 
					@skip_unless_feature("jpg_2000")
 | 
				
			||||||
def test_jp2_icon():
 | 
					def test_jp2_icon() -> None:
 | 
				
			||||||
    # This icon uses JPEG 2000 images instead of the PNG images.
 | 
					    # This icon uses JPEG 2000 images instead of the PNG images.
 | 
				
			||||||
    # The advantage of doing this is that OS X 10.5 supports JPEG 2000
 | 
					    # The advantage of doing this is that OS X 10.5 supports JPEG 2000
 | 
				
			||||||
    # but not PNG; some commercial software therefore does just this.
 | 
					    # but not PNG; some commercial software therefore does just this.
 | 
				
			||||||
| 
						 | 
					@ -127,7 +128,7 @@ def test_jp2_icon():
 | 
				
			||||||
                assert im2.size == (wr, hr)
 | 
					                assert im2.size == (wr, hr)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_getimage():
 | 
					def test_getimage() -> None:
 | 
				
			||||||
    with open(TEST_FILE, "rb") as fp:
 | 
					    with open(TEST_FILE, "rb") as fp:
 | 
				
			||||||
        icns_file = IcnsImagePlugin.IcnsFile(fp)
 | 
					        icns_file = IcnsImagePlugin.IcnsFile(fp)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -140,14 +141,14 @@ def test_getimage():
 | 
				
			||||||
        assert im.size == (512, 512)
 | 
					        assert im.size == (512, 512)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_not_an_icns_file():
 | 
					def test_not_an_icns_file() -> None:
 | 
				
			||||||
    with io.BytesIO(b"invalid\n") as fp:
 | 
					    with io.BytesIO(b"invalid\n") as fp:
 | 
				
			||||||
        with pytest.raises(SyntaxError):
 | 
					        with pytest.raises(SyntaxError):
 | 
				
			||||||
            IcnsImagePlugin.IcnsFile(fp)
 | 
					            IcnsImagePlugin.IcnsFile(fp)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@skip_unless_feature("jpg_2000")
 | 
					@skip_unless_feature("jpg_2000")
 | 
				
			||||||
def test_icns_decompression_bomb():
 | 
					def test_icns_decompression_bomb() -> None:
 | 
				
			||||||
    with Image.open(
 | 
					    with Image.open(
 | 
				
			||||||
        "Tests/images/oom-8ed3316a4109213ca96fb8a256a0bfefdece1461.icns"
 | 
					        "Tests/images/oom-8ed3316a4109213ca96fb8a256a0bfefdece1461.icns"
 | 
				
			||||||
    ) as im:
 | 
					    ) as im:
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -2,6 +2,7 @@ from __future__ import annotations
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import io
 | 
					import io
 | 
				
			||||||
import os
 | 
					import os
 | 
				
			||||||
 | 
					from pathlib import Path
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import pytest
 | 
					import pytest
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -12,7 +13,7 @@ from .helper import assert_image_equal, assert_image_equal_tofile, hopper
 | 
				
			||||||
TEST_ICO_FILE = "Tests/images/hopper.ico"
 | 
					TEST_ICO_FILE = "Tests/images/hopper.ico"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_sanity():
 | 
					def test_sanity() -> None:
 | 
				
			||||||
    with Image.open(TEST_ICO_FILE) as im:
 | 
					    with Image.open(TEST_ICO_FILE) as im:
 | 
				
			||||||
        im.load()
 | 
					        im.load()
 | 
				
			||||||
    assert im.mode == "RGBA"
 | 
					    assert im.mode == "RGBA"
 | 
				
			||||||
| 
						 | 
					@ -21,29 +22,29 @@ def test_sanity():
 | 
				
			||||||
    assert im.get_format_mimetype() == "image/x-icon"
 | 
					    assert im.get_format_mimetype() == "image/x-icon"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_load():
 | 
					def test_load() -> None:
 | 
				
			||||||
    with Image.open(TEST_ICO_FILE) as im:
 | 
					    with Image.open(TEST_ICO_FILE) as im:
 | 
				
			||||||
        assert im.load()[0, 0] == (1, 1, 9, 255)
 | 
					        assert im.load()[0, 0] == (1, 1, 9, 255)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_mask():
 | 
					def test_mask() -> None:
 | 
				
			||||||
    with Image.open("Tests/images/hopper_mask.ico") as im:
 | 
					    with Image.open("Tests/images/hopper_mask.ico") as im:
 | 
				
			||||||
        assert_image_equal_tofile(im, "Tests/images/hopper_mask.png")
 | 
					        assert_image_equal_tofile(im, "Tests/images/hopper_mask.png")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_black_and_white():
 | 
					def test_black_and_white() -> None:
 | 
				
			||||||
    with Image.open("Tests/images/black_and_white.ico") as im:
 | 
					    with Image.open("Tests/images/black_and_white.ico") as im:
 | 
				
			||||||
        assert im.mode == "RGBA"
 | 
					        assert im.mode == "RGBA"
 | 
				
			||||||
        assert im.size == (16, 16)
 | 
					        assert im.size == (16, 16)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_invalid_file():
 | 
					def test_invalid_file() -> None:
 | 
				
			||||||
    with open("Tests/images/flower.jpg", "rb") as fp:
 | 
					    with open("Tests/images/flower.jpg", "rb") as fp:
 | 
				
			||||||
        with pytest.raises(SyntaxError):
 | 
					        with pytest.raises(SyntaxError):
 | 
				
			||||||
            IcoImagePlugin.IcoImageFile(fp)
 | 
					            IcoImagePlugin.IcoImageFile(fp)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_save_to_bytes():
 | 
					def test_save_to_bytes() -> None:
 | 
				
			||||||
    output = io.BytesIO()
 | 
					    output = io.BytesIO()
 | 
				
			||||||
    im = hopper()
 | 
					    im = hopper()
 | 
				
			||||||
    im.save(output, "ico", sizes=[(32, 32), (64, 64)])
 | 
					    im.save(output, "ico", sizes=[(32, 32), (64, 64)])
 | 
				
			||||||
| 
						 | 
					@ -73,7 +74,7 @@ def test_save_to_bytes():
 | 
				
			||||||
        )
 | 
					        )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_getpixel(tmp_path):
 | 
					def test_getpixel(tmp_path: Path) -> None:
 | 
				
			||||||
    temp_file = str(tmp_path / "temp.ico")
 | 
					    temp_file = str(tmp_path / "temp.ico")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    im = hopper()
 | 
					    im = hopper()
 | 
				
			||||||
| 
						 | 
					@ -86,7 +87,7 @@ def test_getpixel(tmp_path):
 | 
				
			||||||
        assert reloaded.getpixel((0, 0)) == (18, 20, 62)
 | 
					        assert reloaded.getpixel((0, 0)) == (18, 20, 62)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_no_duplicates(tmp_path):
 | 
					def test_no_duplicates(tmp_path: Path) -> None:
 | 
				
			||||||
    temp_file = str(tmp_path / "temp.ico")
 | 
					    temp_file = str(tmp_path / "temp.ico")
 | 
				
			||||||
    temp_file2 = str(tmp_path / "temp2.ico")
 | 
					    temp_file2 = str(tmp_path / "temp2.ico")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -100,7 +101,7 @@ def test_no_duplicates(tmp_path):
 | 
				
			||||||
    assert os.path.getsize(temp_file) == os.path.getsize(temp_file2)
 | 
					    assert os.path.getsize(temp_file) == os.path.getsize(temp_file2)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_different_bit_depths(tmp_path):
 | 
					def test_different_bit_depths(tmp_path: Path) -> None:
 | 
				
			||||||
    temp_file = str(tmp_path / "temp.ico")
 | 
					    temp_file = str(tmp_path / "temp.ico")
 | 
				
			||||||
    temp_file2 = str(tmp_path / "temp2.ico")
 | 
					    temp_file2 = str(tmp_path / "temp2.ico")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -134,7 +135,7 @@ def test_different_bit_depths(tmp_path):
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@pytest.mark.parametrize("mode", ("1", "L", "P", "RGB", "RGBA"))
 | 
					@pytest.mark.parametrize("mode", ("1", "L", "P", "RGB", "RGBA"))
 | 
				
			||||||
def test_save_to_bytes_bmp(mode):
 | 
					def test_save_to_bytes_bmp(mode) -> None:
 | 
				
			||||||
    output = io.BytesIO()
 | 
					    output = io.BytesIO()
 | 
				
			||||||
    im = hopper(mode)
 | 
					    im = hopper(mode)
 | 
				
			||||||
    im.save(output, "ico", bitmap_format="bmp", sizes=[(32, 32), (64, 64)])
 | 
					    im.save(output, "ico", bitmap_format="bmp", sizes=[(32, 32), (64, 64)])
 | 
				
			||||||
| 
						 | 
					@ -162,13 +163,13 @@ def test_save_to_bytes_bmp(mode):
 | 
				
			||||||
        assert_image_equal(reloaded, im)
 | 
					        assert_image_equal(reloaded, im)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_incorrect_size():
 | 
					def test_incorrect_size() -> None:
 | 
				
			||||||
    with Image.open(TEST_ICO_FILE) as im:
 | 
					    with Image.open(TEST_ICO_FILE) as im:
 | 
				
			||||||
        with pytest.raises(ValueError):
 | 
					        with pytest.raises(ValueError):
 | 
				
			||||||
            im.size = (1, 1)
 | 
					            im.size = (1, 1)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_save_256x256(tmp_path):
 | 
					def test_save_256x256(tmp_path: Path) -> None:
 | 
				
			||||||
    """Issue #2264 https://github.com/python-pillow/Pillow/issues/2264"""
 | 
					    """Issue #2264 https://github.com/python-pillow/Pillow/issues/2264"""
 | 
				
			||||||
    # Arrange
 | 
					    # Arrange
 | 
				
			||||||
    with Image.open("Tests/images/hopper_256x256.ico") as im:
 | 
					    with Image.open("Tests/images/hopper_256x256.ico") as im:
 | 
				
			||||||
| 
						 | 
					@ -181,7 +182,7 @@ def test_save_256x256(tmp_path):
 | 
				
			||||||
        assert im_saved.size == (256, 256)
 | 
					        assert im_saved.size == (256, 256)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_only_save_relevant_sizes(tmp_path):
 | 
					def test_only_save_relevant_sizes(tmp_path: Path) -> None:
 | 
				
			||||||
    """Issue #2266 https://github.com/python-pillow/Pillow/issues/2266
 | 
					    """Issue #2266 https://github.com/python-pillow/Pillow/issues/2266
 | 
				
			||||||
    Should save in 16x16, 24x24, 32x32, 48x48 sizes
 | 
					    Should save in 16x16, 24x24, 32x32, 48x48 sizes
 | 
				
			||||||
    and not in 16x16, 24x24, 32x32, 48x48, 48x48, 48x48, 48x48 sizes
 | 
					    and not in 16x16, 24x24, 32x32, 48x48, 48x48, 48x48, 48x48 sizes
 | 
				
			||||||
| 
						 | 
					@ -197,7 +198,7 @@ def test_only_save_relevant_sizes(tmp_path):
 | 
				
			||||||
        assert im_saved.info["sizes"] == {(16, 16), (24, 24), (32, 32), (48, 48)}
 | 
					        assert im_saved.info["sizes"] == {(16, 16), (24, 24), (32, 32), (48, 48)}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_save_append_images(tmp_path):
 | 
					def test_save_append_images(tmp_path: Path) -> None:
 | 
				
			||||||
    # append_images should be used for scaled down versions of the image
 | 
					    # append_images should be used for scaled down versions of the image
 | 
				
			||||||
    im = hopper("RGBA")
 | 
					    im = hopper("RGBA")
 | 
				
			||||||
    provided_im = Image.new("RGBA", (32, 32), (255, 0, 0))
 | 
					    provided_im = Image.new("RGBA", (32, 32), (255, 0, 0))
 | 
				
			||||||
| 
						 | 
					@ -211,7 +212,7 @@ def test_save_append_images(tmp_path):
 | 
				
			||||||
        assert_image_equal(reread, provided_im)
 | 
					        assert_image_equal(reread, provided_im)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_unexpected_size():
 | 
					def test_unexpected_size() -> None:
 | 
				
			||||||
    # This image has been manually hexedited to state that it is 16x32
 | 
					    # This image has been manually hexedited to state that it is 16x32
 | 
				
			||||||
    # while the image within is still 16x16
 | 
					    # while the image within is still 16x16
 | 
				
			||||||
    with pytest.warns(UserWarning):
 | 
					    with pytest.warns(UserWarning):
 | 
				
			||||||
| 
						 | 
					@ -219,7 +220,7 @@ def test_unexpected_size():
 | 
				
			||||||
            assert im.size == (16, 16)
 | 
					            assert im.size == (16, 16)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_draw_reloaded(tmp_path):
 | 
					def test_draw_reloaded(tmp_path: Path) -> None:
 | 
				
			||||||
    with Image.open(TEST_ICO_FILE) as im:
 | 
					    with Image.open(TEST_ICO_FILE) as im:
 | 
				
			||||||
        outfile = str(tmp_path / "temp_saved_hopper_draw.ico")
 | 
					        outfile = str(tmp_path / "temp_saved_hopper_draw.ico")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -2,6 +2,7 @@ from __future__ import annotations
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import filecmp
 | 
					import filecmp
 | 
				
			||||||
import warnings
 | 
					import warnings
 | 
				
			||||||
 | 
					from pathlib import Path
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import pytest
 | 
					import pytest
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -13,7 +14,7 @@ from .helper import assert_image_equal_tofile, hopper, is_pypy
 | 
				
			||||||
TEST_IM = "Tests/images/hopper.im"
 | 
					TEST_IM = "Tests/images/hopper.im"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_sanity():
 | 
					def test_sanity() -> None:
 | 
				
			||||||
    with Image.open(TEST_IM) as im:
 | 
					    with Image.open(TEST_IM) as im:
 | 
				
			||||||
        im.load()
 | 
					        im.load()
 | 
				
			||||||
        assert im.mode == "RGB"
 | 
					        assert im.mode == "RGB"
 | 
				
			||||||
| 
						 | 
					@ -21,7 +22,7 @@ def test_sanity():
 | 
				
			||||||
        assert im.format == "IM"
 | 
					        assert im.format == "IM"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_name_limit(tmp_path):
 | 
					def test_name_limit(tmp_path: Path) -> None:
 | 
				
			||||||
    out = str(tmp_path / ("name_limit_test" * 7 + ".im"))
 | 
					    out = str(tmp_path / ("name_limit_test" * 7 + ".im"))
 | 
				
			||||||
    with Image.open(TEST_IM) as im:
 | 
					    with Image.open(TEST_IM) as im:
 | 
				
			||||||
        im.save(out)
 | 
					        im.save(out)
 | 
				
			||||||
| 
						 | 
					@ -29,8 +30,8 @@ def test_name_limit(tmp_path):
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@pytest.mark.skipif(is_pypy(), reason="Requires CPython")
 | 
					@pytest.mark.skipif(is_pypy(), reason="Requires CPython")
 | 
				
			||||||
def test_unclosed_file():
 | 
					def test_unclosed_file() -> None:
 | 
				
			||||||
    def open():
 | 
					    def open() -> None:
 | 
				
			||||||
        im = Image.open(TEST_IM)
 | 
					        im = Image.open(TEST_IM)
 | 
				
			||||||
        im.load()
 | 
					        im.load()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -38,20 +39,20 @@ def test_unclosed_file():
 | 
				
			||||||
        open()
 | 
					        open()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_closed_file():
 | 
					def test_closed_file() -> None:
 | 
				
			||||||
    with warnings.catch_warnings():
 | 
					    with warnings.catch_warnings():
 | 
				
			||||||
        im = Image.open(TEST_IM)
 | 
					        im = Image.open(TEST_IM)
 | 
				
			||||||
        im.load()
 | 
					        im.load()
 | 
				
			||||||
        im.close()
 | 
					        im.close()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_context_manager():
 | 
					def test_context_manager() -> None:
 | 
				
			||||||
    with warnings.catch_warnings():
 | 
					    with warnings.catch_warnings():
 | 
				
			||||||
        with Image.open(TEST_IM) as im:
 | 
					        with Image.open(TEST_IM) as im:
 | 
				
			||||||
            im.load()
 | 
					            im.load()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_tell():
 | 
					def test_tell() -> None:
 | 
				
			||||||
    # Arrange
 | 
					    # Arrange
 | 
				
			||||||
    with Image.open(TEST_IM) as im:
 | 
					    with Image.open(TEST_IM) as im:
 | 
				
			||||||
        # Act
 | 
					        # Act
 | 
				
			||||||
| 
						 | 
					@ -61,13 +62,13 @@ def test_tell():
 | 
				
			||||||
    assert frame == 0
 | 
					    assert frame == 0
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_n_frames():
 | 
					def test_n_frames() -> None:
 | 
				
			||||||
    with Image.open(TEST_IM) as im:
 | 
					    with Image.open(TEST_IM) as im:
 | 
				
			||||||
        assert im.n_frames == 1
 | 
					        assert im.n_frames == 1
 | 
				
			||||||
        assert not im.is_animated
 | 
					        assert not im.is_animated
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_eoferror():
 | 
					def test_eoferror() -> None:
 | 
				
			||||||
    with Image.open(TEST_IM) as im:
 | 
					    with Image.open(TEST_IM) as im:
 | 
				
			||||||
        n_frames = im.n_frames
 | 
					        n_frames = im.n_frames
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -81,14 +82,14 @@ def test_eoferror():
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@pytest.mark.parametrize("mode", ("RGB", "P", "PA"))
 | 
					@pytest.mark.parametrize("mode", ("RGB", "P", "PA"))
 | 
				
			||||||
def test_roundtrip(mode, tmp_path):
 | 
					def test_roundtrip(mode, tmp_path: Path) -> None:
 | 
				
			||||||
    out = str(tmp_path / "temp.im")
 | 
					    out = str(tmp_path / "temp.im")
 | 
				
			||||||
    im = hopper(mode)
 | 
					    im = hopper(mode)
 | 
				
			||||||
    im.save(out)
 | 
					    im.save(out)
 | 
				
			||||||
    assert_image_equal_tofile(im, out)
 | 
					    assert_image_equal_tofile(im, out)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_small_palette(tmp_path):
 | 
					def test_small_palette(tmp_path: Path) -> None:
 | 
				
			||||||
    im = Image.new("P", (1, 1))
 | 
					    im = Image.new("P", (1, 1))
 | 
				
			||||||
    colors = [0, 1, 2]
 | 
					    colors = [0, 1, 2]
 | 
				
			||||||
    im.putpalette(colors)
 | 
					    im.putpalette(colors)
 | 
				
			||||||
| 
						 | 
					@ -100,19 +101,19 @@ def test_small_palette(tmp_path):
 | 
				
			||||||
        assert reloaded.getpalette() == colors + [0] * 765
 | 
					        assert reloaded.getpalette() == colors + [0] * 765
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_save_unsupported_mode(tmp_path):
 | 
					def test_save_unsupported_mode(tmp_path: Path) -> None:
 | 
				
			||||||
    out = str(tmp_path / "temp.im")
 | 
					    out = str(tmp_path / "temp.im")
 | 
				
			||||||
    im = hopper("HSV")
 | 
					    im = hopper("HSV")
 | 
				
			||||||
    with pytest.raises(ValueError):
 | 
					    with pytest.raises(ValueError):
 | 
				
			||||||
        im.save(out)
 | 
					        im.save(out)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_invalid_file():
 | 
					def test_invalid_file() -> None:
 | 
				
			||||||
    invalid_file = "Tests/images/flower.jpg"
 | 
					    invalid_file = "Tests/images/flower.jpg"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    with pytest.raises(SyntaxError):
 | 
					    with pytest.raises(SyntaxError):
 | 
				
			||||||
        ImImagePlugin.ImImageFile(invalid_file)
 | 
					        ImImagePlugin.ImImageFile(invalid_file)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_number():
 | 
					def test_number() -> None:
 | 
				
			||||||
    assert ImImagePlugin.number("1.2") == 1.2
 | 
					    assert ImImagePlugin.number("1.2") == 1.2
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -12,7 +12,7 @@ from .helper import assert_image_equal, hopper
 | 
				
			||||||
TEST_FILE = "Tests/images/iptc.jpg"
 | 
					TEST_FILE = "Tests/images/iptc.jpg"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_open():
 | 
					def test_open() -> None:
 | 
				
			||||||
    expected = Image.new("L", (1, 1))
 | 
					    expected = Image.new("L", (1, 1))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    f = BytesIO(
 | 
					    f = BytesIO(
 | 
				
			||||||
| 
						 | 
					@ -24,7 +24,7 @@ def test_open():
 | 
				
			||||||
        assert_image_equal(im, expected)
 | 
					        assert_image_equal(im, expected)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_getiptcinfo_jpg_none():
 | 
					def test_getiptcinfo_jpg_none() -> None:
 | 
				
			||||||
    # Arrange
 | 
					    # Arrange
 | 
				
			||||||
    with hopper() as im:
 | 
					    with hopper() as im:
 | 
				
			||||||
        # Act
 | 
					        # Act
 | 
				
			||||||
| 
						 | 
					@ -34,7 +34,7 @@ def test_getiptcinfo_jpg_none():
 | 
				
			||||||
    assert iptc is None
 | 
					    assert iptc is None
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_getiptcinfo_jpg_found():
 | 
					def test_getiptcinfo_jpg_found() -> None:
 | 
				
			||||||
    # Arrange
 | 
					    # Arrange
 | 
				
			||||||
    with Image.open(TEST_FILE) as im:
 | 
					    with Image.open(TEST_FILE) as im:
 | 
				
			||||||
        # Act
 | 
					        # Act
 | 
				
			||||||
| 
						 | 
					@ -46,7 +46,7 @@ def test_getiptcinfo_jpg_found():
 | 
				
			||||||
    assert iptc[(2, 101)] == b"Hungary"
 | 
					    assert iptc[(2, 101)] == b"Hungary"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_getiptcinfo_fotostation():
 | 
					def test_getiptcinfo_fotostation() -> None:
 | 
				
			||||||
    # Arrange
 | 
					    # Arrange
 | 
				
			||||||
    with open(TEST_FILE, "rb") as fp:
 | 
					    with open(TEST_FILE, "rb") as fp:
 | 
				
			||||||
        data = bytearray(fp.read())
 | 
					        data = bytearray(fp.read())
 | 
				
			||||||
| 
						 | 
					@ -63,7 +63,7 @@ def test_getiptcinfo_fotostation():
 | 
				
			||||||
    pytest.fail("FotoStation tag not found")
 | 
					    pytest.fail("FotoStation tag not found")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_getiptcinfo_zero_padding():
 | 
					def test_getiptcinfo_zero_padding() -> None:
 | 
				
			||||||
    # Arrange
 | 
					    # Arrange
 | 
				
			||||||
    with Image.open(TEST_FILE) as im:
 | 
					    with Image.open(TEST_FILE) as im:
 | 
				
			||||||
        im.info["photoshop"][0x0404] += b"\x00\x00\x00"
 | 
					        im.info["photoshop"][0x0404] += b"\x00\x00\x00"
 | 
				
			||||||
| 
						 | 
					@ -76,7 +76,7 @@ def test_getiptcinfo_zero_padding():
 | 
				
			||||||
    assert len(iptc) == 3
 | 
					    assert len(iptc) == 3
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_getiptcinfo_tiff_none():
 | 
					def test_getiptcinfo_tiff_none() -> None:
 | 
				
			||||||
    # Arrange
 | 
					    # Arrange
 | 
				
			||||||
    with Image.open("Tests/images/hopper.tif") as im:
 | 
					    with Image.open("Tests/images/hopper.tif") as im:
 | 
				
			||||||
        # Act
 | 
					        # Act
 | 
				
			||||||
| 
						 | 
					@ -86,7 +86,7 @@ def test_getiptcinfo_tiff_none():
 | 
				
			||||||
    assert iptc is None
 | 
					    assert iptc is None
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_i():
 | 
					def test_i() -> None:
 | 
				
			||||||
    # Arrange
 | 
					    # Arrange
 | 
				
			||||||
    c = b"a"
 | 
					    c = b"a"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -98,7 +98,7 @@ def test_i():
 | 
				
			||||||
    assert ret == 97
 | 
					    assert ret == 97
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_dump(monkeypatch):
 | 
					def test_dump(monkeypatch) -> None:
 | 
				
			||||||
    # Arrange
 | 
					    # Arrange
 | 
				
			||||||
    c = b"abc"
 | 
					    c = b"abc"
 | 
				
			||||||
    # Temporarily redirect stdout
 | 
					    # Temporarily redirect stdout
 | 
				
			||||||
| 
						 | 
					@ -113,6 +113,6 @@ def test_dump(monkeypatch):
 | 
				
			||||||
    assert mystdout.getvalue() == "61 62 63 \n"
 | 
					    assert mystdout.getvalue() == "61 62 63 \n"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_pad_deprecation():
 | 
					def test_pad_deprecation() -> None:
 | 
				
			||||||
    with pytest.warns(DeprecationWarning):
 | 
					    with pytest.warns(DeprecationWarning):
 | 
				
			||||||
        assert IptcImagePlugin.PAD == b"\0\0\0\0"
 | 
					        assert IptcImagePlugin.PAD == b"\0\0\0\0"
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -4,6 +4,7 @@ import os
 | 
				
			||||||
import re
 | 
					import re
 | 
				
			||||||
import warnings
 | 
					import warnings
 | 
				
			||||||
from io import BytesIO
 | 
					from io import BytesIO
 | 
				
			||||||
 | 
					from pathlib import Path
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import pytest
 | 
					import pytest
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -50,7 +51,7 @@ class TestFileJpeg:
 | 
				
			||||||
        im.bytes = test_bytes  # for testing only
 | 
					        im.bytes = test_bytes  # for testing only
 | 
				
			||||||
        return im
 | 
					        return im
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def gen_random_image(self, size, mode="RGB"):
 | 
					    def gen_random_image(self, size, mode: str = "RGB"):
 | 
				
			||||||
        """Generates a very hard to compress file
 | 
					        """Generates a very hard to compress file
 | 
				
			||||||
        :param size: tuple
 | 
					        :param size: tuple
 | 
				
			||||||
        :param mode: optional image mode
 | 
					        :param mode: optional image mode
 | 
				
			||||||
| 
						 | 
					@ -58,7 +59,7 @@ class TestFileJpeg:
 | 
				
			||||||
        """
 | 
					        """
 | 
				
			||||||
        return Image.frombytes(mode, size, os.urandom(size[0] * size[1] * len(mode)))
 | 
					        return Image.frombytes(mode, size, os.urandom(size[0] * size[1] * len(mode)))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_sanity(self):
 | 
					    def test_sanity(self) -> None:
 | 
				
			||||||
        # internal version number
 | 
					        # internal version number
 | 
				
			||||||
        assert re.search(r"\d+\.\d+$", features.version_codec("jpg"))
 | 
					        assert re.search(r"\d+\.\d+$", features.version_codec("jpg"))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -70,13 +71,13 @@ class TestFileJpeg:
 | 
				
			||||||
            assert im.get_format_mimetype() == "image/jpeg"
 | 
					            assert im.get_format_mimetype() == "image/jpeg"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    @pytest.mark.parametrize("size", ((1, 0), (0, 1), (0, 0)))
 | 
					    @pytest.mark.parametrize("size", ((1, 0), (0, 1), (0, 0)))
 | 
				
			||||||
    def test_zero(self, size, tmp_path):
 | 
					    def test_zero(self, size, tmp_path: Path) -> None:
 | 
				
			||||||
        f = str(tmp_path / "temp.jpg")
 | 
					        f = str(tmp_path / "temp.jpg")
 | 
				
			||||||
        im = Image.new("RGB", size)
 | 
					        im = Image.new("RGB", size)
 | 
				
			||||||
        with pytest.raises(ValueError):
 | 
					        with pytest.raises(ValueError):
 | 
				
			||||||
            im.save(f)
 | 
					            im.save(f)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_app(self):
 | 
					    def test_app(self) -> None:
 | 
				
			||||||
        # Test APP/COM reader (@PIL135)
 | 
					        # Test APP/COM reader (@PIL135)
 | 
				
			||||||
        with Image.open(TEST_FILE) as im:
 | 
					        with Image.open(TEST_FILE) as im:
 | 
				
			||||||
            assert im.applist[0] == ("APP0", b"JFIF\x00\x01\x01\x01\x00`\x00`\x00\x00")
 | 
					            assert im.applist[0] == ("APP0", b"JFIF\x00\x01\x01\x01\x00`\x00`\x00\x00")
 | 
				
			||||||
| 
						 | 
					@ -89,7 +90,7 @@ class TestFileJpeg:
 | 
				
			||||||
            assert im.info["comment"] == b"File written by Adobe Photoshop\xa8 4.0\x00"
 | 
					            assert im.info["comment"] == b"File written by Adobe Photoshop\xa8 4.0\x00"
 | 
				
			||||||
            assert im.app["COM"] == im.info["comment"]
 | 
					            assert im.app["COM"] == im.info["comment"]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_comment_write(self):
 | 
					    def test_comment_write(self) -> None:
 | 
				
			||||||
        with Image.open(TEST_FILE) as im:
 | 
					        with Image.open(TEST_FILE) as im:
 | 
				
			||||||
            assert im.info["comment"] == b"File written by Adobe Photoshop\xa8 4.0\x00"
 | 
					            assert im.info["comment"] == b"File written by Adobe Photoshop\xa8 4.0\x00"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -115,7 +116,7 @@ class TestFileJpeg:
 | 
				
			||||||
                        comment = comment.encode()
 | 
					                        comment = comment.encode()
 | 
				
			||||||
                    assert reloaded.info["comment"] == comment
 | 
					                    assert reloaded.info["comment"] == comment
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_cmyk(self):
 | 
					    def test_cmyk(self) -> None:
 | 
				
			||||||
        # Test CMYK handling.  Thanks to Tim and Charlie for test data,
 | 
					        # Test CMYK handling.  Thanks to Tim and Charlie for test data,
 | 
				
			||||||
        # Michael for getting me to look one more time.
 | 
					        # Michael for getting me to look one more time.
 | 
				
			||||||
        f = "Tests/images/pil_sample_cmyk.jpg"
 | 
					        f = "Tests/images/pil_sample_cmyk.jpg"
 | 
				
			||||||
| 
						 | 
					@ -143,7 +144,7 @@ class TestFileJpeg:
 | 
				
			||||||
            )
 | 
					            )
 | 
				
			||||||
            assert k > 0.9
 | 
					            assert k > 0.9
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_rgb(self):
 | 
					    def test_rgb(self) -> None:
 | 
				
			||||||
        def getchannels(im):
 | 
					        def getchannels(im):
 | 
				
			||||||
            return tuple(v[0] for v in im.layer)
 | 
					            return tuple(v[0] for v in im.layer)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -160,7 +161,7 @@ class TestFileJpeg:
 | 
				
			||||||
        "test_image_path",
 | 
					        "test_image_path",
 | 
				
			||||||
        [TEST_FILE, "Tests/images/pil_sample_cmyk.jpg"],
 | 
					        [TEST_FILE, "Tests/images/pil_sample_cmyk.jpg"],
 | 
				
			||||||
    )
 | 
					    )
 | 
				
			||||||
    def test_dpi(self, test_image_path):
 | 
					    def test_dpi(self, test_image_path) -> None:
 | 
				
			||||||
        def test(xdpi, ydpi=None):
 | 
					        def test(xdpi, ydpi=None):
 | 
				
			||||||
            with Image.open(test_image_path) as im:
 | 
					            with Image.open(test_image_path) as im:
 | 
				
			||||||
                im = self.roundtrip(im, dpi=(xdpi, ydpi or xdpi))
 | 
					                im = self.roundtrip(im, dpi=(xdpi, ydpi or xdpi))
 | 
				
			||||||
| 
						 | 
					@ -174,7 +175,7 @@ class TestFileJpeg:
 | 
				
			||||||
    @mark_if_feature_version(
 | 
					    @mark_if_feature_version(
 | 
				
			||||||
        pytest.mark.valgrind_known_error, "libjpeg_turbo", "2.0", reason="Known Failing"
 | 
					        pytest.mark.valgrind_known_error, "libjpeg_turbo", "2.0", reason="Known Failing"
 | 
				
			||||||
    )
 | 
					    )
 | 
				
			||||||
    def test_icc(self, tmp_path):
 | 
					    def test_icc(self, tmp_path: Path) -> None:
 | 
				
			||||||
        # Test ICC support
 | 
					        # Test ICC support
 | 
				
			||||||
        with Image.open("Tests/images/rgb.jpg") as im1:
 | 
					        with Image.open("Tests/images/rgb.jpg") as im1:
 | 
				
			||||||
            icc_profile = im1.info["icc_profile"]
 | 
					            icc_profile = im1.info["icc_profile"]
 | 
				
			||||||
| 
						 | 
					@ -206,7 +207,7 @@ class TestFileJpeg:
 | 
				
			||||||
            ImageFile.MAXBLOCK * 4 + 3,  # large block
 | 
					            ImageFile.MAXBLOCK * 4 + 3,  # large block
 | 
				
			||||||
        ),
 | 
					        ),
 | 
				
			||||||
    )
 | 
					    )
 | 
				
			||||||
    def test_icc_big(self, n):
 | 
					    def test_icc_big(self, n) -> None:
 | 
				
			||||||
        # Make sure that the "extra" support handles large blocks
 | 
					        # Make sure that the "extra" support handles large blocks
 | 
				
			||||||
        # The ICC APP marker can store 65519 bytes per marker, so
 | 
					        # The ICC APP marker can store 65519 bytes per marker, so
 | 
				
			||||||
        # using a 4-byte test code should allow us to detect out of
 | 
					        # using a 4-byte test code should allow us to detect out of
 | 
				
			||||||
| 
						 | 
					@ -219,7 +220,7 @@ class TestFileJpeg:
 | 
				
			||||||
    @mark_if_feature_version(
 | 
					    @mark_if_feature_version(
 | 
				
			||||||
        pytest.mark.valgrind_known_error, "libjpeg_turbo", "2.0", reason="Known Failing"
 | 
					        pytest.mark.valgrind_known_error, "libjpeg_turbo", "2.0", reason="Known Failing"
 | 
				
			||||||
    )
 | 
					    )
 | 
				
			||||||
    def test_large_icc_meta(self, tmp_path):
 | 
					    def test_large_icc_meta(self, tmp_path: Path) -> None:
 | 
				
			||||||
        # https://github.com/python-pillow/Pillow/issues/148
 | 
					        # https://github.com/python-pillow/Pillow/issues/148
 | 
				
			||||||
        # Sometimes the meta data on the icc_profile block is bigger than
 | 
					        # Sometimes the meta data on the icc_profile block is bigger than
 | 
				
			||||||
        # Image.MAXBLOCK or the image size.
 | 
					        # Image.MAXBLOCK or the image size.
 | 
				
			||||||
| 
						 | 
					@ -243,7 +244,7 @@ class TestFileJpeg:
 | 
				
			||||||
            f = str(tmp_path / "temp3.jpg")
 | 
					            f = str(tmp_path / "temp3.jpg")
 | 
				
			||||||
            im.save(f, progressive=True, quality=94, exif=b" " * 43668)
 | 
					            im.save(f, progressive=True, quality=94, exif=b" " * 43668)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_optimize(self):
 | 
					    def test_optimize(self) -> None:
 | 
				
			||||||
        im1 = self.roundtrip(hopper())
 | 
					        im1 = self.roundtrip(hopper())
 | 
				
			||||||
        im2 = self.roundtrip(hopper(), optimize=0)
 | 
					        im2 = self.roundtrip(hopper(), optimize=0)
 | 
				
			||||||
        im3 = self.roundtrip(hopper(), optimize=1)
 | 
					        im3 = self.roundtrip(hopper(), optimize=1)
 | 
				
			||||||
| 
						 | 
					@ -252,14 +253,14 @@ class TestFileJpeg:
 | 
				
			||||||
        assert im1.bytes >= im2.bytes
 | 
					        assert im1.bytes >= im2.bytes
 | 
				
			||||||
        assert im1.bytes >= im3.bytes
 | 
					        assert im1.bytes >= im3.bytes
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_optimize_large_buffer(self, tmp_path):
 | 
					    def test_optimize_large_buffer(self, tmp_path: Path) -> None:
 | 
				
			||||||
        # https://github.com/python-pillow/Pillow/issues/148
 | 
					        # https://github.com/python-pillow/Pillow/issues/148
 | 
				
			||||||
        f = str(tmp_path / "temp.jpg")
 | 
					        f = str(tmp_path / "temp.jpg")
 | 
				
			||||||
        # this requires ~ 1.5x Image.MAXBLOCK
 | 
					        # this requires ~ 1.5x Image.MAXBLOCK
 | 
				
			||||||
        im = Image.new("RGB", (4096, 4096), 0xFF3333)
 | 
					        im = Image.new("RGB", (4096, 4096), 0xFF3333)
 | 
				
			||||||
        im.save(f, format="JPEG", optimize=True)
 | 
					        im.save(f, format="JPEG", optimize=True)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_progressive(self):
 | 
					    def test_progressive(self) -> None:
 | 
				
			||||||
        im1 = self.roundtrip(hopper())
 | 
					        im1 = self.roundtrip(hopper())
 | 
				
			||||||
        im2 = self.roundtrip(hopper(), progressive=False)
 | 
					        im2 = self.roundtrip(hopper(), progressive=False)
 | 
				
			||||||
        im3 = self.roundtrip(hopper(), progressive=True)
 | 
					        im3 = self.roundtrip(hopper(), progressive=True)
 | 
				
			||||||
| 
						 | 
					@ -270,25 +271,25 @@ class TestFileJpeg:
 | 
				
			||||||
        assert_image_equal(im1, im3)
 | 
					        assert_image_equal(im1, im3)
 | 
				
			||||||
        assert im1.bytes >= im3.bytes
 | 
					        assert im1.bytes >= im3.bytes
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_progressive_large_buffer(self, tmp_path):
 | 
					    def test_progressive_large_buffer(self, tmp_path: Path) -> None:
 | 
				
			||||||
        f = str(tmp_path / "temp.jpg")
 | 
					        f = str(tmp_path / "temp.jpg")
 | 
				
			||||||
        # this requires ~ 1.5x Image.MAXBLOCK
 | 
					        # this requires ~ 1.5x Image.MAXBLOCK
 | 
				
			||||||
        im = Image.new("RGB", (4096, 4096), 0xFF3333)
 | 
					        im = Image.new("RGB", (4096, 4096), 0xFF3333)
 | 
				
			||||||
        im.save(f, format="JPEG", progressive=True)
 | 
					        im.save(f, format="JPEG", progressive=True)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_progressive_large_buffer_highest_quality(self, tmp_path):
 | 
					    def test_progressive_large_buffer_highest_quality(self, tmp_path: Path) -> None:
 | 
				
			||||||
        f = str(tmp_path / "temp.jpg")
 | 
					        f = str(tmp_path / "temp.jpg")
 | 
				
			||||||
        im = self.gen_random_image((255, 255))
 | 
					        im = self.gen_random_image((255, 255))
 | 
				
			||||||
        # this requires more bytes than pixels in the image
 | 
					        # this requires more bytes than pixels in the image
 | 
				
			||||||
        im.save(f, format="JPEG", progressive=True, quality=100)
 | 
					        im.save(f, format="JPEG", progressive=True, quality=100)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_progressive_cmyk_buffer(self):
 | 
					    def test_progressive_cmyk_buffer(self) -> None:
 | 
				
			||||||
        # Issue 2272, quality 90 cmyk image is tripping the large buffer bug.
 | 
					        # Issue 2272, quality 90 cmyk image is tripping the large buffer bug.
 | 
				
			||||||
        f = BytesIO()
 | 
					        f = BytesIO()
 | 
				
			||||||
        im = self.gen_random_image((256, 256), "CMYK")
 | 
					        im = self.gen_random_image((256, 256), "CMYK")
 | 
				
			||||||
        im.save(f, format="JPEG", progressive=True, quality=94)
 | 
					        im.save(f, format="JPEG", progressive=True, quality=94)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_large_exif(self, tmp_path):
 | 
					    def test_large_exif(self, tmp_path: Path) -> None:
 | 
				
			||||||
        # https://github.com/python-pillow/Pillow/issues/148
 | 
					        # https://github.com/python-pillow/Pillow/issues/148
 | 
				
			||||||
        f = str(tmp_path / "temp.jpg")
 | 
					        f = str(tmp_path / "temp.jpg")
 | 
				
			||||||
        im = hopper()
 | 
					        im = hopper()
 | 
				
			||||||
| 
						 | 
					@ -297,12 +298,12 @@ class TestFileJpeg:
 | 
				
			||||||
        with pytest.raises(ValueError):
 | 
					        with pytest.raises(ValueError):
 | 
				
			||||||
            im.save(f, "JPEG", quality=90, exif=b"1" * 65534)
 | 
					            im.save(f, "JPEG", quality=90, exif=b"1" * 65534)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_exif_typeerror(self):
 | 
					    def test_exif_typeerror(self) -> None:
 | 
				
			||||||
        with Image.open("Tests/images/exif_typeerror.jpg") as im:
 | 
					        with Image.open("Tests/images/exif_typeerror.jpg") as im:
 | 
				
			||||||
            # Should not raise a TypeError
 | 
					            # Should not raise a TypeError
 | 
				
			||||||
            im._getexif()
 | 
					            im._getexif()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_exif_gps(self, tmp_path):
 | 
					    def test_exif_gps(self, tmp_path: Path) -> None:
 | 
				
			||||||
        expected_exif_gps = {
 | 
					        expected_exif_gps = {
 | 
				
			||||||
            0: b"\x00\x00\x00\x01",
 | 
					            0: b"\x00\x00\x00\x01",
 | 
				
			||||||
            2: 4294967295,
 | 
					            2: 4294967295,
 | 
				
			||||||
| 
						 | 
					@ -327,7 +328,7 @@ class TestFileJpeg:
 | 
				
			||||||
            exif = reloaded._getexif()
 | 
					            exif = reloaded._getexif()
 | 
				
			||||||
            assert exif[gps_index] == expected_exif_gps
 | 
					            assert exif[gps_index] == expected_exif_gps
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_empty_exif_gps(self):
 | 
					    def test_empty_exif_gps(self) -> None:
 | 
				
			||||||
        with Image.open("Tests/images/empty_gps_ifd.jpg") as im:
 | 
					        with Image.open("Tests/images/empty_gps_ifd.jpg") as im:
 | 
				
			||||||
            exif = im.getexif()
 | 
					            exif = im.getexif()
 | 
				
			||||||
            del exif[0x8769]
 | 
					            del exif[0x8769]
 | 
				
			||||||
| 
						 | 
					@ -345,7 +346,7 @@ class TestFileJpeg:
 | 
				
			||||||
        # Assert that it was transposed
 | 
					        # Assert that it was transposed
 | 
				
			||||||
        assert 0x0112 not in exif
 | 
					        assert 0x0112 not in exif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_exif_equality(self):
 | 
					    def test_exif_equality(self) -> None:
 | 
				
			||||||
        # In 7.2.0, Exif rationals were changed to be read as
 | 
					        # In 7.2.0, Exif rationals were changed to be read as
 | 
				
			||||||
        # TiffImagePlugin.IFDRational. This class had a bug in __eq__,
 | 
					        # TiffImagePlugin.IFDRational. This class had a bug in __eq__,
 | 
				
			||||||
        # breaking the self-equality of Exif data
 | 
					        # breaking the self-equality of Exif data
 | 
				
			||||||
| 
						 | 
					@ -355,7 +356,7 @@ class TestFileJpeg:
 | 
				
			||||||
                exifs.append(im._getexif())
 | 
					                exifs.append(im._getexif())
 | 
				
			||||||
        assert exifs[0] == exifs[1]
 | 
					        assert exifs[0] == exifs[1]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_exif_rollback(self):
 | 
					    def test_exif_rollback(self) -> None:
 | 
				
			||||||
        # rolling back exif support in 3.1 to pre-3.0 formatting.
 | 
					        # rolling back exif support in 3.1 to pre-3.0 formatting.
 | 
				
			||||||
        # expected from 2.9, with b/u qualifiers switched for 3.2 compatibility
 | 
					        # expected from 2.9, with b/u qualifiers switched for 3.2 compatibility
 | 
				
			||||||
        # this test passes on 2.9 and 3.1, but not 3.0
 | 
					        # this test passes on 2.9 and 3.1, but not 3.0
 | 
				
			||||||
| 
						 | 
					@ -390,12 +391,12 @@ class TestFileJpeg:
 | 
				
			||||||
        for tag, value in expected_exif.items():
 | 
					        for tag, value in expected_exif.items():
 | 
				
			||||||
            assert value == exif[tag]
 | 
					            assert value == exif[tag]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_exif_gps_typeerror(self):
 | 
					    def test_exif_gps_typeerror(self) -> None:
 | 
				
			||||||
        with Image.open("Tests/images/exif_gps_typeerror.jpg") as im:
 | 
					        with Image.open("Tests/images/exif_gps_typeerror.jpg") as im:
 | 
				
			||||||
            # Should not raise a TypeError
 | 
					            # Should not raise a TypeError
 | 
				
			||||||
            im._getexif()
 | 
					            im._getexif()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_progressive_compat(self):
 | 
					    def test_progressive_compat(self) -> None:
 | 
				
			||||||
        im1 = self.roundtrip(hopper())
 | 
					        im1 = self.roundtrip(hopper())
 | 
				
			||||||
        assert not im1.info.get("progressive")
 | 
					        assert not im1.info.get("progressive")
 | 
				
			||||||
        assert not im1.info.get("progression")
 | 
					        assert not im1.info.get("progression")
 | 
				
			||||||
| 
						 | 
					@ -416,7 +417,7 @@ class TestFileJpeg:
 | 
				
			||||||
        assert im3.info.get("progressive")
 | 
					        assert im3.info.get("progressive")
 | 
				
			||||||
        assert im3.info.get("progression")
 | 
					        assert im3.info.get("progression")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_quality(self):
 | 
					    def test_quality(self) -> None:
 | 
				
			||||||
        im1 = self.roundtrip(hopper())
 | 
					        im1 = self.roundtrip(hopper())
 | 
				
			||||||
        im2 = self.roundtrip(hopper(), quality=50)
 | 
					        im2 = self.roundtrip(hopper(), quality=50)
 | 
				
			||||||
        assert_image(im1, im2.mode, im2.size)
 | 
					        assert_image(im1, im2.mode, im2.size)
 | 
				
			||||||
| 
						 | 
					@ -426,12 +427,12 @@ class TestFileJpeg:
 | 
				
			||||||
        assert_image(im1, im3.mode, im3.size)
 | 
					        assert_image(im1, im3.mode, im3.size)
 | 
				
			||||||
        assert im2.bytes > im3.bytes
 | 
					        assert im2.bytes > im3.bytes
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_smooth(self):
 | 
					    def test_smooth(self) -> None:
 | 
				
			||||||
        im1 = self.roundtrip(hopper())
 | 
					        im1 = self.roundtrip(hopper())
 | 
				
			||||||
        im2 = self.roundtrip(hopper(), smooth=100)
 | 
					        im2 = self.roundtrip(hopper(), smooth=100)
 | 
				
			||||||
        assert_image(im1, im2.mode, im2.size)
 | 
					        assert_image(im1, im2.mode, im2.size)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_subsampling(self):
 | 
					    def test_subsampling(self) -> None:
 | 
				
			||||||
        def getsampling(im):
 | 
					        def getsampling(im):
 | 
				
			||||||
            layer = im.layer
 | 
					            layer = im.layer
 | 
				
			||||||
            return layer[0][1:3] + layer[1][1:3] + layer[2][1:3]
 | 
					            return layer[0][1:3] + layer[1][1:3] + layer[2][1:3]
 | 
				
			||||||
| 
						 | 
					@ -463,23 +464,23 @@ class TestFileJpeg:
 | 
				
			||||||
        with pytest.raises(TypeError):
 | 
					        with pytest.raises(TypeError):
 | 
				
			||||||
            self.roundtrip(hopper(), subsampling="1:1:1")
 | 
					            self.roundtrip(hopper(), subsampling="1:1:1")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_exif(self):
 | 
					    def test_exif(self) -> None:
 | 
				
			||||||
        with Image.open("Tests/images/pil_sample_rgb.jpg") as im:
 | 
					        with Image.open("Tests/images/pil_sample_rgb.jpg") as im:
 | 
				
			||||||
            info = im._getexif()
 | 
					            info = im._getexif()
 | 
				
			||||||
            assert info[305] == "Adobe Photoshop CS Macintosh"
 | 
					            assert info[305] == "Adobe Photoshop CS Macintosh"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_get_child_images(self):
 | 
					    def test_get_child_images(self) -> None:
 | 
				
			||||||
        with Image.open("Tests/images/flower.jpg") as im:
 | 
					        with Image.open("Tests/images/flower.jpg") as im:
 | 
				
			||||||
            ims = im.get_child_images()
 | 
					            ims = im.get_child_images()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        assert len(ims) == 1
 | 
					        assert len(ims) == 1
 | 
				
			||||||
        assert_image_similar_tofile(ims[0], "Tests/images/flower_thumbnail.png", 2.1)
 | 
					        assert_image_similar_tofile(ims[0], "Tests/images/flower_thumbnail.png", 2.1)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_mp(self):
 | 
					    def test_mp(self) -> None:
 | 
				
			||||||
        with Image.open("Tests/images/pil_sample_rgb.jpg") as im:
 | 
					        with Image.open("Tests/images/pil_sample_rgb.jpg") as im:
 | 
				
			||||||
            assert im._getmp() is None
 | 
					            assert im._getmp() is None
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_quality_keep(self, tmp_path):
 | 
					    def test_quality_keep(self, tmp_path: Path) -> None:
 | 
				
			||||||
        # RGB
 | 
					        # RGB
 | 
				
			||||||
        with Image.open("Tests/images/hopper.jpg") as im:
 | 
					        with Image.open("Tests/images/hopper.jpg") as im:
 | 
				
			||||||
            f = str(tmp_path / "temp.jpg")
 | 
					            f = str(tmp_path / "temp.jpg")
 | 
				
			||||||
| 
						 | 
					@ -493,13 +494,13 @@ class TestFileJpeg:
 | 
				
			||||||
            f = str(tmp_path / "temp.jpg")
 | 
					            f = str(tmp_path / "temp.jpg")
 | 
				
			||||||
            im.save(f, quality="keep")
 | 
					            im.save(f, quality="keep")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_junk_jpeg_header(self):
 | 
					    def test_junk_jpeg_header(self) -> None:
 | 
				
			||||||
        # https://github.com/python-pillow/Pillow/issues/630
 | 
					        # https://github.com/python-pillow/Pillow/issues/630
 | 
				
			||||||
        filename = "Tests/images/junk_jpeg_header.jpg"
 | 
					        filename = "Tests/images/junk_jpeg_header.jpg"
 | 
				
			||||||
        with Image.open(filename):
 | 
					        with Image.open(filename):
 | 
				
			||||||
            pass
 | 
					            pass
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_ff00_jpeg_header(self):
 | 
					    def test_ff00_jpeg_header(self) -> None:
 | 
				
			||||||
        filename = "Tests/images/jpeg_ff00_header.jpg"
 | 
					        filename = "Tests/images/jpeg_ff00_header.jpg"
 | 
				
			||||||
        with Image.open(filename):
 | 
					        with Image.open(filename):
 | 
				
			||||||
            pass
 | 
					            pass
 | 
				
			||||||
| 
						 | 
					@ -507,7 +508,7 @@ class TestFileJpeg:
 | 
				
			||||||
    @mark_if_feature_version(
 | 
					    @mark_if_feature_version(
 | 
				
			||||||
        pytest.mark.valgrind_known_error, "libjpeg_turbo", "2.0", reason="Known Failing"
 | 
					        pytest.mark.valgrind_known_error, "libjpeg_turbo", "2.0", reason="Known Failing"
 | 
				
			||||||
    )
 | 
					    )
 | 
				
			||||||
    def test_truncated_jpeg_should_read_all_the_data(self):
 | 
					    def test_truncated_jpeg_should_read_all_the_data(self) -> None:
 | 
				
			||||||
        filename = "Tests/images/truncated_jpeg.jpg"
 | 
					        filename = "Tests/images/truncated_jpeg.jpg"
 | 
				
			||||||
        ImageFile.LOAD_TRUNCATED_IMAGES = True
 | 
					        ImageFile.LOAD_TRUNCATED_IMAGES = True
 | 
				
			||||||
        with Image.open(filename) as im:
 | 
					        with Image.open(filename) as im:
 | 
				
			||||||
| 
						 | 
					@ -515,7 +516,7 @@ class TestFileJpeg:
 | 
				
			||||||
            ImageFile.LOAD_TRUNCATED_IMAGES = False
 | 
					            ImageFile.LOAD_TRUNCATED_IMAGES = False
 | 
				
			||||||
            assert im.getbbox() is not None
 | 
					            assert im.getbbox() is not None
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_truncated_jpeg_throws_oserror(self):
 | 
					    def test_truncated_jpeg_throws_oserror(self) -> None:
 | 
				
			||||||
        filename = "Tests/images/truncated_jpeg.jpg"
 | 
					        filename = "Tests/images/truncated_jpeg.jpg"
 | 
				
			||||||
        with Image.open(filename) as im:
 | 
					        with Image.open(filename) as im:
 | 
				
			||||||
            with pytest.raises(OSError):
 | 
					            with pytest.raises(OSError):
 | 
				
			||||||
| 
						 | 
					@ -528,8 +529,8 @@ class TestFileJpeg:
 | 
				
			||||||
    @mark_if_feature_version(
 | 
					    @mark_if_feature_version(
 | 
				
			||||||
        pytest.mark.valgrind_known_error, "libjpeg_turbo", "2.0", reason="Known Failing"
 | 
					        pytest.mark.valgrind_known_error, "libjpeg_turbo", "2.0", reason="Known Failing"
 | 
				
			||||||
    )
 | 
					    )
 | 
				
			||||||
    def test_qtables(self, tmp_path):
 | 
					    def test_qtables(self, tmp_path: Path) -> None:
 | 
				
			||||||
        def _n_qtables_helper(n, test_file):
 | 
					        def _n_qtables_helper(n, test_file) -> None:
 | 
				
			||||||
            with Image.open(test_file) as im:
 | 
					            with Image.open(test_file) as im:
 | 
				
			||||||
                f = str(tmp_path / "temp.jpg")
 | 
					                f = str(tmp_path / "temp.jpg")
 | 
				
			||||||
                im.save(f, qtables=[[n] * 64] * n)
 | 
					                im.save(f, qtables=[[n] * 64] * n)
 | 
				
			||||||
| 
						 | 
					@ -637,24 +638,24 @@ class TestFileJpeg:
 | 
				
			||||||
            with pytest.raises(ValueError):
 | 
					            with pytest.raises(ValueError):
 | 
				
			||||||
                self.roundtrip(im, qtables=[[1, 2, 3, 4]])
 | 
					                self.roundtrip(im, qtables=[[1, 2, 3, 4]])
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_load_16bit_qtables(self):
 | 
					    def test_load_16bit_qtables(self) -> None:
 | 
				
			||||||
        with Image.open("Tests/images/hopper_16bit_qtables.jpg") as im:
 | 
					        with Image.open("Tests/images/hopper_16bit_qtables.jpg") as im:
 | 
				
			||||||
            assert len(im.quantization) == 2
 | 
					            assert len(im.quantization) == 2
 | 
				
			||||||
            assert len(im.quantization[0]) == 64
 | 
					            assert len(im.quantization[0]) == 64
 | 
				
			||||||
            assert max(im.quantization[0]) > 255
 | 
					            assert max(im.quantization[0]) > 255
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_save_multiple_16bit_qtables(self):
 | 
					    def test_save_multiple_16bit_qtables(self) -> None:
 | 
				
			||||||
        with Image.open("Tests/images/hopper_16bit_qtables.jpg") as im:
 | 
					        with Image.open("Tests/images/hopper_16bit_qtables.jpg") as im:
 | 
				
			||||||
            im2 = self.roundtrip(im, qtables="keep")
 | 
					            im2 = self.roundtrip(im, qtables="keep")
 | 
				
			||||||
            assert im.quantization == im2.quantization
 | 
					            assert im.quantization == im2.quantization
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_save_single_16bit_qtable(self):
 | 
					    def test_save_single_16bit_qtable(self) -> None:
 | 
				
			||||||
        with Image.open("Tests/images/hopper_16bit_qtables.jpg") as im:
 | 
					        with Image.open("Tests/images/hopper_16bit_qtables.jpg") as im:
 | 
				
			||||||
            im2 = self.roundtrip(im, qtables={0: im.quantization[0]})
 | 
					            im2 = self.roundtrip(im, qtables={0: im.quantization[0]})
 | 
				
			||||||
            assert len(im2.quantization) == 1
 | 
					            assert len(im2.quantization) == 1
 | 
				
			||||||
            assert im2.quantization[0] == im.quantization[0]
 | 
					            assert im2.quantization[0] == im.quantization[0]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_save_low_quality_baseline_qtables(self):
 | 
					    def test_save_low_quality_baseline_qtables(self) -> None:
 | 
				
			||||||
        with Image.open(TEST_FILE) as im:
 | 
					        with Image.open(TEST_FILE) as im:
 | 
				
			||||||
            im2 = self.roundtrip(im, quality=10)
 | 
					            im2 = self.roundtrip(im, quality=10)
 | 
				
			||||||
            assert len(im2.quantization) == 2
 | 
					            assert len(im2.quantization) == 2
 | 
				
			||||||
| 
						 | 
					@ -665,7 +666,7 @@ class TestFileJpeg:
 | 
				
			||||||
        "blocks, rows, markers",
 | 
					        "blocks, rows, markers",
 | 
				
			||||||
        ((0, 0, 0), (1, 0, 15), (3, 0, 5), (8, 0, 1), (0, 1, 3), (0, 2, 1)),
 | 
					        ((0, 0, 0), (1, 0, 15), (3, 0, 5), (8, 0, 1), (0, 1, 3), (0, 2, 1)),
 | 
				
			||||||
    )
 | 
					    )
 | 
				
			||||||
    def test_restart_markers(self, blocks, rows, markers):
 | 
					    def test_restart_markers(self, blocks, rows, markers) -> None:
 | 
				
			||||||
        im = Image.new("RGB", (32, 32))  # 16 MCUs
 | 
					        im = Image.new("RGB", (32, 32))  # 16 MCUs
 | 
				
			||||||
        out = BytesIO()
 | 
					        out = BytesIO()
 | 
				
			||||||
        im.save(
 | 
					        im.save(
 | 
				
			||||||
| 
						 | 
					@ -679,20 +680,20 @@ class TestFileJpeg:
 | 
				
			||||||
        assert len(re.findall(b"\xff[\xd0-\xd7]", out.getvalue())) == markers
 | 
					        assert len(re.findall(b"\xff[\xd0-\xd7]", out.getvalue())) == markers
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    @pytest.mark.skipif(not djpeg_available(), reason="djpeg not available")
 | 
					    @pytest.mark.skipif(not djpeg_available(), reason="djpeg not available")
 | 
				
			||||||
    def test_load_djpeg(self):
 | 
					    def test_load_djpeg(self) -> None:
 | 
				
			||||||
        with Image.open(TEST_FILE) as img:
 | 
					        with Image.open(TEST_FILE) as img:
 | 
				
			||||||
            img.load_djpeg()
 | 
					            img.load_djpeg()
 | 
				
			||||||
            assert_image_similar_tofile(img, TEST_FILE, 5)
 | 
					            assert_image_similar_tofile(img, TEST_FILE, 5)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    @pytest.mark.skipif(not cjpeg_available(), reason="cjpeg not available")
 | 
					    @pytest.mark.skipif(not cjpeg_available(), reason="cjpeg not available")
 | 
				
			||||||
    def test_save_cjpeg(self, tmp_path):
 | 
					    def test_save_cjpeg(self, tmp_path: Path) -> None:
 | 
				
			||||||
        with Image.open(TEST_FILE) as img:
 | 
					        with Image.open(TEST_FILE) as img:
 | 
				
			||||||
            tempfile = str(tmp_path / "temp.jpg")
 | 
					            tempfile = str(tmp_path / "temp.jpg")
 | 
				
			||||||
            JpegImagePlugin._save_cjpeg(img, 0, tempfile)
 | 
					            JpegImagePlugin._save_cjpeg(img, 0, tempfile)
 | 
				
			||||||
            # Default save quality is 75%, so a tiny bit of difference is alright
 | 
					            # Default save quality is 75%, so a tiny bit of difference is alright
 | 
				
			||||||
            assert_image_similar_tofile(img, tempfile, 17)
 | 
					            assert_image_similar_tofile(img, tempfile, 17)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_no_duplicate_0x1001_tag(self):
 | 
					    def test_no_duplicate_0x1001_tag(self) -> None:
 | 
				
			||||||
        # Arrange
 | 
					        # Arrange
 | 
				
			||||||
        tag_ids = {v: k for k, v in ExifTags.TAGS.items()}
 | 
					        tag_ids = {v: k for k, v in ExifTags.TAGS.items()}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -700,7 +701,7 @@ class TestFileJpeg:
 | 
				
			||||||
        assert tag_ids["RelatedImageWidth"] == 0x1001
 | 
					        assert tag_ids["RelatedImageWidth"] == 0x1001
 | 
				
			||||||
        assert tag_ids["RelatedImageLength"] == 0x1002
 | 
					        assert tag_ids["RelatedImageLength"] == 0x1002
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_MAXBLOCK_scaling(self, tmp_path):
 | 
					    def test_MAXBLOCK_scaling(self, tmp_path: Path) -> None:
 | 
				
			||||||
        im = self.gen_random_image((512, 512))
 | 
					        im = self.gen_random_image((512, 512))
 | 
				
			||||||
        f = str(tmp_path / "temp.jpeg")
 | 
					        f = str(tmp_path / "temp.jpeg")
 | 
				
			||||||
        im.save(f, quality=100, optimize=True)
 | 
					        im.save(f, quality=100, optimize=True)
 | 
				
			||||||
| 
						 | 
					@ -711,7 +712,7 @@ class TestFileJpeg:
 | 
				
			||||||
            reloaded.save(f, quality="keep", progressive=True)
 | 
					            reloaded.save(f, quality="keep", progressive=True)
 | 
				
			||||||
            reloaded.save(f, quality="keep", optimize=True)
 | 
					            reloaded.save(f, quality="keep", optimize=True)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_bad_mpo_header(self):
 | 
					    def test_bad_mpo_header(self) -> None:
 | 
				
			||||||
        """Treat unknown MPO as JPEG"""
 | 
					        """Treat unknown MPO as JPEG"""
 | 
				
			||||||
        # Arrange
 | 
					        # Arrange
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -723,20 +724,20 @@ class TestFileJpeg:
 | 
				
			||||||
            assert im.format == "JPEG"
 | 
					            assert im.format == "JPEG"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    @pytest.mark.parametrize("mode", ("1", "L", "RGB", "RGBX", "CMYK", "YCbCr"))
 | 
					    @pytest.mark.parametrize("mode", ("1", "L", "RGB", "RGBX", "CMYK", "YCbCr"))
 | 
				
			||||||
    def test_save_correct_modes(self, mode):
 | 
					    def test_save_correct_modes(self, mode) -> None:
 | 
				
			||||||
        out = BytesIO()
 | 
					        out = BytesIO()
 | 
				
			||||||
        img = Image.new(mode, (20, 20))
 | 
					        img = Image.new(mode, (20, 20))
 | 
				
			||||||
        img.save(out, "JPEG")
 | 
					        img.save(out, "JPEG")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    @pytest.mark.parametrize("mode", ("LA", "La", "RGBA", "RGBa", "P"))
 | 
					    @pytest.mark.parametrize("mode", ("LA", "La", "RGBA", "RGBa", "P"))
 | 
				
			||||||
    def test_save_wrong_modes(self, mode):
 | 
					    def test_save_wrong_modes(self, mode) -> None:
 | 
				
			||||||
        # ref https://github.com/python-pillow/Pillow/issues/2005
 | 
					        # ref https://github.com/python-pillow/Pillow/issues/2005
 | 
				
			||||||
        out = BytesIO()
 | 
					        out = BytesIO()
 | 
				
			||||||
        img = Image.new(mode, (20, 20))
 | 
					        img = Image.new(mode, (20, 20))
 | 
				
			||||||
        with pytest.raises(OSError):
 | 
					        with pytest.raises(OSError):
 | 
				
			||||||
            img.save(out, "JPEG")
 | 
					            img.save(out, "JPEG")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_save_tiff_with_dpi(self, tmp_path):
 | 
					    def test_save_tiff_with_dpi(self, tmp_path: Path) -> None:
 | 
				
			||||||
        # Arrange
 | 
					        # Arrange
 | 
				
			||||||
        outfile = str(tmp_path / "temp.tif")
 | 
					        outfile = str(tmp_path / "temp.tif")
 | 
				
			||||||
        with Image.open("Tests/images/hopper.tif") as im:
 | 
					        with Image.open("Tests/images/hopper.tif") as im:
 | 
				
			||||||
| 
						 | 
					@ -748,7 +749,7 @@ class TestFileJpeg:
 | 
				
			||||||
                reloaded.load()
 | 
					                reloaded.load()
 | 
				
			||||||
                assert im.info["dpi"] == reloaded.info["dpi"]
 | 
					                assert im.info["dpi"] == reloaded.info["dpi"]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_save_dpi_rounding(self, tmp_path):
 | 
					    def test_save_dpi_rounding(self, tmp_path: Path) -> None:
 | 
				
			||||||
        outfile = str(tmp_path / "temp.jpg")
 | 
					        outfile = str(tmp_path / "temp.jpg")
 | 
				
			||||||
        with Image.open("Tests/images/hopper.jpg") as im:
 | 
					        with Image.open("Tests/images/hopper.jpg") as im:
 | 
				
			||||||
            im.save(outfile, dpi=(72.2, 72.2))
 | 
					            im.save(outfile, dpi=(72.2, 72.2))
 | 
				
			||||||
| 
						 | 
					@ -761,7 +762,7 @@ class TestFileJpeg:
 | 
				
			||||||
        with Image.open(outfile) as reloaded:
 | 
					        with Image.open(outfile) as reloaded:
 | 
				
			||||||
            assert reloaded.info["dpi"] == (73, 73)
 | 
					            assert reloaded.info["dpi"] == (73, 73)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_dpi_tuple_from_exif(self):
 | 
					    def test_dpi_tuple_from_exif(self) -> None:
 | 
				
			||||||
        # Arrange
 | 
					        # Arrange
 | 
				
			||||||
        # This Photoshop CC 2017 image has DPI in EXIF not metadata
 | 
					        # This Photoshop CC 2017 image has DPI in EXIF not metadata
 | 
				
			||||||
        # EXIF XResolution is (2000000, 10000)
 | 
					        # EXIF XResolution is (2000000, 10000)
 | 
				
			||||||
| 
						 | 
					@ -769,7 +770,7 @@ class TestFileJpeg:
 | 
				
			||||||
            # Act / Assert
 | 
					            # Act / Assert
 | 
				
			||||||
            assert im.info.get("dpi") == (200, 200)
 | 
					            assert im.info.get("dpi") == (200, 200)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_dpi_int_from_exif(self):
 | 
					    def test_dpi_int_from_exif(self) -> None:
 | 
				
			||||||
        # Arrange
 | 
					        # Arrange
 | 
				
			||||||
        # This image has DPI in EXIF not metadata
 | 
					        # This image has DPI in EXIF not metadata
 | 
				
			||||||
        # EXIF XResolution is 72
 | 
					        # EXIF XResolution is 72
 | 
				
			||||||
| 
						 | 
					@ -777,7 +778,7 @@ class TestFileJpeg:
 | 
				
			||||||
            # Act / Assert
 | 
					            # Act / Assert
 | 
				
			||||||
            assert im.info.get("dpi") == (72, 72)
 | 
					            assert im.info.get("dpi") == (72, 72)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_dpi_from_dpcm_exif(self):
 | 
					    def test_dpi_from_dpcm_exif(self) -> None:
 | 
				
			||||||
        # Arrange
 | 
					        # Arrange
 | 
				
			||||||
        # This is photoshop-200dpi.jpg with EXIF resolution unit set to cm:
 | 
					        # This is photoshop-200dpi.jpg with EXIF resolution unit set to cm:
 | 
				
			||||||
        # exiftool -exif:ResolutionUnit=cm photoshop-200dpi.jpg
 | 
					        # exiftool -exif:ResolutionUnit=cm photoshop-200dpi.jpg
 | 
				
			||||||
| 
						 | 
					@ -785,7 +786,7 @@ class TestFileJpeg:
 | 
				
			||||||
            # Act / Assert
 | 
					            # Act / Assert
 | 
				
			||||||
            assert im.info.get("dpi") == (508, 508)
 | 
					            assert im.info.get("dpi") == (508, 508)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_dpi_exif_zero_division(self):
 | 
					    def test_dpi_exif_zero_division(self) -> None:
 | 
				
			||||||
        # Arrange
 | 
					        # Arrange
 | 
				
			||||||
        # This is photoshop-200dpi.jpg with EXIF resolution set to 0/0:
 | 
					        # This is photoshop-200dpi.jpg with EXIF resolution set to 0/0:
 | 
				
			||||||
        # exiftool -XResolution=0/0 -YResolution=0/0 photoshop-200dpi.jpg
 | 
					        # exiftool -XResolution=0/0 -YResolution=0/0 photoshop-200dpi.jpg
 | 
				
			||||||
| 
						 | 
					@ -794,7 +795,7 @@ class TestFileJpeg:
 | 
				
			||||||
            # This should return the default, and not raise a ZeroDivisionError
 | 
					            # This should return the default, and not raise a ZeroDivisionError
 | 
				
			||||||
            assert im.info.get("dpi") == (72, 72)
 | 
					            assert im.info.get("dpi") == (72, 72)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_dpi_exif_string(self):
 | 
					    def test_dpi_exif_string(self) -> None:
 | 
				
			||||||
        # Arrange
 | 
					        # Arrange
 | 
				
			||||||
        # 0x011A tag in this exif contains string '300300\x02'
 | 
					        # 0x011A tag in this exif contains string '300300\x02'
 | 
				
			||||||
        with Image.open("Tests/images/broken_exif_dpi.jpg") as im:
 | 
					        with Image.open("Tests/images/broken_exif_dpi.jpg") as im:
 | 
				
			||||||
| 
						 | 
					@ -802,14 +803,14 @@ class TestFileJpeg:
 | 
				
			||||||
            # This should return the default
 | 
					            # This should return the default
 | 
				
			||||||
            assert im.info.get("dpi") == (72, 72)
 | 
					            assert im.info.get("dpi") == (72, 72)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_dpi_exif_truncated(self):
 | 
					    def test_dpi_exif_truncated(self) -> None:
 | 
				
			||||||
        # Arrange
 | 
					        # Arrange
 | 
				
			||||||
        with Image.open("Tests/images/truncated_exif_dpi.jpg") as im:
 | 
					        with Image.open("Tests/images/truncated_exif_dpi.jpg") as im:
 | 
				
			||||||
            # Act / Assert
 | 
					            # Act / Assert
 | 
				
			||||||
            # This should return the default
 | 
					            # This should return the default
 | 
				
			||||||
            assert im.info.get("dpi") == (72, 72)
 | 
					            assert im.info.get("dpi") == (72, 72)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_no_dpi_in_exif(self):
 | 
					    def test_no_dpi_in_exif(self) -> None:
 | 
				
			||||||
        # Arrange
 | 
					        # Arrange
 | 
				
			||||||
        # This is photoshop-200dpi.jpg with resolution removed from EXIF:
 | 
					        # This is photoshop-200dpi.jpg with resolution removed from EXIF:
 | 
				
			||||||
        # exiftool "-*resolution*"= photoshop-200dpi.jpg
 | 
					        # exiftool "-*resolution*"= photoshop-200dpi.jpg
 | 
				
			||||||
| 
						 | 
					@ -819,7 +820,7 @@ class TestFileJpeg:
 | 
				
			||||||
            # https://exiv2.org/tags.html
 | 
					            # https://exiv2.org/tags.html
 | 
				
			||||||
            assert im.info.get("dpi") == (72, 72)
 | 
					            assert im.info.get("dpi") == (72, 72)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_invalid_exif(self):
 | 
					    def test_invalid_exif(self) -> None:
 | 
				
			||||||
        # This is no-dpi-in-exif with the tiff header of the exif block
 | 
					        # This is no-dpi-in-exif with the tiff header of the exif block
 | 
				
			||||||
        # hexedited from MM * to FF FF FF FF
 | 
					        # hexedited from MM * to FF FF FF FF
 | 
				
			||||||
        with Image.open("Tests/images/invalid-exif.jpg") as im:
 | 
					        with Image.open("Tests/images/invalid-exif.jpg") as im:
 | 
				
			||||||
| 
						 | 
					@ -830,7 +831,7 @@ class TestFileJpeg:
 | 
				
			||||||
    @mark_if_feature_version(
 | 
					    @mark_if_feature_version(
 | 
				
			||||||
        pytest.mark.valgrind_known_error, "libjpeg_turbo", "2.0", reason="Known Failing"
 | 
					        pytest.mark.valgrind_known_error, "libjpeg_turbo", "2.0", reason="Known Failing"
 | 
				
			||||||
    )
 | 
					    )
 | 
				
			||||||
    def test_exif_x_resolution(self, tmp_path):
 | 
					    def test_exif_x_resolution(self, tmp_path: Path) -> None:
 | 
				
			||||||
        with Image.open("Tests/images/flower.jpg") as im:
 | 
					        with Image.open("Tests/images/flower.jpg") as im:
 | 
				
			||||||
            exif = im.getexif()
 | 
					            exif = im.getexif()
 | 
				
			||||||
            assert exif[282] == 180
 | 
					            assert exif[282] == 180
 | 
				
			||||||
| 
						 | 
					@ -842,14 +843,14 @@ class TestFileJpeg:
 | 
				
			||||||
        with Image.open(out) as reloaded:
 | 
					        with Image.open(out) as reloaded:
 | 
				
			||||||
            assert reloaded.getexif()[282] == 180
 | 
					            assert reloaded.getexif()[282] == 180
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_invalid_exif_x_resolution(self):
 | 
					    def test_invalid_exif_x_resolution(self) -> None:
 | 
				
			||||||
        # When no x or y resolution is defined in EXIF
 | 
					        # When no x or y resolution is defined in EXIF
 | 
				
			||||||
        with Image.open("Tests/images/invalid-exif-without-x-resolution.jpg") as im:
 | 
					        with Image.open("Tests/images/invalid-exif-without-x-resolution.jpg") as im:
 | 
				
			||||||
            # This should return the default, and not a ValueError or
 | 
					            # This should return the default, and not a ValueError or
 | 
				
			||||||
            # OSError for an unidentified image.
 | 
					            # OSError for an unidentified image.
 | 
				
			||||||
            assert im.info.get("dpi") == (72, 72)
 | 
					            assert im.info.get("dpi") == (72, 72)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_ifd_offset_exif(self):
 | 
					    def test_ifd_offset_exif(self) -> None:
 | 
				
			||||||
        # Arrange
 | 
					        # Arrange
 | 
				
			||||||
        # This image has been manually hexedited to have an IFD offset of 10,
 | 
					        # This image has been manually hexedited to have an IFD offset of 10,
 | 
				
			||||||
        # in contrast to normal 8
 | 
					        # in contrast to normal 8
 | 
				
			||||||
| 
						 | 
					@ -857,14 +858,14 @@ class TestFileJpeg:
 | 
				
			||||||
            # Act / Assert
 | 
					            # Act / Assert
 | 
				
			||||||
            assert im._getexif()[306] == "2017:03:13 23:03:09"
 | 
					            assert im._getexif()[306] == "2017:03:13 23:03:09"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_multiple_exif(self):
 | 
					    def test_multiple_exif(self) -> None:
 | 
				
			||||||
        with Image.open("Tests/images/multiple_exif.jpg") as im:
 | 
					        with Image.open("Tests/images/multiple_exif.jpg") as im:
 | 
				
			||||||
            assert im.info["exif"] == b"Exif\x00\x00firstsecond"
 | 
					            assert im.info["exif"] == b"Exif\x00\x00firstsecond"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    @mark_if_feature_version(
 | 
					    @mark_if_feature_version(
 | 
				
			||||||
        pytest.mark.valgrind_known_error, "libjpeg_turbo", "2.0", reason="Known Failing"
 | 
					        pytest.mark.valgrind_known_error, "libjpeg_turbo", "2.0", reason="Known Failing"
 | 
				
			||||||
    )
 | 
					    )
 | 
				
			||||||
    def test_photoshop(self):
 | 
					    def test_photoshop(self) -> None:
 | 
				
			||||||
        with Image.open("Tests/images/photoshop-200dpi.jpg") as im:
 | 
					        with Image.open("Tests/images/photoshop-200dpi.jpg") as im:
 | 
				
			||||||
            assert im.info["photoshop"][0x03ED] == {
 | 
					            assert im.info["photoshop"][0x03ED] == {
 | 
				
			||||||
                "XResolution": 200.0,
 | 
					                "XResolution": 200.0,
 | 
				
			||||||
| 
						 | 
					@ -881,14 +882,14 @@ class TestFileJpeg:
 | 
				
			||||||
        with Image.open("Tests/images/app13.jpg") as im:
 | 
					        with Image.open("Tests/images/app13.jpg") as im:
 | 
				
			||||||
            assert "photoshop" not in im.info
 | 
					            assert "photoshop" not in im.info
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_photoshop_malformed_and_multiple(self):
 | 
					    def test_photoshop_malformed_and_multiple(self) -> None:
 | 
				
			||||||
        with Image.open("Tests/images/app13-multiple.jpg") as im:
 | 
					        with Image.open("Tests/images/app13-multiple.jpg") as im:
 | 
				
			||||||
            assert "photoshop" in im.info
 | 
					            assert "photoshop" in im.info
 | 
				
			||||||
            assert 24 == len(im.info["photoshop"])
 | 
					            assert 24 == len(im.info["photoshop"])
 | 
				
			||||||
            apps_13_lengths = [len(v) for k, v in im.applist if k == "APP13"]
 | 
					            apps_13_lengths = [len(v) for k, v in im.applist if k == "APP13"]
 | 
				
			||||||
            assert [65504, 24] == apps_13_lengths
 | 
					            assert [65504, 24] == apps_13_lengths
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_adobe_transform(self):
 | 
					    def test_adobe_transform(self) -> None:
 | 
				
			||||||
        with Image.open("Tests/images/pil_sample_rgb.jpg") as im:
 | 
					        with Image.open("Tests/images/pil_sample_rgb.jpg") as im:
 | 
				
			||||||
            assert im.info["adobe_transform"] == 1
 | 
					            assert im.info["adobe_transform"] == 1
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -902,11 +903,11 @@ class TestFileJpeg:
 | 
				
			||||||
            assert "adobe" in im.info
 | 
					            assert "adobe" in im.info
 | 
				
			||||||
            assert "adobe_transform" not in im.info
 | 
					            assert "adobe_transform" not in im.info
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_icc_after_SOF(self):
 | 
					    def test_icc_after_SOF(self) -> None:
 | 
				
			||||||
        with Image.open("Tests/images/icc-after-SOF.jpg") as im:
 | 
					        with Image.open("Tests/images/icc-after-SOF.jpg") as im:
 | 
				
			||||||
            assert im.info["icc_profile"] == b"profile"
 | 
					            assert im.info["icc_profile"] == b"profile"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_jpeg_magic_number(self):
 | 
					    def test_jpeg_magic_number(self) -> None:
 | 
				
			||||||
        size = 4097
 | 
					        size = 4097
 | 
				
			||||||
        buffer = BytesIO(b"\xFF" * size)  # Many xFF bytes
 | 
					        buffer = BytesIO(b"\xFF" * size)  # Many xFF bytes
 | 
				
			||||||
        buffer.max_pos = 0
 | 
					        buffer.max_pos = 0
 | 
				
			||||||
| 
						 | 
					@ -925,7 +926,7 @@ class TestFileJpeg:
 | 
				
			||||||
        # Assert the entire file has not been read
 | 
					        # Assert the entire file has not been read
 | 
				
			||||||
        assert 0 < buffer.max_pos < size
 | 
					        assert 0 < buffer.max_pos < size
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_getxmp(self):
 | 
					    def test_getxmp(self) -> None:
 | 
				
			||||||
        with Image.open("Tests/images/xmp_test.jpg") as im:
 | 
					        with Image.open("Tests/images/xmp_test.jpg") as im:
 | 
				
			||||||
            if ElementTree is None:
 | 
					            if ElementTree is None:
 | 
				
			||||||
                with pytest.warns(
 | 
					                with pytest.warns(
 | 
				
			||||||
| 
						 | 
					@ -954,7 +955,7 @@ class TestFileJpeg:
 | 
				
			||||||
            with Image.open("Tests/images/hopper.jpg") as im:
 | 
					            with Image.open("Tests/images/hopper.jpg") as im:
 | 
				
			||||||
                assert im.getxmp() == {}
 | 
					                assert im.getxmp() == {}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_getxmp_no_prefix(self):
 | 
					    def test_getxmp_no_prefix(self) -> None:
 | 
				
			||||||
        with Image.open("Tests/images/xmp_no_prefix.jpg") as im:
 | 
					        with Image.open("Tests/images/xmp_no_prefix.jpg") as im:
 | 
				
			||||||
            if ElementTree is None:
 | 
					            if ElementTree is None:
 | 
				
			||||||
                with pytest.warns(
 | 
					                with pytest.warns(
 | 
				
			||||||
| 
						 | 
					@ -965,7 +966,7 @@ class TestFileJpeg:
 | 
				
			||||||
            else:
 | 
					            else:
 | 
				
			||||||
                assert im.getxmp() == {"xmpmeta": {"key": "value"}}
 | 
					                assert im.getxmp() == {"xmpmeta": {"key": "value"}}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_getxmp_padded(self):
 | 
					    def test_getxmp_padded(self) -> None:
 | 
				
			||||||
        with Image.open("Tests/images/xmp_padded.jpg") as im:
 | 
					        with Image.open("Tests/images/xmp_padded.jpg") as im:
 | 
				
			||||||
            if ElementTree is None:
 | 
					            if ElementTree is None:
 | 
				
			||||||
                with pytest.warns(
 | 
					                with pytest.warns(
 | 
				
			||||||
| 
						 | 
					@ -977,7 +978,7 @@ class TestFileJpeg:
 | 
				
			||||||
                assert im.getxmp() == {"xmpmeta": None}
 | 
					                assert im.getxmp() == {"xmpmeta": None}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    @pytest.mark.timeout(timeout=1)
 | 
					    @pytest.mark.timeout(timeout=1)
 | 
				
			||||||
    def test_eof(self):
 | 
					    def test_eof(self) -> None:
 | 
				
			||||||
        # Even though this decoder never says that it is finished
 | 
					        # Even though this decoder never says that it is finished
 | 
				
			||||||
        # the image should still end when there is no new data
 | 
					        # the image should still end when there is no new data
 | 
				
			||||||
        class InfiniteMockPyDecoder(ImageFile.PyDecoder):
 | 
					        class InfiniteMockPyDecoder(ImageFile.PyDecoder):
 | 
				
			||||||
| 
						 | 
					@ -1000,7 +1001,7 @@ class TestFileJpeg:
 | 
				
			||||||
            im.load()
 | 
					            im.load()
 | 
				
			||||||
            ImageFile.LOAD_TRUNCATED_IMAGES = False
 | 
					            ImageFile.LOAD_TRUNCATED_IMAGES = False
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_separate_tables(self):
 | 
					    def test_separate_tables(self) -> None:
 | 
				
			||||||
        im = hopper()
 | 
					        im = hopper()
 | 
				
			||||||
        data = []  # [interchange, tables-only, image-only]
 | 
					        data = []  # [interchange, tables-only, image-only]
 | 
				
			||||||
        for streamtype in range(3):
 | 
					        for streamtype in range(3):
 | 
				
			||||||
| 
						 | 
					@ -1022,14 +1023,14 @@ class TestFileJpeg:
 | 
				
			||||||
            with Image.open(BytesIO(data[1] + data[2])) as combined_im:
 | 
					            with Image.open(BytesIO(data[1] + data[2])) as combined_im:
 | 
				
			||||||
                assert_image_equal(interchange_im, combined_im)
 | 
					                assert_image_equal(interchange_im, combined_im)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_repr_jpeg(self):
 | 
					    def test_repr_jpeg(self) -> None:
 | 
				
			||||||
        im = hopper()
 | 
					        im = hopper()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        with Image.open(BytesIO(im._repr_jpeg_())) as repr_jpeg:
 | 
					        with Image.open(BytesIO(im._repr_jpeg_())) as repr_jpeg:
 | 
				
			||||||
            assert repr_jpeg.format == "JPEG"
 | 
					            assert repr_jpeg.format == "JPEG"
 | 
				
			||||||
            assert_image_similar(im, repr_jpeg, 17)
 | 
					            assert_image_similar(im, repr_jpeg, 17)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_repr_jpeg_error_returns_none(self):
 | 
					    def test_repr_jpeg_error_returns_none(self) -> None:
 | 
				
			||||||
        im = hopper("F")
 | 
					        im = hopper("F")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        assert im._repr_jpeg_() is None
 | 
					        assert im._repr_jpeg_() is None
 | 
				
			||||||
| 
						 | 
					@ -1038,7 +1039,7 @@ class TestFileJpeg:
 | 
				
			||||||
@pytest.mark.skipif(not is_win32(), reason="Windows only")
 | 
					@pytest.mark.skipif(not is_win32(), reason="Windows only")
 | 
				
			||||||
@skip_unless_feature("jpg")
 | 
					@skip_unless_feature("jpg")
 | 
				
			||||||
class TestFileCloseW32:
 | 
					class TestFileCloseW32:
 | 
				
			||||||
    def test_fd_leak(self, tmp_path):
 | 
					    def test_fd_leak(self, tmp_path: Path) -> None:
 | 
				
			||||||
        tmpfile = str(tmp_path / "temp.jpg")
 | 
					        tmpfile = str(tmp_path / "temp.jpg")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        with Image.open("Tests/images/hopper.jpg") as im:
 | 
					        with Image.open("Tests/images/hopper.jpg") as im:
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -3,6 +3,7 @@ from __future__ import annotations
 | 
				
			||||||
import os
 | 
					import os
 | 
				
			||||||
import re
 | 
					import re
 | 
				
			||||||
from io import BytesIO
 | 
					from io import BytesIO
 | 
				
			||||||
 | 
					from pathlib import Path
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import pytest
 | 
					import pytest
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -46,7 +47,7 @@ def roundtrip(im, **options):
 | 
				
			||||||
    return im
 | 
					    return im
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_sanity():
 | 
					def test_sanity() -> None:
 | 
				
			||||||
    # Internal version number
 | 
					    # Internal version number
 | 
				
			||||||
    assert re.search(r"\d+\.\d+\.\d+$", features.version_codec("jpg_2000"))
 | 
					    assert re.search(r"\d+\.\d+\.\d+$", features.version_codec("jpg_2000"))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -59,20 +60,20 @@ def test_sanity():
 | 
				
			||||||
        assert im.get_format_mimetype() == "image/jp2"
 | 
					        assert im.get_format_mimetype() == "image/jp2"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_jpf():
 | 
					def test_jpf() -> None:
 | 
				
			||||||
    with Image.open("Tests/images/balloon.jpf") as im:
 | 
					    with Image.open("Tests/images/balloon.jpf") as im:
 | 
				
			||||||
        assert im.format == "JPEG2000"
 | 
					        assert im.format == "JPEG2000"
 | 
				
			||||||
        assert im.get_format_mimetype() == "image/jpx"
 | 
					        assert im.get_format_mimetype() == "image/jpx"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_invalid_file():
 | 
					def test_invalid_file() -> None:
 | 
				
			||||||
    invalid_file = "Tests/images/flower.jpg"
 | 
					    invalid_file = "Tests/images/flower.jpg"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    with pytest.raises(SyntaxError):
 | 
					    with pytest.raises(SyntaxError):
 | 
				
			||||||
        Jpeg2KImagePlugin.Jpeg2KImageFile(invalid_file)
 | 
					        Jpeg2KImagePlugin.Jpeg2KImageFile(invalid_file)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_bytesio():
 | 
					def test_bytesio() -> None:
 | 
				
			||||||
    with open("Tests/images/test-card-lossless.jp2", "rb") as f:
 | 
					    with open("Tests/images/test-card-lossless.jp2", "rb") as f:
 | 
				
			||||||
        data = BytesIO(f.read())
 | 
					        data = BytesIO(f.read())
 | 
				
			||||||
    assert_image_similar_tofile(test_card, data, 1.0e-3)
 | 
					    assert_image_similar_tofile(test_card, data, 1.0e-3)
 | 
				
			||||||
| 
						 | 
					@ -82,7 +83,7 @@ def test_bytesio():
 | 
				
			||||||
# PIL (they were made using Adobe Photoshop)
 | 
					# PIL (they were made using Adobe Photoshop)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_lossless(tmp_path):
 | 
					def test_lossless(tmp_path: Path) -> None:
 | 
				
			||||||
    with Image.open("Tests/images/test-card-lossless.jp2") as im:
 | 
					    with Image.open("Tests/images/test-card-lossless.jp2") as im:
 | 
				
			||||||
        im.load()
 | 
					        im.load()
 | 
				
			||||||
        outfile = str(tmp_path / "temp_test-card.png")
 | 
					        outfile = str(tmp_path / "temp_test-card.png")
 | 
				
			||||||
| 
						 | 
					@ -90,54 +91,54 @@ def test_lossless(tmp_path):
 | 
				
			||||||
    assert_image_similar(im, test_card, 1.0e-3)
 | 
					    assert_image_similar(im, test_card, 1.0e-3)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_lossy_tiled():
 | 
					def test_lossy_tiled() -> None:
 | 
				
			||||||
    assert_image_similar_tofile(
 | 
					    assert_image_similar_tofile(
 | 
				
			||||||
        test_card, "Tests/images/test-card-lossy-tiled.jp2", 2.0
 | 
					        test_card, "Tests/images/test-card-lossy-tiled.jp2", 2.0
 | 
				
			||||||
    )
 | 
					    )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_lossless_rt():
 | 
					def test_lossless_rt() -> None:
 | 
				
			||||||
    im = roundtrip(test_card)
 | 
					    im = roundtrip(test_card)
 | 
				
			||||||
    assert_image_equal(im, test_card)
 | 
					    assert_image_equal(im, test_card)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_lossy_rt():
 | 
					def test_lossy_rt() -> None:
 | 
				
			||||||
    im = roundtrip(test_card, quality_layers=[20])
 | 
					    im = roundtrip(test_card, quality_layers=[20])
 | 
				
			||||||
    assert_image_similar(im, test_card, 2.0)
 | 
					    assert_image_similar(im, test_card, 2.0)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_tiled_rt():
 | 
					def test_tiled_rt() -> None:
 | 
				
			||||||
    im = roundtrip(test_card, tile_size=(128, 128))
 | 
					    im = roundtrip(test_card, tile_size=(128, 128))
 | 
				
			||||||
    assert_image_equal(im, test_card)
 | 
					    assert_image_equal(im, test_card)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_tiled_offset_rt():
 | 
					def test_tiled_offset_rt() -> None:
 | 
				
			||||||
    im = roundtrip(test_card, tile_size=(128, 128), tile_offset=(0, 0), offset=(32, 32))
 | 
					    im = roundtrip(test_card, tile_size=(128, 128), tile_offset=(0, 0), offset=(32, 32))
 | 
				
			||||||
    assert_image_equal(im, test_card)
 | 
					    assert_image_equal(im, test_card)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_tiled_offset_too_small():
 | 
					def test_tiled_offset_too_small() -> None:
 | 
				
			||||||
    with pytest.raises(ValueError):
 | 
					    with pytest.raises(ValueError):
 | 
				
			||||||
        roundtrip(test_card, tile_size=(128, 128), tile_offset=(0, 0), offset=(128, 32))
 | 
					        roundtrip(test_card, tile_size=(128, 128), tile_offset=(0, 0), offset=(128, 32))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_irreversible_rt():
 | 
					def test_irreversible_rt() -> None:
 | 
				
			||||||
    im = roundtrip(test_card, irreversible=True, quality_layers=[20])
 | 
					    im = roundtrip(test_card, irreversible=True, quality_layers=[20])
 | 
				
			||||||
    assert_image_similar(im, test_card, 2.0)
 | 
					    assert_image_similar(im, test_card, 2.0)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_prog_qual_rt():
 | 
					def test_prog_qual_rt() -> None:
 | 
				
			||||||
    im = roundtrip(test_card, quality_layers=[60, 40, 20], progression="LRCP")
 | 
					    im = roundtrip(test_card, quality_layers=[60, 40, 20], progression="LRCP")
 | 
				
			||||||
    assert_image_similar(im, test_card, 2.0)
 | 
					    assert_image_similar(im, test_card, 2.0)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_prog_res_rt():
 | 
					def test_prog_res_rt() -> None:
 | 
				
			||||||
    im = roundtrip(test_card, num_resolutions=8, progression="RLCP")
 | 
					    im = roundtrip(test_card, num_resolutions=8, progression="RLCP")
 | 
				
			||||||
    assert_image_equal(im, test_card)
 | 
					    assert_image_equal(im, test_card)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@pytest.mark.parametrize("num_resolutions", range(2, 6))
 | 
					@pytest.mark.parametrize("num_resolutions", range(2, 6))
 | 
				
			||||||
def test_default_num_resolutions(num_resolutions):
 | 
					def test_default_num_resolutions(num_resolutions) -> None:
 | 
				
			||||||
    d = 1 << (num_resolutions - 1)
 | 
					    d = 1 << (num_resolutions - 1)
 | 
				
			||||||
    im = test_card.resize((d - 1, d - 1))
 | 
					    im = test_card.resize((d - 1, d - 1))
 | 
				
			||||||
    with pytest.raises(OSError):
 | 
					    with pytest.raises(OSError):
 | 
				
			||||||
| 
						 | 
					@ -146,7 +147,7 @@ def test_default_num_resolutions(num_resolutions):
 | 
				
			||||||
    assert_image_equal(im, reloaded)
 | 
					    assert_image_equal(im, reloaded)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_reduce():
 | 
					def test_reduce() -> None:
 | 
				
			||||||
    with Image.open("Tests/images/test-card-lossless.jp2") as im:
 | 
					    with Image.open("Tests/images/test-card-lossless.jp2") as im:
 | 
				
			||||||
        assert callable(im.reduce)
 | 
					        assert callable(im.reduce)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -160,7 +161,7 @@ def test_reduce():
 | 
				
			||||||
        assert im.size == (40, 30)
 | 
					        assert im.size == (40, 30)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_load_dpi():
 | 
					def test_load_dpi() -> None:
 | 
				
			||||||
    with Image.open("Tests/images/test-card-lossless.jp2") as im:
 | 
					    with Image.open("Tests/images/test-card-lossless.jp2") as im:
 | 
				
			||||||
        assert im.info["dpi"] == (71.9836, 71.9836)
 | 
					        assert im.info["dpi"] == (71.9836, 71.9836)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -168,7 +169,7 @@ def test_load_dpi():
 | 
				
			||||||
        assert "dpi" not in im.info
 | 
					        assert "dpi" not in im.info
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_restricted_icc_profile():
 | 
					def test_restricted_icc_profile() -> None:
 | 
				
			||||||
    ImageFile.LOAD_TRUNCATED_IMAGES = True
 | 
					    ImageFile.LOAD_TRUNCATED_IMAGES = True
 | 
				
			||||||
    try:
 | 
					    try:
 | 
				
			||||||
        # JPEG2000 image with a restricted ICC profile and a known colorspace
 | 
					        # JPEG2000 image with a restricted ICC profile and a known colorspace
 | 
				
			||||||
| 
						 | 
					@ -178,7 +179,7 @@ def test_restricted_icc_profile():
 | 
				
			||||||
        ImageFile.LOAD_TRUNCATED_IMAGES = False
 | 
					        ImageFile.LOAD_TRUNCATED_IMAGES = False
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_header_errors():
 | 
					def test_header_errors() -> None:
 | 
				
			||||||
    for path in (
 | 
					    for path in (
 | 
				
			||||||
        "Tests/images/invalid_header_length.jp2",
 | 
					        "Tests/images/invalid_header_length.jp2",
 | 
				
			||||||
        "Tests/images/not_enough_data.jp2",
 | 
					        "Tests/images/not_enough_data.jp2",
 | 
				
			||||||
| 
						 | 
					@ -192,7 +193,7 @@ def test_header_errors():
 | 
				
			||||||
            pass
 | 
					            pass
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_layers_type(tmp_path):
 | 
					def test_layers_type(tmp_path: Path) -> None:
 | 
				
			||||||
    outfile = str(tmp_path / "temp_layers.jp2")
 | 
					    outfile = str(tmp_path / "temp_layers.jp2")
 | 
				
			||||||
    for quality_layers in [[100, 50, 10], (100, 50, 10), None]:
 | 
					    for quality_layers in [[100, 50, 10], (100, 50, 10), None]:
 | 
				
			||||||
        test_card.save(outfile, quality_layers=quality_layers)
 | 
					        test_card.save(outfile, quality_layers=quality_layers)
 | 
				
			||||||
| 
						 | 
					@ -202,7 +203,7 @@ def test_layers_type(tmp_path):
 | 
				
			||||||
            test_card.save(outfile, quality_layers=quality_layers)
 | 
					            test_card.save(outfile, quality_layers=quality_layers)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_layers():
 | 
					def test_layers() -> None:
 | 
				
			||||||
    out = BytesIO()
 | 
					    out = BytesIO()
 | 
				
			||||||
    test_card.save(out, "JPEG2000", quality_layers=[100, 50, 10], progression="LRCP")
 | 
					    test_card.save(out, "JPEG2000", quality_layers=[100, 50, 10], progression="LRCP")
 | 
				
			||||||
    out.seek(0)
 | 
					    out.seek(0)
 | 
				
			||||||
| 
						 | 
					@ -232,7 +233,7 @@ def test_layers():
 | 
				
			||||||
        ("foo.jp2", {"no_jp2": False}, 4, b"jP"),
 | 
					        ("foo.jp2", {"no_jp2": False}, 4, b"jP"),
 | 
				
			||||||
    ),
 | 
					    ),
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
def test_no_jp2(name, args, offset, data):
 | 
					def test_no_jp2(name, args, offset, data) -> None:
 | 
				
			||||||
    out = BytesIO()
 | 
					    out = BytesIO()
 | 
				
			||||||
    if name:
 | 
					    if name:
 | 
				
			||||||
        out.name = name
 | 
					        out.name = name
 | 
				
			||||||
| 
						 | 
					@ -241,7 +242,7 @@ def test_no_jp2(name, args, offset, data):
 | 
				
			||||||
    assert out.read(2) == data
 | 
					    assert out.read(2) == data
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_mct():
 | 
					def test_mct() -> None:
 | 
				
			||||||
    # Three component
 | 
					    # Three component
 | 
				
			||||||
    for val in (0, 1):
 | 
					    for val in (0, 1):
 | 
				
			||||||
        out = BytesIO()
 | 
					        out = BytesIO()
 | 
				
			||||||
| 
						 | 
					@ -262,7 +263,7 @@ def test_mct():
 | 
				
			||||||
            assert_image_similar(im, jp2, 1.0e-3)
 | 
					            assert_image_similar(im, jp2, 1.0e-3)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_sgnd(tmp_path):
 | 
					def test_sgnd(tmp_path: Path) -> None:
 | 
				
			||||||
    outfile = str(tmp_path / "temp.jp2")
 | 
					    outfile = str(tmp_path / "temp.jp2")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    im = Image.new("L", (1, 1))
 | 
					    im = Image.new("L", (1, 1))
 | 
				
			||||||
| 
						 | 
					@ -277,7 +278,7 @@ def test_sgnd(tmp_path):
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@pytest.mark.parametrize("ext", (".j2k", ".jp2"))
 | 
					@pytest.mark.parametrize("ext", (".j2k", ".jp2"))
 | 
				
			||||||
def test_rgba(ext):
 | 
					def test_rgba(ext) -> None:
 | 
				
			||||||
    # Arrange
 | 
					    # Arrange
 | 
				
			||||||
    with Image.open("Tests/images/rgb_trns_ycbc" + ext) as im:
 | 
					    with Image.open("Tests/images/rgb_trns_ycbc" + ext) as im:
 | 
				
			||||||
        # Act
 | 
					        # Act
 | 
				
			||||||
| 
						 | 
					@ -288,47 +289,47 @@ def test_rgba(ext):
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@pytest.mark.parametrize("ext", (".j2k", ".jp2"))
 | 
					@pytest.mark.parametrize("ext", (".j2k", ".jp2"))
 | 
				
			||||||
def test_16bit_monochrome_has_correct_mode(ext):
 | 
					def test_16bit_monochrome_has_correct_mode(ext) -> None:
 | 
				
			||||||
    with Image.open("Tests/images/16bit.cropped" + ext) as im:
 | 
					    with Image.open("Tests/images/16bit.cropped" + ext) as im:
 | 
				
			||||||
        im.load()
 | 
					        im.load()
 | 
				
			||||||
        assert im.mode == "I;16"
 | 
					        assert im.mode == "I;16"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_16bit_monochrome_jp2_like_tiff():
 | 
					def test_16bit_monochrome_jp2_like_tiff() -> None:
 | 
				
			||||||
    with Image.open("Tests/images/16bit.cropped.tif") as tiff_16bit:
 | 
					    with Image.open("Tests/images/16bit.cropped.tif") as tiff_16bit:
 | 
				
			||||||
        assert_image_similar_tofile(tiff_16bit, "Tests/images/16bit.cropped.jp2", 1e-3)
 | 
					        assert_image_similar_tofile(tiff_16bit, "Tests/images/16bit.cropped.jp2", 1e-3)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_16bit_monochrome_j2k_like_tiff():
 | 
					def test_16bit_monochrome_j2k_like_tiff() -> None:
 | 
				
			||||||
    with Image.open("Tests/images/16bit.cropped.tif") as tiff_16bit:
 | 
					    with Image.open("Tests/images/16bit.cropped.tif") as tiff_16bit:
 | 
				
			||||||
        assert_image_similar_tofile(tiff_16bit, "Tests/images/16bit.cropped.j2k", 1e-3)
 | 
					        assert_image_similar_tofile(tiff_16bit, "Tests/images/16bit.cropped.j2k", 1e-3)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_16bit_j2k_roundtrips():
 | 
					def test_16bit_j2k_roundtrips() -> None:
 | 
				
			||||||
    with Image.open("Tests/images/16bit.cropped.j2k") as j2k:
 | 
					    with Image.open("Tests/images/16bit.cropped.j2k") as j2k:
 | 
				
			||||||
        im = roundtrip(j2k)
 | 
					        im = roundtrip(j2k)
 | 
				
			||||||
        assert_image_equal(im, j2k)
 | 
					        assert_image_equal(im, j2k)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_16bit_jp2_roundtrips():
 | 
					def test_16bit_jp2_roundtrips() -> None:
 | 
				
			||||||
    with Image.open("Tests/images/16bit.cropped.jp2") as jp2:
 | 
					    with Image.open("Tests/images/16bit.cropped.jp2") as jp2:
 | 
				
			||||||
        im = roundtrip(jp2)
 | 
					        im = roundtrip(jp2)
 | 
				
			||||||
        assert_image_equal(im, jp2)
 | 
					        assert_image_equal(im, jp2)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_issue_6194():
 | 
					def test_issue_6194() -> None:
 | 
				
			||||||
    with Image.open("Tests/images/issue_6194.j2k") as im:
 | 
					    with Image.open("Tests/images/issue_6194.j2k") as im:
 | 
				
			||||||
        assert im.getpixel((5, 5)) == 31
 | 
					        assert im.getpixel((5, 5)) == 31
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_unbound_local():
 | 
					def test_unbound_local() -> None:
 | 
				
			||||||
    # prepatch, a malformed jp2 file could cause an UnboundLocalError exception.
 | 
					    # prepatch, a malformed jp2 file could cause an UnboundLocalError exception.
 | 
				
			||||||
    with pytest.raises(OSError):
 | 
					    with pytest.raises(OSError):
 | 
				
			||||||
        with Image.open("Tests/images/unbound_variable.jp2"):
 | 
					        with Image.open("Tests/images/unbound_variable.jp2"):
 | 
				
			||||||
            pass
 | 
					            pass
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_parser_feed():
 | 
					def test_parser_feed() -> None:
 | 
				
			||||||
    # Arrange
 | 
					    # Arrange
 | 
				
			||||||
    with open("Tests/images/test-card-lossless.jp2", "rb") as f:
 | 
					    with open("Tests/images/test-card-lossless.jp2", "rb") as f:
 | 
				
			||||||
        data = f.read()
 | 
					        data = f.read()
 | 
				
			||||||
| 
						 | 
					@ -345,7 +346,7 @@ def test_parser_feed():
 | 
				
			||||||
    not os.path.exists(EXTRA_DIR), reason="Extra image files not installed"
 | 
					    not os.path.exists(EXTRA_DIR), reason="Extra image files not installed"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
@pytest.mark.parametrize("name", ("subsampling_1", "subsampling_2", "zoo1", "zoo2"))
 | 
					@pytest.mark.parametrize("name", ("subsampling_1", "subsampling_2", "zoo1", "zoo2"))
 | 
				
			||||||
def test_subsampling_decode(name):
 | 
					def test_subsampling_decode(name) -> None:
 | 
				
			||||||
    test = f"{EXTRA_DIR}/{name}.jp2"
 | 
					    test = f"{EXTRA_DIR}/{name}.jp2"
 | 
				
			||||||
    reference = f"{EXTRA_DIR}/{name}.ppm"
 | 
					    reference = f"{EXTRA_DIR}/{name}.ppm"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -361,7 +362,7 @@ def test_subsampling_decode(name):
 | 
				
			||||||
        assert_image_similar(im, expected, epsilon)
 | 
					        assert_image_similar(im, expected, epsilon)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_comment():
 | 
					def test_comment() -> None:
 | 
				
			||||||
    with Image.open("Tests/images/comment.jp2") as im:
 | 
					    with Image.open("Tests/images/comment.jp2") as im:
 | 
				
			||||||
        assert im.info["comment"] == b"Created by OpenJPEG version 2.5.0"
 | 
					        assert im.info["comment"] == b"Created by OpenJPEG version 2.5.0"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -372,7 +373,7 @@ def test_comment():
 | 
				
			||||||
            pass
 | 
					            pass
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_save_comment():
 | 
					def test_save_comment() -> None:
 | 
				
			||||||
    for comment in ("Created by Pillow", b"Created by Pillow"):
 | 
					    for comment in ("Created by Pillow", b"Created by Pillow"):
 | 
				
			||||||
        out = BytesIO()
 | 
					        out = BytesIO()
 | 
				
			||||||
        test_card.save(out, "JPEG2000", comment=comment)
 | 
					        test_card.save(out, "JPEG2000", comment=comment)
 | 
				
			||||||
| 
						 | 
					@ -399,7 +400,7 @@ def test_save_comment():
 | 
				
			||||||
        "Tests/images/crash-d2c93af851d3ab9a19e34503626368b2ecde9c03.j2k",
 | 
					        "Tests/images/crash-d2c93af851d3ab9a19e34503626368b2ecde9c03.j2k",
 | 
				
			||||||
    ],
 | 
					    ],
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
def test_crashes(test_file):
 | 
					def test_crashes(test_file) -> None:
 | 
				
			||||||
    with open(test_file, "rb") as f:
 | 
					    with open(test_file, "rb") as f:
 | 
				
			||||||
        with Image.open(f) as im:
 | 
					        with Image.open(f) as im:
 | 
				
			||||||
            # Valgrind should not complain here
 | 
					            # Valgrind should not complain here
 | 
				
			||||||
| 
						 | 
					@ -410,7 +411,7 @@ def test_crashes(test_file):
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@skip_unless_feature_version("jpg_2000", "2.4.0")
 | 
					@skip_unless_feature_version("jpg_2000", "2.4.0")
 | 
				
			||||||
def test_plt_marker():
 | 
					def test_plt_marker() -> None:
 | 
				
			||||||
    # Search the start of the codesteam for PLT
 | 
					    # Search the start of the codesteam for PLT
 | 
				
			||||||
    out = BytesIO()
 | 
					    out = BytesIO()
 | 
				
			||||||
    test_card.save(out, "JPEG2000", no_jp2=True, plt=True)
 | 
					    test_card.save(out, "JPEG2000", no_jp2=True, plt=True)
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -7,6 +7,7 @@ import os
 | 
				
			||||||
import re
 | 
					import re
 | 
				
			||||||
import sys
 | 
					import sys
 | 
				
			||||||
from collections import namedtuple
 | 
					from collections import namedtuple
 | 
				
			||||||
 | 
					from pathlib import Path
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import pytest
 | 
					import pytest
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -26,7 +27,7 @@ from .helper import (
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@skip_unless_feature("libtiff")
 | 
					@skip_unless_feature("libtiff")
 | 
				
			||||||
class LibTiffTestCase:
 | 
					class LibTiffTestCase:
 | 
				
			||||||
    def _assert_noerr(self, tmp_path, im):
 | 
					    def _assert_noerr(self, tmp_path: Path, im) -> None:
 | 
				
			||||||
        """Helper tests that assert basic sanity about the g4 tiff reading"""
 | 
					        """Helper tests that assert basic sanity about the g4 tiff reading"""
 | 
				
			||||||
        # 1 bit
 | 
					        # 1 bit
 | 
				
			||||||
        assert im.mode == "1"
 | 
					        assert im.mode == "1"
 | 
				
			||||||
| 
						 | 
					@ -50,10 +51,10 @@ class LibTiffTestCase:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class TestFileLibTiff(LibTiffTestCase):
 | 
					class TestFileLibTiff(LibTiffTestCase):
 | 
				
			||||||
    def test_version(self):
 | 
					    def test_version(self) -> None:
 | 
				
			||||||
        assert re.search(r"\d+\.\d+\.\d+$", features.version_codec("libtiff"))
 | 
					        assert re.search(r"\d+\.\d+\.\d+$", features.version_codec("libtiff"))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_g4_tiff(self, tmp_path):
 | 
					    def test_g4_tiff(self, tmp_path: Path) -> None:
 | 
				
			||||||
        """Test the ordinary file path load path"""
 | 
					        """Test the ordinary file path load path"""
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        test_file = "Tests/images/hopper_g4_500.tif"
 | 
					        test_file = "Tests/images/hopper_g4_500.tif"
 | 
				
			||||||
| 
						 | 
					@ -61,12 +62,12 @@ class TestFileLibTiff(LibTiffTestCase):
 | 
				
			||||||
            assert im.size == (500, 500)
 | 
					            assert im.size == (500, 500)
 | 
				
			||||||
            self._assert_noerr(tmp_path, im)
 | 
					            self._assert_noerr(tmp_path, im)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_g4_large(self, tmp_path):
 | 
					    def test_g4_large(self, tmp_path: Path) -> None:
 | 
				
			||||||
        test_file = "Tests/images/pport_g4.tif"
 | 
					        test_file = "Tests/images/pport_g4.tif"
 | 
				
			||||||
        with Image.open(test_file) as im:
 | 
					        with Image.open(test_file) as im:
 | 
				
			||||||
            self._assert_noerr(tmp_path, im)
 | 
					            self._assert_noerr(tmp_path, im)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_g4_tiff_file(self, tmp_path):
 | 
					    def test_g4_tiff_file(self, tmp_path: Path) -> None:
 | 
				
			||||||
        """Testing the string load path"""
 | 
					        """Testing the string load path"""
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        test_file = "Tests/images/hopper_g4_500.tif"
 | 
					        test_file = "Tests/images/hopper_g4_500.tif"
 | 
				
			||||||
| 
						 | 
					@ -75,7 +76,7 @@ class TestFileLibTiff(LibTiffTestCase):
 | 
				
			||||||
                assert im.size == (500, 500)
 | 
					                assert im.size == (500, 500)
 | 
				
			||||||
                self._assert_noerr(tmp_path, im)
 | 
					                self._assert_noerr(tmp_path, im)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_g4_tiff_bytesio(self, tmp_path):
 | 
					    def test_g4_tiff_bytesio(self, tmp_path: Path) -> None:
 | 
				
			||||||
        """Testing the stringio loading code path"""
 | 
					        """Testing the stringio loading code path"""
 | 
				
			||||||
        test_file = "Tests/images/hopper_g4_500.tif"
 | 
					        test_file = "Tests/images/hopper_g4_500.tif"
 | 
				
			||||||
        s = io.BytesIO()
 | 
					        s = io.BytesIO()
 | 
				
			||||||
| 
						 | 
					@ -86,7 +87,7 @@ class TestFileLibTiff(LibTiffTestCase):
 | 
				
			||||||
            assert im.size == (500, 500)
 | 
					            assert im.size == (500, 500)
 | 
				
			||||||
            self._assert_noerr(tmp_path, im)
 | 
					            self._assert_noerr(tmp_path, im)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_g4_non_disk_file_object(self, tmp_path):
 | 
					    def test_g4_non_disk_file_object(self, tmp_path: Path) -> None:
 | 
				
			||||||
        """Testing loading from non-disk non-BytesIO file object"""
 | 
					        """Testing loading from non-disk non-BytesIO file object"""
 | 
				
			||||||
        test_file = "Tests/images/hopper_g4_500.tif"
 | 
					        test_file = "Tests/images/hopper_g4_500.tif"
 | 
				
			||||||
        s = io.BytesIO()
 | 
					        s = io.BytesIO()
 | 
				
			||||||
| 
						 | 
					@ -98,18 +99,18 @@ class TestFileLibTiff(LibTiffTestCase):
 | 
				
			||||||
            assert im.size == (500, 500)
 | 
					            assert im.size == (500, 500)
 | 
				
			||||||
            self._assert_noerr(tmp_path, im)
 | 
					            self._assert_noerr(tmp_path, im)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_g4_eq_png(self):
 | 
					    def test_g4_eq_png(self) -> None:
 | 
				
			||||||
        """Checking that we're actually getting the data that we expect"""
 | 
					        """Checking that we're actually getting the data that we expect"""
 | 
				
			||||||
        with Image.open("Tests/images/hopper_bw_500.png") as png:
 | 
					        with Image.open("Tests/images/hopper_bw_500.png") as png:
 | 
				
			||||||
            assert_image_equal_tofile(png, "Tests/images/hopper_g4_500.tif")
 | 
					            assert_image_equal_tofile(png, "Tests/images/hopper_g4_500.tif")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    # see https://github.com/python-pillow/Pillow/issues/279
 | 
					    # see https://github.com/python-pillow/Pillow/issues/279
 | 
				
			||||||
    def test_g4_fillorder_eq_png(self):
 | 
					    def test_g4_fillorder_eq_png(self) -> None:
 | 
				
			||||||
        """Checking that we're actually getting the data that we expect"""
 | 
					        """Checking that we're actually getting the data that we expect"""
 | 
				
			||||||
        with Image.open("Tests/images/g4-fillorder-test.tif") as g4:
 | 
					        with Image.open("Tests/images/g4-fillorder-test.tif") as g4:
 | 
				
			||||||
            assert_image_equal_tofile(g4, "Tests/images/g4-fillorder-test.png")
 | 
					            assert_image_equal_tofile(g4, "Tests/images/g4-fillorder-test.png")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_g4_write(self, tmp_path):
 | 
					    def test_g4_write(self, tmp_path: Path) -> None:
 | 
				
			||||||
        """Checking to see that the saved image is the same as what we wrote"""
 | 
					        """Checking to see that the saved image is the same as what we wrote"""
 | 
				
			||||||
        test_file = "Tests/images/hopper_g4_500.tif"
 | 
					        test_file = "Tests/images/hopper_g4_500.tif"
 | 
				
			||||||
        with Image.open(test_file) as orig:
 | 
					        with Image.open(test_file) as orig:
 | 
				
			||||||
| 
						 | 
					@ -128,7 +129,7 @@ class TestFileLibTiff(LibTiffTestCase):
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                assert orig.tobytes() != reread.tobytes()
 | 
					                assert orig.tobytes() != reread.tobytes()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_adobe_deflate_tiff(self):
 | 
					    def test_adobe_deflate_tiff(self) -> None:
 | 
				
			||||||
        test_file = "Tests/images/tiff_adobe_deflate.tif"
 | 
					        test_file = "Tests/images/tiff_adobe_deflate.tif"
 | 
				
			||||||
        with Image.open(test_file) as im:
 | 
					        with Image.open(test_file) as im:
 | 
				
			||||||
            assert im.mode == "RGB"
 | 
					            assert im.mode == "RGB"
 | 
				
			||||||
| 
						 | 
					@ -139,7 +140,7 @@ class TestFileLibTiff(LibTiffTestCase):
 | 
				
			||||||
            assert_image_equal_tofile(im, "Tests/images/tiff_adobe_deflate.png")
 | 
					            assert_image_equal_tofile(im, "Tests/images/tiff_adobe_deflate.png")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    @pytest.mark.parametrize("legacy_api", (False, True))
 | 
					    @pytest.mark.parametrize("legacy_api", (False, True))
 | 
				
			||||||
    def test_write_metadata(self, legacy_api, tmp_path):
 | 
					    def test_write_metadata(self, legacy_api, tmp_path: Path) -> None:
 | 
				
			||||||
        """Test metadata writing through libtiff"""
 | 
					        """Test metadata writing through libtiff"""
 | 
				
			||||||
        f = str(tmp_path / "temp.tiff")
 | 
					        f = str(tmp_path / "temp.tiff")
 | 
				
			||||||
        with Image.open("Tests/images/hopper_g4.tif") as img:
 | 
					        with Image.open("Tests/images/hopper_g4.tif") as img:
 | 
				
			||||||
| 
						 | 
					@ -184,7 +185,7 @@ class TestFileLibTiff(LibTiffTestCase):
 | 
				
			||||||
            assert field in reloaded, f"{field} not in metadata"
 | 
					            assert field in reloaded, f"{field} not in metadata"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    @pytest.mark.valgrind_known_error(reason="Known invalid metadata")
 | 
					    @pytest.mark.valgrind_known_error(reason="Known invalid metadata")
 | 
				
			||||||
    def test_additional_metadata(self, tmp_path):
 | 
					    def test_additional_metadata(self, tmp_path: Path) -> None:
 | 
				
			||||||
        # these should not crash. Seriously dummy data, most of it doesn't make
 | 
					        # these should not crash. Seriously dummy data, most of it doesn't make
 | 
				
			||||||
        # any sense, so we're running up against limits where we're asking
 | 
					        # any sense, so we're running up against limits where we're asking
 | 
				
			||||||
        # libtiff to do stupid things.
 | 
					        # libtiff to do stupid things.
 | 
				
			||||||
| 
						 | 
					@ -241,7 +242,7 @@ class TestFileLibTiff(LibTiffTestCase):
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        TiffImagePlugin.WRITE_LIBTIFF = False
 | 
					        TiffImagePlugin.WRITE_LIBTIFF = False
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_custom_metadata(self, tmp_path):
 | 
					    def test_custom_metadata(self, tmp_path: Path) -> None:
 | 
				
			||||||
        tc = namedtuple("test_case", "value,type,supported_by_default")
 | 
					        tc = namedtuple("test_case", "value,type,supported_by_default")
 | 
				
			||||||
        custom = {
 | 
					        custom = {
 | 
				
			||||||
            37000 + k: v
 | 
					            37000 + k: v
 | 
				
			||||||
| 
						 | 
					@ -283,7 +284,7 @@ class TestFileLibTiff(LibTiffTestCase):
 | 
				
			||||||
        for libtiff in libtiffs:
 | 
					        for libtiff in libtiffs:
 | 
				
			||||||
            TiffImagePlugin.WRITE_LIBTIFF = libtiff
 | 
					            TiffImagePlugin.WRITE_LIBTIFF = libtiff
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            def check_tags(tiffinfo):
 | 
					            def check_tags(tiffinfo) -> None:
 | 
				
			||||||
                im = hopper()
 | 
					                im = hopper()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                out = str(tmp_path / "temp.tif")
 | 
					                out = str(tmp_path / "temp.tif")
 | 
				
			||||||
| 
						 | 
					@ -322,7 +323,7 @@ class TestFileLibTiff(LibTiffTestCase):
 | 
				
			||||||
            )
 | 
					            )
 | 
				
			||||||
        TiffImagePlugin.WRITE_LIBTIFF = False
 | 
					        TiffImagePlugin.WRITE_LIBTIFF = False
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_subifd(self, tmp_path):
 | 
					    def test_subifd(self, tmp_path: Path) -> None:
 | 
				
			||||||
        outfile = str(tmp_path / "temp.tif")
 | 
					        outfile = str(tmp_path / "temp.tif")
 | 
				
			||||||
        with Image.open("Tests/images/g4_orientation_6.tif") as im:
 | 
					        with Image.open("Tests/images/g4_orientation_6.tif") as im:
 | 
				
			||||||
            im.tag_v2[SUBIFD] = 10000
 | 
					            im.tag_v2[SUBIFD] = 10000
 | 
				
			||||||
| 
						 | 
					@ -330,7 +331,7 @@ class TestFileLibTiff(LibTiffTestCase):
 | 
				
			||||||
            # Should not segfault
 | 
					            # Should not segfault
 | 
				
			||||||
            im.save(outfile)
 | 
					            im.save(outfile)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_xmlpacket_tag(self, tmp_path):
 | 
					    def test_xmlpacket_tag(self, tmp_path: Path) -> None:
 | 
				
			||||||
        TiffImagePlugin.WRITE_LIBTIFF = True
 | 
					        TiffImagePlugin.WRITE_LIBTIFF = True
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        out = str(tmp_path / "temp.tif")
 | 
					        out = str(tmp_path / "temp.tif")
 | 
				
			||||||
| 
						 | 
					@ -341,7 +342,7 @@ class TestFileLibTiff(LibTiffTestCase):
 | 
				
			||||||
            if 700 in reloaded.tag_v2:
 | 
					            if 700 in reloaded.tag_v2:
 | 
				
			||||||
                assert reloaded.tag_v2[700] == b"xmlpacket tag"
 | 
					                assert reloaded.tag_v2[700] == b"xmlpacket tag"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_int_dpi(self, tmp_path):
 | 
					    def test_int_dpi(self, tmp_path: Path) -> None:
 | 
				
			||||||
        # issue #1765
 | 
					        # issue #1765
 | 
				
			||||||
        im = hopper("RGB")
 | 
					        im = hopper("RGB")
 | 
				
			||||||
        out = str(tmp_path / "temp.tif")
 | 
					        out = str(tmp_path / "temp.tif")
 | 
				
			||||||
| 
						 | 
					@ -351,7 +352,7 @@ class TestFileLibTiff(LibTiffTestCase):
 | 
				
			||||||
        with Image.open(out) as reloaded:
 | 
					        with Image.open(out) as reloaded:
 | 
				
			||||||
            assert reloaded.info["dpi"] == (72.0, 72.0)
 | 
					            assert reloaded.info["dpi"] == (72.0, 72.0)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_g3_compression(self, tmp_path):
 | 
					    def test_g3_compression(self, tmp_path: Path) -> None:
 | 
				
			||||||
        with Image.open("Tests/images/hopper_g4_500.tif") as i:
 | 
					        with Image.open("Tests/images/hopper_g4_500.tif") as i:
 | 
				
			||||||
            out = str(tmp_path / "temp.tif")
 | 
					            out = str(tmp_path / "temp.tif")
 | 
				
			||||||
            i.save(out, compression="group3")
 | 
					            i.save(out, compression="group3")
 | 
				
			||||||
| 
						 | 
					@ -360,7 +361,7 @@ class TestFileLibTiff(LibTiffTestCase):
 | 
				
			||||||
                assert reread.info["compression"] == "group3"
 | 
					                assert reread.info["compression"] == "group3"
 | 
				
			||||||
                assert_image_equal(reread, i)
 | 
					                assert_image_equal(reread, i)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_little_endian(self, tmp_path):
 | 
					    def test_little_endian(self, tmp_path: Path) -> None:
 | 
				
			||||||
        with Image.open("Tests/images/16bit.deflate.tif") as im:
 | 
					        with Image.open("Tests/images/16bit.deflate.tif") as im:
 | 
				
			||||||
            assert im.getpixel((0, 0)) == 480
 | 
					            assert im.getpixel((0, 0)) == 480
 | 
				
			||||||
            assert im.mode == "I;16"
 | 
					            assert im.mode == "I;16"
 | 
				
			||||||
| 
						 | 
					@ -379,7 +380,7 @@ class TestFileLibTiff(LibTiffTestCase):
 | 
				
			||||||
        # UNDONE - libtiff defaults to writing in native endian, so
 | 
					        # UNDONE - libtiff defaults to writing in native endian, so
 | 
				
			||||||
        # on big endian, we'll get back mode = 'I;16B' here.
 | 
					        # on big endian, we'll get back mode = 'I;16B' here.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_big_endian(self, tmp_path):
 | 
					    def test_big_endian(self, tmp_path: Path) -> None:
 | 
				
			||||||
        with Image.open("Tests/images/16bit.MM.deflate.tif") as im:
 | 
					        with Image.open("Tests/images/16bit.MM.deflate.tif") as im:
 | 
				
			||||||
            assert im.getpixel((0, 0)) == 480
 | 
					            assert im.getpixel((0, 0)) == 480
 | 
				
			||||||
            assert im.mode == "I;16B"
 | 
					            assert im.mode == "I;16B"
 | 
				
			||||||
| 
						 | 
					@ -396,7 +397,7 @@ class TestFileLibTiff(LibTiffTestCase):
 | 
				
			||||||
                assert reread.info["compression"] == im.info["compression"]
 | 
					                assert reread.info["compression"] == im.info["compression"]
 | 
				
			||||||
                assert reread.getpixel((0, 0)) == 480
 | 
					                assert reread.getpixel((0, 0)) == 480
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_g4_string_info(self, tmp_path):
 | 
					    def test_g4_string_info(self, tmp_path: Path) -> None:
 | 
				
			||||||
        """Tests String data in info directory"""
 | 
					        """Tests String data in info directory"""
 | 
				
			||||||
        test_file = "Tests/images/hopper_g4_500.tif"
 | 
					        test_file = "Tests/images/hopper_g4_500.tif"
 | 
				
			||||||
        with Image.open(test_file) as orig:
 | 
					        with Image.open(test_file) as orig:
 | 
				
			||||||
| 
						 | 
					@ -409,7 +410,7 @@ class TestFileLibTiff(LibTiffTestCase):
 | 
				
			||||||
            assert "temp.tif" == reread.tag_v2[269]
 | 
					            assert "temp.tif" == reread.tag_v2[269]
 | 
				
			||||||
            assert "temp.tif" == reread.tag[269][0]
 | 
					            assert "temp.tif" == reread.tag[269][0]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_12bit_rawmode(self):
 | 
					    def test_12bit_rawmode(self) -> None:
 | 
				
			||||||
        """Are we generating the same interpretation
 | 
					        """Are we generating the same interpretation
 | 
				
			||||||
        of the image as Imagemagick is?"""
 | 
					        of the image as Imagemagick is?"""
 | 
				
			||||||
        TiffImagePlugin.READ_LIBTIFF = True
 | 
					        TiffImagePlugin.READ_LIBTIFF = True
 | 
				
			||||||
| 
						 | 
					@ -424,7 +425,7 @@ class TestFileLibTiff(LibTiffTestCase):
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            assert_image_equal_tofile(im, "Tests/images/12in16bit.tif")
 | 
					            assert_image_equal_tofile(im, "Tests/images/12in16bit.tif")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_blur(self, tmp_path):
 | 
					    def test_blur(self, tmp_path: Path) -> None:
 | 
				
			||||||
        # test case from irc, how to do blur on b/w image
 | 
					        # test case from irc, how to do blur on b/w image
 | 
				
			||||||
        # and save to compressed tif.
 | 
					        # and save to compressed tif.
 | 
				
			||||||
        out = str(tmp_path / "temp.tif")
 | 
					        out = str(tmp_path / "temp.tif")
 | 
				
			||||||
| 
						 | 
					@ -436,7 +437,7 @@ class TestFileLibTiff(LibTiffTestCase):
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        assert_image_equal_tofile(im, out)
 | 
					        assert_image_equal_tofile(im, out)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_compressions(self, tmp_path):
 | 
					    def test_compressions(self, tmp_path: Path) -> None:
 | 
				
			||||||
        # Test various tiff compressions and assert similar image content but reduced
 | 
					        # Test various tiff compressions and assert similar image content but reduced
 | 
				
			||||||
        # file sizes.
 | 
					        # file sizes.
 | 
				
			||||||
        im = hopper("RGB")
 | 
					        im = hopper("RGB")
 | 
				
			||||||
| 
						 | 
					@ -462,7 +463,7 @@ class TestFileLibTiff(LibTiffTestCase):
 | 
				
			||||||
        assert size_compressed > size_jpeg
 | 
					        assert size_compressed > size_jpeg
 | 
				
			||||||
        assert size_jpeg > size_jpeg_30
 | 
					        assert size_jpeg > size_jpeg_30
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_tiff_jpeg_compression(self, tmp_path):
 | 
					    def test_tiff_jpeg_compression(self, tmp_path: Path) -> None:
 | 
				
			||||||
        im = hopper("RGB")
 | 
					        im = hopper("RGB")
 | 
				
			||||||
        out = str(tmp_path / "temp.tif")
 | 
					        out = str(tmp_path / "temp.tif")
 | 
				
			||||||
        im.save(out, compression="tiff_jpeg")
 | 
					        im.save(out, compression="tiff_jpeg")
 | 
				
			||||||
| 
						 | 
					@ -470,7 +471,7 @@ class TestFileLibTiff(LibTiffTestCase):
 | 
				
			||||||
        with Image.open(out) as reloaded:
 | 
					        with Image.open(out) as reloaded:
 | 
				
			||||||
            assert reloaded.info["compression"] == "jpeg"
 | 
					            assert reloaded.info["compression"] == "jpeg"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_tiff_deflate_compression(self, tmp_path):
 | 
					    def test_tiff_deflate_compression(self, tmp_path: Path) -> None:
 | 
				
			||||||
        im = hopper("RGB")
 | 
					        im = hopper("RGB")
 | 
				
			||||||
        out = str(tmp_path / "temp.tif")
 | 
					        out = str(tmp_path / "temp.tif")
 | 
				
			||||||
        im.save(out, compression="tiff_deflate")
 | 
					        im.save(out, compression="tiff_deflate")
 | 
				
			||||||
| 
						 | 
					@ -478,7 +479,7 @@ class TestFileLibTiff(LibTiffTestCase):
 | 
				
			||||||
        with Image.open(out) as reloaded:
 | 
					        with Image.open(out) as reloaded:
 | 
				
			||||||
            assert reloaded.info["compression"] == "tiff_adobe_deflate"
 | 
					            assert reloaded.info["compression"] == "tiff_adobe_deflate"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_quality(self, tmp_path):
 | 
					    def test_quality(self, tmp_path: Path) -> None:
 | 
				
			||||||
        im = hopper("RGB")
 | 
					        im = hopper("RGB")
 | 
				
			||||||
        out = str(tmp_path / "temp.tif")
 | 
					        out = str(tmp_path / "temp.tif")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -493,7 +494,7 @@ class TestFileLibTiff(LibTiffTestCase):
 | 
				
			||||||
        im.save(out, compression="jpeg", quality=0)
 | 
					        im.save(out, compression="jpeg", quality=0)
 | 
				
			||||||
        im.save(out, compression="jpeg", quality=100)
 | 
					        im.save(out, compression="jpeg", quality=100)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_cmyk_save(self, tmp_path):
 | 
					    def test_cmyk_save(self, tmp_path: Path) -> None:
 | 
				
			||||||
        im = hopper("CMYK")
 | 
					        im = hopper("CMYK")
 | 
				
			||||||
        out = str(tmp_path / "temp.tif")
 | 
					        out = str(tmp_path / "temp.tif")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -501,7 +502,7 @@ class TestFileLibTiff(LibTiffTestCase):
 | 
				
			||||||
        assert_image_equal_tofile(im, out)
 | 
					        assert_image_equal_tofile(im, out)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    @pytest.mark.parametrize("im", (hopper("P"), Image.new("P", (1, 1), "#000")))
 | 
					    @pytest.mark.parametrize("im", (hopper("P"), Image.new("P", (1, 1), "#000")))
 | 
				
			||||||
    def test_palette_save(self, im, tmp_path):
 | 
					    def test_palette_save(self, im, tmp_path: Path) -> None:
 | 
				
			||||||
        out = str(tmp_path / "temp.tif")
 | 
					        out = str(tmp_path / "temp.tif")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        TiffImagePlugin.WRITE_LIBTIFF = True
 | 
					        TiffImagePlugin.WRITE_LIBTIFF = True
 | 
				
			||||||
| 
						 | 
					@ -513,14 +514,14 @@ class TestFileLibTiff(LibTiffTestCase):
 | 
				
			||||||
            assert len(reloaded.tag_v2[320]) == 768
 | 
					            assert len(reloaded.tag_v2[320]) == 768
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    @pytest.mark.parametrize("compression", ("tiff_ccitt", "group3", "group4"))
 | 
					    @pytest.mark.parametrize("compression", ("tiff_ccitt", "group3", "group4"))
 | 
				
			||||||
    def test_bw_compression_w_rgb(self, compression, tmp_path):
 | 
					    def test_bw_compression_w_rgb(self, compression, tmp_path: Path) -> None:
 | 
				
			||||||
        im = hopper("RGB")
 | 
					        im = hopper("RGB")
 | 
				
			||||||
        out = str(tmp_path / "temp.tif")
 | 
					        out = str(tmp_path / "temp.tif")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        with pytest.raises(OSError):
 | 
					        with pytest.raises(OSError):
 | 
				
			||||||
            im.save(out, compression=compression)
 | 
					            im.save(out, compression=compression)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_fp_leak(self):
 | 
					    def test_fp_leak(self) -> None:
 | 
				
			||||||
        im = Image.open("Tests/images/hopper_g4_500.tif")
 | 
					        im = Image.open("Tests/images/hopper_g4_500.tif")
 | 
				
			||||||
        fn = im.fp.fileno()
 | 
					        fn = im.fp.fileno()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -534,7 +535,7 @@ class TestFileLibTiff(LibTiffTestCase):
 | 
				
			||||||
        with pytest.raises(OSError):
 | 
					        with pytest.raises(OSError):
 | 
				
			||||||
            os.close(fn)
 | 
					            os.close(fn)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_multipage(self):
 | 
					    def test_multipage(self) -> None:
 | 
				
			||||||
        # issue #862
 | 
					        # issue #862
 | 
				
			||||||
        TiffImagePlugin.READ_LIBTIFF = True
 | 
					        TiffImagePlugin.READ_LIBTIFF = True
 | 
				
			||||||
        with Image.open("Tests/images/multipage.tiff") as im:
 | 
					        with Image.open("Tests/images/multipage.tiff") as im:
 | 
				
			||||||
| 
						 | 
					@ -557,7 +558,7 @@ class TestFileLibTiff(LibTiffTestCase):
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        TiffImagePlugin.READ_LIBTIFF = False
 | 
					        TiffImagePlugin.READ_LIBTIFF = False
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_multipage_nframes(self):
 | 
					    def test_multipage_nframes(self) -> None:
 | 
				
			||||||
        # issue #862
 | 
					        # issue #862
 | 
				
			||||||
        TiffImagePlugin.READ_LIBTIFF = True
 | 
					        TiffImagePlugin.READ_LIBTIFF = True
 | 
				
			||||||
        with Image.open("Tests/images/multipage.tiff") as im:
 | 
					        with Image.open("Tests/images/multipage.tiff") as im:
 | 
				
			||||||
| 
						 | 
					@ -570,7 +571,7 @@ class TestFileLibTiff(LibTiffTestCase):
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        TiffImagePlugin.READ_LIBTIFF = False
 | 
					        TiffImagePlugin.READ_LIBTIFF = False
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_multipage_seek_backwards(self):
 | 
					    def test_multipage_seek_backwards(self) -> None:
 | 
				
			||||||
        TiffImagePlugin.READ_LIBTIFF = True
 | 
					        TiffImagePlugin.READ_LIBTIFF = True
 | 
				
			||||||
        with Image.open("Tests/images/multipage.tiff") as im:
 | 
					        with Image.open("Tests/images/multipage.tiff") as im:
 | 
				
			||||||
            im.seek(1)
 | 
					            im.seek(1)
 | 
				
			||||||
| 
						 | 
					@ -581,14 +582,14 @@ class TestFileLibTiff(LibTiffTestCase):
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        TiffImagePlugin.READ_LIBTIFF = False
 | 
					        TiffImagePlugin.READ_LIBTIFF = False
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test__next(self):
 | 
					    def test__next(self) -> None:
 | 
				
			||||||
        TiffImagePlugin.READ_LIBTIFF = True
 | 
					        TiffImagePlugin.READ_LIBTIFF = True
 | 
				
			||||||
        with Image.open("Tests/images/hopper.tif") as im:
 | 
					        with Image.open("Tests/images/hopper.tif") as im:
 | 
				
			||||||
            assert not im.tag.next
 | 
					            assert not im.tag.next
 | 
				
			||||||
            im.load()
 | 
					            im.load()
 | 
				
			||||||
            assert not im.tag.next
 | 
					            assert not im.tag.next
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_4bit(self):
 | 
					    def test_4bit(self) -> None:
 | 
				
			||||||
        # Arrange
 | 
					        # Arrange
 | 
				
			||||||
        test_file = "Tests/images/hopper_gray_4bpp.tif"
 | 
					        test_file = "Tests/images/hopper_gray_4bpp.tif"
 | 
				
			||||||
        original = hopper("L")
 | 
					        original = hopper("L")
 | 
				
			||||||
| 
						 | 
					@ -603,7 +604,7 @@ class TestFileLibTiff(LibTiffTestCase):
 | 
				
			||||||
            assert im.mode == "L"
 | 
					            assert im.mode == "L"
 | 
				
			||||||
            assert_image_similar(im, original, 7.3)
 | 
					            assert_image_similar(im, original, 7.3)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_gray_semibyte_per_pixel(self):
 | 
					    def test_gray_semibyte_per_pixel(self) -> None:
 | 
				
			||||||
        test_files = (
 | 
					        test_files = (
 | 
				
			||||||
            (
 | 
					            (
 | 
				
			||||||
                24.8,  # epsilon
 | 
					                24.8,  # epsilon
 | 
				
			||||||
| 
						 | 
					@ -636,7 +637,7 @@ class TestFileLibTiff(LibTiffTestCase):
 | 
				
			||||||
                    assert im2.mode == "L"
 | 
					                    assert im2.mode == "L"
 | 
				
			||||||
                    assert_image_equal(im, im2)
 | 
					                    assert_image_equal(im, im2)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_save_bytesio(self):
 | 
					    def test_save_bytesio(self) -> None:
 | 
				
			||||||
        # PR 1011
 | 
					        # PR 1011
 | 
				
			||||||
        # Test TIFF saving to io.BytesIO() object.
 | 
					        # Test TIFF saving to io.BytesIO() object.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -646,7 +647,7 @@ class TestFileLibTiff(LibTiffTestCase):
 | 
				
			||||||
        # Generate test image
 | 
					        # Generate test image
 | 
				
			||||||
        pilim = hopper()
 | 
					        pilim = hopper()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        def save_bytesio(compression=None):
 | 
					        def save_bytesio(compression=None) -> None:
 | 
				
			||||||
            buffer_io = io.BytesIO()
 | 
					            buffer_io = io.BytesIO()
 | 
				
			||||||
            pilim.save(buffer_io, format="tiff", compression=compression)
 | 
					            pilim.save(buffer_io, format="tiff", compression=compression)
 | 
				
			||||||
            buffer_io.seek(0)
 | 
					            buffer_io.seek(0)
 | 
				
			||||||
| 
						 | 
					@ -661,7 +662,7 @@ class TestFileLibTiff(LibTiffTestCase):
 | 
				
			||||||
        TiffImagePlugin.WRITE_LIBTIFF = False
 | 
					        TiffImagePlugin.WRITE_LIBTIFF = False
 | 
				
			||||||
        TiffImagePlugin.READ_LIBTIFF = False
 | 
					        TiffImagePlugin.READ_LIBTIFF = False
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_save_ycbcr(self, tmp_path):
 | 
					    def test_save_ycbcr(self, tmp_path: Path) -> None:
 | 
				
			||||||
        im = hopper("YCbCr")
 | 
					        im = hopper("YCbCr")
 | 
				
			||||||
        outfile = str(tmp_path / "temp.tif")
 | 
					        outfile = str(tmp_path / "temp.tif")
 | 
				
			||||||
        im.save(outfile, compression="jpeg")
 | 
					        im.save(outfile, compression="jpeg")
 | 
				
			||||||
| 
						 | 
					@ -670,7 +671,7 @@ class TestFileLibTiff(LibTiffTestCase):
 | 
				
			||||||
            assert reloaded.tag_v2[530] == (1, 1)
 | 
					            assert reloaded.tag_v2[530] == (1, 1)
 | 
				
			||||||
            assert reloaded.tag_v2[532] == (0, 255, 128, 255, 128, 255)
 | 
					            assert reloaded.tag_v2[532] == (0, 255, 128, 255, 128, 255)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_exif_ifd(self, tmp_path):
 | 
					    def test_exif_ifd(self, tmp_path: Path) -> None:
 | 
				
			||||||
        outfile = str(tmp_path / "temp.tif")
 | 
					        outfile = str(tmp_path / "temp.tif")
 | 
				
			||||||
        with Image.open("Tests/images/tiff_adobe_deflate.tif") as im:
 | 
					        with Image.open("Tests/images/tiff_adobe_deflate.tif") as im:
 | 
				
			||||||
            assert im.tag_v2[34665] == 125456
 | 
					            assert im.tag_v2[34665] == 125456
 | 
				
			||||||
| 
						 | 
					@ -680,7 +681,7 @@ class TestFileLibTiff(LibTiffTestCase):
 | 
				
			||||||
            if Image.core.libtiff_support_custom_tags:
 | 
					            if Image.core.libtiff_support_custom_tags:
 | 
				
			||||||
                assert reloaded.tag_v2[34665] == 125456
 | 
					                assert reloaded.tag_v2[34665] == 125456
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_crashing_metadata(self, tmp_path):
 | 
					    def test_crashing_metadata(self, tmp_path: Path) -> None:
 | 
				
			||||||
        # issue 1597
 | 
					        # issue 1597
 | 
				
			||||||
        with Image.open("Tests/images/rdf.tif") as im:
 | 
					        with Image.open("Tests/images/rdf.tif") as im:
 | 
				
			||||||
            out = str(tmp_path / "temp.tif")
 | 
					            out = str(tmp_path / "temp.tif")
 | 
				
			||||||
| 
						 | 
					@ -690,7 +691,7 @@ class TestFileLibTiff(LibTiffTestCase):
 | 
				
			||||||
            im.save(out, format="TIFF")
 | 
					            im.save(out, format="TIFF")
 | 
				
			||||||
        TiffImagePlugin.WRITE_LIBTIFF = False
 | 
					        TiffImagePlugin.WRITE_LIBTIFF = False
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_page_number_x_0(self, tmp_path):
 | 
					    def test_page_number_x_0(self, tmp_path: Path) -> None:
 | 
				
			||||||
        # Issue 973
 | 
					        # Issue 973
 | 
				
			||||||
        # Test TIFF with tag 297 (Page Number) having value of 0 0.
 | 
					        # Test TIFF with tag 297 (Page Number) having value of 0 0.
 | 
				
			||||||
        # The first number is the current page number.
 | 
					        # The first number is the current page number.
 | 
				
			||||||
| 
						 | 
					@ -704,7 +705,7 @@ class TestFileLibTiff(LibTiffTestCase):
 | 
				
			||||||
            # Should not divide by zero
 | 
					            # Should not divide by zero
 | 
				
			||||||
            im.save(outfile)
 | 
					            im.save(outfile)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_fd_duplication(self, tmp_path):
 | 
					    def test_fd_duplication(self, tmp_path: Path) -> None:
 | 
				
			||||||
        # https://github.com/python-pillow/Pillow/issues/1651
 | 
					        # https://github.com/python-pillow/Pillow/issues/1651
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        tmpfile = str(tmp_path / "temp.tif")
 | 
					        tmpfile = str(tmp_path / "temp.tif")
 | 
				
			||||||
| 
						 | 
					@ -718,7 +719,7 @@ class TestFileLibTiff(LibTiffTestCase):
 | 
				
			||||||
        # Should not raise PermissionError.
 | 
					        # Should not raise PermissionError.
 | 
				
			||||||
        os.remove(tmpfile)
 | 
					        os.remove(tmpfile)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_read_icc(self):
 | 
					    def test_read_icc(self) -> None:
 | 
				
			||||||
        with Image.open("Tests/images/hopper.iccprofile.tif") as img:
 | 
					        with Image.open("Tests/images/hopper.iccprofile.tif") as img:
 | 
				
			||||||
            icc = img.info.get("icc_profile")
 | 
					            icc = img.info.get("icc_profile")
 | 
				
			||||||
            assert icc is not None
 | 
					            assert icc is not None
 | 
				
			||||||
| 
						 | 
					@ -729,8 +730,8 @@ class TestFileLibTiff(LibTiffTestCase):
 | 
				
			||||||
        TiffImagePlugin.READ_LIBTIFF = False
 | 
					        TiffImagePlugin.READ_LIBTIFF = False
 | 
				
			||||||
        assert icc == icc_libtiff
 | 
					        assert icc == icc_libtiff
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_write_icc(self, tmp_path):
 | 
					    def test_write_icc(self, tmp_path: Path) -> None:
 | 
				
			||||||
        def check_write(libtiff):
 | 
					        def check_write(libtiff) -> None:
 | 
				
			||||||
            TiffImagePlugin.WRITE_LIBTIFF = libtiff
 | 
					            TiffImagePlugin.WRITE_LIBTIFF = libtiff
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            with Image.open("Tests/images/hopper.iccprofile.tif") as img:
 | 
					            with Image.open("Tests/images/hopper.iccprofile.tif") as img:
 | 
				
			||||||
| 
						 | 
					@ -749,7 +750,7 @@ class TestFileLibTiff(LibTiffTestCase):
 | 
				
			||||||
        for libtiff in libtiffs:
 | 
					        for libtiff in libtiffs:
 | 
				
			||||||
            check_write(libtiff)
 | 
					            check_write(libtiff)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_multipage_compression(self):
 | 
					    def test_multipage_compression(self) -> None:
 | 
				
			||||||
        with Image.open("Tests/images/compression.tif") as im:
 | 
					        with Image.open("Tests/images/compression.tif") as im:
 | 
				
			||||||
            im.seek(0)
 | 
					            im.seek(0)
 | 
				
			||||||
            assert im._compression == "tiff_ccitt"
 | 
					            assert im._compression == "tiff_ccitt"
 | 
				
			||||||
| 
						 | 
					@ -765,7 +766,7 @@ class TestFileLibTiff(LibTiffTestCase):
 | 
				
			||||||
            assert im.size == (10, 10)
 | 
					            assert im.size == (10, 10)
 | 
				
			||||||
            im.load()
 | 
					            im.load()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_save_tiff_with_jpegtables(self, tmp_path):
 | 
					    def test_save_tiff_with_jpegtables(self, tmp_path: Path) -> None:
 | 
				
			||||||
        # Arrange
 | 
					        # Arrange
 | 
				
			||||||
        outfile = str(tmp_path / "temp.tif")
 | 
					        outfile = str(tmp_path / "temp.tif")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -777,7 +778,7 @@ class TestFileLibTiff(LibTiffTestCase):
 | 
				
			||||||
            # Should not raise UnicodeDecodeError or anything else
 | 
					            # Should not raise UnicodeDecodeError or anything else
 | 
				
			||||||
            im.save(outfile)
 | 
					            im.save(outfile)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_16bit_RGB_tiff(self):
 | 
					    def test_16bit_RGB_tiff(self) -> None:
 | 
				
			||||||
        with Image.open("Tests/images/tiff_16bit_RGB.tiff") as im:
 | 
					        with Image.open("Tests/images/tiff_16bit_RGB.tiff") as im:
 | 
				
			||||||
            assert im.mode == "RGB"
 | 
					            assert im.mode == "RGB"
 | 
				
			||||||
            assert im.size == (100, 40)
 | 
					            assert im.size == (100, 40)
 | 
				
			||||||
| 
						 | 
					@ -793,7 +794,7 @@ class TestFileLibTiff(LibTiffTestCase):
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            assert_image_equal_tofile(im, "Tests/images/tiff_16bit_RGB_target.png")
 | 
					            assert_image_equal_tofile(im, "Tests/images/tiff_16bit_RGB_target.png")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_16bit_RGBa_tiff(self):
 | 
					    def test_16bit_RGBa_tiff(self) -> None:
 | 
				
			||||||
        with Image.open("Tests/images/tiff_16bit_RGBa.tiff") as im:
 | 
					        with Image.open("Tests/images/tiff_16bit_RGBa.tiff") as im:
 | 
				
			||||||
            assert im.mode == "RGBA"
 | 
					            assert im.mode == "RGBA"
 | 
				
			||||||
            assert im.size == (100, 40)
 | 
					            assert im.size == (100, 40)
 | 
				
			||||||
| 
						 | 
					@ -805,7 +806,7 @@ class TestFileLibTiff(LibTiffTestCase):
 | 
				
			||||||
            assert_image_equal_tofile(im, "Tests/images/tiff_16bit_RGBa_target.png")
 | 
					            assert_image_equal_tofile(im, "Tests/images/tiff_16bit_RGBa_target.png")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    @skip_unless_feature("jpg")
 | 
					    @skip_unless_feature("jpg")
 | 
				
			||||||
    def test_gimp_tiff(self):
 | 
					    def test_gimp_tiff(self) -> None:
 | 
				
			||||||
        # Read TIFF JPEG images from GIMP [@PIL168]
 | 
					        # Read TIFF JPEG images from GIMP [@PIL168]
 | 
				
			||||||
        filename = "Tests/images/pil168.tif"
 | 
					        filename = "Tests/images/pil168.tif"
 | 
				
			||||||
        with Image.open(filename) as im:
 | 
					        with Image.open(filename) as im:
 | 
				
			||||||
| 
						 | 
					@ -818,14 +819,14 @@ class TestFileLibTiff(LibTiffTestCase):
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            assert_image_equal_tofile(im, "Tests/images/pil168.png")
 | 
					            assert_image_equal_tofile(im, "Tests/images/pil168.png")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_sampleformat(self):
 | 
					    def test_sampleformat(self) -> None:
 | 
				
			||||||
        # https://github.com/python-pillow/Pillow/issues/1466
 | 
					        # https://github.com/python-pillow/Pillow/issues/1466
 | 
				
			||||||
        with Image.open("Tests/images/copyleft.tiff") as im:
 | 
					        with Image.open("Tests/images/copyleft.tiff") as im:
 | 
				
			||||||
            assert im.mode == "RGB"
 | 
					            assert im.mode == "RGB"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            assert_image_equal_tofile(im, "Tests/images/copyleft.png", mode="RGB")
 | 
					            assert_image_equal_tofile(im, "Tests/images/copyleft.png", mode="RGB")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_sampleformat_write(self, tmp_path):
 | 
					    def test_sampleformat_write(self, tmp_path: Path) -> None:
 | 
				
			||||||
        im = Image.new("F", (1, 1))
 | 
					        im = Image.new("F", (1, 1))
 | 
				
			||||||
        out = str(tmp_path / "temp.tif")
 | 
					        out = str(tmp_path / "temp.tif")
 | 
				
			||||||
        TiffImagePlugin.WRITE_LIBTIFF = True
 | 
					        TiffImagePlugin.WRITE_LIBTIFF = True
 | 
				
			||||||
| 
						 | 
					@ -874,7 +875,7 @@ class TestFileLibTiff(LibTiffTestCase):
 | 
				
			||||||
            sys.stderr.write(captured.err)
 | 
					            sys.stderr.write(captured.err)
 | 
				
			||||||
            raise
 | 
					            raise
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_lzw(self):
 | 
					    def test_lzw(self) -> None:
 | 
				
			||||||
        with Image.open("Tests/images/hopper_lzw.tif") as im:
 | 
					        with Image.open("Tests/images/hopper_lzw.tif") as im:
 | 
				
			||||||
            assert im.mode == "RGB"
 | 
					            assert im.mode == "RGB"
 | 
				
			||||||
            assert im.size == (128, 128)
 | 
					            assert im.size == (128, 128)
 | 
				
			||||||
| 
						 | 
					@ -882,12 +883,12 @@ class TestFileLibTiff(LibTiffTestCase):
 | 
				
			||||||
            im2 = hopper()
 | 
					            im2 = hopper()
 | 
				
			||||||
            assert_image_similar(im, im2, 5)
 | 
					            assert_image_similar(im, im2, 5)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_strip_cmyk_jpeg(self):
 | 
					    def test_strip_cmyk_jpeg(self) -> None:
 | 
				
			||||||
        infile = "Tests/images/tiff_strip_cmyk_jpeg.tif"
 | 
					        infile = "Tests/images/tiff_strip_cmyk_jpeg.tif"
 | 
				
			||||||
        with Image.open(infile) as im:
 | 
					        with Image.open(infile) as im:
 | 
				
			||||||
            assert_image_similar_tofile(im, "Tests/images/pil_sample_cmyk.jpg", 0.5)
 | 
					            assert_image_similar_tofile(im, "Tests/images/pil_sample_cmyk.jpg", 0.5)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_strip_cmyk_16l_jpeg(self):
 | 
					    def test_strip_cmyk_16l_jpeg(self) -> None:
 | 
				
			||||||
        infile = "Tests/images/tiff_strip_cmyk_16l_jpeg.tif"
 | 
					        infile = "Tests/images/tiff_strip_cmyk_16l_jpeg.tif"
 | 
				
			||||||
        with Image.open(infile) as im:
 | 
					        with Image.open(infile) as im:
 | 
				
			||||||
            assert_image_similar_tofile(im, "Tests/images/pil_sample_cmyk.jpg", 0.5)
 | 
					            assert_image_similar_tofile(im, "Tests/images/pil_sample_cmyk.jpg", 0.5)
 | 
				
			||||||
| 
						 | 
					@ -895,7 +896,7 @@ class TestFileLibTiff(LibTiffTestCase):
 | 
				
			||||||
    @mark_if_feature_version(
 | 
					    @mark_if_feature_version(
 | 
				
			||||||
        pytest.mark.valgrind_known_error, "libjpeg_turbo", "2.0", reason="Known Failing"
 | 
					        pytest.mark.valgrind_known_error, "libjpeg_turbo", "2.0", reason="Known Failing"
 | 
				
			||||||
    )
 | 
					    )
 | 
				
			||||||
    def test_strip_ycbcr_jpeg_2x2_sampling(self):
 | 
					    def test_strip_ycbcr_jpeg_2x2_sampling(self) -> None:
 | 
				
			||||||
        infile = "Tests/images/tiff_strip_ycbcr_jpeg_2x2_sampling.tif"
 | 
					        infile = "Tests/images/tiff_strip_ycbcr_jpeg_2x2_sampling.tif"
 | 
				
			||||||
        with Image.open(infile) as im:
 | 
					        with Image.open(infile) as im:
 | 
				
			||||||
            assert_image_similar_tofile(im, "Tests/images/flower.jpg", 1.2)
 | 
					            assert_image_similar_tofile(im, "Tests/images/flower.jpg", 1.2)
 | 
				
			||||||
| 
						 | 
					@ -903,12 +904,12 @@ class TestFileLibTiff(LibTiffTestCase):
 | 
				
			||||||
    @mark_if_feature_version(
 | 
					    @mark_if_feature_version(
 | 
				
			||||||
        pytest.mark.valgrind_known_error, "libjpeg_turbo", "2.0", reason="Known Failing"
 | 
					        pytest.mark.valgrind_known_error, "libjpeg_turbo", "2.0", reason="Known Failing"
 | 
				
			||||||
    )
 | 
					    )
 | 
				
			||||||
    def test_strip_ycbcr_jpeg_1x1_sampling(self):
 | 
					    def test_strip_ycbcr_jpeg_1x1_sampling(self) -> None:
 | 
				
			||||||
        infile = "Tests/images/tiff_strip_ycbcr_jpeg_1x1_sampling.tif"
 | 
					        infile = "Tests/images/tiff_strip_ycbcr_jpeg_1x1_sampling.tif"
 | 
				
			||||||
        with Image.open(infile) as im:
 | 
					        with Image.open(infile) as im:
 | 
				
			||||||
            assert_image_similar_tofile(im, "Tests/images/flower2.jpg", 0.01)
 | 
					            assert_image_similar_tofile(im, "Tests/images/flower2.jpg", 0.01)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_tiled_cmyk_jpeg(self):
 | 
					    def test_tiled_cmyk_jpeg(self) -> None:
 | 
				
			||||||
        infile = "Tests/images/tiff_tiled_cmyk_jpeg.tif"
 | 
					        infile = "Tests/images/tiff_tiled_cmyk_jpeg.tif"
 | 
				
			||||||
        with Image.open(infile) as im:
 | 
					        with Image.open(infile) as im:
 | 
				
			||||||
            assert_image_similar_tofile(im, "Tests/images/pil_sample_cmyk.jpg", 0.5)
 | 
					            assert_image_similar_tofile(im, "Tests/images/pil_sample_cmyk.jpg", 0.5)
 | 
				
			||||||
| 
						 | 
					@ -916,7 +917,7 @@ class TestFileLibTiff(LibTiffTestCase):
 | 
				
			||||||
    @mark_if_feature_version(
 | 
					    @mark_if_feature_version(
 | 
				
			||||||
        pytest.mark.valgrind_known_error, "libjpeg_turbo", "2.0", reason="Known Failing"
 | 
					        pytest.mark.valgrind_known_error, "libjpeg_turbo", "2.0", reason="Known Failing"
 | 
				
			||||||
    )
 | 
					    )
 | 
				
			||||||
    def test_tiled_ycbcr_jpeg_1x1_sampling(self):
 | 
					    def test_tiled_ycbcr_jpeg_1x1_sampling(self) -> None:
 | 
				
			||||||
        infile = "Tests/images/tiff_tiled_ycbcr_jpeg_1x1_sampling.tif"
 | 
					        infile = "Tests/images/tiff_tiled_ycbcr_jpeg_1x1_sampling.tif"
 | 
				
			||||||
        with Image.open(infile) as im:
 | 
					        with Image.open(infile) as im:
 | 
				
			||||||
            assert_image_similar_tofile(im, "Tests/images/flower2.jpg", 0.01)
 | 
					            assert_image_similar_tofile(im, "Tests/images/flower2.jpg", 0.01)
 | 
				
			||||||
| 
						 | 
					@ -924,45 +925,45 @@ class TestFileLibTiff(LibTiffTestCase):
 | 
				
			||||||
    @mark_if_feature_version(
 | 
					    @mark_if_feature_version(
 | 
				
			||||||
        pytest.mark.valgrind_known_error, "libjpeg_turbo", "2.0", reason="Known Failing"
 | 
					        pytest.mark.valgrind_known_error, "libjpeg_turbo", "2.0", reason="Known Failing"
 | 
				
			||||||
    )
 | 
					    )
 | 
				
			||||||
    def test_tiled_ycbcr_jpeg_2x2_sampling(self):
 | 
					    def test_tiled_ycbcr_jpeg_2x2_sampling(self) -> None:
 | 
				
			||||||
        infile = "Tests/images/tiff_tiled_ycbcr_jpeg_2x2_sampling.tif"
 | 
					        infile = "Tests/images/tiff_tiled_ycbcr_jpeg_2x2_sampling.tif"
 | 
				
			||||||
        with Image.open(infile) as im:
 | 
					        with Image.open(infile) as im:
 | 
				
			||||||
            assert_image_similar_tofile(im, "Tests/images/flower.jpg", 1.5)
 | 
					            assert_image_similar_tofile(im, "Tests/images/flower.jpg", 1.5)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_strip_planar_rgb(self):
 | 
					    def test_strip_planar_rgb(self) -> None:
 | 
				
			||||||
        # gdal_translate -co TILED=no -co INTERLEAVE=BAND -co COMPRESS=LZW \
 | 
					        # gdal_translate -co TILED=no -co INTERLEAVE=BAND -co COMPRESS=LZW \
 | 
				
			||||||
        # tiff_strip_raw.tif tiff_strip_planar_lzw.tiff
 | 
					        # tiff_strip_raw.tif tiff_strip_planar_lzw.tiff
 | 
				
			||||||
        infile = "Tests/images/tiff_strip_planar_lzw.tiff"
 | 
					        infile = "Tests/images/tiff_strip_planar_lzw.tiff"
 | 
				
			||||||
        with Image.open(infile) as im:
 | 
					        with Image.open(infile) as im:
 | 
				
			||||||
            assert_image_equal_tofile(im, "Tests/images/tiff_adobe_deflate.png")
 | 
					            assert_image_equal_tofile(im, "Tests/images/tiff_adobe_deflate.png")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_tiled_planar_rgb(self):
 | 
					    def test_tiled_planar_rgb(self) -> None:
 | 
				
			||||||
        # gdal_translate -co TILED=yes -co INTERLEAVE=BAND -co COMPRESS=LZW \
 | 
					        # gdal_translate -co TILED=yes -co INTERLEAVE=BAND -co COMPRESS=LZW \
 | 
				
			||||||
        # tiff_tiled_raw.tif tiff_tiled_planar_lzw.tiff
 | 
					        # tiff_tiled_raw.tif tiff_tiled_planar_lzw.tiff
 | 
				
			||||||
        infile = "Tests/images/tiff_tiled_planar_lzw.tiff"
 | 
					        infile = "Tests/images/tiff_tiled_planar_lzw.tiff"
 | 
				
			||||||
        with Image.open(infile) as im:
 | 
					        with Image.open(infile) as im:
 | 
				
			||||||
            assert_image_equal_tofile(im, "Tests/images/tiff_adobe_deflate.png")
 | 
					            assert_image_equal_tofile(im, "Tests/images/tiff_adobe_deflate.png")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_tiled_planar_16bit_RGB(self):
 | 
					    def test_tiled_planar_16bit_RGB(self) -> None:
 | 
				
			||||||
        # gdal_translate -co TILED=yes -co INTERLEAVE=BAND -co COMPRESS=LZW \
 | 
					        # gdal_translate -co TILED=yes -co INTERLEAVE=BAND -co COMPRESS=LZW \
 | 
				
			||||||
        # tiff_16bit_RGB.tiff tiff_tiled_planar_16bit_RGB.tiff
 | 
					        # tiff_16bit_RGB.tiff tiff_tiled_planar_16bit_RGB.tiff
 | 
				
			||||||
        with Image.open("Tests/images/tiff_tiled_planar_16bit_RGB.tiff") as im:
 | 
					        with Image.open("Tests/images/tiff_tiled_planar_16bit_RGB.tiff") as im:
 | 
				
			||||||
            assert_image_equal_tofile(im, "Tests/images/tiff_16bit_RGB_target.png")
 | 
					            assert_image_equal_tofile(im, "Tests/images/tiff_16bit_RGB_target.png")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_strip_planar_16bit_RGB(self):
 | 
					    def test_strip_planar_16bit_RGB(self) -> None:
 | 
				
			||||||
        # gdal_translate -co TILED=no -co INTERLEAVE=BAND -co COMPRESS=LZW \
 | 
					        # gdal_translate -co TILED=no -co INTERLEAVE=BAND -co COMPRESS=LZW \
 | 
				
			||||||
        # tiff_16bit_RGB.tiff tiff_strip_planar_16bit_RGB.tiff
 | 
					        # tiff_16bit_RGB.tiff tiff_strip_planar_16bit_RGB.tiff
 | 
				
			||||||
        with Image.open("Tests/images/tiff_strip_planar_16bit_RGB.tiff") as im:
 | 
					        with Image.open("Tests/images/tiff_strip_planar_16bit_RGB.tiff") as im:
 | 
				
			||||||
            assert_image_equal_tofile(im, "Tests/images/tiff_16bit_RGB_target.png")
 | 
					            assert_image_equal_tofile(im, "Tests/images/tiff_16bit_RGB_target.png")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_tiled_planar_16bit_RGBa(self):
 | 
					    def test_tiled_planar_16bit_RGBa(self) -> None:
 | 
				
			||||||
        # gdal_translate -co TILED=yes \
 | 
					        # gdal_translate -co TILED=yes \
 | 
				
			||||||
        # -co INTERLEAVE=BAND -co COMPRESS=LZW -co ALPHA=PREMULTIPLIED \
 | 
					        # -co INTERLEAVE=BAND -co COMPRESS=LZW -co ALPHA=PREMULTIPLIED \
 | 
				
			||||||
        # tiff_16bit_RGBa.tiff tiff_tiled_planar_16bit_RGBa.tiff
 | 
					        # tiff_16bit_RGBa.tiff tiff_tiled_planar_16bit_RGBa.tiff
 | 
				
			||||||
        with Image.open("Tests/images/tiff_tiled_planar_16bit_RGBa.tiff") as im:
 | 
					        with Image.open("Tests/images/tiff_tiled_planar_16bit_RGBa.tiff") as im:
 | 
				
			||||||
            assert_image_equal_tofile(im, "Tests/images/tiff_16bit_RGBa_target.png")
 | 
					            assert_image_equal_tofile(im, "Tests/images/tiff_16bit_RGBa_target.png")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_strip_planar_16bit_RGBa(self):
 | 
					    def test_strip_planar_16bit_RGBa(self) -> None:
 | 
				
			||||||
        # gdal_translate -co TILED=no \
 | 
					        # gdal_translate -co TILED=no \
 | 
				
			||||||
        # -co INTERLEAVE=BAND -co COMPRESS=LZW -co ALPHA=PREMULTIPLIED \
 | 
					        # -co INTERLEAVE=BAND -co COMPRESS=LZW -co ALPHA=PREMULTIPLIED \
 | 
				
			||||||
        # tiff_16bit_RGBa.tiff tiff_strip_planar_16bit_RGBa.tiff
 | 
					        # tiff_16bit_RGBa.tiff tiff_strip_planar_16bit_RGBa.tiff
 | 
				
			||||||
| 
						 | 
					@ -970,7 +971,7 @@ class TestFileLibTiff(LibTiffTestCase):
 | 
				
			||||||
            assert_image_equal_tofile(im, "Tests/images/tiff_16bit_RGBa_target.png")
 | 
					            assert_image_equal_tofile(im, "Tests/images/tiff_16bit_RGBa_target.png")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    @pytest.mark.parametrize("compression", (None, "jpeg"))
 | 
					    @pytest.mark.parametrize("compression", (None, "jpeg"))
 | 
				
			||||||
    def test_block_tile_tags(self, compression, tmp_path):
 | 
					    def test_block_tile_tags(self, compression, tmp_path: Path) -> None:
 | 
				
			||||||
        im = hopper()
 | 
					        im = hopper()
 | 
				
			||||||
        out = str(tmp_path / "temp.tif")
 | 
					        out = str(tmp_path / "temp.tif")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -986,11 +987,11 @@ class TestFileLibTiff(LibTiffTestCase):
 | 
				
			||||||
            for tag in tags:
 | 
					            for tag in tags:
 | 
				
			||||||
                assert tag not in reloaded.getexif()
 | 
					                assert tag not in reloaded.getexif()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_old_style_jpeg(self):
 | 
					    def test_old_style_jpeg(self) -> None:
 | 
				
			||||||
        with Image.open("Tests/images/old-style-jpeg-compression.tif") as im:
 | 
					        with Image.open("Tests/images/old-style-jpeg-compression.tif") as im:
 | 
				
			||||||
            assert_image_equal_tofile(im, "Tests/images/old-style-jpeg-compression.png")
 | 
					            assert_image_equal_tofile(im, "Tests/images/old-style-jpeg-compression.png")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_open_missing_samplesperpixel(self):
 | 
					    def test_open_missing_samplesperpixel(self) -> None:
 | 
				
			||||||
        with Image.open(
 | 
					        with Image.open(
 | 
				
			||||||
            "Tests/images/old-style-jpeg-compression-no-samplesperpixel.tif"
 | 
					            "Tests/images/old-style-jpeg-compression-no-samplesperpixel.tif"
 | 
				
			||||||
        ) as im:
 | 
					        ) as im:
 | 
				
			||||||
| 
						 | 
					@ -1019,21 +1020,21 @@ class TestFileLibTiff(LibTiffTestCase):
 | 
				
			||||||
            ),
 | 
					            ),
 | 
				
			||||||
        ],
 | 
					        ],
 | 
				
			||||||
    )
 | 
					    )
 | 
				
			||||||
    def test_wrong_bits_per_sample(self, file_name, mode, size, tile):
 | 
					    def test_wrong_bits_per_sample(self, file_name, mode, size, tile) -> None:
 | 
				
			||||||
        with Image.open("Tests/images/" + file_name) as im:
 | 
					        with Image.open("Tests/images/" + file_name) as im:
 | 
				
			||||||
            assert im.mode == mode
 | 
					            assert im.mode == mode
 | 
				
			||||||
            assert im.size == size
 | 
					            assert im.size == size
 | 
				
			||||||
            assert im.tile == tile
 | 
					            assert im.tile == tile
 | 
				
			||||||
            im.load()
 | 
					            im.load()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_no_rows_per_strip(self):
 | 
					    def test_no_rows_per_strip(self) -> None:
 | 
				
			||||||
        # This image does not have a RowsPerStrip TIFF tag
 | 
					        # This image does not have a RowsPerStrip TIFF tag
 | 
				
			||||||
        infile = "Tests/images/no_rows_per_strip.tif"
 | 
					        infile = "Tests/images/no_rows_per_strip.tif"
 | 
				
			||||||
        with Image.open(infile) as im:
 | 
					        with Image.open(infile) as im:
 | 
				
			||||||
            im.load()
 | 
					            im.load()
 | 
				
			||||||
        assert im.size == (950, 975)
 | 
					        assert im.size == (950, 975)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_orientation(self):
 | 
					    def test_orientation(self) -> None:
 | 
				
			||||||
        with Image.open("Tests/images/g4_orientation_1.tif") as base_im:
 | 
					        with Image.open("Tests/images/g4_orientation_1.tif") as base_im:
 | 
				
			||||||
            for i in range(2, 9):
 | 
					            for i in range(2, 9):
 | 
				
			||||||
                with Image.open("Tests/images/g4_orientation_" + str(i) + ".tif") as im:
 | 
					                with Image.open("Tests/images/g4_orientation_" + str(i) + ".tif") as im:
 | 
				
			||||||
| 
						 | 
					@ -1044,7 +1045,7 @@ class TestFileLibTiff(LibTiffTestCase):
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                    assert_image_similar(base_im, im, 0.7)
 | 
					                    assert_image_similar(base_im, im, 0.7)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_exif_transpose(self):
 | 
					    def test_exif_transpose(self) -> None:
 | 
				
			||||||
        with Image.open("Tests/images/g4_orientation_1.tif") as base_im:
 | 
					        with Image.open("Tests/images/g4_orientation_1.tif") as base_im:
 | 
				
			||||||
            for i in range(2, 9):
 | 
					            for i in range(2, 9):
 | 
				
			||||||
                with Image.open("Tests/images/g4_orientation_" + str(i) + ".tif") as im:
 | 
					                with Image.open("Tests/images/g4_orientation_" + str(i) + ".tif") as im:
 | 
				
			||||||
| 
						 | 
					@ -1053,7 +1054,7 @@ class TestFileLibTiff(LibTiffTestCase):
 | 
				
			||||||
                    assert_image_similar(base_im, im, 0.7)
 | 
					                    assert_image_similar(base_im, im, 0.7)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    @pytest.mark.valgrind_known_error(reason="Backtrace in Python Core")
 | 
					    @pytest.mark.valgrind_known_error(reason="Backtrace in Python Core")
 | 
				
			||||||
    def test_sampleformat_not_corrupted(self):
 | 
					    def test_sampleformat_not_corrupted(self) -> None:
 | 
				
			||||||
        # Assert that a TIFF image with SampleFormat=UINT tag is not corrupted
 | 
					        # Assert that a TIFF image with SampleFormat=UINT tag is not corrupted
 | 
				
			||||||
        # when saving to a new file.
 | 
					        # when saving to a new file.
 | 
				
			||||||
        # Pillow 6.0 fails with "OSError: cannot identify image file".
 | 
					        # Pillow 6.0 fails with "OSError: cannot identify image file".
 | 
				
			||||||
| 
						 | 
					@ -1074,7 +1075,7 @@ class TestFileLibTiff(LibTiffTestCase):
 | 
				
			||||||
        with Image.open(out) as im:
 | 
					        with Image.open(out) as im:
 | 
				
			||||||
            im.load()
 | 
					            im.load()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_realloc_overflow(self):
 | 
					    def test_realloc_overflow(self) -> None:
 | 
				
			||||||
        TiffImagePlugin.READ_LIBTIFF = True
 | 
					        TiffImagePlugin.READ_LIBTIFF = True
 | 
				
			||||||
        with Image.open("Tests/images/tiff_overflow_rows_per_strip.tif") as im:
 | 
					        with Image.open("Tests/images/tiff_overflow_rows_per_strip.tif") as im:
 | 
				
			||||||
            with pytest.raises(OSError) as e:
 | 
					            with pytest.raises(OSError) as e:
 | 
				
			||||||
| 
						 | 
					@ -1085,7 +1086,7 @@ class TestFileLibTiff(LibTiffTestCase):
 | 
				
			||||||
        TiffImagePlugin.READ_LIBTIFF = False
 | 
					        TiffImagePlugin.READ_LIBTIFF = False
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    @pytest.mark.parametrize("compression", ("tiff_adobe_deflate", "jpeg"))
 | 
					    @pytest.mark.parametrize("compression", ("tiff_adobe_deflate", "jpeg"))
 | 
				
			||||||
    def test_save_multistrip(self, compression, tmp_path):
 | 
					    def test_save_multistrip(self, compression, tmp_path: Path) -> None:
 | 
				
			||||||
        im = hopper("RGB").resize((256, 256))
 | 
					        im = hopper("RGB").resize((256, 256))
 | 
				
			||||||
        out = str(tmp_path / "temp.tif")
 | 
					        out = str(tmp_path / "temp.tif")
 | 
				
			||||||
        im.save(out, compression=compression)
 | 
					        im.save(out, compression=compression)
 | 
				
			||||||
| 
						 | 
					@ -1095,7 +1096,7 @@ class TestFileLibTiff(LibTiffTestCase):
 | 
				
			||||||
            assert len(im.tag_v2[STRIPOFFSETS]) > 1
 | 
					            assert len(im.tag_v2[STRIPOFFSETS]) > 1
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    @pytest.mark.parametrize("argument", (True, False))
 | 
					    @pytest.mark.parametrize("argument", (True, False))
 | 
				
			||||||
    def test_save_single_strip(self, argument, tmp_path):
 | 
					    def test_save_single_strip(self, argument, tmp_path: Path) -> None:
 | 
				
			||||||
        im = hopper("RGB").resize((256, 256))
 | 
					        im = hopper("RGB").resize((256, 256))
 | 
				
			||||||
        out = str(tmp_path / "temp.tif")
 | 
					        out = str(tmp_path / "temp.tif")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1113,13 +1114,13 @@ class TestFileLibTiff(LibTiffTestCase):
 | 
				
			||||||
            TiffImagePlugin.STRIP_SIZE = 65536
 | 
					            TiffImagePlugin.STRIP_SIZE = 65536
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    @pytest.mark.parametrize("compression", ("tiff_adobe_deflate", None))
 | 
					    @pytest.mark.parametrize("compression", ("tiff_adobe_deflate", None))
 | 
				
			||||||
    def test_save_zero(self, compression, tmp_path):
 | 
					    def test_save_zero(self, compression, tmp_path: Path) -> None:
 | 
				
			||||||
        im = Image.new("RGB", (0, 0))
 | 
					        im = Image.new("RGB", (0, 0))
 | 
				
			||||||
        out = str(tmp_path / "temp.tif")
 | 
					        out = str(tmp_path / "temp.tif")
 | 
				
			||||||
        with pytest.raises(SystemError):
 | 
					        with pytest.raises(SystemError):
 | 
				
			||||||
            im.save(out, compression=compression)
 | 
					            im.save(out, compression=compression)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_save_many_compressed(self, tmp_path):
 | 
					    def test_save_many_compressed(self, tmp_path: Path) -> None:
 | 
				
			||||||
        im = hopper()
 | 
					        im = hopper()
 | 
				
			||||||
        out = str(tmp_path / "temp.tif")
 | 
					        out = str(tmp_path / "temp.tif")
 | 
				
			||||||
        for _ in range(10000):
 | 
					        for _ in range(10000):
 | 
				
			||||||
| 
						 | 
					@ -1133,7 +1134,7 @@ class TestFileLibTiff(LibTiffTestCase):
 | 
				
			||||||
            ("Tests/images/child_ifd_jpeg.tiff", (20,)),
 | 
					            ("Tests/images/child_ifd_jpeg.tiff", (20,)),
 | 
				
			||||||
        ),
 | 
					        ),
 | 
				
			||||||
    )
 | 
					    )
 | 
				
			||||||
    def test_get_child_images(self, path, sizes):
 | 
					    def test_get_child_images(self, path, sizes) -> None:
 | 
				
			||||||
        with Image.open(path) as im:
 | 
					        with Image.open(path) as im:
 | 
				
			||||||
            ims = im.get_child_images()
 | 
					            ims = im.get_child_images()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,6 +1,7 @@
 | 
				
			||||||
from __future__ import annotations
 | 
					from __future__ import annotations
 | 
				
			||||||
 | 
					
 | 
				
			||||||
from io import BytesIO
 | 
					from io import BytesIO
 | 
				
			||||||
 | 
					from pathlib import Path
 | 
				
			||||||
 | 
					
 | 
				
			||||||
from PIL import Image
 | 
					from PIL import Image
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -17,7 +18,7 @@ class TestFileLibTiffSmall(LibTiffTestCase):
 | 
				
			||||||
    file just before reading in libtiff. These tests remain
 | 
					    file just before reading in libtiff. These tests remain
 | 
				
			||||||
    to ensure that it stays fixed."""
 | 
					    to ensure that it stays fixed."""
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_g4_hopper_file(self, tmp_path):
 | 
					    def test_g4_hopper_file(self, tmp_path: Path) -> None:
 | 
				
			||||||
        """Testing the open file load path"""
 | 
					        """Testing the open file load path"""
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        test_file = "Tests/images/hopper_g4.tif"
 | 
					        test_file = "Tests/images/hopper_g4.tif"
 | 
				
			||||||
| 
						 | 
					@ -26,7 +27,7 @@ class TestFileLibTiffSmall(LibTiffTestCase):
 | 
				
			||||||
                assert im.size == (128, 128)
 | 
					                assert im.size == (128, 128)
 | 
				
			||||||
                self._assert_noerr(tmp_path, im)
 | 
					                self._assert_noerr(tmp_path, im)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_g4_hopper_bytesio(self, tmp_path):
 | 
					    def test_g4_hopper_bytesio(self, tmp_path: Path) -> None:
 | 
				
			||||||
        """Testing the bytesio loading code path"""
 | 
					        """Testing the bytesio loading code path"""
 | 
				
			||||||
        test_file = "Tests/images/hopper_g4.tif"
 | 
					        test_file = "Tests/images/hopper_g4.tif"
 | 
				
			||||||
        s = BytesIO()
 | 
					        s = BytesIO()
 | 
				
			||||||
| 
						 | 
					@ -37,7 +38,7 @@ class TestFileLibTiffSmall(LibTiffTestCase):
 | 
				
			||||||
            assert im.size == (128, 128)
 | 
					            assert im.size == (128, 128)
 | 
				
			||||||
            self._assert_noerr(tmp_path, im)
 | 
					            self._assert_noerr(tmp_path, im)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_g4_hopper(self, tmp_path):
 | 
					    def test_g4_hopper(self, tmp_path: Path) -> None:
 | 
				
			||||||
        """The 128x128 lena image failed for some reason."""
 | 
					        """The 128x128 lena image failed for some reason."""
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        test_file = "Tests/images/hopper_g4.tif"
 | 
					        test_file = "Tests/images/hopper_g4.tif"
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -13,7 +13,7 @@ pytestmark = skip_unless_feature("libtiff")
 | 
				
			||||||
TEST_FILE = "Tests/images/hopper.mic"
 | 
					TEST_FILE = "Tests/images/hopper.mic"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_sanity():
 | 
					def test_sanity() -> None:
 | 
				
			||||||
    with Image.open(TEST_FILE) as im:
 | 
					    with Image.open(TEST_FILE) as im:
 | 
				
			||||||
        im.load()
 | 
					        im.load()
 | 
				
			||||||
        assert im.mode == "RGBA"
 | 
					        assert im.mode == "RGBA"
 | 
				
			||||||
| 
						 | 
					@ -28,22 +28,22 @@ def test_sanity():
 | 
				
			||||||
        assert_image_similar(im, im2, 10)
 | 
					        assert_image_similar(im, im2, 10)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_n_frames():
 | 
					def test_n_frames() -> None:
 | 
				
			||||||
    with Image.open(TEST_FILE) as im:
 | 
					    with Image.open(TEST_FILE) as im:
 | 
				
			||||||
        assert im.n_frames == 1
 | 
					        assert im.n_frames == 1
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_is_animated():
 | 
					def test_is_animated() -> None:
 | 
				
			||||||
    with Image.open(TEST_FILE) as im:
 | 
					    with Image.open(TEST_FILE) as im:
 | 
				
			||||||
        assert not im.is_animated
 | 
					        assert not im.is_animated
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_tell():
 | 
					def test_tell() -> None:
 | 
				
			||||||
    with Image.open(TEST_FILE) as im:
 | 
					    with Image.open(TEST_FILE) as im:
 | 
				
			||||||
        assert im.tell() == 0
 | 
					        assert im.tell() == 0
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_seek():
 | 
					def test_seek() -> None:
 | 
				
			||||||
    with Image.open(TEST_FILE) as im:
 | 
					    with Image.open(TEST_FILE) as im:
 | 
				
			||||||
        im.seek(0)
 | 
					        im.seek(0)
 | 
				
			||||||
        assert im.tell() == 0
 | 
					        assert im.tell() == 0
 | 
				
			||||||
| 
						 | 
					@ -53,7 +53,7 @@ def test_seek():
 | 
				
			||||||
        assert im.tell() == 0
 | 
					        assert im.tell() == 0
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_close():
 | 
					def test_close() -> None:
 | 
				
			||||||
    with Image.open(TEST_FILE) as im:
 | 
					    with Image.open(TEST_FILE) as im:
 | 
				
			||||||
        pass
 | 
					        pass
 | 
				
			||||||
    assert im.ole.fp.closed
 | 
					    assert im.ole.fp.closed
 | 
				
			||||||
| 
						 | 
					@ -63,7 +63,7 @@ def test_close():
 | 
				
			||||||
    assert im.ole.fp.closed
 | 
					    assert im.ole.fp.closed
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_invalid_file():
 | 
					def test_invalid_file() -> None:
 | 
				
			||||||
    # Test an invalid OLE file
 | 
					    # Test an invalid OLE file
 | 
				
			||||||
    invalid_file = "Tests/images/flower.jpg"
 | 
					    invalid_file = "Tests/images/flower.jpg"
 | 
				
			||||||
    with pytest.raises(SyntaxError):
 | 
					    with pytest.raises(SyntaxError):
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -30,7 +30,7 @@ def roundtrip(im, **options):
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@pytest.mark.parametrize("test_file", test_files)
 | 
					@pytest.mark.parametrize("test_file", test_files)
 | 
				
			||||||
def test_sanity(test_file):
 | 
					def test_sanity(test_file) -> None:
 | 
				
			||||||
    with Image.open(test_file) as im:
 | 
					    with Image.open(test_file) as im:
 | 
				
			||||||
        im.load()
 | 
					        im.load()
 | 
				
			||||||
        assert im.mode == "RGB"
 | 
					        assert im.mode == "RGB"
 | 
				
			||||||
| 
						 | 
					@ -39,8 +39,8 @@ def test_sanity(test_file):
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@pytest.mark.skipif(is_pypy(), reason="Requires CPython")
 | 
					@pytest.mark.skipif(is_pypy(), reason="Requires CPython")
 | 
				
			||||||
def test_unclosed_file():
 | 
					def test_unclosed_file() -> None:
 | 
				
			||||||
    def open():
 | 
					    def open() -> None:
 | 
				
			||||||
        im = Image.open(test_files[0])
 | 
					        im = Image.open(test_files[0])
 | 
				
			||||||
        im.load()
 | 
					        im.load()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -48,14 +48,14 @@ def test_unclosed_file():
 | 
				
			||||||
        open()
 | 
					        open()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_closed_file():
 | 
					def test_closed_file() -> None:
 | 
				
			||||||
    with warnings.catch_warnings():
 | 
					    with warnings.catch_warnings():
 | 
				
			||||||
        im = Image.open(test_files[0])
 | 
					        im = Image.open(test_files[0])
 | 
				
			||||||
        im.load()
 | 
					        im.load()
 | 
				
			||||||
        im.close()
 | 
					        im.close()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_seek_after_close():
 | 
					def test_seek_after_close() -> None:
 | 
				
			||||||
    im = Image.open(test_files[0])
 | 
					    im = Image.open(test_files[0])
 | 
				
			||||||
    im.close()
 | 
					    im.close()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -63,14 +63,14 @@ def test_seek_after_close():
 | 
				
			||||||
        im.seek(1)
 | 
					        im.seek(1)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_context_manager():
 | 
					def test_context_manager() -> None:
 | 
				
			||||||
    with warnings.catch_warnings():
 | 
					    with warnings.catch_warnings():
 | 
				
			||||||
        with Image.open(test_files[0]) as im:
 | 
					        with Image.open(test_files[0]) as im:
 | 
				
			||||||
            im.load()
 | 
					            im.load()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@pytest.mark.parametrize("test_file", test_files)
 | 
					@pytest.mark.parametrize("test_file", test_files)
 | 
				
			||||||
def test_app(test_file):
 | 
					def test_app(test_file) -> None:
 | 
				
			||||||
    # Test APP/COM reader (@PIL135)
 | 
					    # Test APP/COM reader (@PIL135)
 | 
				
			||||||
    with Image.open(test_file) as im:
 | 
					    with Image.open(test_file) as im:
 | 
				
			||||||
        assert im.applist[0][0] == "APP1"
 | 
					        assert im.applist[0][0] == "APP1"
 | 
				
			||||||
| 
						 | 
					@ -82,7 +82,7 @@ def test_app(test_file):
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@pytest.mark.parametrize("test_file", test_files)
 | 
					@pytest.mark.parametrize("test_file", test_files)
 | 
				
			||||||
def test_exif(test_file):
 | 
					def test_exif(test_file) -> None:
 | 
				
			||||||
    with Image.open(test_file) as im_original:
 | 
					    with Image.open(test_file) as im_original:
 | 
				
			||||||
        im_reloaded = roundtrip(im_original, save_all=True, exif=im_original.getexif())
 | 
					        im_reloaded = roundtrip(im_original, save_all=True, exif=im_original.getexif())
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -93,7 +93,7 @@ def test_exif(test_file):
 | 
				
			||||||
        assert info[34665] == 188
 | 
					        assert info[34665] == 188
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_frame_size():
 | 
					def test_frame_size() -> None:
 | 
				
			||||||
    # This image has been hexedited to contain a different size
 | 
					    # This image has been hexedited to contain a different size
 | 
				
			||||||
    # in the EXIF data of the second frame
 | 
					    # in the EXIF data of the second frame
 | 
				
			||||||
    with Image.open("Tests/images/sugarshack_frame_size.mpo") as im:
 | 
					    with Image.open("Tests/images/sugarshack_frame_size.mpo") as im:
 | 
				
			||||||
| 
						 | 
					@ -106,7 +106,7 @@ def test_frame_size():
 | 
				
			||||||
        assert im.size == (640, 480)
 | 
					        assert im.size == (640, 480)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_ignore_frame_size():
 | 
					def test_ignore_frame_size() -> None:
 | 
				
			||||||
    # Ignore the different size of the second frame
 | 
					    # Ignore the different size of the second frame
 | 
				
			||||||
    # since this is not a "Large Thumbnail" image
 | 
					    # since this is not a "Large Thumbnail" image
 | 
				
			||||||
    with Image.open("Tests/images/ignore_frame_size.mpo") as im:
 | 
					    with Image.open("Tests/images/ignore_frame_size.mpo") as im:
 | 
				
			||||||
| 
						 | 
					@ -120,7 +120,7 @@ def test_ignore_frame_size():
 | 
				
			||||||
        assert im.size == (64, 64)
 | 
					        assert im.size == (64, 64)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_parallax():
 | 
					def test_parallax() -> None:
 | 
				
			||||||
    # Nintendo
 | 
					    # Nintendo
 | 
				
			||||||
    with Image.open("Tests/images/sugarshack.mpo") as im:
 | 
					    with Image.open("Tests/images/sugarshack.mpo") as im:
 | 
				
			||||||
        exif = im.getexif()
 | 
					        exif = im.getexif()
 | 
				
			||||||
| 
						 | 
					@ -133,7 +133,7 @@ def test_parallax():
 | 
				
			||||||
        assert exif.get_ifd(0x927C)[0xB211] == -3.125
 | 
					        assert exif.get_ifd(0x927C)[0xB211] == -3.125
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_reload_exif_after_seek():
 | 
					def test_reload_exif_after_seek() -> None:
 | 
				
			||||||
    with Image.open("Tests/images/sugarshack.mpo") as im:
 | 
					    with Image.open("Tests/images/sugarshack.mpo") as im:
 | 
				
			||||||
        exif = im.getexif()
 | 
					        exif = im.getexif()
 | 
				
			||||||
        del exif[296]
 | 
					        del exif[296]
 | 
				
			||||||
| 
						 | 
					@ -143,14 +143,14 @@ def test_reload_exif_after_seek():
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@pytest.mark.parametrize("test_file", test_files)
 | 
					@pytest.mark.parametrize("test_file", test_files)
 | 
				
			||||||
def test_mp(test_file):
 | 
					def test_mp(test_file) -> None:
 | 
				
			||||||
    with Image.open(test_file) as im:
 | 
					    with Image.open(test_file) as im:
 | 
				
			||||||
        mpinfo = im._getmp()
 | 
					        mpinfo = im._getmp()
 | 
				
			||||||
        assert mpinfo[45056] == b"0100"
 | 
					        assert mpinfo[45056] == b"0100"
 | 
				
			||||||
        assert mpinfo[45057] == 2
 | 
					        assert mpinfo[45057] == 2
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_mp_offset():
 | 
					def test_mp_offset() -> None:
 | 
				
			||||||
    # This image has been manually hexedited to have an IFD offset of 10
 | 
					    # This image has been manually hexedited to have an IFD offset of 10
 | 
				
			||||||
    # in APP2 data, in contrast to normal 8
 | 
					    # in APP2 data, in contrast to normal 8
 | 
				
			||||||
    with Image.open("Tests/images/sugarshack_ifd_offset.mpo") as im:
 | 
					    with Image.open("Tests/images/sugarshack_ifd_offset.mpo") as im:
 | 
				
			||||||
| 
						 | 
					@ -159,7 +159,7 @@ def test_mp_offset():
 | 
				
			||||||
        assert mpinfo[45057] == 2
 | 
					        assert mpinfo[45057] == 2
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_mp_no_data():
 | 
					def test_mp_no_data() -> None:
 | 
				
			||||||
    # This image has been manually hexedited to have the second frame
 | 
					    # This image has been manually hexedited to have the second frame
 | 
				
			||||||
    # beyond the end of the file
 | 
					    # beyond the end of the file
 | 
				
			||||||
    with Image.open("Tests/images/sugarshack_no_data.mpo") as im:
 | 
					    with Image.open("Tests/images/sugarshack_no_data.mpo") as im:
 | 
				
			||||||
| 
						 | 
					@ -168,7 +168,7 @@ def test_mp_no_data():
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@pytest.mark.parametrize("test_file", test_files)
 | 
					@pytest.mark.parametrize("test_file", test_files)
 | 
				
			||||||
def test_mp_attribute(test_file):
 | 
					def test_mp_attribute(test_file) -> None:
 | 
				
			||||||
    with Image.open(test_file) as im:
 | 
					    with Image.open(test_file) as im:
 | 
				
			||||||
        mpinfo = im._getmp()
 | 
					        mpinfo = im._getmp()
 | 
				
			||||||
    for frame_number, mpentry in enumerate(mpinfo[0xB002]):
 | 
					    for frame_number, mpentry in enumerate(mpinfo[0xB002]):
 | 
				
			||||||
| 
						 | 
					@ -185,7 +185,7 @@ def test_mp_attribute(test_file):
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@pytest.mark.parametrize("test_file", test_files)
 | 
					@pytest.mark.parametrize("test_file", test_files)
 | 
				
			||||||
def test_seek(test_file):
 | 
					def test_seek(test_file) -> None:
 | 
				
			||||||
    with Image.open(test_file) as im:
 | 
					    with Image.open(test_file) as im:
 | 
				
			||||||
        assert im.tell() == 0
 | 
					        assert im.tell() == 0
 | 
				
			||||||
        # prior to first image raises an error, both blatant and borderline
 | 
					        # prior to first image raises an error, both blatant and borderline
 | 
				
			||||||
| 
						 | 
					@ -209,13 +209,13 @@ def test_seek(test_file):
 | 
				
			||||||
        assert im.tell() == 0
 | 
					        assert im.tell() == 0
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_n_frames():
 | 
					def test_n_frames() -> None:
 | 
				
			||||||
    with Image.open("Tests/images/sugarshack.mpo") as im:
 | 
					    with Image.open("Tests/images/sugarshack.mpo") as im:
 | 
				
			||||||
        assert im.n_frames == 2
 | 
					        assert im.n_frames == 2
 | 
				
			||||||
        assert im.is_animated
 | 
					        assert im.is_animated
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_eoferror():
 | 
					def test_eoferror() -> None:
 | 
				
			||||||
    with Image.open("Tests/images/sugarshack.mpo") as im:
 | 
					    with Image.open("Tests/images/sugarshack.mpo") as im:
 | 
				
			||||||
        n_frames = im.n_frames
 | 
					        n_frames = im.n_frames
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -229,7 +229,7 @@ def test_eoferror():
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@pytest.mark.parametrize("test_file", test_files)
 | 
					@pytest.mark.parametrize("test_file", test_files)
 | 
				
			||||||
def test_image_grab(test_file):
 | 
					def test_image_grab(test_file) -> None:
 | 
				
			||||||
    with Image.open(test_file) as im:
 | 
					    with Image.open(test_file) as im:
 | 
				
			||||||
        assert im.tell() == 0
 | 
					        assert im.tell() == 0
 | 
				
			||||||
        im0 = im.tobytes()
 | 
					        im0 = im.tobytes()
 | 
				
			||||||
| 
						 | 
					@ -244,7 +244,7 @@ def test_image_grab(test_file):
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@pytest.mark.parametrize("test_file", test_files)
 | 
					@pytest.mark.parametrize("test_file", test_files)
 | 
				
			||||||
def test_save(test_file):
 | 
					def test_save(test_file) -> None:
 | 
				
			||||||
    with Image.open(test_file) as im:
 | 
					    with Image.open(test_file) as im:
 | 
				
			||||||
        assert im.tell() == 0
 | 
					        assert im.tell() == 0
 | 
				
			||||||
        jpg0 = roundtrip(im)
 | 
					        jpg0 = roundtrip(im)
 | 
				
			||||||
| 
						 | 
					@ -255,7 +255,7 @@ def test_save(test_file):
 | 
				
			||||||
        assert_image_similar(im, jpg1, 30)
 | 
					        assert_image_similar(im, jpg1, 30)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_save_all():
 | 
					def test_save_all() -> None:
 | 
				
			||||||
    for test_file in test_files:
 | 
					    for test_file in test_files:
 | 
				
			||||||
        with Image.open(test_file) as im:
 | 
					        with Image.open(test_file) as im:
 | 
				
			||||||
            im_reloaded = roundtrip(im, save_all=True)
 | 
					            im_reloaded = roundtrip(im, save_all=True)
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,6 +1,7 @@
 | 
				
			||||||
from __future__ import annotations
 | 
					from __future__ import annotations
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import os
 | 
					import os
 | 
				
			||||||
 | 
					from pathlib import Path
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import pytest
 | 
					import pytest
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -13,7 +14,7 @@ EXTRA_DIR = "Tests/images/picins"
 | 
				
			||||||
YA_EXTRA_DIR = "Tests/images/msp"
 | 
					YA_EXTRA_DIR = "Tests/images/msp"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_sanity(tmp_path):
 | 
					def test_sanity(tmp_path: Path) -> None:
 | 
				
			||||||
    test_file = str(tmp_path / "temp.msp")
 | 
					    test_file = str(tmp_path / "temp.msp")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    hopper("1").save(test_file)
 | 
					    hopper("1").save(test_file)
 | 
				
			||||||
| 
						 | 
					@ -25,14 +26,14 @@ def test_sanity(tmp_path):
 | 
				
			||||||
        assert im.format == "MSP"
 | 
					        assert im.format == "MSP"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_invalid_file():
 | 
					def test_invalid_file() -> None:
 | 
				
			||||||
    invalid_file = "Tests/images/flower.jpg"
 | 
					    invalid_file = "Tests/images/flower.jpg"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    with pytest.raises(SyntaxError):
 | 
					    with pytest.raises(SyntaxError):
 | 
				
			||||||
        MspImagePlugin.MspImageFile(invalid_file)
 | 
					        MspImagePlugin.MspImageFile(invalid_file)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_bad_checksum():
 | 
					def test_bad_checksum() -> None:
 | 
				
			||||||
    # Arrange
 | 
					    # Arrange
 | 
				
			||||||
    # This was created by forcing Pillow to save with checksum=0
 | 
					    # This was created by forcing Pillow to save with checksum=0
 | 
				
			||||||
    bad_checksum = "Tests/images/hopper_bad_checksum.msp"
 | 
					    bad_checksum = "Tests/images/hopper_bad_checksum.msp"
 | 
				
			||||||
| 
						 | 
					@ -42,7 +43,7 @@ def test_bad_checksum():
 | 
				
			||||||
        MspImagePlugin.MspImageFile(bad_checksum)
 | 
					        MspImagePlugin.MspImageFile(bad_checksum)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_open_windows_v1():
 | 
					def test_open_windows_v1() -> None:
 | 
				
			||||||
    # Arrange
 | 
					    # Arrange
 | 
				
			||||||
    # Act
 | 
					    # Act
 | 
				
			||||||
    with Image.open(TEST_FILE) as im:
 | 
					    with Image.open(TEST_FILE) as im:
 | 
				
			||||||
| 
						 | 
					@ -51,7 +52,7 @@ def test_open_windows_v1():
 | 
				
			||||||
        assert isinstance(im, MspImagePlugin.MspImageFile)
 | 
					        assert isinstance(im, MspImagePlugin.MspImageFile)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def _assert_file_image_equal(source_path, target_path):
 | 
					def _assert_file_image_equal(source_path, target_path) -> None:
 | 
				
			||||||
    with Image.open(source_path) as im:
 | 
					    with Image.open(source_path) as im:
 | 
				
			||||||
        assert_image_equal_tofile(im, target_path)
 | 
					        assert_image_equal_tofile(im, target_path)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -59,7 +60,7 @@ def _assert_file_image_equal(source_path, target_path):
 | 
				
			||||||
@pytest.mark.skipif(
 | 
					@pytest.mark.skipif(
 | 
				
			||||||
    not os.path.exists(EXTRA_DIR), reason="Extra image files not installed"
 | 
					    not os.path.exists(EXTRA_DIR), reason="Extra image files not installed"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
def test_open_windows_v2():
 | 
					def test_open_windows_v2() -> None:
 | 
				
			||||||
    files = (
 | 
					    files = (
 | 
				
			||||||
        os.path.join(EXTRA_DIR, f)
 | 
					        os.path.join(EXTRA_DIR, f)
 | 
				
			||||||
        for f in os.listdir(EXTRA_DIR)
 | 
					        for f in os.listdir(EXTRA_DIR)
 | 
				
			||||||
| 
						 | 
					@ -72,7 +73,7 @@ def test_open_windows_v2():
 | 
				
			||||||
@pytest.mark.skipif(
 | 
					@pytest.mark.skipif(
 | 
				
			||||||
    not os.path.exists(YA_EXTRA_DIR), reason="Even More Extra image files not installed"
 | 
					    not os.path.exists(YA_EXTRA_DIR), reason="Even More Extra image files not installed"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
def test_msp_v2():
 | 
					def test_msp_v2() -> None:
 | 
				
			||||||
    for f in os.listdir(YA_EXTRA_DIR):
 | 
					    for f in os.listdir(YA_EXTRA_DIR):
 | 
				
			||||||
        if ".MSP" not in f:
 | 
					        if ".MSP" not in f:
 | 
				
			||||||
            continue
 | 
					            continue
 | 
				
			||||||
| 
						 | 
					@ -80,7 +81,7 @@ def test_msp_v2():
 | 
				
			||||||
        _assert_file_image_equal(path, path.replace(".MSP", ".png"))
 | 
					        _assert_file_image_equal(path, path.replace(".MSP", ".png"))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_cannot_save_wrong_mode(tmp_path):
 | 
					def test_cannot_save_wrong_mode(tmp_path: Path) -> None:
 | 
				
			||||||
    # Arrange
 | 
					    # Arrange
 | 
				
			||||||
    im = hopper()
 | 
					    im = hopper()
 | 
				
			||||||
    filename = str(tmp_path / "temp.msp")
 | 
					    filename = str(tmp_path / "temp.msp")
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -2,6 +2,7 @@ from __future__ import annotations
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import os.path
 | 
					import os.path
 | 
				
			||||||
import subprocess
 | 
					import subprocess
 | 
				
			||||||
 | 
					from pathlib import Path
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import pytest
 | 
					import pytest
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -10,7 +11,7 @@ from PIL import Image
 | 
				
			||||||
from .helper import assert_image_equal, hopper, magick_command
 | 
					from .helper import assert_image_equal, hopper, magick_command
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def helper_save_as_palm(tmp_path, mode):
 | 
					def helper_save_as_palm(tmp_path: Path, mode) -> None:
 | 
				
			||||||
    # Arrange
 | 
					    # Arrange
 | 
				
			||||||
    im = hopper(mode)
 | 
					    im = hopper(mode)
 | 
				
			||||||
    outfile = str(tmp_path / ("temp_" + mode + ".palm"))
 | 
					    outfile = str(tmp_path / ("temp_" + mode + ".palm"))
 | 
				
			||||||
| 
						 | 
					@ -23,7 +24,7 @@ def helper_save_as_palm(tmp_path, mode):
 | 
				
			||||||
    assert os.path.getsize(outfile) > 0
 | 
					    assert os.path.getsize(outfile) > 0
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def open_with_magick(magick, tmp_path, f):
 | 
					def open_with_magick(magick, tmp_path: Path, f):
 | 
				
			||||||
    outfile = str(tmp_path / "temp.png")
 | 
					    outfile = str(tmp_path / "temp.png")
 | 
				
			||||||
    rc = subprocess.call(
 | 
					    rc = subprocess.call(
 | 
				
			||||||
        magick + [f, outfile], stdout=subprocess.DEVNULL, stderr=subprocess.STDOUT
 | 
					        magick + [f, outfile], stdout=subprocess.DEVNULL, stderr=subprocess.STDOUT
 | 
				
			||||||
| 
						 | 
					@ -32,7 +33,7 @@ def open_with_magick(magick, tmp_path, f):
 | 
				
			||||||
    return Image.open(outfile)
 | 
					    return Image.open(outfile)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def roundtrip(tmp_path, mode):
 | 
					def roundtrip(tmp_path: Path, mode) -> None:
 | 
				
			||||||
    magick = magick_command()
 | 
					    magick = magick_command()
 | 
				
			||||||
    if not magick:
 | 
					    if not magick:
 | 
				
			||||||
        return
 | 
					        return
 | 
				
			||||||
| 
						 | 
					@ -45,7 +46,7 @@ def roundtrip(tmp_path, mode):
 | 
				
			||||||
    assert_image_equal(converted, im)
 | 
					    assert_image_equal(converted, im)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_monochrome(tmp_path):
 | 
					def test_monochrome(tmp_path: Path) -> None:
 | 
				
			||||||
    # Arrange
 | 
					    # Arrange
 | 
				
			||||||
    mode = "1"
 | 
					    mode = "1"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -55,7 +56,7 @@ def test_monochrome(tmp_path):
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@pytest.mark.xfail(reason="Palm P image is wrong")
 | 
					@pytest.mark.xfail(reason="Palm P image is wrong")
 | 
				
			||||||
def test_p_mode(tmp_path):
 | 
					def test_p_mode(tmp_path: Path) -> None:
 | 
				
			||||||
    # Arrange
 | 
					    # Arrange
 | 
				
			||||||
    mode = "P"
 | 
					    mode = "P"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -65,6 +66,6 @@ def test_p_mode(tmp_path):
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@pytest.mark.parametrize("mode", ("L", "RGB"))
 | 
					@pytest.mark.parametrize("mode", ("L", "RGB"))
 | 
				
			||||||
def test_oserror(tmp_path, mode):
 | 
					def test_oserror(tmp_path: Path, mode) -> None:
 | 
				
			||||||
    with pytest.raises(OSError):
 | 
					    with pytest.raises(OSError):
 | 
				
			||||||
        helper_save_as_palm(tmp_path, mode)
 | 
					        helper_save_as_palm(tmp_path, mode)
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,5 +1,7 @@
 | 
				
			||||||
from __future__ import annotations
 | 
					from __future__ import annotations
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					from pathlib import Path
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import pytest
 | 
					import pytest
 | 
				
			||||||
 | 
					
 | 
				
			||||||
from PIL import Image, ImageFile, PcxImagePlugin
 | 
					from PIL import Image, ImageFile, PcxImagePlugin
 | 
				
			||||||
| 
						 | 
					@ -7,7 +9,7 @@ from PIL import Image, ImageFile, PcxImagePlugin
 | 
				
			||||||
from .helper import assert_image_equal, hopper
 | 
					from .helper import assert_image_equal, hopper
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def _roundtrip(tmp_path, im):
 | 
					def _roundtrip(tmp_path: Path, im) -> None:
 | 
				
			||||||
    f = str(tmp_path / "temp.pcx")
 | 
					    f = str(tmp_path / "temp.pcx")
 | 
				
			||||||
    im.save(f)
 | 
					    im.save(f)
 | 
				
			||||||
    with Image.open(f) as im2:
 | 
					    with Image.open(f) as im2:
 | 
				
			||||||
| 
						 | 
					@ -18,7 +20,7 @@ def _roundtrip(tmp_path, im):
 | 
				
			||||||
        assert_image_equal(im2, im)
 | 
					        assert_image_equal(im2, im)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_sanity(tmp_path):
 | 
					def test_sanity(tmp_path: Path) -> None:
 | 
				
			||||||
    for mode in ("1", "L", "P", "RGB"):
 | 
					    for mode in ("1", "L", "P", "RGB"):
 | 
				
			||||||
        _roundtrip(tmp_path, hopper(mode))
 | 
					        _roundtrip(tmp_path, hopper(mode))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -34,7 +36,7 @@ def test_sanity(tmp_path):
 | 
				
			||||||
        im.save(f)
 | 
					        im.save(f)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_invalid_file():
 | 
					def test_invalid_file() -> None:
 | 
				
			||||||
    invalid_file = "Tests/images/flower.jpg"
 | 
					    invalid_file = "Tests/images/flower.jpg"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    with pytest.raises(SyntaxError):
 | 
					    with pytest.raises(SyntaxError):
 | 
				
			||||||
| 
						 | 
					@ -42,7 +44,7 @@ def test_invalid_file():
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@pytest.mark.parametrize("mode", ("1", "L", "P", "RGB"))
 | 
					@pytest.mark.parametrize("mode", ("1", "L", "P", "RGB"))
 | 
				
			||||||
def test_odd(tmp_path, mode):
 | 
					def test_odd(tmp_path: Path, mode) -> None:
 | 
				
			||||||
    # See issue #523, odd sized images should have a stride that's even.
 | 
					    # See issue #523, odd sized images should have a stride that's even.
 | 
				
			||||||
    # Not that ImageMagick or GIMP write PCX that way.
 | 
					    # Not that ImageMagick or GIMP write PCX that way.
 | 
				
			||||||
    # We were not handling properly.
 | 
					    # We were not handling properly.
 | 
				
			||||||
| 
						 | 
					@ -51,7 +53,7 @@ def test_odd(tmp_path, mode):
 | 
				
			||||||
    _roundtrip(tmp_path, hopper(mode).resize((511, 511)))
 | 
					    _roundtrip(tmp_path, hopper(mode).resize((511, 511)))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_odd_read():
 | 
					def test_odd_read() -> None:
 | 
				
			||||||
    # Reading an image with an odd stride, making it malformed
 | 
					    # Reading an image with an odd stride, making it malformed
 | 
				
			||||||
    with Image.open("Tests/images/odd_stride.pcx") as im:
 | 
					    with Image.open("Tests/images/odd_stride.pcx") as im:
 | 
				
			||||||
        im.load()
 | 
					        im.load()
 | 
				
			||||||
| 
						 | 
					@ -59,7 +61,7 @@ def test_odd_read():
 | 
				
			||||||
        assert im.size == (371, 150)
 | 
					        assert im.size == (371, 150)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_pil184():
 | 
					def test_pil184() -> None:
 | 
				
			||||||
    # Check reading of files where xmin/xmax is not zero.
 | 
					    # Check reading of files where xmin/xmax is not zero.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    test_file = "Tests/images/pil184.pcx"
 | 
					    test_file = "Tests/images/pil184.pcx"
 | 
				
			||||||
| 
						 | 
					@ -71,7 +73,7 @@ def test_pil184():
 | 
				
			||||||
        assert im.histogram()[0] + im.histogram()[255] == 447 * 144
 | 
					        assert im.histogram()[0] + im.histogram()[255] == 447 * 144
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_1px_width(tmp_path):
 | 
					def test_1px_width(tmp_path: Path) -> None:
 | 
				
			||||||
    im = Image.new("L", (1, 256))
 | 
					    im = Image.new("L", (1, 256))
 | 
				
			||||||
    px = im.load()
 | 
					    px = im.load()
 | 
				
			||||||
    for y in range(256):
 | 
					    for y in range(256):
 | 
				
			||||||
| 
						 | 
					@ -79,7 +81,7 @@ def test_1px_width(tmp_path):
 | 
				
			||||||
    _roundtrip(tmp_path, im)
 | 
					    _roundtrip(tmp_path, im)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_large_count(tmp_path):
 | 
					def test_large_count(tmp_path: Path) -> None:
 | 
				
			||||||
    im = Image.new("L", (256, 1))
 | 
					    im = Image.new("L", (256, 1))
 | 
				
			||||||
    px = im.load()
 | 
					    px = im.load()
 | 
				
			||||||
    for x in range(256):
 | 
					    for x in range(256):
 | 
				
			||||||
| 
						 | 
					@ -87,7 +89,7 @@ def test_large_count(tmp_path):
 | 
				
			||||||
    _roundtrip(tmp_path, im)
 | 
					    _roundtrip(tmp_path, im)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def _test_buffer_overflow(tmp_path, im, size=1024):
 | 
					def _test_buffer_overflow(tmp_path: Path, im, size: int = 1024) -> None:
 | 
				
			||||||
    _last = ImageFile.MAXBLOCK
 | 
					    _last = ImageFile.MAXBLOCK
 | 
				
			||||||
    ImageFile.MAXBLOCK = size
 | 
					    ImageFile.MAXBLOCK = size
 | 
				
			||||||
    try:
 | 
					    try:
 | 
				
			||||||
| 
						 | 
					@ -96,7 +98,7 @@ def _test_buffer_overflow(tmp_path, im, size=1024):
 | 
				
			||||||
        ImageFile.MAXBLOCK = _last
 | 
					        ImageFile.MAXBLOCK = _last
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_break_in_count_overflow(tmp_path):
 | 
					def test_break_in_count_overflow(tmp_path: Path) -> None:
 | 
				
			||||||
    im = Image.new("L", (256, 5))
 | 
					    im = Image.new("L", (256, 5))
 | 
				
			||||||
    px = im.load()
 | 
					    px = im.load()
 | 
				
			||||||
    for y in range(4):
 | 
					    for y in range(4):
 | 
				
			||||||
| 
						 | 
					@ -105,7 +107,7 @@ def test_break_in_count_overflow(tmp_path):
 | 
				
			||||||
    _test_buffer_overflow(tmp_path, im)
 | 
					    _test_buffer_overflow(tmp_path, im)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_break_one_in_loop(tmp_path):
 | 
					def test_break_one_in_loop(tmp_path: Path) -> None:
 | 
				
			||||||
    im = Image.new("L", (256, 5))
 | 
					    im = Image.new("L", (256, 5))
 | 
				
			||||||
    px = im.load()
 | 
					    px = im.load()
 | 
				
			||||||
    for y in range(5):
 | 
					    for y in range(5):
 | 
				
			||||||
| 
						 | 
					@ -114,7 +116,7 @@ def test_break_one_in_loop(tmp_path):
 | 
				
			||||||
    _test_buffer_overflow(tmp_path, im)
 | 
					    _test_buffer_overflow(tmp_path, im)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_break_many_in_loop(tmp_path):
 | 
					def test_break_many_in_loop(tmp_path: Path) -> None:
 | 
				
			||||||
    im = Image.new("L", (256, 5))
 | 
					    im = Image.new("L", (256, 5))
 | 
				
			||||||
    px = im.load()
 | 
					    px = im.load()
 | 
				
			||||||
    for y in range(4):
 | 
					    for y in range(4):
 | 
				
			||||||
| 
						 | 
					@ -125,7 +127,7 @@ def test_break_many_in_loop(tmp_path):
 | 
				
			||||||
    _test_buffer_overflow(tmp_path, im)
 | 
					    _test_buffer_overflow(tmp_path, im)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_break_one_at_end(tmp_path):
 | 
					def test_break_one_at_end(tmp_path: Path) -> None:
 | 
				
			||||||
    im = Image.new("L", (256, 5))
 | 
					    im = Image.new("L", (256, 5))
 | 
				
			||||||
    px = im.load()
 | 
					    px = im.load()
 | 
				
			||||||
    for y in range(5):
 | 
					    for y in range(5):
 | 
				
			||||||
| 
						 | 
					@ -135,7 +137,7 @@ def test_break_one_at_end(tmp_path):
 | 
				
			||||||
    _test_buffer_overflow(tmp_path, im)
 | 
					    _test_buffer_overflow(tmp_path, im)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_break_many_at_end(tmp_path):
 | 
					def test_break_many_at_end(tmp_path: Path) -> None:
 | 
				
			||||||
    im = Image.new("L", (256, 5))
 | 
					    im = Image.new("L", (256, 5))
 | 
				
			||||||
    px = im.load()
 | 
					    px = im.load()
 | 
				
			||||||
    for y in range(5):
 | 
					    for y in range(5):
 | 
				
			||||||
| 
						 | 
					@ -147,7 +149,7 @@ def test_break_many_at_end(tmp_path):
 | 
				
			||||||
    _test_buffer_overflow(tmp_path, im)
 | 
					    _test_buffer_overflow(tmp_path, im)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_break_padding(tmp_path):
 | 
					def test_break_padding(tmp_path: Path) -> None:
 | 
				
			||||||
    im = Image.new("L", (257, 5))
 | 
					    im = Image.new("L", (257, 5))
 | 
				
			||||||
    px = im.load()
 | 
					    px = im.load()
 | 
				
			||||||
    for y in range(5):
 | 
					    for y in range(5):
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -5,6 +5,7 @@ import os
 | 
				
			||||||
import os.path
 | 
					import os.path
 | 
				
			||||||
import tempfile
 | 
					import tempfile
 | 
				
			||||||
import time
 | 
					import time
 | 
				
			||||||
 | 
					from pathlib import Path
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import pytest
 | 
					import pytest
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -13,7 +14,7 @@ from PIL import Image, PdfParser, features
 | 
				
			||||||
from .helper import hopper, mark_if_feature_version, skip_unless_feature
 | 
					from .helper import hopper, mark_if_feature_version, skip_unless_feature
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def helper_save_as_pdf(tmp_path, mode, **kwargs):
 | 
					def helper_save_as_pdf(tmp_path: Path, mode, **kwargs):
 | 
				
			||||||
    # Arrange
 | 
					    # Arrange
 | 
				
			||||||
    im = hopper(mode)
 | 
					    im = hopper(mode)
 | 
				
			||||||
    outfile = str(tmp_path / ("temp_" + mode + ".pdf"))
 | 
					    outfile = str(tmp_path / ("temp_" + mode + ".pdf"))
 | 
				
			||||||
| 
						 | 
					@ -40,17 +41,17 @@ def helper_save_as_pdf(tmp_path, mode, **kwargs):
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@pytest.mark.parametrize("mode", ("L", "P", "RGB", "CMYK"))
 | 
					@pytest.mark.parametrize("mode", ("L", "P", "RGB", "CMYK"))
 | 
				
			||||||
def test_save(tmp_path, mode):
 | 
					def test_save(tmp_path: Path, mode) -> None:
 | 
				
			||||||
    helper_save_as_pdf(tmp_path, mode)
 | 
					    helper_save_as_pdf(tmp_path, mode)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@skip_unless_feature("jpg_2000")
 | 
					@skip_unless_feature("jpg_2000")
 | 
				
			||||||
@pytest.mark.parametrize("mode", ("LA", "RGBA"))
 | 
					@pytest.mark.parametrize("mode", ("LA", "RGBA"))
 | 
				
			||||||
def test_save_alpha(tmp_path, mode):
 | 
					def test_save_alpha(tmp_path: Path, mode) -> None:
 | 
				
			||||||
    helper_save_as_pdf(tmp_path, mode)
 | 
					    helper_save_as_pdf(tmp_path, mode)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_p_alpha(tmp_path):
 | 
					def test_p_alpha(tmp_path: Path) -> None:
 | 
				
			||||||
    # Arrange
 | 
					    # Arrange
 | 
				
			||||||
    outfile = str(tmp_path / "temp.pdf")
 | 
					    outfile = str(tmp_path / "temp.pdf")
 | 
				
			||||||
    with Image.open("Tests/images/pil123p.png") as im:
 | 
					    with Image.open("Tests/images/pil123p.png") as im:
 | 
				
			||||||
| 
						 | 
					@ -66,7 +67,7 @@ def test_p_alpha(tmp_path):
 | 
				
			||||||
    assert b"\n/SMask " in contents
 | 
					    assert b"\n/SMask " in contents
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_monochrome(tmp_path):
 | 
					def test_monochrome(tmp_path: Path) -> None:
 | 
				
			||||||
    # Arrange
 | 
					    # Arrange
 | 
				
			||||||
    mode = "1"
 | 
					    mode = "1"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -75,7 +76,7 @@ def test_monochrome(tmp_path):
 | 
				
			||||||
    assert os.path.getsize(outfile) < (5000 if features.check("libtiff") else 15000)
 | 
					    assert os.path.getsize(outfile) < (5000 if features.check("libtiff") else 15000)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_unsupported_mode(tmp_path):
 | 
					def test_unsupported_mode(tmp_path: Path) -> None:
 | 
				
			||||||
    im = hopper("PA")
 | 
					    im = hopper("PA")
 | 
				
			||||||
    outfile = str(tmp_path / "temp_PA.pdf")
 | 
					    outfile = str(tmp_path / "temp_PA.pdf")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -83,7 +84,7 @@ def test_unsupported_mode(tmp_path):
 | 
				
			||||||
        im.save(outfile)
 | 
					        im.save(outfile)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_resolution(tmp_path):
 | 
					def test_resolution(tmp_path: Path) -> None:
 | 
				
			||||||
    im = hopper()
 | 
					    im = hopper()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    outfile = str(tmp_path / "temp.pdf")
 | 
					    outfile = str(tmp_path / "temp.pdf")
 | 
				
			||||||
| 
						 | 
					@ -111,7 +112,7 @@ def test_resolution(tmp_path):
 | 
				
			||||||
        {"dpi": (75, 150), "resolution": 200},
 | 
					        {"dpi": (75, 150), "resolution": 200},
 | 
				
			||||||
    ),
 | 
					    ),
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
def test_dpi(params, tmp_path):
 | 
					def test_dpi(params, tmp_path: Path) -> None:
 | 
				
			||||||
    im = hopper()
 | 
					    im = hopper()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    outfile = str(tmp_path / "temp.pdf")
 | 
					    outfile = str(tmp_path / "temp.pdf")
 | 
				
			||||||
| 
						 | 
					@ -135,7 +136,7 @@ def test_dpi(params, tmp_path):
 | 
				
			||||||
@mark_if_feature_version(
 | 
					@mark_if_feature_version(
 | 
				
			||||||
    pytest.mark.valgrind_known_error, "libjpeg_turbo", "2.0", reason="Known Failing"
 | 
					    pytest.mark.valgrind_known_error, "libjpeg_turbo", "2.0", reason="Known Failing"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
def test_save_all(tmp_path):
 | 
					def test_save_all(tmp_path: Path) -> None:
 | 
				
			||||||
    # Single frame image
 | 
					    # Single frame image
 | 
				
			||||||
    helper_save_as_pdf(tmp_path, "RGB", save_all=True)
 | 
					    helper_save_as_pdf(tmp_path, "RGB", save_all=True)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -171,7 +172,7 @@ def test_save_all(tmp_path):
 | 
				
			||||||
    assert os.path.getsize(outfile) > 0
 | 
					    assert os.path.getsize(outfile) > 0
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_multiframe_normal_save(tmp_path):
 | 
					def test_multiframe_normal_save(tmp_path: Path) -> None:
 | 
				
			||||||
    # Test saving a multiframe image without save_all
 | 
					    # Test saving a multiframe image without save_all
 | 
				
			||||||
    with Image.open("Tests/images/dispose_bgnd.gif") as im:
 | 
					    with Image.open("Tests/images/dispose_bgnd.gif") as im:
 | 
				
			||||||
        outfile = str(tmp_path / "temp.pdf")
 | 
					        outfile = str(tmp_path / "temp.pdf")
 | 
				
			||||||
| 
						 | 
					@ -181,7 +182,7 @@ def test_multiframe_normal_save(tmp_path):
 | 
				
			||||||
    assert os.path.getsize(outfile) > 0
 | 
					    assert os.path.getsize(outfile) > 0
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_pdf_open(tmp_path):
 | 
					def test_pdf_open(tmp_path: Path) -> None:
 | 
				
			||||||
    # fail on a buffer full of null bytes
 | 
					    # fail on a buffer full of null bytes
 | 
				
			||||||
    with pytest.raises(PdfParser.PdfFormatError):
 | 
					    with pytest.raises(PdfParser.PdfFormatError):
 | 
				
			||||||
        PdfParser.PdfParser(buf=bytearray(65536))
 | 
					        PdfParser.PdfParser(buf=bytearray(65536))
 | 
				
			||||||
| 
						 | 
					@ -218,14 +219,14 @@ def test_pdf_open(tmp_path):
 | 
				
			||||||
            assert not hopper_pdf.should_close_file
 | 
					            assert not hopper_pdf.should_close_file
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_pdf_append_fails_on_nonexistent_file():
 | 
					def test_pdf_append_fails_on_nonexistent_file() -> None:
 | 
				
			||||||
    im = hopper("RGB")
 | 
					    im = hopper("RGB")
 | 
				
			||||||
    with tempfile.TemporaryDirectory() as temp_dir:
 | 
					    with tempfile.TemporaryDirectory() as temp_dir:
 | 
				
			||||||
        with pytest.raises(OSError):
 | 
					        with pytest.raises(OSError):
 | 
				
			||||||
            im.save(os.path.join(temp_dir, "nonexistent.pdf"), append=True)
 | 
					            im.save(os.path.join(temp_dir, "nonexistent.pdf"), append=True)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def check_pdf_pages_consistency(pdf):
 | 
					def check_pdf_pages_consistency(pdf) -> None:
 | 
				
			||||||
    pages_info = pdf.read_indirect(pdf.pages_ref)
 | 
					    pages_info = pdf.read_indirect(pdf.pages_ref)
 | 
				
			||||||
    assert b"Parent" not in pages_info
 | 
					    assert b"Parent" not in pages_info
 | 
				
			||||||
    assert b"Kids" in pages_info
 | 
					    assert b"Kids" in pages_info
 | 
				
			||||||
| 
						 | 
					@ -243,7 +244,7 @@ def check_pdf_pages_consistency(pdf):
 | 
				
			||||||
    assert kids_not_used == []
 | 
					    assert kids_not_used == []
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_pdf_append(tmp_path):
 | 
					def test_pdf_append(tmp_path: Path) -> None:
 | 
				
			||||||
    # make a PDF file
 | 
					    # make a PDF file
 | 
				
			||||||
    pdf_filename = helper_save_as_pdf(tmp_path, "RGB", producer="PdfParser")
 | 
					    pdf_filename = helper_save_as_pdf(tmp_path, "RGB", producer="PdfParser")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -294,7 +295,7 @@ def test_pdf_append(tmp_path):
 | 
				
			||||||
        check_pdf_pages_consistency(pdf)
 | 
					        check_pdf_pages_consistency(pdf)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_pdf_info(tmp_path):
 | 
					def test_pdf_info(tmp_path: Path) -> None:
 | 
				
			||||||
    # make a PDF file
 | 
					    # make a PDF file
 | 
				
			||||||
    pdf_filename = helper_save_as_pdf(
 | 
					    pdf_filename = helper_save_as_pdf(
 | 
				
			||||||
        tmp_path,
 | 
					        tmp_path,
 | 
				
			||||||
| 
						 | 
					@ -323,7 +324,7 @@ def test_pdf_info(tmp_path):
 | 
				
			||||||
        check_pdf_pages_consistency(pdf)
 | 
					        check_pdf_pages_consistency(pdf)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_pdf_append_to_bytesio():
 | 
					def test_pdf_append_to_bytesio() -> None:
 | 
				
			||||||
    im = hopper("RGB")
 | 
					    im = hopper("RGB")
 | 
				
			||||||
    f = io.BytesIO()
 | 
					    f = io.BytesIO()
 | 
				
			||||||
    im.save(f, format="PDF")
 | 
					    im.save(f, format="PDF")
 | 
				
			||||||
| 
						 | 
					@ -338,7 +339,7 @@ def test_pdf_append_to_bytesio():
 | 
				
			||||||
@pytest.mark.timeout(1)
 | 
					@pytest.mark.timeout(1)
 | 
				
			||||||
@pytest.mark.skipif("PILLOW_VALGRIND_TEST" in os.environ, reason="Valgrind is slower")
 | 
					@pytest.mark.skipif("PILLOW_VALGRIND_TEST" in os.environ, reason="Valgrind is slower")
 | 
				
			||||||
@pytest.mark.parametrize("newline", (b"\r", b"\n"))
 | 
					@pytest.mark.parametrize("newline", (b"\r", b"\n"))
 | 
				
			||||||
def test_redos(newline):
 | 
					def test_redos(newline) -> None:
 | 
				
			||||||
    malicious = b" trailer<<>>" + newline * 3456
 | 
					    malicious = b" trailer<<>>" + newline * 3456
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    # This particular exception isn't relevant here.
 | 
					    # This particular exception isn't relevant here.
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -5,6 +5,7 @@ import sys
 | 
				
			||||||
import warnings
 | 
					import warnings
 | 
				
			||||||
import zlib
 | 
					import zlib
 | 
				
			||||||
from io import BytesIO
 | 
					from io import BytesIO
 | 
				
			||||||
 | 
					from pathlib import Path
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import pytest
 | 
					import pytest
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -79,7 +80,7 @@ class TestFilePng:
 | 
				
			||||||
                    png.crc(cid, s)
 | 
					                    png.crc(cid, s)
 | 
				
			||||||
        return chunks
 | 
					        return chunks
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_sanity(self, tmp_path):
 | 
					    def test_sanity(self, tmp_path: Path) -> None:
 | 
				
			||||||
        # internal version number
 | 
					        # internal version number
 | 
				
			||||||
        assert re.search(r"\d+(\.\d+){1,3}$", features.version_codec("zlib"))
 | 
					        assert re.search(r"\d+(\.\d+){1,3}$", features.version_codec("zlib"))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -102,13 +103,13 @@ class TestFilePng:
 | 
				
			||||||
                    reloaded = reloaded.convert(mode)
 | 
					                    reloaded = reloaded.convert(mode)
 | 
				
			||||||
                assert_image_equal(reloaded, im)
 | 
					                assert_image_equal(reloaded, im)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_invalid_file(self):
 | 
					    def test_invalid_file(self) -> None:
 | 
				
			||||||
        invalid_file = "Tests/images/flower.jpg"
 | 
					        invalid_file = "Tests/images/flower.jpg"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        with pytest.raises(SyntaxError):
 | 
					        with pytest.raises(SyntaxError):
 | 
				
			||||||
            PngImagePlugin.PngImageFile(invalid_file)
 | 
					            PngImagePlugin.PngImageFile(invalid_file)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_broken(self):
 | 
					    def test_broken(self) -> None:
 | 
				
			||||||
        # Check reading of totally broken files.  In this case, the test
 | 
					        # Check reading of totally broken files.  In this case, the test
 | 
				
			||||||
        # file was checked into Subversion as a text file.
 | 
					        # file was checked into Subversion as a text file.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -117,7 +118,7 @@ class TestFilePng:
 | 
				
			||||||
            with Image.open(test_file):
 | 
					            with Image.open(test_file):
 | 
				
			||||||
                pass
 | 
					                pass
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_bad_text(self):
 | 
					    def test_bad_text(self) -> None:
 | 
				
			||||||
        # Make sure PIL can read malformed tEXt chunks (@PIL152)
 | 
					        # Make sure PIL can read malformed tEXt chunks (@PIL152)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        im = load(HEAD + chunk(b"tEXt") + TAIL)
 | 
					        im = load(HEAD + chunk(b"tEXt") + TAIL)
 | 
				
			||||||
| 
						 | 
					@ -135,7 +136,7 @@ class TestFilePng:
 | 
				
			||||||
        im = load(HEAD + chunk(b"tEXt", b"spam\0egg\0") + TAIL)
 | 
					        im = load(HEAD + chunk(b"tEXt", b"spam\0egg\0") + TAIL)
 | 
				
			||||||
        assert im.info == {"spam": "egg\x00"}
 | 
					        assert im.info == {"spam": "egg\x00"}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_bad_ztxt(self):
 | 
					    def test_bad_ztxt(self) -> None:
 | 
				
			||||||
        # Test reading malformed zTXt chunks (python-pillow/Pillow#318)
 | 
					        # Test reading malformed zTXt chunks (python-pillow/Pillow#318)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        im = load(HEAD + chunk(b"zTXt") + TAIL)
 | 
					        im = load(HEAD + chunk(b"zTXt") + TAIL)
 | 
				
			||||||
| 
						 | 
					@ -156,7 +157,7 @@ class TestFilePng:
 | 
				
			||||||
        im = load(HEAD + chunk(b"zTXt", b"spam\0\0" + zlib.compress(b"egg")) + TAIL)
 | 
					        im = load(HEAD + chunk(b"zTXt", b"spam\0\0" + zlib.compress(b"egg")) + TAIL)
 | 
				
			||||||
        assert im.info == {"spam": "egg"}
 | 
					        assert im.info == {"spam": "egg"}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_bad_itxt(self):
 | 
					    def test_bad_itxt(self) -> None:
 | 
				
			||||||
        im = load(HEAD + chunk(b"iTXt") + TAIL)
 | 
					        im = load(HEAD + chunk(b"iTXt") + TAIL)
 | 
				
			||||||
        assert im.info == {}
 | 
					        assert im.info == {}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -200,7 +201,7 @@ class TestFilePng:
 | 
				
			||||||
        assert im.info["spam"].lang == "en"
 | 
					        assert im.info["spam"].lang == "en"
 | 
				
			||||||
        assert im.info["spam"].tkey == "Spam"
 | 
					        assert im.info["spam"].tkey == "Spam"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_interlace(self):
 | 
					    def test_interlace(self) -> None:
 | 
				
			||||||
        test_file = "Tests/images/pil123p.png"
 | 
					        test_file = "Tests/images/pil123p.png"
 | 
				
			||||||
        with Image.open(test_file) as im:
 | 
					        with Image.open(test_file) as im:
 | 
				
			||||||
            assert_image(im, "P", (162, 150))
 | 
					            assert_image(im, "P", (162, 150))
 | 
				
			||||||
| 
						 | 
					@ -215,7 +216,7 @@ class TestFilePng:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            im.load()
 | 
					            im.load()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_load_transparent_p(self):
 | 
					    def test_load_transparent_p(self) -> None:
 | 
				
			||||||
        test_file = "Tests/images/pil123p.png"
 | 
					        test_file = "Tests/images/pil123p.png"
 | 
				
			||||||
        with Image.open(test_file) as im:
 | 
					        with Image.open(test_file) as im:
 | 
				
			||||||
            assert_image(im, "P", (162, 150))
 | 
					            assert_image(im, "P", (162, 150))
 | 
				
			||||||
| 
						 | 
					@ -225,7 +226,7 @@ class TestFilePng:
 | 
				
			||||||
        # image has 124 unique alpha values
 | 
					        # image has 124 unique alpha values
 | 
				
			||||||
        assert len(im.getchannel("A").getcolors()) == 124
 | 
					        assert len(im.getchannel("A").getcolors()) == 124
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_load_transparent_rgb(self):
 | 
					    def test_load_transparent_rgb(self) -> None:
 | 
				
			||||||
        test_file = "Tests/images/rgb_trns.png"
 | 
					        test_file = "Tests/images/rgb_trns.png"
 | 
				
			||||||
        with Image.open(test_file) as im:
 | 
					        with Image.open(test_file) as im:
 | 
				
			||||||
            assert im.info["transparency"] == (0, 255, 52)
 | 
					            assert im.info["transparency"] == (0, 255, 52)
 | 
				
			||||||
| 
						 | 
					@ -237,7 +238,7 @@ class TestFilePng:
 | 
				
			||||||
        # image has 876 transparent pixels
 | 
					        # image has 876 transparent pixels
 | 
				
			||||||
        assert im.getchannel("A").getcolors()[0][0] == 876
 | 
					        assert im.getchannel("A").getcolors()[0][0] == 876
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_save_p_transparent_palette(self, tmp_path):
 | 
					    def test_save_p_transparent_palette(self, tmp_path: Path) -> None:
 | 
				
			||||||
        in_file = "Tests/images/pil123p.png"
 | 
					        in_file = "Tests/images/pil123p.png"
 | 
				
			||||||
        with Image.open(in_file) as im:
 | 
					        with Image.open(in_file) as im:
 | 
				
			||||||
            # 'transparency' contains a byte string with the opacity for
 | 
					            # 'transparency' contains a byte string with the opacity for
 | 
				
			||||||
| 
						 | 
					@ -258,7 +259,7 @@ class TestFilePng:
 | 
				
			||||||
        # image has 124 unique alpha values
 | 
					        # image has 124 unique alpha values
 | 
				
			||||||
        assert len(im.getchannel("A").getcolors()) == 124
 | 
					        assert len(im.getchannel("A").getcolors()) == 124
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_save_p_single_transparency(self, tmp_path):
 | 
					    def test_save_p_single_transparency(self, tmp_path: Path) -> None:
 | 
				
			||||||
        in_file = "Tests/images/p_trns_single.png"
 | 
					        in_file = "Tests/images/p_trns_single.png"
 | 
				
			||||||
        with Image.open(in_file) as im:
 | 
					        with Image.open(in_file) as im:
 | 
				
			||||||
            # pixel value 164 is full transparent
 | 
					            # pixel value 164 is full transparent
 | 
				
			||||||
| 
						 | 
					@ -281,7 +282,7 @@ class TestFilePng:
 | 
				
			||||||
        # image has 876 transparent pixels
 | 
					        # image has 876 transparent pixels
 | 
				
			||||||
        assert im.getchannel("A").getcolors()[0][0] == 876
 | 
					        assert im.getchannel("A").getcolors()[0][0] == 876
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_save_p_transparent_black(self, tmp_path):
 | 
					    def test_save_p_transparent_black(self, tmp_path: Path) -> None:
 | 
				
			||||||
        # check if solid black image with full transparency
 | 
					        # check if solid black image with full transparency
 | 
				
			||||||
        # is supported (check for #1838)
 | 
					        # is supported (check for #1838)
 | 
				
			||||||
        im = Image.new("RGBA", (10, 10), (0, 0, 0, 0))
 | 
					        im = Image.new("RGBA", (10, 10), (0, 0, 0, 0))
 | 
				
			||||||
| 
						 | 
					@ -299,7 +300,7 @@ class TestFilePng:
 | 
				
			||||||
        assert_image(im, "RGBA", (10, 10))
 | 
					        assert_image(im, "RGBA", (10, 10))
 | 
				
			||||||
        assert im.getcolors() == [(100, (0, 0, 0, 0))]
 | 
					        assert im.getcolors() == [(100, (0, 0, 0, 0))]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_save_grayscale_transparency(self, tmp_path):
 | 
					    def test_save_grayscale_transparency(self, tmp_path: Path) -> None:
 | 
				
			||||||
        for mode, num_transparent in {"1": 1994, "L": 559, "I": 559}.items():
 | 
					        for mode, num_transparent in {"1": 1994, "L": 559, "I": 559}.items():
 | 
				
			||||||
            in_file = "Tests/images/" + mode.lower() + "_trns.png"
 | 
					            in_file = "Tests/images/" + mode.lower() + "_trns.png"
 | 
				
			||||||
            with Image.open(in_file) as im:
 | 
					            with Image.open(in_file) as im:
 | 
				
			||||||
| 
						 | 
					@ -320,13 +321,13 @@ class TestFilePng:
 | 
				
			||||||
            test_im_rgba = test_im.convert("RGBA")
 | 
					            test_im_rgba = test_im.convert("RGBA")
 | 
				
			||||||
            assert test_im_rgba.getchannel("A").getcolors()[0][0] == num_transparent
 | 
					            assert test_im_rgba.getchannel("A").getcolors()[0][0] == num_transparent
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_save_rgb_single_transparency(self, tmp_path):
 | 
					    def test_save_rgb_single_transparency(self, tmp_path: Path) -> None:
 | 
				
			||||||
        in_file = "Tests/images/caption_6_33_22.png"
 | 
					        in_file = "Tests/images/caption_6_33_22.png"
 | 
				
			||||||
        with Image.open(in_file) as im:
 | 
					        with Image.open(in_file) as im:
 | 
				
			||||||
            test_file = str(tmp_path / "temp.png")
 | 
					            test_file = str(tmp_path / "temp.png")
 | 
				
			||||||
            im.save(test_file)
 | 
					            im.save(test_file)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_load_verify(self):
 | 
					    def test_load_verify(self) -> None:
 | 
				
			||||||
        # Check open/load/verify exception (@PIL150)
 | 
					        # Check open/load/verify exception (@PIL150)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        with Image.open(TEST_PNG_FILE) as im:
 | 
					        with Image.open(TEST_PNG_FILE) as im:
 | 
				
			||||||
| 
						 | 
					@ -339,7 +340,7 @@ class TestFilePng:
 | 
				
			||||||
            with pytest.raises(RuntimeError):
 | 
					            with pytest.raises(RuntimeError):
 | 
				
			||||||
                im.verify()
 | 
					                im.verify()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_verify_struct_error(self):
 | 
					    def test_verify_struct_error(self) -> None:
 | 
				
			||||||
        # Check open/load/verify exception (#1755)
 | 
					        # Check open/load/verify exception (#1755)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        # offsets to test, -10: breaks in i32() in read. (OSError)
 | 
					        # offsets to test, -10: breaks in i32() in read. (OSError)
 | 
				
			||||||
| 
						 | 
					@ -355,7 +356,7 @@ class TestFilePng:
 | 
				
			||||||
                with pytest.raises((OSError, SyntaxError)):
 | 
					                with pytest.raises((OSError, SyntaxError)):
 | 
				
			||||||
                    im.verify()
 | 
					                    im.verify()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_verify_ignores_crc_error(self):
 | 
					    def test_verify_ignores_crc_error(self) -> None:
 | 
				
			||||||
        # check ignores crc errors in ancillary chunks
 | 
					        # check ignores crc errors in ancillary chunks
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        chunk_data = chunk(b"tEXt", b"spam")
 | 
					        chunk_data = chunk(b"tEXt", b"spam")
 | 
				
			||||||
| 
						 | 
					@ -372,7 +373,7 @@ class TestFilePng:
 | 
				
			||||||
        finally:
 | 
					        finally:
 | 
				
			||||||
            ImageFile.LOAD_TRUNCATED_IMAGES = False
 | 
					            ImageFile.LOAD_TRUNCATED_IMAGES = False
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_verify_not_ignores_crc_error_in_required_chunk(self):
 | 
					    def test_verify_not_ignores_crc_error_in_required_chunk(self) -> None:
 | 
				
			||||||
        # check does not ignore crc errors in required chunks
 | 
					        # check does not ignore crc errors in required chunks
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        image_data = MAGIC + IHDR[:-1] + b"q" + TAIL
 | 
					        image_data = MAGIC + IHDR[:-1] + b"q" + TAIL
 | 
				
			||||||
| 
						 | 
					@ -384,18 +385,18 @@ class TestFilePng:
 | 
				
			||||||
        finally:
 | 
					        finally:
 | 
				
			||||||
            ImageFile.LOAD_TRUNCATED_IMAGES = False
 | 
					            ImageFile.LOAD_TRUNCATED_IMAGES = False
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_roundtrip_dpi(self):
 | 
					    def test_roundtrip_dpi(self) -> None:
 | 
				
			||||||
        # Check dpi roundtripping
 | 
					        # Check dpi roundtripping
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        with Image.open(TEST_PNG_FILE) as im:
 | 
					        with Image.open(TEST_PNG_FILE) as im:
 | 
				
			||||||
            im = roundtrip(im, dpi=(100.33, 100.33))
 | 
					            im = roundtrip(im, dpi=(100.33, 100.33))
 | 
				
			||||||
        assert im.info["dpi"] == (100.33, 100.33)
 | 
					        assert im.info["dpi"] == (100.33, 100.33)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_load_float_dpi(self):
 | 
					    def test_load_float_dpi(self) -> None:
 | 
				
			||||||
        with Image.open(TEST_PNG_FILE) as im:
 | 
					        with Image.open(TEST_PNG_FILE) as im:
 | 
				
			||||||
            assert im.info["dpi"] == (95.9866, 95.9866)
 | 
					            assert im.info["dpi"] == (95.9866, 95.9866)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_roundtrip_text(self):
 | 
					    def test_roundtrip_text(self) -> None:
 | 
				
			||||||
        # Check text roundtripping
 | 
					        # Check text roundtripping
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        with Image.open(TEST_PNG_FILE) as im:
 | 
					        with Image.open(TEST_PNG_FILE) as im:
 | 
				
			||||||
| 
						 | 
					@ -407,7 +408,7 @@ class TestFilePng:
 | 
				
			||||||
        assert im.info == {"TXT": "VALUE", "ZIP": "VALUE"}
 | 
					        assert im.info == {"TXT": "VALUE", "ZIP": "VALUE"}
 | 
				
			||||||
        assert im.text == {"TXT": "VALUE", "ZIP": "VALUE"}
 | 
					        assert im.text == {"TXT": "VALUE", "ZIP": "VALUE"}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_roundtrip_itxt(self):
 | 
					    def test_roundtrip_itxt(self) -> None:
 | 
				
			||||||
        # Check iTXt roundtripping
 | 
					        # Check iTXt roundtripping
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        im = Image.new("RGB", (32, 32))
 | 
					        im = Image.new("RGB", (32, 32))
 | 
				
			||||||
| 
						 | 
					@ -423,7 +424,7 @@ class TestFilePng:
 | 
				
			||||||
        assert im.text["eggs"].lang == "en"
 | 
					        assert im.text["eggs"].lang == "en"
 | 
				
			||||||
        assert im.text["eggs"].tkey == "Eggs"
 | 
					        assert im.text["eggs"].tkey == "Eggs"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_nonunicode_text(self):
 | 
					    def test_nonunicode_text(self) -> None:
 | 
				
			||||||
        # Check so that non-Unicode text is saved as a tEXt rather than iTXt
 | 
					        # Check so that non-Unicode text is saved as a tEXt rather than iTXt
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        im = Image.new("RGB", (32, 32))
 | 
					        im = Image.new("RGB", (32, 32))
 | 
				
			||||||
| 
						 | 
					@ -432,10 +433,10 @@ class TestFilePng:
 | 
				
			||||||
        im = roundtrip(im, pnginfo=info)
 | 
					        im = roundtrip(im, pnginfo=info)
 | 
				
			||||||
        assert isinstance(im.info["Text"], str)
 | 
					        assert isinstance(im.info["Text"], str)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_unicode_text(self):
 | 
					    def test_unicode_text(self) -> None:
 | 
				
			||||||
        # Check preservation of non-ASCII characters
 | 
					        # Check preservation of non-ASCII characters
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        def rt_text(value):
 | 
					        def rt_text(value) -> None:
 | 
				
			||||||
            im = Image.new("RGB", (32, 32))
 | 
					            im = Image.new("RGB", (32, 32))
 | 
				
			||||||
            info = PngImagePlugin.PngInfo()
 | 
					            info = PngImagePlugin.PngInfo()
 | 
				
			||||||
            info.add_text("Text", value)
 | 
					            info.add_text("Text", value)
 | 
				
			||||||
| 
						 | 
					@ -448,7 +449,7 @@ class TestFilePng:
 | 
				
			||||||
        rt_text(chr(0x4E00) + chr(0x66F0) + chr(0x9FBA) + chr(0x3042) + chr(0xAC00))
 | 
					        rt_text(chr(0x4E00) + chr(0x66F0) + chr(0x9FBA) + chr(0x3042) + chr(0xAC00))
 | 
				
			||||||
        rt_text("A" + chr(0xC4) + chr(0x472) + chr(0x3042))  # Combined
 | 
					        rt_text("A" + chr(0xC4) + chr(0x472) + chr(0x3042))  # Combined
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_scary(self):
 | 
					    def test_scary(self) -> None:
 | 
				
			||||||
        # Check reading of evil PNG file.  For information, see:
 | 
					        # Check reading of evil PNG file.  For information, see:
 | 
				
			||||||
        # http://scary.beasts.org/security/CESA-2004-001.txt
 | 
					        # http://scary.beasts.org/security/CESA-2004-001.txt
 | 
				
			||||||
        # The first byte is removed from pngtest_bad.png
 | 
					        # The first byte is removed from pngtest_bad.png
 | 
				
			||||||
| 
						 | 
					@ -462,7 +463,7 @@ class TestFilePng:
 | 
				
			||||||
            with Image.open(pngfile):
 | 
					            with Image.open(pngfile):
 | 
				
			||||||
                pass
 | 
					                pass
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_trns_rgb(self):
 | 
					    def test_trns_rgb(self) -> None:
 | 
				
			||||||
        # Check writing and reading of tRNS chunks for RGB images.
 | 
					        # Check writing and reading of tRNS chunks for RGB images.
 | 
				
			||||||
        # Independent file sample provided by Sebastian Spaeth.
 | 
					        # Independent file sample provided by Sebastian Spaeth.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -477,7 +478,7 @@ class TestFilePng:
 | 
				
			||||||
        im = roundtrip(im, transparency=(0, 1, 2))
 | 
					        im = roundtrip(im, transparency=(0, 1, 2))
 | 
				
			||||||
        assert im.info["transparency"] == (0, 1, 2)
 | 
					        assert im.info["transparency"] == (0, 1, 2)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_trns_p(self, tmp_path):
 | 
					    def test_trns_p(self, tmp_path: Path) -> None:
 | 
				
			||||||
        # Check writing a transparency of 0, issue #528
 | 
					        # Check writing a transparency of 0, issue #528
 | 
				
			||||||
        im = hopper("P")
 | 
					        im = hopper("P")
 | 
				
			||||||
        im.info["transparency"] = 0
 | 
					        im.info["transparency"] = 0
 | 
				
			||||||
| 
						 | 
					@ -490,13 +491,13 @@ class TestFilePng:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            assert_image_equal(im2.convert("RGBA"), im.convert("RGBA"))
 | 
					            assert_image_equal(im2.convert("RGBA"), im.convert("RGBA"))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_trns_null(self):
 | 
					    def test_trns_null(self) -> None:
 | 
				
			||||||
        # Check reading images with null tRNS value, issue #1239
 | 
					        # Check reading images with null tRNS value, issue #1239
 | 
				
			||||||
        test_file = "Tests/images/tRNS_null_1x1.png"
 | 
					        test_file = "Tests/images/tRNS_null_1x1.png"
 | 
				
			||||||
        with Image.open(test_file) as im:
 | 
					        with Image.open(test_file) as im:
 | 
				
			||||||
            assert im.info["transparency"] == 0
 | 
					            assert im.info["transparency"] == 0
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_save_icc_profile(self):
 | 
					    def test_save_icc_profile(self) -> None:
 | 
				
			||||||
        with Image.open("Tests/images/icc_profile_none.png") as im:
 | 
					        with Image.open("Tests/images/icc_profile_none.png") as im:
 | 
				
			||||||
            assert im.info["icc_profile"] is None
 | 
					            assert im.info["icc_profile"] is None
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -506,40 +507,40 @@ class TestFilePng:
 | 
				
			||||||
                im = roundtrip(im, icc_profile=expected_icc)
 | 
					                im = roundtrip(im, icc_profile=expected_icc)
 | 
				
			||||||
                assert im.info["icc_profile"] == expected_icc
 | 
					                assert im.info["icc_profile"] == expected_icc
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_discard_icc_profile(self):
 | 
					    def test_discard_icc_profile(self) -> None:
 | 
				
			||||||
        with Image.open("Tests/images/icc_profile.png") as im:
 | 
					        with Image.open("Tests/images/icc_profile.png") as im:
 | 
				
			||||||
            assert "icc_profile" in im.info
 | 
					            assert "icc_profile" in im.info
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            im = roundtrip(im, icc_profile=None)
 | 
					            im = roundtrip(im, icc_profile=None)
 | 
				
			||||||
        assert "icc_profile" not in im.info
 | 
					        assert "icc_profile" not in im.info
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_roundtrip_icc_profile(self):
 | 
					    def test_roundtrip_icc_profile(self) -> None:
 | 
				
			||||||
        with Image.open("Tests/images/icc_profile.png") as im:
 | 
					        with Image.open("Tests/images/icc_profile.png") as im:
 | 
				
			||||||
            expected_icc = im.info["icc_profile"]
 | 
					            expected_icc = im.info["icc_profile"]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            im = roundtrip(im)
 | 
					            im = roundtrip(im)
 | 
				
			||||||
        assert im.info["icc_profile"] == expected_icc
 | 
					        assert im.info["icc_profile"] == expected_icc
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_roundtrip_no_icc_profile(self):
 | 
					    def test_roundtrip_no_icc_profile(self) -> None:
 | 
				
			||||||
        with Image.open("Tests/images/icc_profile_none.png") as im:
 | 
					        with Image.open("Tests/images/icc_profile_none.png") as im:
 | 
				
			||||||
            assert im.info["icc_profile"] is None
 | 
					            assert im.info["icc_profile"] is None
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            im = roundtrip(im)
 | 
					            im = roundtrip(im)
 | 
				
			||||||
        assert "icc_profile" not in im.info
 | 
					        assert "icc_profile" not in im.info
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_repr_png(self):
 | 
					    def test_repr_png(self) -> None:
 | 
				
			||||||
        im = hopper()
 | 
					        im = hopper()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        with Image.open(BytesIO(im._repr_png_())) as repr_png:
 | 
					        with Image.open(BytesIO(im._repr_png_())) as repr_png:
 | 
				
			||||||
            assert repr_png.format == "PNG"
 | 
					            assert repr_png.format == "PNG"
 | 
				
			||||||
            assert_image_equal(im, repr_png)
 | 
					            assert_image_equal(im, repr_png)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_repr_png_error_returns_none(self):
 | 
					    def test_repr_png_error_returns_none(self) -> None:
 | 
				
			||||||
        im = hopper("F")
 | 
					        im = hopper("F")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        assert im._repr_png_() is None
 | 
					        assert im._repr_png_() is None
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_chunk_order(self, tmp_path):
 | 
					    def test_chunk_order(self, tmp_path: Path) -> None:
 | 
				
			||||||
        with Image.open("Tests/images/icc_profile.png") as im:
 | 
					        with Image.open("Tests/images/icc_profile.png") as im:
 | 
				
			||||||
            test_file = str(tmp_path / "temp.png")
 | 
					            test_file = str(tmp_path / "temp.png")
 | 
				
			||||||
            im.convert("P").save(test_file, dpi=(100, 100))
 | 
					            im.convert("P").save(test_file, dpi=(100, 100))
 | 
				
			||||||
| 
						 | 
					@ -560,17 +561,17 @@ class TestFilePng:
 | 
				
			||||||
        # pHYs - before IDAT
 | 
					        # pHYs - before IDAT
 | 
				
			||||||
        assert chunks.index(b"pHYs") < chunks.index(b"IDAT")
 | 
					        assert chunks.index(b"pHYs") < chunks.index(b"IDAT")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_getchunks(self):
 | 
					    def test_getchunks(self) -> None:
 | 
				
			||||||
        im = hopper()
 | 
					        im = hopper()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        chunks = PngImagePlugin.getchunks(im)
 | 
					        chunks = PngImagePlugin.getchunks(im)
 | 
				
			||||||
        assert len(chunks) == 3
 | 
					        assert len(chunks) == 3
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_read_private_chunks(self):
 | 
					    def test_read_private_chunks(self) -> None:
 | 
				
			||||||
        with Image.open("Tests/images/exif.png") as im:
 | 
					        with Image.open("Tests/images/exif.png") as im:
 | 
				
			||||||
            assert im.private_chunks == [(b"orNT", b"\x01")]
 | 
					            assert im.private_chunks == [(b"orNT", b"\x01")]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_roundtrip_private_chunk(self):
 | 
					    def test_roundtrip_private_chunk(self) -> None:
 | 
				
			||||||
        # Check private chunk roundtripping
 | 
					        # Check private chunk roundtripping
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        with Image.open(TEST_PNG_FILE) as im:
 | 
					        with Image.open(TEST_PNG_FILE) as im:
 | 
				
			||||||
| 
						 | 
					@ -588,7 +589,7 @@ class TestFilePng:
 | 
				
			||||||
            (b"prIV", b"VALUE3", True),
 | 
					            (b"prIV", b"VALUE3", True),
 | 
				
			||||||
        ]
 | 
					        ]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_textual_chunks_after_idat(self):
 | 
					    def test_textual_chunks_after_idat(self) -> None:
 | 
				
			||||||
        with Image.open("Tests/images/hopper.png") as im:
 | 
					        with Image.open("Tests/images/hopper.png") as im:
 | 
				
			||||||
            assert "comment" in im.text
 | 
					            assert "comment" in im.text
 | 
				
			||||||
            for k, v in {
 | 
					            for k, v in {
 | 
				
			||||||
| 
						 | 
					@ -615,7 +616,7 @@ class TestFilePng:
 | 
				
			||||||
        with Image.open("Tests/images/hopper_idat_after_image_end.png") as im:
 | 
					        with Image.open("Tests/images/hopper_idat_after_image_end.png") as im:
 | 
				
			||||||
            assert im.text == {"TXT": "VALUE", "ZIP": "VALUE"}
 | 
					            assert im.text == {"TXT": "VALUE", "ZIP": "VALUE"}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_padded_idat(self):
 | 
					    def test_padded_idat(self) -> None:
 | 
				
			||||||
        # This image has been manually hexedited
 | 
					        # This image has been manually hexedited
 | 
				
			||||||
        # so that the IDAT chunk has padding at the end
 | 
					        # so that the IDAT chunk has padding at the end
 | 
				
			||||||
        # Set MAXBLOCK to the length of the actual data
 | 
					        # Set MAXBLOCK to the length of the actual data
 | 
				
			||||||
| 
						 | 
					@ -635,7 +636,7 @@ class TestFilePng:
 | 
				
			||||||
    @pytest.mark.parametrize(
 | 
					    @pytest.mark.parametrize(
 | 
				
			||||||
        "cid", (b"IHDR", b"sRGB", b"pHYs", b"acTL", b"fcTL", b"fdAT")
 | 
					        "cid", (b"IHDR", b"sRGB", b"pHYs", b"acTL", b"fcTL", b"fdAT")
 | 
				
			||||||
    )
 | 
					    )
 | 
				
			||||||
    def test_truncated_chunks(self, cid):
 | 
					    def test_truncated_chunks(self, cid) -> None:
 | 
				
			||||||
        fp = BytesIO()
 | 
					        fp = BytesIO()
 | 
				
			||||||
        with PngImagePlugin.PngStream(fp) as png:
 | 
					        with PngImagePlugin.PngStream(fp) as png:
 | 
				
			||||||
            with pytest.raises(ValueError):
 | 
					            with pytest.raises(ValueError):
 | 
				
			||||||
| 
						 | 
					@ -645,7 +646,7 @@ class TestFilePng:
 | 
				
			||||||
            png.call(cid, 0, 0)
 | 
					            png.call(cid, 0, 0)
 | 
				
			||||||
            ImageFile.LOAD_TRUNCATED_IMAGES = False
 | 
					            ImageFile.LOAD_TRUNCATED_IMAGES = False
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_specify_bits(self, tmp_path):
 | 
					    def test_specify_bits(self, tmp_path: Path) -> None:
 | 
				
			||||||
        im = hopper("P")
 | 
					        im = hopper("P")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        out = str(tmp_path / "temp.png")
 | 
					        out = str(tmp_path / "temp.png")
 | 
				
			||||||
| 
						 | 
					@ -654,7 +655,7 @@ class TestFilePng:
 | 
				
			||||||
        with Image.open(out) as reloaded:
 | 
					        with Image.open(out) as reloaded:
 | 
				
			||||||
            assert len(reloaded.png.im_palette[1]) == 48
 | 
					            assert len(reloaded.png.im_palette[1]) == 48
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_plte_length(self, tmp_path):
 | 
					    def test_plte_length(self, tmp_path: Path) -> None:
 | 
				
			||||||
        im = Image.new("P", (1, 1))
 | 
					        im = Image.new("P", (1, 1))
 | 
				
			||||||
        im.putpalette((1, 1, 1))
 | 
					        im.putpalette((1, 1, 1))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -664,7 +665,7 @@ class TestFilePng:
 | 
				
			||||||
        with Image.open(out) as reloaded:
 | 
					        with Image.open(out) as reloaded:
 | 
				
			||||||
            assert len(reloaded.png.im_palette[1]) == 3
 | 
					            assert len(reloaded.png.im_palette[1]) == 3
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_getxmp(self):
 | 
					    def test_getxmp(self) -> None:
 | 
				
			||||||
        with Image.open("Tests/images/color_snakes.png") as im:
 | 
					        with Image.open("Tests/images/color_snakes.png") as im:
 | 
				
			||||||
            if ElementTree is None:
 | 
					            if ElementTree is None:
 | 
				
			||||||
                with pytest.warns(
 | 
					                with pytest.warns(
 | 
				
			||||||
| 
						 | 
					@ -679,7 +680,7 @@ class TestFilePng:
 | 
				
			||||||
                assert description["PixelXDimension"] == "10"
 | 
					                assert description["PixelXDimension"] == "10"
 | 
				
			||||||
                assert description["subject"]["Seq"] is None
 | 
					                assert description["subject"]["Seq"] is None
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_exif(self):
 | 
					    def test_exif(self) -> None:
 | 
				
			||||||
        # With an EXIF chunk
 | 
					        # With an EXIF chunk
 | 
				
			||||||
        with Image.open("Tests/images/exif.png") as im:
 | 
					        with Image.open("Tests/images/exif.png") as im:
 | 
				
			||||||
            exif = im._getexif()
 | 
					            exif = im._getexif()
 | 
				
			||||||
| 
						 | 
					@ -705,7 +706,7 @@ class TestFilePng:
 | 
				
			||||||
            exif = im.getexif()
 | 
					            exif = im.getexif()
 | 
				
			||||||
        assert exif[274] == 3
 | 
					        assert exif[274] == 3
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_exif_save(self, tmp_path):
 | 
					    def test_exif_save(self, tmp_path: Path) -> None:
 | 
				
			||||||
        # Test exif is not saved from info
 | 
					        # Test exif is not saved from info
 | 
				
			||||||
        test_file = str(tmp_path / "temp.png")
 | 
					        test_file = str(tmp_path / "temp.png")
 | 
				
			||||||
        with Image.open("Tests/images/exif.png") as im:
 | 
					        with Image.open("Tests/images/exif.png") as im:
 | 
				
			||||||
| 
						 | 
					@ -725,7 +726,7 @@ class TestFilePng:
 | 
				
			||||||
    @mark_if_feature_version(
 | 
					    @mark_if_feature_version(
 | 
				
			||||||
        pytest.mark.valgrind_known_error, "libjpeg_turbo", "2.0", reason="Known Failing"
 | 
					        pytest.mark.valgrind_known_error, "libjpeg_turbo", "2.0", reason="Known Failing"
 | 
				
			||||||
    )
 | 
					    )
 | 
				
			||||||
    def test_exif_from_jpg(self, tmp_path):
 | 
					    def test_exif_from_jpg(self, tmp_path: Path) -> None:
 | 
				
			||||||
        with Image.open("Tests/images/pil_sample_rgb.jpg") as im:
 | 
					        with Image.open("Tests/images/pil_sample_rgb.jpg") as im:
 | 
				
			||||||
            test_file = str(tmp_path / "temp.png")
 | 
					            test_file = str(tmp_path / "temp.png")
 | 
				
			||||||
            im.save(test_file, exif=im.getexif())
 | 
					            im.save(test_file, exif=im.getexif())
 | 
				
			||||||
| 
						 | 
					@ -734,7 +735,7 @@ class TestFilePng:
 | 
				
			||||||
            exif = reloaded._getexif()
 | 
					            exif = reloaded._getexif()
 | 
				
			||||||
        assert exif[305] == "Adobe Photoshop CS Macintosh"
 | 
					        assert exif[305] == "Adobe Photoshop CS Macintosh"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_exif_argument(self, tmp_path):
 | 
					    def test_exif_argument(self, tmp_path: Path) -> None:
 | 
				
			||||||
        with Image.open(TEST_PNG_FILE) as im:
 | 
					        with Image.open(TEST_PNG_FILE) as im:
 | 
				
			||||||
            test_file = str(tmp_path / "temp.png")
 | 
					            test_file = str(tmp_path / "temp.png")
 | 
				
			||||||
            im.save(test_file, exif=b"exifstring")
 | 
					            im.save(test_file, exif=b"exifstring")
 | 
				
			||||||
| 
						 | 
					@ -742,11 +743,11 @@ class TestFilePng:
 | 
				
			||||||
        with Image.open(test_file) as reloaded:
 | 
					        with Image.open(test_file) as reloaded:
 | 
				
			||||||
            assert reloaded.info["exif"] == b"Exif\x00\x00exifstring"
 | 
					            assert reloaded.info["exif"] == b"Exif\x00\x00exifstring"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_tell(self):
 | 
					    def test_tell(self) -> None:
 | 
				
			||||||
        with Image.open(TEST_PNG_FILE) as im:
 | 
					        with Image.open(TEST_PNG_FILE) as im:
 | 
				
			||||||
            assert im.tell() == 0
 | 
					            assert im.tell() == 0
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_seek(self):
 | 
					    def test_seek(self) -> None:
 | 
				
			||||||
        with Image.open(TEST_PNG_FILE) as im:
 | 
					        with Image.open(TEST_PNG_FILE) as im:
 | 
				
			||||||
            im.seek(0)
 | 
					            im.seek(0)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -754,7 +755,7 @@ class TestFilePng:
 | 
				
			||||||
                im.seek(1)
 | 
					                im.seek(1)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    @pytest.mark.parametrize("buffer", (True, False))
 | 
					    @pytest.mark.parametrize("buffer", (True, False))
 | 
				
			||||||
    def test_save_stdout(self, buffer):
 | 
					    def test_save_stdout(self, buffer) -> None:
 | 
				
			||||||
        old_stdout = sys.stdout
 | 
					        old_stdout = sys.stdout
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if buffer:
 | 
					        if buffer:
 | 
				
			||||||
| 
						 | 
					@ -786,7 +787,7 @@ class TestTruncatedPngPLeaks(PillowLeakTestCase):
 | 
				
			||||||
    mem_limit = 2 * 1024  # max increase in K
 | 
					    mem_limit = 2 * 1024  # max increase in K
 | 
				
			||||||
    iterations = 100  # Leak is 56k/iteration, this will leak 5.6megs
 | 
					    iterations = 100  # Leak is 56k/iteration, this will leak 5.6megs
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_leak_load(self):
 | 
					    def test_leak_load(self) -> None:
 | 
				
			||||||
        with open("Tests/images/hopper.png", "rb") as f:
 | 
					        with open("Tests/images/hopper.png", "rb") as f:
 | 
				
			||||||
            DATA = BytesIO(f.read(16 * 1024))
 | 
					            DATA = BytesIO(f.read(16 * 1024))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -794,7 +795,7 @@ class TestTruncatedPngPLeaks(PillowLeakTestCase):
 | 
				
			||||||
        with Image.open(DATA) as im:
 | 
					        with Image.open(DATA) as im:
 | 
				
			||||||
            im.load()
 | 
					            im.load()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        def core():
 | 
					        def core() -> None:
 | 
				
			||||||
            with Image.open(DATA) as im:
 | 
					            with Image.open(DATA) as im:
 | 
				
			||||||
                im.load()
 | 
					                im.load()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -2,6 +2,7 @@ from __future__ import annotations
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import sys
 | 
					import sys
 | 
				
			||||||
from io import BytesIO
 | 
					from io import BytesIO
 | 
				
			||||||
 | 
					from pathlib import Path
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import pytest
 | 
					import pytest
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -18,7 +19,7 @@ from .helper import (
 | 
				
			||||||
TEST_FILE = "Tests/images/hopper.ppm"
 | 
					TEST_FILE = "Tests/images/hopper.ppm"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_sanity():
 | 
					def test_sanity() -> None:
 | 
				
			||||||
    with Image.open(TEST_FILE) as im:
 | 
					    with Image.open(TEST_FILE) as im:
 | 
				
			||||||
        assert im.mode == "RGB"
 | 
					        assert im.mode == "RGB"
 | 
				
			||||||
        assert im.size == (128, 128)
 | 
					        assert im.size == (128, 128)
 | 
				
			||||||
| 
						 | 
					@ -69,7 +70,7 @@ def test_sanity():
 | 
				
			||||||
        ),
 | 
					        ),
 | 
				
			||||||
    ),
 | 
					    ),
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
def test_arbitrary_maxval(data, mode, pixels):
 | 
					def test_arbitrary_maxval(data, mode, pixels) -> None:
 | 
				
			||||||
    fp = BytesIO(data)
 | 
					    fp = BytesIO(data)
 | 
				
			||||||
    with Image.open(fp) as im:
 | 
					    with Image.open(fp) as im:
 | 
				
			||||||
        assert im.size == (3, 1)
 | 
					        assert im.size == (3, 1)
 | 
				
			||||||
| 
						 | 
					@ -79,7 +80,7 @@ def test_arbitrary_maxval(data, mode, pixels):
 | 
				
			||||||
        assert tuple(px[x, 0] for x in range(3)) == pixels
 | 
					        assert tuple(px[x, 0] for x in range(3)) == pixels
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_16bit_pgm():
 | 
					def test_16bit_pgm() -> None:
 | 
				
			||||||
    with Image.open("Tests/images/16_bit_binary.pgm") as im:
 | 
					    with Image.open("Tests/images/16_bit_binary.pgm") as im:
 | 
				
			||||||
        assert im.mode == "I"
 | 
					        assert im.mode == "I"
 | 
				
			||||||
        assert im.size == (20, 100)
 | 
					        assert im.size == (20, 100)
 | 
				
			||||||
| 
						 | 
					@ -88,7 +89,7 @@ def test_16bit_pgm():
 | 
				
			||||||
        assert_image_equal_tofile(im, "Tests/images/16_bit_binary_pgm.png")
 | 
					        assert_image_equal_tofile(im, "Tests/images/16_bit_binary_pgm.png")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_16bit_pgm_write(tmp_path):
 | 
					def test_16bit_pgm_write(tmp_path: Path) -> None:
 | 
				
			||||||
    with Image.open("Tests/images/16_bit_binary.pgm") as im:
 | 
					    with Image.open("Tests/images/16_bit_binary.pgm") as im:
 | 
				
			||||||
        filename = str(tmp_path / "temp.pgm")
 | 
					        filename = str(tmp_path / "temp.pgm")
 | 
				
			||||||
        im.save(filename, "PPM")
 | 
					        im.save(filename, "PPM")
 | 
				
			||||||
| 
						 | 
					@ -96,7 +97,7 @@ def test_16bit_pgm_write(tmp_path):
 | 
				
			||||||
        assert_image_equal_tofile(im, filename)
 | 
					        assert_image_equal_tofile(im, filename)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_pnm(tmp_path):
 | 
					def test_pnm(tmp_path: Path) -> None:
 | 
				
			||||||
    with Image.open("Tests/images/hopper.pnm") as im:
 | 
					    with Image.open("Tests/images/hopper.pnm") as im:
 | 
				
			||||||
        assert_image_similar(im, hopper(), 0.0001)
 | 
					        assert_image_similar(im, hopper(), 0.0001)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -106,7 +107,7 @@ def test_pnm(tmp_path):
 | 
				
			||||||
        assert_image_equal_tofile(im, filename)
 | 
					        assert_image_equal_tofile(im, filename)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_pfm(tmp_path):
 | 
					def test_pfm(tmp_path: Path) -> None:
 | 
				
			||||||
    with Image.open("Tests/images/hopper.pfm") as im:
 | 
					    with Image.open("Tests/images/hopper.pfm") as im:
 | 
				
			||||||
        assert im.info["scale"] == 1.0
 | 
					        assert im.info["scale"] == 1.0
 | 
				
			||||||
        assert_image_equal(im, hopper("F"))
 | 
					        assert_image_equal(im, hopper("F"))
 | 
				
			||||||
| 
						 | 
					@ -117,7 +118,7 @@ def test_pfm(tmp_path):
 | 
				
			||||||
        assert_image_equal_tofile(im, filename)
 | 
					        assert_image_equal_tofile(im, filename)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_pfm_big_endian(tmp_path):
 | 
					def test_pfm_big_endian(tmp_path: Path) -> None:
 | 
				
			||||||
    with Image.open("Tests/images/hopper_be.pfm") as im:
 | 
					    with Image.open("Tests/images/hopper_be.pfm") as im:
 | 
				
			||||||
        assert im.info["scale"] == 2.5
 | 
					        assert im.info["scale"] == 2.5
 | 
				
			||||||
        assert_image_equal(im, hopper("F"))
 | 
					        assert_image_equal(im, hopper("F"))
 | 
				
			||||||
| 
						 | 
					@ -138,7 +139,7 @@ def test_pfm_big_endian(tmp_path):
 | 
				
			||||||
        b"Pf 1 1 -0.0 \0\0\0\0",
 | 
					        b"Pf 1 1 -0.0 \0\0\0\0",
 | 
				
			||||||
    ],
 | 
					    ],
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
def test_pfm_invalid(data):
 | 
					def test_pfm_invalid(data) -> None:
 | 
				
			||||||
    with pytest.raises(ValueError):
 | 
					    with pytest.raises(ValueError):
 | 
				
			||||||
        with Image.open(BytesIO(data)):
 | 
					        with Image.open(BytesIO(data)):
 | 
				
			||||||
            pass
 | 
					            pass
 | 
				
			||||||
| 
						 | 
					@ -161,12 +162,12 @@ def test_pfm_invalid(data):
 | 
				
			||||||
        ),
 | 
					        ),
 | 
				
			||||||
    ),
 | 
					    ),
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
def test_plain(plain_path, raw_path):
 | 
					def test_plain(plain_path, raw_path) -> None:
 | 
				
			||||||
    with Image.open(plain_path) as im:
 | 
					    with Image.open(plain_path) as im:
 | 
				
			||||||
        assert_image_equal_tofile(im, raw_path)
 | 
					        assert_image_equal_tofile(im, raw_path)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_16bit_plain_pgm():
 | 
					def test_16bit_plain_pgm() -> None:
 | 
				
			||||||
    # P2 with maxval 2 ** 16 - 1
 | 
					    # P2 with maxval 2 ** 16 - 1
 | 
				
			||||||
    with Image.open("Tests/images/hopper_16bit_plain.pgm") as im:
 | 
					    with Image.open("Tests/images/hopper_16bit_plain.pgm") as im:
 | 
				
			||||||
        assert im.mode == "I"
 | 
					        assert im.mode == "I"
 | 
				
			||||||
| 
						 | 
					@ -185,7 +186,7 @@ def test_16bit_plain_pgm():
 | 
				
			||||||
        (b"P3\n2 2\n255", b"0 0 0 001 1 1 2 2 2 255 255 255", 10**6),
 | 
					        (b"P3\n2 2\n255", b"0 0 0 001 1 1 2 2 2 255 255 255", 10**6),
 | 
				
			||||||
    ),
 | 
					    ),
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
def test_plain_data_with_comment(tmp_path, header, data, comment_count):
 | 
					def test_plain_data_with_comment(tmp_path: Path, header, data, comment_count) -> None:
 | 
				
			||||||
    path1 = str(tmp_path / "temp1.ppm")
 | 
					    path1 = str(tmp_path / "temp1.ppm")
 | 
				
			||||||
    path2 = str(tmp_path / "temp2.ppm")
 | 
					    path2 = str(tmp_path / "temp2.ppm")
 | 
				
			||||||
    comment = b"# comment" * comment_count
 | 
					    comment = b"# comment" * comment_count
 | 
				
			||||||
| 
						 | 
					@ -198,7 +199,7 @@ def test_plain_data_with_comment(tmp_path, header, data, comment_count):
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@pytest.mark.parametrize("data", (b"P1\n128 128\n", b"P3\n128 128\n255\n"))
 | 
					@pytest.mark.parametrize("data", (b"P1\n128 128\n", b"P3\n128 128\n255\n"))
 | 
				
			||||||
def test_plain_truncated_data(tmp_path, data):
 | 
					def test_plain_truncated_data(tmp_path: Path, data) -> None:
 | 
				
			||||||
    path = str(tmp_path / "temp.ppm")
 | 
					    path = str(tmp_path / "temp.ppm")
 | 
				
			||||||
    with open(path, "wb") as f:
 | 
					    with open(path, "wb") as f:
 | 
				
			||||||
        f.write(data)
 | 
					        f.write(data)
 | 
				
			||||||
| 
						 | 
					@ -209,7 +210,7 @@ def test_plain_truncated_data(tmp_path, data):
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@pytest.mark.parametrize("data", (b"P1\n128 128\n1009", b"P3\n128 128\n255\n100A"))
 | 
					@pytest.mark.parametrize("data", (b"P1\n128 128\n1009", b"P3\n128 128\n255\n100A"))
 | 
				
			||||||
def test_plain_invalid_data(tmp_path, data):
 | 
					def test_plain_invalid_data(tmp_path: Path, data) -> None:
 | 
				
			||||||
    path = str(tmp_path / "temp.ppm")
 | 
					    path = str(tmp_path / "temp.ppm")
 | 
				
			||||||
    with open(path, "wb") as f:
 | 
					    with open(path, "wb") as f:
 | 
				
			||||||
        f.write(data)
 | 
					        f.write(data)
 | 
				
			||||||
| 
						 | 
					@ -226,7 +227,7 @@ def test_plain_invalid_data(tmp_path, data):
 | 
				
			||||||
        b"P3\n128 128\n255\n012345678910 0",  # token too long
 | 
					        b"P3\n128 128\n255\n012345678910 0",  # token too long
 | 
				
			||||||
    ),
 | 
					    ),
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
def test_plain_ppm_token_too_long(tmp_path, data):
 | 
					def test_plain_ppm_token_too_long(tmp_path: Path, data) -> None:
 | 
				
			||||||
    path = str(tmp_path / "temp.ppm")
 | 
					    path = str(tmp_path / "temp.ppm")
 | 
				
			||||||
    with open(path, "wb") as f:
 | 
					    with open(path, "wb") as f:
 | 
				
			||||||
        f.write(data)
 | 
					        f.write(data)
 | 
				
			||||||
| 
						 | 
					@ -236,7 +237,7 @@ def test_plain_ppm_token_too_long(tmp_path, data):
 | 
				
			||||||
            im.load()
 | 
					            im.load()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_plain_ppm_value_too_large(tmp_path):
 | 
					def test_plain_ppm_value_too_large(tmp_path: Path) -> None:
 | 
				
			||||||
    path = str(tmp_path / "temp.ppm")
 | 
					    path = str(tmp_path / "temp.ppm")
 | 
				
			||||||
    with open(path, "wb") as f:
 | 
					    with open(path, "wb") as f:
 | 
				
			||||||
        f.write(b"P3\n128 128\n255\n256")
 | 
					        f.write(b"P3\n128 128\n255\n256")
 | 
				
			||||||
| 
						 | 
					@ -246,12 +247,12 @@ def test_plain_ppm_value_too_large(tmp_path):
 | 
				
			||||||
            im.load()
 | 
					            im.load()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_magic():
 | 
					def test_magic() -> None:
 | 
				
			||||||
    with pytest.raises(SyntaxError):
 | 
					    with pytest.raises(SyntaxError):
 | 
				
			||||||
        PpmImagePlugin.PpmImageFile(fp=BytesIO(b"PyInvalid"))
 | 
					        PpmImagePlugin.PpmImageFile(fp=BytesIO(b"PyInvalid"))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_header_with_comments(tmp_path):
 | 
					def test_header_with_comments(tmp_path: Path) -> None:
 | 
				
			||||||
    path = str(tmp_path / "temp.ppm")
 | 
					    path = str(tmp_path / "temp.ppm")
 | 
				
			||||||
    with open(path, "wb") as f:
 | 
					    with open(path, "wb") as f:
 | 
				
			||||||
        f.write(b"P6 #comment\n#comment\r12#comment\r8\n128 #comment\n255\n")
 | 
					        f.write(b"P6 #comment\n#comment\r12#comment\r8\n128 #comment\n255\n")
 | 
				
			||||||
| 
						 | 
					@ -260,7 +261,7 @@ def test_header_with_comments(tmp_path):
 | 
				
			||||||
        assert im.size == (128, 128)
 | 
					        assert im.size == (128, 128)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_non_integer_token(tmp_path):
 | 
					def test_non_integer_token(tmp_path: Path) -> None:
 | 
				
			||||||
    path = str(tmp_path / "temp.ppm")
 | 
					    path = str(tmp_path / "temp.ppm")
 | 
				
			||||||
    with open(path, "wb") as f:
 | 
					    with open(path, "wb") as f:
 | 
				
			||||||
        f.write(b"P6\nTEST")
 | 
					        f.write(b"P6\nTEST")
 | 
				
			||||||
| 
						 | 
					@ -270,7 +271,7 @@ def test_non_integer_token(tmp_path):
 | 
				
			||||||
            pass
 | 
					            pass
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_header_token_too_long(tmp_path):
 | 
					def test_header_token_too_long(tmp_path: Path) -> None:
 | 
				
			||||||
    path = str(tmp_path / "temp.ppm")
 | 
					    path = str(tmp_path / "temp.ppm")
 | 
				
			||||||
    with open(path, "wb") as f:
 | 
					    with open(path, "wb") as f:
 | 
				
			||||||
        f.write(b"P6\n 01234567890")
 | 
					        f.write(b"P6\n 01234567890")
 | 
				
			||||||
| 
						 | 
					@ -282,7 +283,7 @@ def test_header_token_too_long(tmp_path):
 | 
				
			||||||
    assert str(e.value) == "Token too long in file header: 01234567890"
 | 
					    assert str(e.value) == "Token too long in file header: 01234567890"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_truncated_file(tmp_path):
 | 
					def test_truncated_file(tmp_path: Path) -> None:
 | 
				
			||||||
    # Test EOF in header
 | 
					    # Test EOF in header
 | 
				
			||||||
    path = str(tmp_path / "temp.pgm")
 | 
					    path = str(tmp_path / "temp.pgm")
 | 
				
			||||||
    with open(path, "wb") as f:
 | 
					    with open(path, "wb") as f:
 | 
				
			||||||
| 
						 | 
					@ -301,7 +302,7 @@ def test_truncated_file(tmp_path):
 | 
				
			||||||
            im.load()
 | 
					            im.load()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_not_enough_image_data(tmp_path):
 | 
					def test_not_enough_image_data(tmp_path: Path) -> None:
 | 
				
			||||||
    path = str(tmp_path / "temp.ppm")
 | 
					    path = str(tmp_path / "temp.ppm")
 | 
				
			||||||
    with open(path, "wb") as f:
 | 
					    with open(path, "wb") as f:
 | 
				
			||||||
        f.write(b"P2 1 2 255 255")
 | 
					        f.write(b"P2 1 2 255 255")
 | 
				
			||||||
| 
						 | 
					@ -312,7 +313,7 @@ def test_not_enough_image_data(tmp_path):
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@pytest.mark.parametrize("maxval", (b"0", b"65536"))
 | 
					@pytest.mark.parametrize("maxval", (b"0", b"65536"))
 | 
				
			||||||
def test_invalid_maxval(maxval, tmp_path):
 | 
					def test_invalid_maxval(maxval, tmp_path: Path) -> None:
 | 
				
			||||||
    path = str(tmp_path / "temp.ppm")
 | 
					    path = str(tmp_path / "temp.ppm")
 | 
				
			||||||
    with open(path, "wb") as f:
 | 
					    with open(path, "wb") as f:
 | 
				
			||||||
        f.write(b"P6\n3 1 " + maxval)
 | 
					        f.write(b"P6\n3 1 " + maxval)
 | 
				
			||||||
| 
						 | 
					@ -324,7 +325,7 @@ def test_invalid_maxval(maxval, tmp_path):
 | 
				
			||||||
    assert str(e.value) == "maxval must be greater than 0 and less than 65536"
 | 
					    assert str(e.value) == "maxval must be greater than 0 and less than 65536"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_neg_ppm():
 | 
					def test_neg_ppm() -> None:
 | 
				
			||||||
    # Storage.c accepted negative values for xsize, ysize.  the
 | 
					    # Storage.c accepted negative values for xsize, ysize.  the
 | 
				
			||||||
    # internal open_ppm function didn't check for sanity but it
 | 
					    # internal open_ppm function didn't check for sanity but it
 | 
				
			||||||
    # has been removed. The default opener doesn't accept negative
 | 
					    # has been removed. The default opener doesn't accept negative
 | 
				
			||||||
| 
						 | 
					@ -335,7 +336,7 @@ def test_neg_ppm():
 | 
				
			||||||
            pass
 | 
					            pass
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_mimetypes(tmp_path):
 | 
					def test_mimetypes(tmp_path: Path) -> None:
 | 
				
			||||||
    path = str(tmp_path / "temp.pgm")
 | 
					    path = str(tmp_path / "temp.pgm")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    with open(path, "wb") as f:
 | 
					    with open(path, "wb") as f:
 | 
				
			||||||
| 
						 | 
					@ -350,7 +351,7 @@ def test_mimetypes(tmp_path):
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@pytest.mark.parametrize("buffer", (True, False))
 | 
					@pytest.mark.parametrize("buffer", (True, False))
 | 
				
			||||||
def test_save_stdout(buffer):
 | 
					def test_save_stdout(buffer) -> None:
 | 
				
			||||||
    old_stdout = sys.stdout
 | 
					    old_stdout = sys.stdout
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if buffer:
 | 
					    if buffer:
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -11,7 +11,7 @@ from .helper import assert_image_equal_tofile, assert_image_similar, hopper, is_
 | 
				
			||||||
test_file = "Tests/images/hopper.psd"
 | 
					test_file = "Tests/images/hopper.psd"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_sanity():
 | 
					def test_sanity() -> None:
 | 
				
			||||||
    with Image.open(test_file) as im:
 | 
					    with Image.open(test_file) as im:
 | 
				
			||||||
        im.load()
 | 
					        im.load()
 | 
				
			||||||
        assert im.mode == "RGB"
 | 
					        assert im.mode == "RGB"
 | 
				
			||||||
| 
						 | 
					@ -24,8 +24,8 @@ def test_sanity():
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@pytest.mark.skipif(is_pypy(), reason="Requires CPython")
 | 
					@pytest.mark.skipif(is_pypy(), reason="Requires CPython")
 | 
				
			||||||
def test_unclosed_file():
 | 
					def test_unclosed_file() -> None:
 | 
				
			||||||
    def open():
 | 
					    def open() -> None:
 | 
				
			||||||
        im = Image.open(test_file)
 | 
					        im = Image.open(test_file)
 | 
				
			||||||
        im.load()
 | 
					        im.load()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -33,27 +33,27 @@ def test_unclosed_file():
 | 
				
			||||||
        open()
 | 
					        open()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_closed_file():
 | 
					def test_closed_file() -> None:
 | 
				
			||||||
    with warnings.catch_warnings():
 | 
					    with warnings.catch_warnings():
 | 
				
			||||||
        im = Image.open(test_file)
 | 
					        im = Image.open(test_file)
 | 
				
			||||||
        im.load()
 | 
					        im.load()
 | 
				
			||||||
        im.close()
 | 
					        im.close()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_context_manager():
 | 
					def test_context_manager() -> None:
 | 
				
			||||||
    with warnings.catch_warnings():
 | 
					    with warnings.catch_warnings():
 | 
				
			||||||
        with Image.open(test_file) as im:
 | 
					        with Image.open(test_file) as im:
 | 
				
			||||||
            im.load()
 | 
					            im.load()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_invalid_file():
 | 
					def test_invalid_file() -> None:
 | 
				
			||||||
    invalid_file = "Tests/images/flower.jpg"
 | 
					    invalid_file = "Tests/images/flower.jpg"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    with pytest.raises(SyntaxError):
 | 
					    with pytest.raises(SyntaxError):
 | 
				
			||||||
        PsdImagePlugin.PsdImageFile(invalid_file)
 | 
					        PsdImagePlugin.PsdImageFile(invalid_file)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_n_frames():
 | 
					def test_n_frames() -> None:
 | 
				
			||||||
    with Image.open("Tests/images/hopper_merged.psd") as im:
 | 
					    with Image.open("Tests/images/hopper_merged.psd") as im:
 | 
				
			||||||
        assert im.n_frames == 1
 | 
					        assert im.n_frames == 1
 | 
				
			||||||
        assert not im.is_animated
 | 
					        assert not im.is_animated
 | 
				
			||||||
| 
						 | 
					@ -64,7 +64,7 @@ def test_n_frames():
 | 
				
			||||||
            assert im.is_animated
 | 
					            assert im.is_animated
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_eoferror():
 | 
					def test_eoferror() -> None:
 | 
				
			||||||
    with Image.open(test_file) as im:
 | 
					    with Image.open(test_file) as im:
 | 
				
			||||||
        # PSD seek index starts at 1 rather than 0
 | 
					        # PSD seek index starts at 1 rather than 0
 | 
				
			||||||
        n_frames = im.n_frames + 1
 | 
					        n_frames = im.n_frames + 1
 | 
				
			||||||
| 
						 | 
					@ -78,7 +78,7 @@ def test_eoferror():
 | 
				
			||||||
        im.seek(n_frames - 1)
 | 
					        im.seek(n_frames - 1)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_seek_tell():
 | 
					def test_seek_tell() -> None:
 | 
				
			||||||
    with Image.open(test_file) as im:
 | 
					    with Image.open(test_file) as im:
 | 
				
			||||||
        layer_number = im.tell()
 | 
					        layer_number = im.tell()
 | 
				
			||||||
        assert layer_number == 1
 | 
					        assert layer_number == 1
 | 
				
			||||||
| 
						 | 
					@ -95,30 +95,30 @@ def test_seek_tell():
 | 
				
			||||||
        assert layer_number == 2
 | 
					        assert layer_number == 2
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_seek_eoferror():
 | 
					def test_seek_eoferror() -> None:
 | 
				
			||||||
    with Image.open(test_file) as im:
 | 
					    with Image.open(test_file) as im:
 | 
				
			||||||
        with pytest.raises(EOFError):
 | 
					        with pytest.raises(EOFError):
 | 
				
			||||||
            im.seek(-1)
 | 
					            im.seek(-1)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_open_after_exclusive_load():
 | 
					def test_open_after_exclusive_load() -> None:
 | 
				
			||||||
    with Image.open(test_file) as im:
 | 
					    with Image.open(test_file) as im:
 | 
				
			||||||
        im.load()
 | 
					        im.load()
 | 
				
			||||||
        im.seek(im.tell() + 1)
 | 
					        im.seek(im.tell() + 1)
 | 
				
			||||||
        im.load()
 | 
					        im.load()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_rgba():
 | 
					def test_rgba() -> None:
 | 
				
			||||||
    with Image.open("Tests/images/rgba.psd") as im:
 | 
					    with Image.open("Tests/images/rgba.psd") as im:
 | 
				
			||||||
        assert_image_equal_tofile(im, "Tests/images/imagedraw_square.png")
 | 
					        assert_image_equal_tofile(im, "Tests/images/imagedraw_square.png")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_layer_skip():
 | 
					def test_layer_skip() -> None:
 | 
				
			||||||
    with Image.open("Tests/images/five_channels.psd") as im:
 | 
					    with Image.open("Tests/images/five_channels.psd") as im:
 | 
				
			||||||
        assert im.n_frames == 1
 | 
					        assert im.n_frames == 1
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_icc_profile():
 | 
					def test_icc_profile() -> None:
 | 
				
			||||||
    with Image.open(test_file) as im:
 | 
					    with Image.open(test_file) as im:
 | 
				
			||||||
        assert "icc_profile" in im.info
 | 
					        assert "icc_profile" in im.info
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -126,12 +126,12 @@ def test_icc_profile():
 | 
				
			||||||
        assert len(icc_profile) == 3144
 | 
					        assert len(icc_profile) == 3144
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_no_icc_profile():
 | 
					def test_no_icc_profile() -> None:
 | 
				
			||||||
    with Image.open("Tests/images/hopper_merged.psd") as im:
 | 
					    with Image.open("Tests/images/hopper_merged.psd") as im:
 | 
				
			||||||
        assert "icc_profile" not in im.info
 | 
					        assert "icc_profile" not in im.info
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_combined_larger_than_size():
 | 
					def test_combined_larger_than_size() -> None:
 | 
				
			||||||
    # The combined size of the individual parts is larger than the
 | 
					    # The combined size of the individual parts is larger than the
 | 
				
			||||||
    # declared 'size' of the extra data field, resulting in a backwards seek.
 | 
					    # declared 'size' of the extra data field, resulting in a backwards seek.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -157,7 +157,7 @@ def test_combined_larger_than_size():
 | 
				
			||||||
        ("Tests/images/timeout-dedc7a4ebd856d79b4359bbcc79e8ef231ce38f6.psd", OSError),
 | 
					        ("Tests/images/timeout-dedc7a4ebd856d79b4359bbcc79e8ef231ce38f6.psd", OSError),
 | 
				
			||||||
    ],
 | 
					    ],
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
def test_crashes(test_file, raises):
 | 
					def test_crashes(test_file, raises) -> None:
 | 
				
			||||||
    with open(test_file, "rb") as f:
 | 
					    with open(test_file, "rb") as f:
 | 
				
			||||||
        with pytest.raises(raises):
 | 
					        with pytest.raises(raises):
 | 
				
			||||||
            with Image.open(f):
 | 
					            with Image.open(f):
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,5 +1,7 @@
 | 
				
			||||||
from __future__ import annotations
 | 
					from __future__ import annotations
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					from pathlib import Path
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import pytest
 | 
					import pytest
 | 
				
			||||||
 | 
					
 | 
				
			||||||
from PIL import Image, SgiImagePlugin
 | 
					from PIL import Image, SgiImagePlugin
 | 
				
			||||||
| 
						 | 
					@ -12,7 +14,7 @@ from .helper import (
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_rgb():
 | 
					def test_rgb() -> None:
 | 
				
			||||||
    # Created with ImageMagick then renamed:
 | 
					    # Created with ImageMagick then renamed:
 | 
				
			||||||
    # convert hopper.ppm -compress None sgi:hopper.rgb
 | 
					    # convert hopper.ppm -compress None sgi:hopper.rgb
 | 
				
			||||||
    test_file = "Tests/images/hopper.rgb"
 | 
					    test_file = "Tests/images/hopper.rgb"
 | 
				
			||||||
| 
						 | 
					@ -22,11 +24,11 @@ def test_rgb():
 | 
				
			||||||
        assert im.get_format_mimetype() == "image/rgb"
 | 
					        assert im.get_format_mimetype() == "image/rgb"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_rgb16():
 | 
					def test_rgb16() -> None:
 | 
				
			||||||
    assert_image_equal_tofile(hopper(), "Tests/images/hopper16.rgb")
 | 
					    assert_image_equal_tofile(hopper(), "Tests/images/hopper16.rgb")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_l():
 | 
					def test_l() -> None:
 | 
				
			||||||
    # Created with ImageMagick
 | 
					    # Created with ImageMagick
 | 
				
			||||||
    # convert hopper.ppm -monochrome -compress None sgi:hopper.bw
 | 
					    # convert hopper.ppm -monochrome -compress None sgi:hopper.bw
 | 
				
			||||||
    test_file = "Tests/images/hopper.bw"
 | 
					    test_file = "Tests/images/hopper.bw"
 | 
				
			||||||
| 
						 | 
					@ -36,7 +38,7 @@ def test_l():
 | 
				
			||||||
        assert im.get_format_mimetype() == "image/sgi"
 | 
					        assert im.get_format_mimetype() == "image/sgi"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_rgba():
 | 
					def test_rgba() -> None:
 | 
				
			||||||
    # Created with ImageMagick:
 | 
					    # Created with ImageMagick:
 | 
				
			||||||
    # convert transparent.png -compress None transparent.sgi
 | 
					    # convert transparent.png -compress None transparent.sgi
 | 
				
			||||||
    test_file = "Tests/images/transparent.sgi"
 | 
					    test_file = "Tests/images/transparent.sgi"
 | 
				
			||||||
| 
						 | 
					@ -46,7 +48,7 @@ def test_rgba():
 | 
				
			||||||
        assert im.get_format_mimetype() == "image/sgi"
 | 
					        assert im.get_format_mimetype() == "image/sgi"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_rle():
 | 
					def test_rle() -> None:
 | 
				
			||||||
    # Created with ImageMagick:
 | 
					    # Created with ImageMagick:
 | 
				
			||||||
    # convert hopper.ppm  hopper.sgi
 | 
					    # convert hopper.ppm  hopper.sgi
 | 
				
			||||||
    test_file = "Tests/images/hopper.sgi"
 | 
					    test_file = "Tests/images/hopper.sgi"
 | 
				
			||||||
| 
						 | 
					@ -55,22 +57,22 @@ def test_rle():
 | 
				
			||||||
        assert_image_equal_tofile(im, "Tests/images/hopper.rgb")
 | 
					        assert_image_equal_tofile(im, "Tests/images/hopper.rgb")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_rle16():
 | 
					def test_rle16() -> None:
 | 
				
			||||||
    test_file = "Tests/images/tv16.sgi"
 | 
					    test_file = "Tests/images/tv16.sgi"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    with Image.open(test_file) as im:
 | 
					    with Image.open(test_file) as im:
 | 
				
			||||||
        assert_image_equal_tofile(im, "Tests/images/tv.rgb")
 | 
					        assert_image_equal_tofile(im, "Tests/images/tv.rgb")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_invalid_file():
 | 
					def test_invalid_file() -> None:
 | 
				
			||||||
    invalid_file = "Tests/images/flower.jpg"
 | 
					    invalid_file = "Tests/images/flower.jpg"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    with pytest.raises(ValueError):
 | 
					    with pytest.raises(ValueError):
 | 
				
			||||||
        SgiImagePlugin.SgiImageFile(invalid_file)
 | 
					        SgiImagePlugin.SgiImageFile(invalid_file)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_write(tmp_path):
 | 
					def test_write(tmp_path: Path) -> None:
 | 
				
			||||||
    def roundtrip(img):
 | 
					    def roundtrip(img) -> None:
 | 
				
			||||||
        out = str(tmp_path / "temp.sgi")
 | 
					        out = str(tmp_path / "temp.sgi")
 | 
				
			||||||
        img.save(out, format="sgi")
 | 
					        img.save(out, format="sgi")
 | 
				
			||||||
        assert_image_equal_tofile(img, out)
 | 
					        assert_image_equal_tofile(img, out)
 | 
				
			||||||
| 
						 | 
					@ -89,7 +91,7 @@ def test_write(tmp_path):
 | 
				
			||||||
    roundtrip(Image.new("L", (10, 1)))
 | 
					    roundtrip(Image.new("L", (10, 1)))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_write16(tmp_path):
 | 
					def test_write16(tmp_path: Path) -> None:
 | 
				
			||||||
    test_file = "Tests/images/hopper16.rgb"
 | 
					    test_file = "Tests/images/hopper16.rgb"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    with Image.open(test_file) as im:
 | 
					    with Image.open(test_file) as im:
 | 
				
			||||||
| 
						 | 
					@ -99,7 +101,7 @@ def test_write16(tmp_path):
 | 
				
			||||||
        assert_image_equal_tofile(im, out)
 | 
					        assert_image_equal_tofile(im, out)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_unsupported_mode(tmp_path):
 | 
					def test_unsupported_mode(tmp_path: Path) -> None:
 | 
				
			||||||
    im = hopper("LA")
 | 
					    im = hopper("LA")
 | 
				
			||||||
    out = str(tmp_path / "temp.sgi")
 | 
					    out = str(tmp_path / "temp.sgi")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -3,6 +3,7 @@ from __future__ import annotations
 | 
				
			||||||
import tempfile
 | 
					import tempfile
 | 
				
			||||||
import warnings
 | 
					import warnings
 | 
				
			||||||
from io import BytesIO
 | 
					from io import BytesIO
 | 
				
			||||||
 | 
					from pathlib import Path
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import pytest
 | 
					import pytest
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -13,7 +14,7 @@ from .helper import assert_image_equal_tofile, hopper, is_pypy
 | 
				
			||||||
TEST_FILE = "Tests/images/hopper.spider"
 | 
					TEST_FILE = "Tests/images/hopper.spider"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_sanity():
 | 
					def test_sanity() -> None:
 | 
				
			||||||
    with Image.open(TEST_FILE) as im:
 | 
					    with Image.open(TEST_FILE) as im:
 | 
				
			||||||
        im.load()
 | 
					        im.load()
 | 
				
			||||||
        assert im.mode == "F"
 | 
					        assert im.mode == "F"
 | 
				
			||||||
| 
						 | 
					@ -22,8 +23,8 @@ def test_sanity():
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@pytest.mark.skipif(is_pypy(), reason="Requires CPython")
 | 
					@pytest.mark.skipif(is_pypy(), reason="Requires CPython")
 | 
				
			||||||
def test_unclosed_file():
 | 
					def test_unclosed_file() -> None:
 | 
				
			||||||
    def open():
 | 
					    def open() -> None:
 | 
				
			||||||
        im = Image.open(TEST_FILE)
 | 
					        im = Image.open(TEST_FILE)
 | 
				
			||||||
        im.load()
 | 
					        im.load()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -31,20 +32,20 @@ def test_unclosed_file():
 | 
				
			||||||
        open()
 | 
					        open()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_closed_file():
 | 
					def test_closed_file() -> None:
 | 
				
			||||||
    with warnings.catch_warnings():
 | 
					    with warnings.catch_warnings():
 | 
				
			||||||
        im = Image.open(TEST_FILE)
 | 
					        im = Image.open(TEST_FILE)
 | 
				
			||||||
        im.load()
 | 
					        im.load()
 | 
				
			||||||
        im.close()
 | 
					        im.close()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_context_manager():
 | 
					def test_context_manager() -> None:
 | 
				
			||||||
    with warnings.catch_warnings():
 | 
					    with warnings.catch_warnings():
 | 
				
			||||||
        with Image.open(TEST_FILE) as im:
 | 
					        with Image.open(TEST_FILE) as im:
 | 
				
			||||||
            im.load()
 | 
					            im.load()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_save(tmp_path):
 | 
					def test_save(tmp_path: Path) -> None:
 | 
				
			||||||
    # Arrange
 | 
					    # Arrange
 | 
				
			||||||
    temp = str(tmp_path / "temp.spider")
 | 
					    temp = str(tmp_path / "temp.spider")
 | 
				
			||||||
    im = hopper()
 | 
					    im = hopper()
 | 
				
			||||||
| 
						 | 
					@ -59,7 +60,7 @@ def test_save(tmp_path):
 | 
				
			||||||
        assert im2.format == "SPIDER"
 | 
					        assert im2.format == "SPIDER"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_tempfile():
 | 
					def test_tempfile() -> None:
 | 
				
			||||||
    # Arrange
 | 
					    # Arrange
 | 
				
			||||||
    im = hopper()
 | 
					    im = hopper()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -75,11 +76,11 @@ def test_tempfile():
 | 
				
			||||||
            assert reloaded.format == "SPIDER"
 | 
					            assert reloaded.format == "SPIDER"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_is_spider_image():
 | 
					def test_is_spider_image() -> None:
 | 
				
			||||||
    assert SpiderImagePlugin.isSpiderImage(TEST_FILE)
 | 
					    assert SpiderImagePlugin.isSpiderImage(TEST_FILE)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_tell():
 | 
					def test_tell() -> None:
 | 
				
			||||||
    # Arrange
 | 
					    # Arrange
 | 
				
			||||||
    with Image.open(TEST_FILE) as im:
 | 
					    with Image.open(TEST_FILE) as im:
 | 
				
			||||||
        # Act
 | 
					        # Act
 | 
				
			||||||
| 
						 | 
					@ -89,13 +90,13 @@ def test_tell():
 | 
				
			||||||
        assert index == 0
 | 
					        assert index == 0
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_n_frames():
 | 
					def test_n_frames() -> None:
 | 
				
			||||||
    with Image.open(TEST_FILE) as im:
 | 
					    with Image.open(TEST_FILE) as im:
 | 
				
			||||||
        assert im.n_frames == 1
 | 
					        assert im.n_frames == 1
 | 
				
			||||||
        assert not im.is_animated
 | 
					        assert not im.is_animated
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_load_image_series():
 | 
					def test_load_image_series() -> None:
 | 
				
			||||||
    # Arrange
 | 
					    # Arrange
 | 
				
			||||||
    not_spider_file = "Tests/images/hopper.ppm"
 | 
					    not_spider_file = "Tests/images/hopper.ppm"
 | 
				
			||||||
    file_list = [TEST_FILE, not_spider_file, "path/not_found.ext"]
 | 
					    file_list = [TEST_FILE, not_spider_file, "path/not_found.ext"]
 | 
				
			||||||
| 
						 | 
					@ -109,7 +110,7 @@ def test_load_image_series():
 | 
				
			||||||
    assert img_list[0].size == (128, 128)
 | 
					    assert img_list[0].size == (128, 128)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_load_image_series_no_input():
 | 
					def test_load_image_series_no_input() -> None:
 | 
				
			||||||
    # Arrange
 | 
					    # Arrange
 | 
				
			||||||
    file_list = None
 | 
					    file_list = None
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -120,7 +121,7 @@ def test_load_image_series_no_input():
 | 
				
			||||||
    assert img_list is None
 | 
					    assert img_list is None
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_is_int_not_a_number():
 | 
					def test_is_int_not_a_number() -> None:
 | 
				
			||||||
    # Arrange
 | 
					    # Arrange
 | 
				
			||||||
    not_a_number = "a"
 | 
					    not_a_number = "a"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -131,7 +132,7 @@ def test_is_int_not_a_number():
 | 
				
			||||||
    assert ret == 0
 | 
					    assert ret == 0
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_invalid_file():
 | 
					def test_invalid_file() -> None:
 | 
				
			||||||
    invalid_file = "Tests/images/invalid.spider"
 | 
					    invalid_file = "Tests/images/invalid.spider"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    with pytest.raises(OSError):
 | 
					    with pytest.raises(OSError):
 | 
				
			||||||
| 
						 | 
					@ -139,20 +140,20 @@ def test_invalid_file():
 | 
				
			||||||
            pass
 | 
					            pass
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_nonstack_file():
 | 
					def test_nonstack_file() -> None:
 | 
				
			||||||
    with Image.open(TEST_FILE) as im:
 | 
					    with Image.open(TEST_FILE) as im:
 | 
				
			||||||
        with pytest.raises(EOFError):
 | 
					        with pytest.raises(EOFError):
 | 
				
			||||||
            im.seek(0)
 | 
					            im.seek(0)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_nonstack_dos():
 | 
					def test_nonstack_dos() -> None:
 | 
				
			||||||
    with Image.open(TEST_FILE) as im:
 | 
					    with Image.open(TEST_FILE) as im:
 | 
				
			||||||
        for i, frame in enumerate(ImageSequence.Iterator(im)):
 | 
					        for i, frame in enumerate(ImageSequence.Iterator(im)):
 | 
				
			||||||
            assert i <= 1, "Non-stack DOS file test failed"
 | 
					            assert i <= 1, "Non-stack DOS file test failed"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# for issue #4093
 | 
					# for issue #4093
 | 
				
			||||||
def test_odd_size():
 | 
					def test_odd_size() -> None:
 | 
				
			||||||
    data = BytesIO()
 | 
					    data = BytesIO()
 | 
				
			||||||
    width = 100
 | 
					    width = 100
 | 
				
			||||||
    im = Image.new("F", (width, 64))
 | 
					    im = Image.new("F", (width, 64))
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -11,7 +11,7 @@ from .helper import assert_image_equal_tofile, assert_image_similar, hopper
 | 
				
			||||||
EXTRA_DIR = "Tests/images/sunraster"
 | 
					EXTRA_DIR = "Tests/images/sunraster"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_sanity():
 | 
					def test_sanity() -> None:
 | 
				
			||||||
    # Arrange
 | 
					    # Arrange
 | 
				
			||||||
    # Created with ImageMagick: convert hopper.jpg hopper.ras
 | 
					    # Created with ImageMagick: convert hopper.jpg hopper.ras
 | 
				
			||||||
    test_file = "Tests/images/hopper.ras"
 | 
					    test_file = "Tests/images/hopper.ras"
 | 
				
			||||||
| 
						 | 
					@ -28,7 +28,7 @@ def test_sanity():
 | 
				
			||||||
        SunImagePlugin.SunImageFile(invalid_file)
 | 
					        SunImagePlugin.SunImageFile(invalid_file)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_im1():
 | 
					def test_im1() -> None:
 | 
				
			||||||
    with Image.open("Tests/images/sunraster.im1") as im:
 | 
					    with Image.open("Tests/images/sunraster.im1") as im:
 | 
				
			||||||
        assert_image_equal_tofile(im, "Tests/images/sunraster.im1.png")
 | 
					        assert_image_equal_tofile(im, "Tests/images/sunraster.im1.png")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -36,7 +36,7 @@ def test_im1():
 | 
				
			||||||
@pytest.mark.skipif(
 | 
					@pytest.mark.skipif(
 | 
				
			||||||
    not os.path.exists(EXTRA_DIR), reason="Extra image files not installed"
 | 
					    not os.path.exists(EXTRA_DIR), reason="Extra image files not installed"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
def test_others():
 | 
					def test_others() -> None:
 | 
				
			||||||
    files = (
 | 
					    files = (
 | 
				
			||||||
        os.path.join(EXTRA_DIR, f)
 | 
					        os.path.join(EXTRA_DIR, f)
 | 
				
			||||||
        for f in os.listdir(EXTRA_DIR)
 | 
					        for f in os.listdir(EXTRA_DIR)
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -19,7 +19,7 @@ TEST_TAR_FILE = "Tests/images/hopper.tar"
 | 
				
			||||||
        ("jpg", "hopper.jpg", "JPEG"),
 | 
					        ("jpg", "hopper.jpg", "JPEG"),
 | 
				
			||||||
    ),
 | 
					    ),
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
def test_sanity(codec, test_path, format):
 | 
					def test_sanity(codec, test_path, format) -> None:
 | 
				
			||||||
    if features.check(codec):
 | 
					    if features.check(codec):
 | 
				
			||||||
        with TarIO.TarIO(TEST_TAR_FILE, test_path) as tar:
 | 
					        with TarIO.TarIO(TEST_TAR_FILE, test_path) as tar:
 | 
				
			||||||
            with Image.open(tar) as im:
 | 
					            with Image.open(tar) as im:
 | 
				
			||||||
| 
						 | 
					@ -30,18 +30,18 @@ def test_sanity(codec, test_path, format):
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@pytest.mark.skipif(is_pypy(), reason="Requires CPython")
 | 
					@pytest.mark.skipif(is_pypy(), reason="Requires CPython")
 | 
				
			||||||
def test_unclosed_file():
 | 
					def test_unclosed_file() -> None:
 | 
				
			||||||
    with pytest.warns(ResourceWarning):
 | 
					    with pytest.warns(ResourceWarning):
 | 
				
			||||||
        TarIO.TarIO(TEST_TAR_FILE, "hopper.jpg")
 | 
					        TarIO.TarIO(TEST_TAR_FILE, "hopper.jpg")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_close():
 | 
					def test_close() -> None:
 | 
				
			||||||
    with warnings.catch_warnings():
 | 
					    with warnings.catch_warnings():
 | 
				
			||||||
        tar = TarIO.TarIO(TEST_TAR_FILE, "hopper.jpg")
 | 
					        tar = TarIO.TarIO(TEST_TAR_FILE, "hopper.jpg")
 | 
				
			||||||
        tar.close()
 | 
					        tar.close()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_contextmanager():
 | 
					def test_contextmanager() -> None:
 | 
				
			||||||
    with warnings.catch_warnings():
 | 
					    with warnings.catch_warnings():
 | 
				
			||||||
        with TarIO.TarIO(TEST_TAR_FILE, "hopper.jpg"):
 | 
					        with TarIO.TarIO(TEST_TAR_FILE, "hopper.jpg"):
 | 
				
			||||||
            pass
 | 
					            pass
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -3,6 +3,7 @@ from __future__ import annotations
 | 
				
			||||||
import os
 | 
					import os
 | 
				
			||||||
from glob import glob
 | 
					from glob import glob
 | 
				
			||||||
from itertools import product
 | 
					from itertools import product
 | 
				
			||||||
 | 
					from pathlib import Path
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import pytest
 | 
					import pytest
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -21,8 +22,8 @@ _ORIGIN_TO_ORIENTATION = {"tl": 1, "bl": -1}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@pytest.mark.parametrize("mode", _MODES)
 | 
					@pytest.mark.parametrize("mode", _MODES)
 | 
				
			||||||
def test_sanity(mode, tmp_path):
 | 
					def test_sanity(mode, tmp_path: Path) -> None:
 | 
				
			||||||
    def roundtrip(original_im):
 | 
					    def roundtrip(original_im) -> None:
 | 
				
			||||||
        out = str(tmp_path / "temp.tga")
 | 
					        out = str(tmp_path / "temp.tga")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        original_im.save(out, rle=rle)
 | 
					        original_im.save(out, rle=rle)
 | 
				
			||||||
| 
						 | 
					@ -64,7 +65,7 @@ def test_sanity(mode, tmp_path):
 | 
				
			||||||
                    roundtrip(original_im)
 | 
					                    roundtrip(original_im)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_palette_depth_16(tmp_path):
 | 
					def test_palette_depth_16(tmp_path: Path) -> None:
 | 
				
			||||||
    with Image.open("Tests/images/p_16.tga") as im:
 | 
					    with Image.open("Tests/images/p_16.tga") as im:
 | 
				
			||||||
        assert_image_equal_tofile(im.convert("RGB"), "Tests/images/p_16.png")
 | 
					        assert_image_equal_tofile(im.convert("RGB"), "Tests/images/p_16.png")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -74,7 +75,7 @@ def test_palette_depth_16(tmp_path):
 | 
				
			||||||
            assert_image_equal_tofile(reloaded.convert("RGB"), "Tests/images/p_16.png")
 | 
					            assert_image_equal_tofile(reloaded.convert("RGB"), "Tests/images/p_16.png")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_id_field():
 | 
					def test_id_field() -> None:
 | 
				
			||||||
    # tga file with id field
 | 
					    # tga file with id field
 | 
				
			||||||
    test_file = "Tests/images/tga_id_field.tga"
 | 
					    test_file = "Tests/images/tga_id_field.tga"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -84,7 +85,7 @@ def test_id_field():
 | 
				
			||||||
        assert im.size == (100, 100)
 | 
					        assert im.size == (100, 100)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_id_field_rle():
 | 
					def test_id_field_rle() -> None:
 | 
				
			||||||
    # tga file with id field
 | 
					    # tga file with id field
 | 
				
			||||||
    test_file = "Tests/images/rgb32rle.tga"
 | 
					    test_file = "Tests/images/rgb32rle.tga"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -94,7 +95,7 @@ def test_id_field_rle():
 | 
				
			||||||
        assert im.size == (199, 199)
 | 
					        assert im.size == (199, 199)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_cross_scan_line():
 | 
					def test_cross_scan_line() -> None:
 | 
				
			||||||
    with Image.open("Tests/images/cross_scan_line.tga") as im:
 | 
					    with Image.open("Tests/images/cross_scan_line.tga") as im:
 | 
				
			||||||
        assert_image_equal_tofile(im, "Tests/images/cross_scan_line.png")
 | 
					        assert_image_equal_tofile(im, "Tests/images/cross_scan_line.png")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -103,7 +104,7 @@ def test_cross_scan_line():
 | 
				
			||||||
            im.load()
 | 
					            im.load()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_save(tmp_path):
 | 
					def test_save(tmp_path: Path) -> None:
 | 
				
			||||||
    test_file = "Tests/images/tga_id_field.tga"
 | 
					    test_file = "Tests/images/tga_id_field.tga"
 | 
				
			||||||
    with Image.open(test_file) as im:
 | 
					    with Image.open(test_file) as im:
 | 
				
			||||||
        out = str(tmp_path / "temp.tga")
 | 
					        out = str(tmp_path / "temp.tga")
 | 
				
			||||||
| 
						 | 
					@ -120,7 +121,7 @@ def test_save(tmp_path):
 | 
				
			||||||
        assert test_im.size == (100, 100)
 | 
					        assert test_im.size == (100, 100)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_small_palette(tmp_path):
 | 
					def test_small_palette(tmp_path: Path) -> None:
 | 
				
			||||||
    im = Image.new("P", (1, 1))
 | 
					    im = Image.new("P", (1, 1))
 | 
				
			||||||
    colors = [0, 0, 0]
 | 
					    colors = [0, 0, 0]
 | 
				
			||||||
    im.putpalette(colors)
 | 
					    im.putpalette(colors)
 | 
				
			||||||
| 
						 | 
					@ -132,7 +133,7 @@ def test_small_palette(tmp_path):
 | 
				
			||||||
        assert reloaded.getpalette() == colors
 | 
					        assert reloaded.getpalette() == colors
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_save_wrong_mode(tmp_path):
 | 
					def test_save_wrong_mode(tmp_path: Path) -> None:
 | 
				
			||||||
    im = hopper("PA")
 | 
					    im = hopper("PA")
 | 
				
			||||||
    out = str(tmp_path / "temp.tga")
 | 
					    out = str(tmp_path / "temp.tga")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -140,7 +141,7 @@ def test_save_wrong_mode(tmp_path):
 | 
				
			||||||
        im.save(out)
 | 
					        im.save(out)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_save_mapdepth():
 | 
					def test_save_mapdepth() -> None:
 | 
				
			||||||
    # This image has been manually hexedited from 200x32_p_bl_raw.tga
 | 
					    # This image has been manually hexedited from 200x32_p_bl_raw.tga
 | 
				
			||||||
    # to include an origin
 | 
					    # to include an origin
 | 
				
			||||||
    test_file = "Tests/images/200x32_p_bl_raw_origin.tga"
 | 
					    test_file = "Tests/images/200x32_p_bl_raw_origin.tga"
 | 
				
			||||||
| 
						 | 
					@ -148,7 +149,7 @@ def test_save_mapdepth():
 | 
				
			||||||
        assert_image_equal_tofile(im, "Tests/images/tga/common/200x32_p.png")
 | 
					        assert_image_equal_tofile(im, "Tests/images/tga/common/200x32_p.png")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_save_id_section(tmp_path):
 | 
					def test_save_id_section(tmp_path: Path) -> None:
 | 
				
			||||||
    test_file = "Tests/images/rgb32rle.tga"
 | 
					    test_file = "Tests/images/rgb32rle.tga"
 | 
				
			||||||
    with Image.open(test_file) as im:
 | 
					    with Image.open(test_file) as im:
 | 
				
			||||||
        out = str(tmp_path / "temp.tga")
 | 
					        out = str(tmp_path / "temp.tga")
 | 
				
			||||||
| 
						 | 
					@ -179,7 +180,7 @@ def test_save_id_section(tmp_path):
 | 
				
			||||||
        assert "id_section" not in test_im.info
 | 
					        assert "id_section" not in test_im.info
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_save_orientation(tmp_path):
 | 
					def test_save_orientation(tmp_path: Path) -> None:
 | 
				
			||||||
    test_file = "Tests/images/rgb32rle.tga"
 | 
					    test_file = "Tests/images/rgb32rle.tga"
 | 
				
			||||||
    out = str(tmp_path / "temp.tga")
 | 
					    out = str(tmp_path / "temp.tga")
 | 
				
			||||||
    with Image.open(test_file) as im:
 | 
					    with Image.open(test_file) as im:
 | 
				
			||||||
| 
						 | 
					@ -190,7 +191,7 @@ def test_save_orientation(tmp_path):
 | 
				
			||||||
        assert test_im.info["orientation"] == 1
 | 
					        assert test_im.info["orientation"] == 1
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_horizontal_orientations():
 | 
					def test_horizontal_orientations() -> None:
 | 
				
			||||||
    # These images have been manually hexedited to have the relevant orientations
 | 
					    # These images have been manually hexedited to have the relevant orientations
 | 
				
			||||||
    with Image.open("Tests/images/rgb32rle_top_right.tga") as im:
 | 
					    with Image.open("Tests/images/rgb32rle_top_right.tga") as im:
 | 
				
			||||||
        assert im.load()[90, 90][:3] == (0, 0, 0)
 | 
					        assert im.load()[90, 90][:3] == (0, 0, 0)
 | 
				
			||||||
| 
						 | 
					@ -199,7 +200,7 @@ def test_horizontal_orientations():
 | 
				
			||||||
        assert im.load()[90, 90][:3] == (0, 255, 0)
 | 
					        assert im.load()[90, 90][:3] == (0, 255, 0)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_save_rle(tmp_path):
 | 
					def test_save_rle(tmp_path: Path) -> None:
 | 
				
			||||||
    test_file = "Tests/images/rgb32rle.tga"
 | 
					    test_file = "Tests/images/rgb32rle.tga"
 | 
				
			||||||
    with Image.open(test_file) as im:
 | 
					    with Image.open(test_file) as im:
 | 
				
			||||||
        assert im.info["compression"] == "tga_rle"
 | 
					        assert im.info["compression"] == "tga_rle"
 | 
				
			||||||
| 
						 | 
					@ -232,7 +233,7 @@ def test_save_rle(tmp_path):
 | 
				
			||||||
        assert test_im.info["compression"] == "tga_rle"
 | 
					        assert test_im.info["compression"] == "tga_rle"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_save_l_transparency(tmp_path):
 | 
					def test_save_l_transparency(tmp_path: Path) -> None:
 | 
				
			||||||
    # There are 559 transparent pixels in la.tga.
 | 
					    # There are 559 transparent pixels in la.tga.
 | 
				
			||||||
    num_transparent = 559
 | 
					    num_transparent = 559
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -3,6 +3,7 @@ from __future__ import annotations
 | 
				
			||||||
import os
 | 
					import os
 | 
				
			||||||
import warnings
 | 
					import warnings
 | 
				
			||||||
from io import BytesIO
 | 
					from io import BytesIO
 | 
				
			||||||
 | 
					from pathlib import Path
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import pytest
 | 
					import pytest
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -26,7 +27,7 @@ except ImportError:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class TestFileTiff:
 | 
					class TestFileTiff:
 | 
				
			||||||
    def test_sanity(self, tmp_path):
 | 
					    def test_sanity(self, tmp_path: Path) -> None:
 | 
				
			||||||
        filename = str(tmp_path / "temp.tif")
 | 
					        filename = str(tmp_path / "temp.tif")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        hopper("RGB").save(filename)
 | 
					        hopper("RGB").save(filename)
 | 
				
			||||||
| 
						 | 
					@ -58,21 +59,21 @@ class TestFileTiff:
 | 
				
			||||||
            pass
 | 
					            pass
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    @pytest.mark.skipif(is_pypy(), reason="Requires CPython")
 | 
					    @pytest.mark.skipif(is_pypy(), reason="Requires CPython")
 | 
				
			||||||
    def test_unclosed_file(self):
 | 
					    def test_unclosed_file(self) -> None:
 | 
				
			||||||
        def open():
 | 
					        def open() -> None:
 | 
				
			||||||
            im = Image.open("Tests/images/multipage.tiff")
 | 
					            im = Image.open("Tests/images/multipage.tiff")
 | 
				
			||||||
            im.load()
 | 
					            im.load()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        with pytest.warns(ResourceWarning):
 | 
					        with pytest.warns(ResourceWarning):
 | 
				
			||||||
            open()
 | 
					            open()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_closed_file(self):
 | 
					    def test_closed_file(self) -> None:
 | 
				
			||||||
        with warnings.catch_warnings():
 | 
					        with warnings.catch_warnings():
 | 
				
			||||||
            im = Image.open("Tests/images/multipage.tiff")
 | 
					            im = Image.open("Tests/images/multipage.tiff")
 | 
				
			||||||
            im.load()
 | 
					            im.load()
 | 
				
			||||||
            im.close()
 | 
					            im.close()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_seek_after_close(self):
 | 
					    def test_seek_after_close(self) -> None:
 | 
				
			||||||
        im = Image.open("Tests/images/multipage.tiff")
 | 
					        im = Image.open("Tests/images/multipage.tiff")
 | 
				
			||||||
        im.close()
 | 
					        im.close()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -81,12 +82,12 @@ class TestFileTiff:
 | 
				
			||||||
        with pytest.raises(ValueError):
 | 
					        with pytest.raises(ValueError):
 | 
				
			||||||
            im.seek(1)
 | 
					            im.seek(1)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_context_manager(self):
 | 
					    def test_context_manager(self) -> None:
 | 
				
			||||||
        with warnings.catch_warnings():
 | 
					        with warnings.catch_warnings():
 | 
				
			||||||
            with Image.open("Tests/images/multipage.tiff") as im:
 | 
					            with Image.open("Tests/images/multipage.tiff") as im:
 | 
				
			||||||
                im.load()
 | 
					                im.load()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_mac_tiff(self):
 | 
					    def test_mac_tiff(self) -> None:
 | 
				
			||||||
        # Read RGBa images from macOS [@PIL136]
 | 
					        # Read RGBa images from macOS [@PIL136]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        filename = "Tests/images/pil136.tiff"
 | 
					        filename = "Tests/images/pil136.tiff"
 | 
				
			||||||
| 
						 | 
					@ -98,7 +99,7 @@ class TestFileTiff:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            assert_image_similar_tofile(im, "Tests/images/pil136.png", 1)
 | 
					            assert_image_similar_tofile(im, "Tests/images/pil136.png", 1)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_bigtiff(self, tmp_path):
 | 
					    def test_bigtiff(self, tmp_path: Path) -> None:
 | 
				
			||||||
        with Image.open("Tests/images/hopper_bigtiff.tif") as im:
 | 
					        with Image.open("Tests/images/hopper_bigtiff.tif") as im:
 | 
				
			||||||
            assert_image_equal_tofile(im, "Tests/images/hopper.tif")
 | 
					            assert_image_equal_tofile(im, "Tests/images/hopper.tif")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -109,13 +110,13 @@ class TestFileTiff:
 | 
				
			||||||
            outfile = str(tmp_path / "temp.tif")
 | 
					            outfile = str(tmp_path / "temp.tif")
 | 
				
			||||||
            im.save(outfile, save_all=True, append_images=[im], tiffinfo=im.tag_v2)
 | 
					            im.save(outfile, save_all=True, append_images=[im], tiffinfo=im.tag_v2)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_set_legacy_api(self):
 | 
					    def test_set_legacy_api(self) -> None:
 | 
				
			||||||
        ifd = TiffImagePlugin.ImageFileDirectory_v2()
 | 
					        ifd = TiffImagePlugin.ImageFileDirectory_v2()
 | 
				
			||||||
        with pytest.raises(Exception) as e:
 | 
					        with pytest.raises(Exception) as e:
 | 
				
			||||||
            ifd.legacy_api = None
 | 
					            ifd.legacy_api = None
 | 
				
			||||||
        assert str(e.value) == "Not allowing setting of legacy api"
 | 
					        assert str(e.value) == "Not allowing setting of legacy api"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_xyres_tiff(self):
 | 
					    def test_xyres_tiff(self) -> None:
 | 
				
			||||||
        filename = "Tests/images/pil168.tif"
 | 
					        filename = "Tests/images/pil168.tif"
 | 
				
			||||||
        with Image.open(filename) as im:
 | 
					        with Image.open(filename) as im:
 | 
				
			||||||
            # legacy api
 | 
					            # legacy api
 | 
				
			||||||
| 
						 | 
					@ -128,7 +129,7 @@ class TestFileTiff:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            assert im.info["dpi"] == (72.0, 72.0)
 | 
					            assert im.info["dpi"] == (72.0, 72.0)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_xyres_fallback_tiff(self):
 | 
					    def test_xyres_fallback_tiff(self) -> None:
 | 
				
			||||||
        filename = "Tests/images/compression.tif"
 | 
					        filename = "Tests/images/compression.tif"
 | 
				
			||||||
        with Image.open(filename) as im:
 | 
					        with Image.open(filename) as im:
 | 
				
			||||||
            # v2 api
 | 
					            # v2 api
 | 
				
			||||||
| 
						 | 
					@ -142,7 +143,7 @@ class TestFileTiff:
 | 
				
			||||||
            # Fallback "inch".
 | 
					            # Fallback "inch".
 | 
				
			||||||
            assert im.info["dpi"] == (100.0, 100.0)
 | 
					            assert im.info["dpi"] == (100.0, 100.0)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_int_resolution(self):
 | 
					    def test_int_resolution(self) -> None:
 | 
				
			||||||
        filename = "Tests/images/pil168.tif"
 | 
					        filename = "Tests/images/pil168.tif"
 | 
				
			||||||
        with Image.open(filename) as im:
 | 
					        with Image.open(filename) as im:
 | 
				
			||||||
            # Try to read a file where X,Y_RESOLUTION are ints
 | 
					            # Try to read a file where X,Y_RESOLUTION are ints
 | 
				
			||||||
| 
						 | 
					@ -155,14 +156,14 @@ class TestFileTiff:
 | 
				
			||||||
        "resolution_unit, dpi",
 | 
					        "resolution_unit, dpi",
 | 
				
			||||||
        [(None, 72.8), (2, 72.8), (3, 184.912)],
 | 
					        [(None, 72.8), (2, 72.8), (3, 184.912)],
 | 
				
			||||||
    )
 | 
					    )
 | 
				
			||||||
    def test_load_float_dpi(self, resolution_unit, dpi):
 | 
					    def test_load_float_dpi(self, resolution_unit, dpi) -> None:
 | 
				
			||||||
        with Image.open(
 | 
					        with Image.open(
 | 
				
			||||||
            "Tests/images/hopper_float_dpi_" + str(resolution_unit) + ".tif"
 | 
					            "Tests/images/hopper_float_dpi_" + str(resolution_unit) + ".tif"
 | 
				
			||||||
        ) as im:
 | 
					        ) as im:
 | 
				
			||||||
            assert im.tag_v2.get(RESOLUTION_UNIT) == resolution_unit
 | 
					            assert im.tag_v2.get(RESOLUTION_UNIT) == resolution_unit
 | 
				
			||||||
            assert im.info["dpi"] == (dpi, dpi)
 | 
					            assert im.info["dpi"] == (dpi, dpi)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_save_float_dpi(self, tmp_path):
 | 
					    def test_save_float_dpi(self, tmp_path: Path) -> None:
 | 
				
			||||||
        outfile = str(tmp_path / "temp.tif")
 | 
					        outfile = str(tmp_path / "temp.tif")
 | 
				
			||||||
        with Image.open("Tests/images/hopper.tif") as im:
 | 
					        with Image.open("Tests/images/hopper.tif") as im:
 | 
				
			||||||
            dpi = (72.2, 72.2)
 | 
					            dpi = (72.2, 72.2)
 | 
				
			||||||
| 
						 | 
					@ -171,7 +172,7 @@ class TestFileTiff:
 | 
				
			||||||
            with Image.open(outfile) as reloaded:
 | 
					            with Image.open(outfile) as reloaded:
 | 
				
			||||||
                assert reloaded.info["dpi"] == dpi
 | 
					                assert reloaded.info["dpi"] == dpi
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_save_setting_missing_resolution(self):
 | 
					    def test_save_setting_missing_resolution(self) -> None:
 | 
				
			||||||
        b = BytesIO()
 | 
					        b = BytesIO()
 | 
				
			||||||
        with Image.open("Tests/images/10ct_32bit_128.tiff") as im:
 | 
					        with Image.open("Tests/images/10ct_32bit_128.tiff") as im:
 | 
				
			||||||
            im.save(b, format="tiff", resolution=123.45)
 | 
					            im.save(b, format="tiff", resolution=123.45)
 | 
				
			||||||
| 
						 | 
					@ -179,7 +180,7 @@ class TestFileTiff:
 | 
				
			||||||
            assert im.tag_v2[X_RESOLUTION] == 123.45
 | 
					            assert im.tag_v2[X_RESOLUTION] == 123.45
 | 
				
			||||||
            assert im.tag_v2[Y_RESOLUTION] == 123.45
 | 
					            assert im.tag_v2[Y_RESOLUTION] == 123.45
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_invalid_file(self):
 | 
					    def test_invalid_file(self) -> None:
 | 
				
			||||||
        invalid_file = "Tests/images/flower.jpg"
 | 
					        invalid_file = "Tests/images/flower.jpg"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        with pytest.raises(SyntaxError):
 | 
					        with pytest.raises(SyntaxError):
 | 
				
			||||||
| 
						 | 
					@ -190,30 +191,30 @@ class TestFileTiff:
 | 
				
			||||||
            TiffImagePlugin.TiffImageFile(invalid_file)
 | 
					            TiffImagePlugin.TiffImageFile(invalid_file)
 | 
				
			||||||
        TiffImagePlugin.PREFIXES.pop()
 | 
					        TiffImagePlugin.PREFIXES.pop()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_bad_exif(self):
 | 
					    def test_bad_exif(self) -> None:
 | 
				
			||||||
        with Image.open("Tests/images/hopper_bad_exif.jpg") as i:
 | 
					        with Image.open("Tests/images/hopper_bad_exif.jpg") as i:
 | 
				
			||||||
            # Should not raise struct.error.
 | 
					            # Should not raise struct.error.
 | 
				
			||||||
            with pytest.warns(UserWarning):
 | 
					            with pytest.warns(UserWarning):
 | 
				
			||||||
                i._getexif()
 | 
					                i._getexif()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_save_rgba(self, tmp_path):
 | 
					    def test_save_rgba(self, tmp_path: Path) -> None:
 | 
				
			||||||
        im = hopper("RGBA")
 | 
					        im = hopper("RGBA")
 | 
				
			||||||
        outfile = str(tmp_path / "temp.tif")
 | 
					        outfile = str(tmp_path / "temp.tif")
 | 
				
			||||||
        im.save(outfile)
 | 
					        im.save(outfile)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_save_unsupported_mode(self, tmp_path):
 | 
					    def test_save_unsupported_mode(self, tmp_path: Path) -> None:
 | 
				
			||||||
        im = hopper("HSV")
 | 
					        im = hopper("HSV")
 | 
				
			||||||
        outfile = str(tmp_path / "temp.tif")
 | 
					        outfile = str(tmp_path / "temp.tif")
 | 
				
			||||||
        with pytest.raises(OSError):
 | 
					        with pytest.raises(OSError):
 | 
				
			||||||
            im.save(outfile)
 | 
					            im.save(outfile)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_8bit_s(self):
 | 
					    def test_8bit_s(self) -> None:
 | 
				
			||||||
        with Image.open("Tests/images/8bit.s.tif") as im:
 | 
					        with Image.open("Tests/images/8bit.s.tif") as im:
 | 
				
			||||||
            im.load()
 | 
					            im.load()
 | 
				
			||||||
            assert im.mode == "L"
 | 
					            assert im.mode == "L"
 | 
				
			||||||
            assert im.getpixel((50, 50)) == 184
 | 
					            assert im.getpixel((50, 50)) == 184
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_little_endian(self):
 | 
					    def test_little_endian(self) -> None:
 | 
				
			||||||
        with Image.open("Tests/images/16bit.cropped.tif") as im:
 | 
					        with Image.open("Tests/images/16bit.cropped.tif") as im:
 | 
				
			||||||
            assert im.getpixel((0, 0)) == 480
 | 
					            assert im.getpixel((0, 0)) == 480
 | 
				
			||||||
            assert im.mode == "I;16"
 | 
					            assert im.mode == "I;16"
 | 
				
			||||||
| 
						 | 
					@ -223,7 +224,7 @@ class TestFileTiff:
 | 
				
			||||||
        assert b[0] == ord(b"\xe0")
 | 
					        assert b[0] == ord(b"\xe0")
 | 
				
			||||||
        assert b[1] == ord(b"\x01")
 | 
					        assert b[1] == ord(b"\x01")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_big_endian(self):
 | 
					    def test_big_endian(self) -> None:
 | 
				
			||||||
        with Image.open("Tests/images/16bit.MM.cropped.tif") as im:
 | 
					        with Image.open("Tests/images/16bit.MM.cropped.tif") as im:
 | 
				
			||||||
            assert im.getpixel((0, 0)) == 480
 | 
					            assert im.getpixel((0, 0)) == 480
 | 
				
			||||||
            assert im.mode == "I;16B"
 | 
					            assert im.mode == "I;16B"
 | 
				
			||||||
| 
						 | 
					@ -233,7 +234,7 @@ class TestFileTiff:
 | 
				
			||||||
        assert b[0] == ord(b"\x01")
 | 
					        assert b[0] == ord(b"\x01")
 | 
				
			||||||
        assert b[1] == ord(b"\xe0")
 | 
					        assert b[1] == ord(b"\xe0")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_16bit_r(self):
 | 
					    def test_16bit_r(self) -> None:
 | 
				
			||||||
        with Image.open("Tests/images/16bit.r.tif") as im:
 | 
					        with Image.open("Tests/images/16bit.r.tif") as im:
 | 
				
			||||||
            assert im.getpixel((0, 0)) == 480
 | 
					            assert im.getpixel((0, 0)) == 480
 | 
				
			||||||
            assert im.mode == "I;16"
 | 
					            assert im.mode == "I;16"
 | 
				
			||||||
| 
						 | 
					@ -242,14 +243,14 @@ class TestFileTiff:
 | 
				
			||||||
        assert b[0] == ord(b"\xe0")
 | 
					        assert b[0] == ord(b"\xe0")
 | 
				
			||||||
        assert b[1] == ord(b"\x01")
 | 
					        assert b[1] == ord(b"\x01")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_16bit_s(self):
 | 
					    def test_16bit_s(self) -> None:
 | 
				
			||||||
        with Image.open("Tests/images/16bit.s.tif") as im:
 | 
					        with Image.open("Tests/images/16bit.s.tif") as im:
 | 
				
			||||||
            im.load()
 | 
					            im.load()
 | 
				
			||||||
            assert im.mode == "I"
 | 
					            assert im.mode == "I"
 | 
				
			||||||
            assert im.getpixel((0, 0)) == 32767
 | 
					            assert im.getpixel((0, 0)) == 32767
 | 
				
			||||||
            assert im.getpixel((0, 1)) == 0
 | 
					            assert im.getpixel((0, 1)) == 0
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_12bit_rawmode(self):
 | 
					    def test_12bit_rawmode(self) -> None:
 | 
				
			||||||
        """Are we generating the same interpretation
 | 
					        """Are we generating the same interpretation
 | 
				
			||||||
        of the image as Imagemagick is?"""
 | 
					        of the image as Imagemagick is?"""
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -262,7 +263,7 @@ class TestFileTiff:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            assert_image_equal_tofile(im, "Tests/images/12in16bit.tif")
 | 
					            assert_image_equal_tofile(im, "Tests/images/12in16bit.tif")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_32bit_float(self):
 | 
					    def test_32bit_float(self) -> None:
 | 
				
			||||||
        # Issue 614, specific 32-bit float format
 | 
					        # Issue 614, specific 32-bit float format
 | 
				
			||||||
        path = "Tests/images/10ct_32bit_128.tiff"
 | 
					        path = "Tests/images/10ct_32bit_128.tiff"
 | 
				
			||||||
        with Image.open(path) as im:
 | 
					        with Image.open(path) as im:
 | 
				
			||||||
| 
						 | 
					@ -271,7 +272,7 @@ class TestFileTiff:
 | 
				
			||||||
            assert im.getpixel((0, 0)) == -0.4526388943195343
 | 
					            assert im.getpixel((0, 0)) == -0.4526388943195343
 | 
				
			||||||
            assert im.getextrema() == (-3.140936851501465, 3.140684127807617)
 | 
					            assert im.getextrema() == (-3.140936851501465, 3.140684127807617)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_unknown_pixel_mode(self):
 | 
					    def test_unknown_pixel_mode(self) -> None:
 | 
				
			||||||
        with pytest.raises(OSError):
 | 
					        with pytest.raises(OSError):
 | 
				
			||||||
            with Image.open("Tests/images/hopper_unknown_pixel_mode.tif"):
 | 
					            with Image.open("Tests/images/hopper_unknown_pixel_mode.tif"):
 | 
				
			||||||
                pass
 | 
					                pass
 | 
				
			||||||
| 
						 | 
					@ -283,12 +284,12 @@ class TestFileTiff:
 | 
				
			||||||
            ("Tests/images/multipage.tiff", 3),
 | 
					            ("Tests/images/multipage.tiff", 3),
 | 
				
			||||||
        ),
 | 
					        ),
 | 
				
			||||||
    )
 | 
					    )
 | 
				
			||||||
    def test_n_frames(self, path, n_frames):
 | 
					    def test_n_frames(self, path, n_frames) -> None:
 | 
				
			||||||
        with Image.open(path) as im:
 | 
					        with Image.open(path) as im:
 | 
				
			||||||
            assert im.n_frames == n_frames
 | 
					            assert im.n_frames == n_frames
 | 
				
			||||||
            assert im.is_animated == (n_frames != 1)
 | 
					            assert im.is_animated == (n_frames != 1)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_eoferror(self):
 | 
					    def test_eoferror(self) -> None:
 | 
				
			||||||
        with Image.open("Tests/images/multipage-lastframe.tif") as im:
 | 
					        with Image.open("Tests/images/multipage-lastframe.tif") as im:
 | 
				
			||||||
            n_frames = im.n_frames
 | 
					            n_frames = im.n_frames
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -300,7 +301,7 @@ class TestFileTiff:
 | 
				
			||||||
            # Test that seeking to the last frame does not raise an error
 | 
					            # Test that seeking to the last frame does not raise an error
 | 
				
			||||||
            im.seek(n_frames - 1)
 | 
					            im.seek(n_frames - 1)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_multipage(self):
 | 
					    def test_multipage(self) -> None:
 | 
				
			||||||
        # issue #862
 | 
					        # issue #862
 | 
				
			||||||
        with Image.open("Tests/images/multipage.tiff") as im:
 | 
					        with Image.open("Tests/images/multipage.tiff") as im:
 | 
				
			||||||
            # file is a multipage tiff: 10x10 green, 10x10 red, 20x20 blue
 | 
					            # file is a multipage tiff: 10x10 green, 10x10 red, 20x20 blue
 | 
				
			||||||
| 
						 | 
					@ -324,13 +325,13 @@ class TestFileTiff:
 | 
				
			||||||
            assert im.size == (20, 20)
 | 
					            assert im.size == (20, 20)
 | 
				
			||||||
            assert im.convert("RGB").getpixel((0, 0)) == (0, 0, 255)
 | 
					            assert im.convert("RGB").getpixel((0, 0)) == (0, 0, 255)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_multipage_last_frame(self):
 | 
					    def test_multipage_last_frame(self) -> None:
 | 
				
			||||||
        with Image.open("Tests/images/multipage-lastframe.tif") as im:
 | 
					        with Image.open("Tests/images/multipage-lastframe.tif") as im:
 | 
				
			||||||
            im.load()
 | 
					            im.load()
 | 
				
			||||||
            assert im.size == (20, 20)
 | 
					            assert im.size == (20, 20)
 | 
				
			||||||
            assert im.convert("RGB").getpixel((0, 0)) == (0, 0, 255)
 | 
					            assert im.convert("RGB").getpixel((0, 0)) == (0, 0, 255)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_frame_order(self):
 | 
					    def test_frame_order(self) -> None:
 | 
				
			||||||
        # A frame can't progress to itself after reading
 | 
					        # A frame can't progress to itself after reading
 | 
				
			||||||
        with Image.open("Tests/images/multipage_single_frame_loop.tiff") as im:
 | 
					        with Image.open("Tests/images/multipage_single_frame_loop.tiff") as im:
 | 
				
			||||||
            assert im.n_frames == 1
 | 
					            assert im.n_frames == 1
 | 
				
			||||||
| 
						 | 
					@ -343,7 +344,7 @@ class TestFileTiff:
 | 
				
			||||||
        with Image.open("Tests/images/multipage_out_of_order.tiff") as im:
 | 
					        with Image.open("Tests/images/multipage_out_of_order.tiff") as im:
 | 
				
			||||||
            assert im.n_frames == 3
 | 
					            assert im.n_frames == 3
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test___str__(self):
 | 
					    def test___str__(self) -> None:
 | 
				
			||||||
        filename = "Tests/images/pil136.tiff"
 | 
					        filename = "Tests/images/pil136.tiff"
 | 
				
			||||||
        with Image.open(filename) as im:
 | 
					        with Image.open(filename) as im:
 | 
				
			||||||
            # Act
 | 
					            # Act
 | 
				
			||||||
| 
						 | 
					@ -352,7 +353,7 @@ class TestFileTiff:
 | 
				
			||||||
            # Assert
 | 
					            # Assert
 | 
				
			||||||
            assert isinstance(ret, str)
 | 
					            assert isinstance(ret, str)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_dict(self):
 | 
					    def test_dict(self) -> None:
 | 
				
			||||||
        # Arrange
 | 
					        # Arrange
 | 
				
			||||||
        filename = "Tests/images/pil136.tiff"
 | 
					        filename = "Tests/images/pil136.tiff"
 | 
				
			||||||
        with Image.open(filename) as im:
 | 
					        with Image.open(filename) as im:
 | 
				
			||||||
| 
						 | 
					@ -392,7 +393,7 @@ class TestFileTiff:
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
            assert dict(im.tag) == legacy_tags
 | 
					            assert dict(im.tag) == legacy_tags
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test__delitem__(self):
 | 
					    def test__delitem__(self) -> None:
 | 
				
			||||||
        filename = "Tests/images/pil136.tiff"
 | 
					        filename = "Tests/images/pil136.tiff"
 | 
				
			||||||
        with Image.open(filename) as im:
 | 
					        with Image.open(filename) as im:
 | 
				
			||||||
            len_before = len(dict(im.ifd))
 | 
					            len_before = len(dict(im.ifd))
 | 
				
			||||||
| 
						 | 
					@ -401,36 +402,36 @@ class TestFileTiff:
 | 
				
			||||||
            assert len_before == len_after + 1
 | 
					            assert len_before == len_after + 1
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    @pytest.mark.parametrize("legacy_api", (False, True))
 | 
					    @pytest.mark.parametrize("legacy_api", (False, True))
 | 
				
			||||||
    def test_load_byte(self, legacy_api):
 | 
					    def test_load_byte(self, legacy_api) -> None:
 | 
				
			||||||
        ifd = TiffImagePlugin.ImageFileDirectory_v2()
 | 
					        ifd = TiffImagePlugin.ImageFileDirectory_v2()
 | 
				
			||||||
        data = b"abc"
 | 
					        data = b"abc"
 | 
				
			||||||
        ret = ifd.load_byte(data, legacy_api)
 | 
					        ret = ifd.load_byte(data, legacy_api)
 | 
				
			||||||
        assert ret == b"abc"
 | 
					        assert ret == b"abc"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_load_string(self):
 | 
					    def test_load_string(self) -> None:
 | 
				
			||||||
        ifd = TiffImagePlugin.ImageFileDirectory_v2()
 | 
					        ifd = TiffImagePlugin.ImageFileDirectory_v2()
 | 
				
			||||||
        data = b"abc\0"
 | 
					        data = b"abc\0"
 | 
				
			||||||
        ret = ifd.load_string(data, False)
 | 
					        ret = ifd.load_string(data, False)
 | 
				
			||||||
        assert ret == "abc"
 | 
					        assert ret == "abc"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_load_float(self):
 | 
					    def test_load_float(self) -> None:
 | 
				
			||||||
        ifd = TiffImagePlugin.ImageFileDirectory_v2()
 | 
					        ifd = TiffImagePlugin.ImageFileDirectory_v2()
 | 
				
			||||||
        data = b"abcdabcd"
 | 
					        data = b"abcdabcd"
 | 
				
			||||||
        ret = ifd.load_float(data, False)
 | 
					        ret = ifd.load_float(data, False)
 | 
				
			||||||
        assert ret == (1.6777999408082104e22, 1.6777999408082104e22)
 | 
					        assert ret == (1.6777999408082104e22, 1.6777999408082104e22)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_load_double(self):
 | 
					    def test_load_double(self) -> None:
 | 
				
			||||||
        ifd = TiffImagePlugin.ImageFileDirectory_v2()
 | 
					        ifd = TiffImagePlugin.ImageFileDirectory_v2()
 | 
				
			||||||
        data = b"abcdefghabcdefgh"
 | 
					        data = b"abcdefghabcdefgh"
 | 
				
			||||||
        ret = ifd.load_double(data, False)
 | 
					        ret = ifd.load_double(data, False)
 | 
				
			||||||
        assert ret == (8.540883223036124e194, 8.540883223036124e194)
 | 
					        assert ret == (8.540883223036124e194, 8.540883223036124e194)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_ifd_tag_type(self):
 | 
					    def test_ifd_tag_type(self) -> None:
 | 
				
			||||||
        with Image.open("Tests/images/ifd_tag_type.tiff") as im:
 | 
					        with Image.open("Tests/images/ifd_tag_type.tiff") as im:
 | 
				
			||||||
            assert 0x8825 in im.tag_v2
 | 
					            assert 0x8825 in im.tag_v2
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_exif(self, tmp_path):
 | 
					    def test_exif(self, tmp_path: Path) -> None:
 | 
				
			||||||
        def check_exif(exif):
 | 
					        def check_exif(exif) -> None:
 | 
				
			||||||
            assert sorted(exif.keys()) == [
 | 
					            assert sorted(exif.keys()) == [
 | 
				
			||||||
                256,
 | 
					                256,
 | 
				
			||||||
                257,
 | 
					                257,
 | 
				
			||||||
| 
						 | 
					@ -481,7 +482,7 @@ class TestFileTiff:
 | 
				
			||||||
            exif = im.getexif()
 | 
					            exif = im.getexif()
 | 
				
			||||||
            check_exif(exif)
 | 
					            check_exif(exif)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_modify_exif(self, tmp_path):
 | 
					    def test_modify_exif(self, tmp_path: Path) -> None:
 | 
				
			||||||
        outfile = str(tmp_path / "temp.tif")
 | 
					        outfile = str(tmp_path / "temp.tif")
 | 
				
			||||||
        with Image.open("Tests/images/ifd_tag_type.tiff") as im:
 | 
					        with Image.open("Tests/images/ifd_tag_type.tiff") as im:
 | 
				
			||||||
            exif = im.getexif()
 | 
					            exif = im.getexif()
 | 
				
			||||||
| 
						 | 
					@ -493,7 +494,7 @@ class TestFileTiff:
 | 
				
			||||||
            exif = im.getexif()
 | 
					            exif = im.getexif()
 | 
				
			||||||
            assert exif[264] == 100
 | 
					            assert exif[264] == 100
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_reload_exif_after_seek(self):
 | 
					    def test_reload_exif_after_seek(self) -> None:
 | 
				
			||||||
        with Image.open("Tests/images/multipage.tiff") as im:
 | 
					        with Image.open("Tests/images/multipage.tiff") as im:
 | 
				
			||||||
            exif = im.getexif()
 | 
					            exif = im.getexif()
 | 
				
			||||||
            del exif[256]
 | 
					            del exif[256]
 | 
				
			||||||
| 
						 | 
					@ -501,7 +502,7 @@ class TestFileTiff:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            assert 256 in exif
 | 
					            assert 256 in exif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_exif_frames(self):
 | 
					    def test_exif_frames(self) -> None:
 | 
				
			||||||
        # Test that EXIF data can change across frames
 | 
					        # Test that EXIF data can change across frames
 | 
				
			||||||
        with Image.open("Tests/images/g4-multi.tiff") as im:
 | 
					        with Image.open("Tests/images/g4-multi.tiff") as im:
 | 
				
			||||||
            assert im.getexif()[273] == (328, 815)
 | 
					            assert im.getexif()[273] == (328, 815)
 | 
				
			||||||
| 
						 | 
					@ -510,7 +511,7 @@ class TestFileTiff:
 | 
				
			||||||
            assert im.getexif()[273] == (1408, 1907)
 | 
					            assert im.getexif()[273] == (1408, 1907)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    @pytest.mark.parametrize("mode", ("1", "L"))
 | 
					    @pytest.mark.parametrize("mode", ("1", "L"))
 | 
				
			||||||
    def test_photometric(self, mode, tmp_path):
 | 
					    def test_photometric(self, mode, tmp_path: Path) -> None:
 | 
				
			||||||
        filename = str(tmp_path / "temp.tif")
 | 
					        filename = str(tmp_path / "temp.tif")
 | 
				
			||||||
        im = hopper(mode)
 | 
					        im = hopper(mode)
 | 
				
			||||||
        im.save(filename, tiffinfo={262: 0})
 | 
					        im.save(filename, tiffinfo={262: 0})
 | 
				
			||||||
| 
						 | 
					@ -518,13 +519,13 @@ class TestFileTiff:
 | 
				
			||||||
            assert reloaded.tag_v2[262] == 0
 | 
					            assert reloaded.tag_v2[262] == 0
 | 
				
			||||||
            assert_image_equal(im, reloaded)
 | 
					            assert_image_equal(im, reloaded)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_seek(self):
 | 
					    def test_seek(self) -> None:
 | 
				
			||||||
        filename = "Tests/images/pil136.tiff"
 | 
					        filename = "Tests/images/pil136.tiff"
 | 
				
			||||||
        with Image.open(filename) as im:
 | 
					        with Image.open(filename) as im:
 | 
				
			||||||
            im.seek(0)
 | 
					            im.seek(0)
 | 
				
			||||||
            assert im.tell() == 0
 | 
					            assert im.tell() == 0
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_seek_eof(self):
 | 
					    def test_seek_eof(self) -> None:
 | 
				
			||||||
        filename = "Tests/images/pil136.tiff"
 | 
					        filename = "Tests/images/pil136.tiff"
 | 
				
			||||||
        with Image.open(filename) as im:
 | 
					        with Image.open(filename) as im:
 | 
				
			||||||
            assert im.tell() == 0
 | 
					            assert im.tell() == 0
 | 
				
			||||||
| 
						 | 
					@ -533,21 +534,21 @@ class TestFileTiff:
 | 
				
			||||||
            with pytest.raises(EOFError):
 | 
					            with pytest.raises(EOFError):
 | 
				
			||||||
                im.seek(1)
 | 
					                im.seek(1)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test__limit_rational_int(self):
 | 
					    def test__limit_rational_int(self) -> None:
 | 
				
			||||||
        from PIL.TiffImagePlugin import _limit_rational
 | 
					        from PIL.TiffImagePlugin import _limit_rational
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        value = 34
 | 
					        value = 34
 | 
				
			||||||
        ret = _limit_rational(value, 65536)
 | 
					        ret = _limit_rational(value, 65536)
 | 
				
			||||||
        assert ret == (34, 1)
 | 
					        assert ret == (34, 1)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test__limit_rational_float(self):
 | 
					    def test__limit_rational_float(self) -> None:
 | 
				
			||||||
        from PIL.TiffImagePlugin import _limit_rational
 | 
					        from PIL.TiffImagePlugin import _limit_rational
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        value = 22.3
 | 
					        value = 22.3
 | 
				
			||||||
        ret = _limit_rational(value, 65536)
 | 
					        ret = _limit_rational(value, 65536)
 | 
				
			||||||
        assert ret == (223, 10)
 | 
					        assert ret == (223, 10)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_4bit(self):
 | 
					    def test_4bit(self) -> None:
 | 
				
			||||||
        test_file = "Tests/images/hopper_gray_4bpp.tif"
 | 
					        test_file = "Tests/images/hopper_gray_4bpp.tif"
 | 
				
			||||||
        original = hopper("L")
 | 
					        original = hopper("L")
 | 
				
			||||||
        with Image.open(test_file) as im:
 | 
					        with Image.open(test_file) as im:
 | 
				
			||||||
| 
						 | 
					@ -555,7 +556,7 @@ class TestFileTiff:
 | 
				
			||||||
            assert im.mode == "L"
 | 
					            assert im.mode == "L"
 | 
				
			||||||
            assert_image_similar(im, original, 7.3)
 | 
					            assert_image_similar(im, original, 7.3)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_gray_semibyte_per_pixel(self):
 | 
					    def test_gray_semibyte_per_pixel(self) -> None:
 | 
				
			||||||
        test_files = (
 | 
					        test_files = (
 | 
				
			||||||
            (
 | 
					            (
 | 
				
			||||||
                24.8,  # epsilon
 | 
					                24.8,  # epsilon
 | 
				
			||||||
| 
						 | 
					@ -588,7 +589,7 @@ class TestFileTiff:
 | 
				
			||||||
                        assert im2.mode == "L"
 | 
					                        assert im2.mode == "L"
 | 
				
			||||||
                        assert_image_equal(im, im2)
 | 
					                        assert_image_equal(im, im2)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_with_underscores(self, tmp_path):
 | 
					    def test_with_underscores(self, tmp_path: Path) -> None:
 | 
				
			||||||
        kwargs = {"resolution_unit": "inch", "x_resolution": 72, "y_resolution": 36}
 | 
					        kwargs = {"resolution_unit": "inch", "x_resolution": 72, "y_resolution": 36}
 | 
				
			||||||
        filename = str(tmp_path / "temp.tif")
 | 
					        filename = str(tmp_path / "temp.tif")
 | 
				
			||||||
        hopper("RGB").save(filename, **kwargs)
 | 
					        hopper("RGB").save(filename, **kwargs)
 | 
				
			||||||
| 
						 | 
					@ -601,7 +602,7 @@ class TestFileTiff:
 | 
				
			||||||
            assert im.tag_v2[X_RESOLUTION] == 72
 | 
					            assert im.tag_v2[X_RESOLUTION] == 72
 | 
				
			||||||
            assert im.tag_v2[Y_RESOLUTION] == 36
 | 
					            assert im.tag_v2[Y_RESOLUTION] == 36
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_roundtrip_tiff_uint16(self, tmp_path):
 | 
					    def test_roundtrip_tiff_uint16(self, tmp_path: Path) -> None:
 | 
				
			||||||
        # Test an image of all '0' values
 | 
					        # Test an image of all '0' values
 | 
				
			||||||
        pixel_value = 0x1234
 | 
					        pixel_value = 0x1234
 | 
				
			||||||
        infile = "Tests/images/uint16_1_4660.tif"
 | 
					        infile = "Tests/images/uint16_1_4660.tif"
 | 
				
			||||||
| 
						 | 
					@ -613,7 +614,7 @@ class TestFileTiff:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            assert_image_equal_tofile(im, tmpfile)
 | 
					            assert_image_equal_tofile(im, tmpfile)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_rowsperstrip(self, tmp_path):
 | 
					    def test_rowsperstrip(self, tmp_path: Path) -> None:
 | 
				
			||||||
        outfile = str(tmp_path / "temp.tif")
 | 
					        outfile = str(tmp_path / "temp.tif")
 | 
				
			||||||
        im = hopper()
 | 
					        im = hopper()
 | 
				
			||||||
        im.save(outfile, tiffinfo={278: 256})
 | 
					        im.save(outfile, tiffinfo={278: 256})
 | 
				
			||||||
| 
						 | 
					@ -621,25 +622,25 @@ class TestFileTiff:
 | 
				
			||||||
        with Image.open(outfile) as im:
 | 
					        with Image.open(outfile) as im:
 | 
				
			||||||
            assert im.tag_v2[278] == 256
 | 
					            assert im.tag_v2[278] == 256
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_strip_raw(self):
 | 
					    def test_strip_raw(self) -> None:
 | 
				
			||||||
        infile = "Tests/images/tiff_strip_raw.tif"
 | 
					        infile = "Tests/images/tiff_strip_raw.tif"
 | 
				
			||||||
        with Image.open(infile) as im:
 | 
					        with Image.open(infile) as im:
 | 
				
			||||||
            assert_image_equal_tofile(im, "Tests/images/tiff_adobe_deflate.png")
 | 
					            assert_image_equal_tofile(im, "Tests/images/tiff_adobe_deflate.png")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_strip_planar_raw(self):
 | 
					    def test_strip_planar_raw(self) -> None:
 | 
				
			||||||
        # gdal_translate -of GTiff -co INTERLEAVE=BAND \
 | 
					        # gdal_translate -of GTiff -co INTERLEAVE=BAND \
 | 
				
			||||||
        # tiff_strip_raw.tif tiff_strip_planar_raw.tiff
 | 
					        # tiff_strip_raw.tif tiff_strip_planar_raw.tiff
 | 
				
			||||||
        infile = "Tests/images/tiff_strip_planar_raw.tif"
 | 
					        infile = "Tests/images/tiff_strip_planar_raw.tif"
 | 
				
			||||||
        with Image.open(infile) as im:
 | 
					        with Image.open(infile) as im:
 | 
				
			||||||
            assert_image_equal_tofile(im, "Tests/images/tiff_adobe_deflate.png")
 | 
					            assert_image_equal_tofile(im, "Tests/images/tiff_adobe_deflate.png")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_strip_planar_raw_with_overviews(self):
 | 
					    def test_strip_planar_raw_with_overviews(self) -> None:
 | 
				
			||||||
        # gdaladdo tiff_strip_planar_raw2.tif 2 4 8 16
 | 
					        # gdaladdo tiff_strip_planar_raw2.tif 2 4 8 16
 | 
				
			||||||
        infile = "Tests/images/tiff_strip_planar_raw_with_overviews.tif"
 | 
					        infile = "Tests/images/tiff_strip_planar_raw_with_overviews.tif"
 | 
				
			||||||
        with Image.open(infile) as im:
 | 
					        with Image.open(infile) as im:
 | 
				
			||||||
            assert_image_equal_tofile(im, "Tests/images/tiff_adobe_deflate.png")
 | 
					            assert_image_equal_tofile(im, "Tests/images/tiff_adobe_deflate.png")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_tiled_planar_raw(self):
 | 
					    def test_tiled_planar_raw(self) -> None:
 | 
				
			||||||
        # gdal_translate -of GTiff -co TILED=YES -co BLOCKXSIZE=32 \
 | 
					        # gdal_translate -of GTiff -co TILED=YES -co BLOCKXSIZE=32 \
 | 
				
			||||||
        # -co BLOCKYSIZE=32 -co INTERLEAVE=BAND \
 | 
					        # -co BLOCKYSIZE=32 -co INTERLEAVE=BAND \
 | 
				
			||||||
        # tiff_tiled_raw.tif tiff_tiled_planar_raw.tiff
 | 
					        # tiff_tiled_raw.tif tiff_tiled_planar_raw.tiff
 | 
				
			||||||
| 
						 | 
					@ -647,7 +648,7 @@ class TestFileTiff:
 | 
				
			||||||
        with Image.open(infile) as im:
 | 
					        with Image.open(infile) as im:
 | 
				
			||||||
            assert_image_equal_tofile(im, "Tests/images/tiff_adobe_deflate.png")
 | 
					            assert_image_equal_tofile(im, "Tests/images/tiff_adobe_deflate.png")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_planar_configuration_save(self, tmp_path):
 | 
					    def test_planar_configuration_save(self, tmp_path: Path) -> None:
 | 
				
			||||||
        infile = "Tests/images/tiff_tiled_planar_raw.tif"
 | 
					        infile = "Tests/images/tiff_tiled_planar_raw.tif"
 | 
				
			||||||
        with Image.open(infile) as im:
 | 
					        with Image.open(infile) as im:
 | 
				
			||||||
            assert im._planar_configuration == 2
 | 
					            assert im._planar_configuration == 2
 | 
				
			||||||
| 
						 | 
					@ -659,7 +660,7 @@ class TestFileTiff:
 | 
				
			||||||
                assert_image_equal_tofile(reloaded, infile)
 | 
					                assert_image_equal_tofile(reloaded, infile)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    @pytest.mark.parametrize("mode", ("P", "PA"))
 | 
					    @pytest.mark.parametrize("mode", ("P", "PA"))
 | 
				
			||||||
    def test_palette(self, mode, tmp_path):
 | 
					    def test_palette(self, mode, tmp_path: Path) -> None:
 | 
				
			||||||
        outfile = str(tmp_path / "temp.tif")
 | 
					        outfile = str(tmp_path / "temp.tif")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        im = hopper(mode)
 | 
					        im = hopper(mode)
 | 
				
			||||||
| 
						 | 
					@ -668,7 +669,7 @@ class TestFileTiff:
 | 
				
			||||||
        with Image.open(outfile) as reloaded:
 | 
					        with Image.open(outfile) as reloaded:
 | 
				
			||||||
            assert_image_equal(im.convert("RGB"), reloaded.convert("RGB"))
 | 
					            assert_image_equal(im.convert("RGB"), reloaded.convert("RGB"))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_tiff_save_all(self):
 | 
					    def test_tiff_save_all(self) -> None:
 | 
				
			||||||
        mp = BytesIO()
 | 
					        mp = BytesIO()
 | 
				
			||||||
        with Image.open("Tests/images/multipage.tiff") as im:
 | 
					        with Image.open("Tests/images/multipage.tiff") as im:
 | 
				
			||||||
            im.save(mp, format="tiff", save_all=True)
 | 
					            im.save(mp, format="tiff", save_all=True)
 | 
				
			||||||
| 
						 | 
					@ -698,7 +699,7 @@ class TestFileTiff:
 | 
				
			||||||
        with Image.open(mp) as reread:
 | 
					        with Image.open(mp) as reread:
 | 
				
			||||||
            assert reread.n_frames == 3
 | 
					            assert reread.n_frames == 3
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_saving_icc_profile(self, tmp_path):
 | 
					    def test_saving_icc_profile(self, tmp_path: Path) -> None:
 | 
				
			||||||
        # Tests saving TIFF with icc_profile set.
 | 
					        # Tests saving TIFF with icc_profile set.
 | 
				
			||||||
        # At the time of writing this will only work for non-compressed tiffs
 | 
					        # At the time of writing this will only work for non-compressed tiffs
 | 
				
			||||||
        # as libtiff does not support embedded ICC profiles,
 | 
					        # as libtiff does not support embedded ICC profiles,
 | 
				
			||||||
| 
						 | 
					@ -712,7 +713,7 @@ class TestFileTiff:
 | 
				
			||||||
        with Image.open(tmpfile) as reloaded:
 | 
					        with Image.open(tmpfile) as reloaded:
 | 
				
			||||||
            assert b"Dummy value" == reloaded.info["icc_profile"]
 | 
					            assert b"Dummy value" == reloaded.info["icc_profile"]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_save_icc_profile(self, tmp_path):
 | 
					    def test_save_icc_profile(self, tmp_path: Path) -> None:
 | 
				
			||||||
        im = hopper()
 | 
					        im = hopper()
 | 
				
			||||||
        assert "icc_profile" not in im.info
 | 
					        assert "icc_profile" not in im.info
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -723,14 +724,14 @@ class TestFileTiff:
 | 
				
			||||||
        with Image.open(outfile) as reloaded:
 | 
					        with Image.open(outfile) as reloaded:
 | 
				
			||||||
            assert reloaded.info["icc_profile"] == icc_profile
 | 
					            assert reloaded.info["icc_profile"] == icc_profile
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_save_bmp_compression(self, tmp_path):
 | 
					    def test_save_bmp_compression(self, tmp_path: Path) -> None:
 | 
				
			||||||
        with Image.open("Tests/images/hopper.bmp") as im:
 | 
					        with Image.open("Tests/images/hopper.bmp") as im:
 | 
				
			||||||
            assert im.info["compression"] == 0
 | 
					            assert im.info["compression"] == 0
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            outfile = str(tmp_path / "temp.tif")
 | 
					            outfile = str(tmp_path / "temp.tif")
 | 
				
			||||||
            im.save(outfile)
 | 
					            im.save(outfile)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_discard_icc_profile(self, tmp_path):
 | 
					    def test_discard_icc_profile(self, tmp_path: Path) -> None:
 | 
				
			||||||
        outfile = str(tmp_path / "temp.tif")
 | 
					        outfile = str(tmp_path / "temp.tif")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        with Image.open("Tests/images/icc_profile.png") as im:
 | 
					        with Image.open("Tests/images/icc_profile.png") as im:
 | 
				
			||||||
| 
						 | 
					@ -741,7 +742,7 @@ class TestFileTiff:
 | 
				
			||||||
        with Image.open(outfile) as reloaded:
 | 
					        with Image.open(outfile) as reloaded:
 | 
				
			||||||
            assert "icc_profile" not in reloaded.info
 | 
					            assert "icc_profile" not in reloaded.info
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_getxmp(self):
 | 
					    def test_getxmp(self) -> None:
 | 
				
			||||||
        with Image.open("Tests/images/lab.tif") as im:
 | 
					        with Image.open("Tests/images/lab.tif") as im:
 | 
				
			||||||
            if ElementTree is None:
 | 
					            if ElementTree is None:
 | 
				
			||||||
                with pytest.warns(
 | 
					                with pytest.warns(
 | 
				
			||||||
| 
						 | 
					@ -756,7 +757,7 @@ class TestFileTiff:
 | 
				
			||||||
                assert description[0]["format"] == "image/tiff"
 | 
					                assert description[0]["format"] == "image/tiff"
 | 
				
			||||||
                assert description[3]["BitsPerSample"]["Seq"]["li"] == ["8", "8", "8"]
 | 
					                assert description[3]["BitsPerSample"]["Seq"]["li"] == ["8", "8", "8"]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_get_photoshop_blocks(self):
 | 
					    def test_get_photoshop_blocks(self) -> None:
 | 
				
			||||||
        with Image.open("Tests/images/lab.tif") as im:
 | 
					        with Image.open("Tests/images/lab.tif") as im:
 | 
				
			||||||
            assert list(im.get_photoshop_blocks().keys()) == [
 | 
					            assert list(im.get_photoshop_blocks().keys()) == [
 | 
				
			||||||
                1061,
 | 
					                1061,
 | 
				
			||||||
| 
						 | 
					@ -782,7 +783,7 @@ class TestFileTiff:
 | 
				
			||||||
                4001,
 | 
					                4001,
 | 
				
			||||||
            ]
 | 
					            ]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_tiff_chunks(self, tmp_path):
 | 
					    def test_tiff_chunks(self, tmp_path: Path) -> None:
 | 
				
			||||||
        tmpfile = str(tmp_path / "temp.tif")
 | 
					        tmpfile = str(tmp_path / "temp.tif")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        im = hopper()
 | 
					        im = hopper()
 | 
				
			||||||
| 
						 | 
					@ -803,7 +804,7 @@ class TestFileTiff:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        assert_image_equal_tofile(im, tmpfile)
 | 
					        assert_image_equal_tofile(im, tmpfile)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_close_on_load_exclusive(self, tmp_path):
 | 
					    def test_close_on_load_exclusive(self, tmp_path: Path) -> None:
 | 
				
			||||||
        # similar to test_fd_leak, but runs on unixlike os
 | 
					        # similar to test_fd_leak, but runs on unixlike os
 | 
				
			||||||
        tmpfile = str(tmp_path / "temp.tif")
 | 
					        tmpfile = str(tmp_path / "temp.tif")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -816,7 +817,7 @@ class TestFileTiff:
 | 
				
			||||||
        im.load()
 | 
					        im.load()
 | 
				
			||||||
        assert fp.closed
 | 
					        assert fp.closed
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_close_on_load_nonexclusive(self, tmp_path):
 | 
					    def test_close_on_load_nonexclusive(self, tmp_path: Path) -> None:
 | 
				
			||||||
        tmpfile = str(tmp_path / "temp.tif")
 | 
					        tmpfile = str(tmp_path / "temp.tif")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        with Image.open("Tests/images/uint16_1_4660.tif") as im:
 | 
					        with Image.open("Tests/images/uint16_1_4660.tif") as im:
 | 
				
			||||||
| 
						 | 
					@ -838,7 +839,7 @@ class TestFileTiff:
 | 
				
			||||||
        not os.path.exists("Tests/images/string_dimension.tiff"),
 | 
					        not os.path.exists("Tests/images/string_dimension.tiff"),
 | 
				
			||||||
        reason="Extra image files not installed",
 | 
					        reason="Extra image files not installed",
 | 
				
			||||||
    )
 | 
					    )
 | 
				
			||||||
    def test_string_dimension(self):
 | 
					    def test_string_dimension(self) -> None:
 | 
				
			||||||
        # Assert that an error is raised if one of the dimensions is a string
 | 
					        # Assert that an error is raised if one of the dimensions is a string
 | 
				
			||||||
        with Image.open("Tests/images/string_dimension.tiff") as im:
 | 
					        with Image.open("Tests/images/string_dimension.tiff") as im:
 | 
				
			||||||
            with pytest.raises(OSError):
 | 
					            with pytest.raises(OSError):
 | 
				
			||||||
| 
						 | 
					@ -846,7 +847,7 @@ class TestFileTiff:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    @pytest.mark.timeout(6)
 | 
					    @pytest.mark.timeout(6)
 | 
				
			||||||
    @pytest.mark.filterwarnings("ignore:Truncated File Read")
 | 
					    @pytest.mark.filterwarnings("ignore:Truncated File Read")
 | 
				
			||||||
    def test_timeout(self):
 | 
					    def test_timeout(self) -> None:
 | 
				
			||||||
        with Image.open("Tests/images/timeout-6646305047838720") as im:
 | 
					        with Image.open("Tests/images/timeout-6646305047838720") as im:
 | 
				
			||||||
            ImageFile.LOAD_TRUNCATED_IMAGES = True
 | 
					            ImageFile.LOAD_TRUNCATED_IMAGES = True
 | 
				
			||||||
            im.load()
 | 
					            im.load()
 | 
				
			||||||
| 
						 | 
					@ -859,7 +860,7 @@ class TestFileTiff:
 | 
				
			||||||
        ],
 | 
					        ],
 | 
				
			||||||
    )
 | 
					    )
 | 
				
			||||||
    @pytest.mark.timeout(2)
 | 
					    @pytest.mark.timeout(2)
 | 
				
			||||||
    def test_oom(self, test_file):
 | 
					    def test_oom(self, test_file) -> None:
 | 
				
			||||||
        with pytest.raises(UnidentifiedImageError):
 | 
					        with pytest.raises(UnidentifiedImageError):
 | 
				
			||||||
            with pytest.warns(UserWarning):
 | 
					            with pytest.warns(UserWarning):
 | 
				
			||||||
                with Image.open(test_file):
 | 
					                with Image.open(test_file):
 | 
				
			||||||
| 
						 | 
					@ -868,7 +869,7 @@ class TestFileTiff:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@pytest.mark.skipif(not is_win32(), reason="Windows only")
 | 
					@pytest.mark.skipif(not is_win32(), reason="Windows only")
 | 
				
			||||||
class TestFileTiffW32:
 | 
					class TestFileTiffW32:
 | 
				
			||||||
    def test_fd_leak(self, tmp_path):
 | 
					    def test_fd_leak(self, tmp_path: Path) -> None:
 | 
				
			||||||
        tmpfile = str(tmp_path / "temp.tif")
 | 
					        tmpfile = str(tmp_path / "temp.tif")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        # this is an mmaped file.
 | 
					        # this is an mmaped file.
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -2,6 +2,7 @@ from __future__ import annotations
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import io
 | 
					import io
 | 
				
			||||||
import struct
 | 
					import struct
 | 
				
			||||||
 | 
					from pathlib import Path
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import pytest
 | 
					import pytest
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -13,7 +14,7 @@ from .helper import assert_deep_equal, hopper
 | 
				
			||||||
TAG_IDS = {info.name: info.value for info in TiffTags.TAGS_V2.values()}
 | 
					TAG_IDS = {info.name: info.value for info in TiffTags.TAGS_V2.values()}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_rt_metadata(tmp_path):
 | 
					def test_rt_metadata(tmp_path: Path) -> None:
 | 
				
			||||||
    """Test writing arbitrary metadata into the tiff image directory
 | 
					    """Test writing arbitrary metadata into the tiff image directory
 | 
				
			||||||
    Use case is ImageJ private tags, one numeric, one arbitrary
 | 
					    Use case is ImageJ private tags, one numeric, one arbitrary
 | 
				
			||||||
    data.  https://github.com/python-pillow/Pillow/issues/291
 | 
					    data.  https://github.com/python-pillow/Pillow/issues/291
 | 
				
			||||||
| 
						 | 
					@ -79,7 +80,7 @@ def test_rt_metadata(tmp_path):
 | 
				
			||||||
        assert loaded.tag_v2[ImageJMetaDataByteCounts] == (8, len(bin_data) - 8)
 | 
					        assert loaded.tag_v2[ImageJMetaDataByteCounts] == (8, len(bin_data) - 8)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_read_metadata():
 | 
					def test_read_metadata() -> None:
 | 
				
			||||||
    with Image.open("Tests/images/hopper_g4.tif") as img:
 | 
					    with Image.open("Tests/images/hopper_g4.tif") as img:
 | 
				
			||||||
        assert {
 | 
					        assert {
 | 
				
			||||||
            "YResolution": IFDRational(4294967295, 113653537),
 | 
					            "YResolution": IFDRational(4294967295, 113653537),
 | 
				
			||||||
| 
						 | 
					@ -120,7 +121,7 @@ def test_read_metadata():
 | 
				
			||||||
        } == img.tag.named()
 | 
					        } == img.tag.named()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_write_metadata(tmp_path):
 | 
					def test_write_metadata(tmp_path: Path) -> None:
 | 
				
			||||||
    """Test metadata writing through the python code"""
 | 
					    """Test metadata writing through the python code"""
 | 
				
			||||||
    with Image.open("Tests/images/hopper.tif") as img:
 | 
					    with Image.open("Tests/images/hopper.tif") as img:
 | 
				
			||||||
        f = str(tmp_path / "temp.tiff")
 | 
					        f = str(tmp_path / "temp.tiff")
 | 
				
			||||||
| 
						 | 
					@ -157,7 +158,7 @@ def test_write_metadata(tmp_path):
 | 
				
			||||||
            assert value == reloaded[tag], f"{tag} didn't roundtrip"
 | 
					            assert value == reloaded[tag], f"{tag} didn't roundtrip"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_change_stripbytecounts_tag_type(tmp_path):
 | 
					def test_change_stripbytecounts_tag_type(tmp_path: Path) -> None:
 | 
				
			||||||
    out = str(tmp_path / "temp.tiff")
 | 
					    out = str(tmp_path / "temp.tiff")
 | 
				
			||||||
    with Image.open("Tests/images/hopper.tif") as im:
 | 
					    with Image.open("Tests/images/hopper.tif") as im:
 | 
				
			||||||
        info = im.tag_v2
 | 
					        info = im.tag_v2
 | 
				
			||||||
| 
						 | 
					@ -176,19 +177,19 @@ def test_change_stripbytecounts_tag_type(tmp_path):
 | 
				
			||||||
        assert reloaded.tag_v2.tagtype[TiffImagePlugin.STRIPBYTECOUNTS] == TiffTags.LONG
 | 
					        assert reloaded.tag_v2.tagtype[TiffImagePlugin.STRIPBYTECOUNTS] == TiffTags.LONG
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_no_duplicate_50741_tag():
 | 
					def test_no_duplicate_50741_tag() -> None:
 | 
				
			||||||
    assert TAG_IDS["MakerNoteSafety"] == 50741
 | 
					    assert TAG_IDS["MakerNoteSafety"] == 50741
 | 
				
			||||||
    assert TAG_IDS["BestQualityScale"] == 50780
 | 
					    assert TAG_IDS["BestQualityScale"] == 50780
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_iptc(tmp_path):
 | 
					def test_iptc(tmp_path: Path) -> None:
 | 
				
			||||||
    out = str(tmp_path / "temp.tiff")
 | 
					    out = str(tmp_path / "temp.tiff")
 | 
				
			||||||
    with Image.open("Tests/images/hopper.Lab.tif") as im:
 | 
					    with Image.open("Tests/images/hopper.Lab.tif") as im:
 | 
				
			||||||
        im.save(out)
 | 
					        im.save(out)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@pytest.mark.parametrize("value, expected", ((b"test", "test"), (1, "1")))
 | 
					@pytest.mark.parametrize("value, expected", ((b"test", "test"), (1, "1")))
 | 
				
			||||||
def test_writing_other_types_to_ascii(value, expected, tmp_path):
 | 
					def test_writing_other_types_to_ascii(value, expected, tmp_path: Path) -> None:
 | 
				
			||||||
    info = TiffImagePlugin.ImageFileDirectory_v2()
 | 
					    info = TiffImagePlugin.ImageFileDirectory_v2()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    tag = TiffTags.TAGS_V2[271]
 | 
					    tag = TiffTags.TAGS_V2[271]
 | 
				
			||||||
| 
						 | 
					@ -205,7 +206,7 @@ def test_writing_other_types_to_ascii(value, expected, tmp_path):
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@pytest.mark.parametrize("value", (1, IFDRational(1)))
 | 
					@pytest.mark.parametrize("value", (1, IFDRational(1)))
 | 
				
			||||||
def test_writing_other_types_to_bytes(value, tmp_path):
 | 
					def test_writing_other_types_to_bytes(value, tmp_path: Path) -> None:
 | 
				
			||||||
    im = hopper()
 | 
					    im = hopper()
 | 
				
			||||||
    info = TiffImagePlugin.ImageFileDirectory_v2()
 | 
					    info = TiffImagePlugin.ImageFileDirectory_v2()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -221,7 +222,7 @@ def test_writing_other_types_to_bytes(value, tmp_path):
 | 
				
			||||||
        assert reloaded.tag_v2[700] == b"\x01"
 | 
					        assert reloaded.tag_v2[700] == b"\x01"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_writing_other_types_to_undefined(tmp_path):
 | 
					def test_writing_other_types_to_undefined(tmp_path: Path) -> None:
 | 
				
			||||||
    im = hopper()
 | 
					    im = hopper()
 | 
				
			||||||
    info = TiffImagePlugin.ImageFileDirectory_v2()
 | 
					    info = TiffImagePlugin.ImageFileDirectory_v2()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -237,7 +238,7 @@ def test_writing_other_types_to_undefined(tmp_path):
 | 
				
			||||||
        assert reloaded.tag_v2[33723] == b"1"
 | 
					        assert reloaded.tag_v2[33723] == b"1"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_undefined_zero(tmp_path):
 | 
					def test_undefined_zero(tmp_path: Path) -> None:
 | 
				
			||||||
    # Check that the tag has not been changed since this test was created
 | 
					    # Check that the tag has not been changed since this test was created
 | 
				
			||||||
    tag = TiffTags.TAGS_V2[45059]
 | 
					    tag = TiffTags.TAGS_V2[45059]
 | 
				
			||||||
    assert tag.type == TiffTags.UNDEFINED
 | 
					    assert tag.type == TiffTags.UNDEFINED
 | 
				
			||||||
| 
						 | 
					@ -252,7 +253,7 @@ def test_undefined_zero(tmp_path):
 | 
				
			||||||
    assert info[45059] == original
 | 
					    assert info[45059] == original
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_empty_metadata():
 | 
					def test_empty_metadata() -> None:
 | 
				
			||||||
    f = io.BytesIO(b"II*\x00\x08\x00\x00\x00")
 | 
					    f = io.BytesIO(b"II*\x00\x08\x00\x00\x00")
 | 
				
			||||||
    head = f.read(8)
 | 
					    head = f.read(8)
 | 
				
			||||||
    info = TiffImagePlugin.ImageFileDirectory(head)
 | 
					    info = TiffImagePlugin.ImageFileDirectory(head)
 | 
				
			||||||
| 
						 | 
					@ -261,7 +262,7 @@ def test_empty_metadata():
 | 
				
			||||||
        info.load(f)
 | 
					        info.load(f)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_iccprofile(tmp_path):
 | 
					def test_iccprofile(tmp_path: Path) -> None:
 | 
				
			||||||
    # https://github.com/python-pillow/Pillow/issues/1462
 | 
					    # https://github.com/python-pillow/Pillow/issues/1462
 | 
				
			||||||
    out = str(tmp_path / "temp.tiff")
 | 
					    out = str(tmp_path / "temp.tiff")
 | 
				
			||||||
    with Image.open("Tests/images/hopper.iccprofile.tif") as im:
 | 
					    with Image.open("Tests/images/hopper.iccprofile.tif") as im:
 | 
				
			||||||
| 
						 | 
					@ -272,7 +273,7 @@ def test_iccprofile(tmp_path):
 | 
				
			||||||
        assert im.info["icc_profile"] == reloaded.info["icc_profile"]
 | 
					        assert im.info["icc_profile"] == reloaded.info["icc_profile"]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_iccprofile_binary():
 | 
					def test_iccprofile_binary() -> None:
 | 
				
			||||||
    # https://github.com/python-pillow/Pillow/issues/1526
 | 
					    # https://github.com/python-pillow/Pillow/issues/1526
 | 
				
			||||||
    # We should be able to load this,
 | 
					    # We should be able to load this,
 | 
				
			||||||
    # but probably won't be able to save it.
 | 
					    # but probably won't be able to save it.
 | 
				
			||||||
| 
						 | 
					@ -282,19 +283,19 @@ def test_iccprofile_binary():
 | 
				
			||||||
        assert im.info["icc_profile"]
 | 
					        assert im.info["icc_profile"]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_iccprofile_save_png(tmp_path):
 | 
					def test_iccprofile_save_png(tmp_path: Path) -> None:
 | 
				
			||||||
    with Image.open("Tests/images/hopper.iccprofile.tif") as im:
 | 
					    with Image.open("Tests/images/hopper.iccprofile.tif") as im:
 | 
				
			||||||
        outfile = str(tmp_path / "temp.png")
 | 
					        outfile = str(tmp_path / "temp.png")
 | 
				
			||||||
        im.save(outfile)
 | 
					        im.save(outfile)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_iccprofile_binary_save_png(tmp_path):
 | 
					def test_iccprofile_binary_save_png(tmp_path: Path) -> None:
 | 
				
			||||||
    with Image.open("Tests/images/hopper.iccprofile_binary.tif") as im:
 | 
					    with Image.open("Tests/images/hopper.iccprofile_binary.tif") as im:
 | 
				
			||||||
        outfile = str(tmp_path / "temp.png")
 | 
					        outfile = str(tmp_path / "temp.png")
 | 
				
			||||||
        im.save(outfile)
 | 
					        im.save(outfile)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_exif_div_zero(tmp_path):
 | 
					def test_exif_div_zero(tmp_path: Path) -> None:
 | 
				
			||||||
    im = hopper()
 | 
					    im = hopper()
 | 
				
			||||||
    info = TiffImagePlugin.ImageFileDirectory_v2()
 | 
					    info = TiffImagePlugin.ImageFileDirectory_v2()
 | 
				
			||||||
    info[41988] = TiffImagePlugin.IFDRational(0, 0)
 | 
					    info[41988] = TiffImagePlugin.IFDRational(0, 0)
 | 
				
			||||||
| 
						 | 
					@ -307,7 +308,7 @@ def test_exif_div_zero(tmp_path):
 | 
				
			||||||
        assert 0 == reloaded.tag_v2[41988].denominator
 | 
					        assert 0 == reloaded.tag_v2[41988].denominator
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_ifd_unsigned_rational(tmp_path):
 | 
					def test_ifd_unsigned_rational(tmp_path: Path) -> None:
 | 
				
			||||||
    im = hopper()
 | 
					    im = hopper()
 | 
				
			||||||
    info = TiffImagePlugin.ImageFileDirectory_v2()
 | 
					    info = TiffImagePlugin.ImageFileDirectory_v2()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -338,7 +339,7 @@ def test_ifd_unsigned_rational(tmp_path):
 | 
				
			||||||
        assert 1 == reloaded.tag_v2[41493].denominator
 | 
					        assert 1 == reloaded.tag_v2[41493].denominator
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_ifd_signed_rational(tmp_path):
 | 
					def test_ifd_signed_rational(tmp_path: Path) -> None:
 | 
				
			||||||
    im = hopper()
 | 
					    im = hopper()
 | 
				
			||||||
    info = TiffImagePlugin.ImageFileDirectory_v2()
 | 
					    info = TiffImagePlugin.ImageFileDirectory_v2()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -381,7 +382,7 @@ def test_ifd_signed_rational(tmp_path):
 | 
				
			||||||
        assert -1 == reloaded.tag_v2[37380].denominator
 | 
					        assert -1 == reloaded.tag_v2[37380].denominator
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_ifd_signed_long(tmp_path):
 | 
					def test_ifd_signed_long(tmp_path: Path) -> None:
 | 
				
			||||||
    im = hopper()
 | 
					    im = hopper()
 | 
				
			||||||
    info = TiffImagePlugin.ImageFileDirectory_v2()
 | 
					    info = TiffImagePlugin.ImageFileDirectory_v2()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -394,7 +395,7 @@ def test_ifd_signed_long(tmp_path):
 | 
				
			||||||
        assert reloaded.tag_v2[37000] == -60000
 | 
					        assert reloaded.tag_v2[37000] == -60000
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_empty_values():
 | 
					def test_empty_values() -> None:
 | 
				
			||||||
    data = io.BytesIO(
 | 
					    data = io.BytesIO(
 | 
				
			||||||
        b"II*\x00\x08\x00\x00\x00\x03\x00\x1a\x01\x05\x00\x00\x00\x00\x00"
 | 
					        b"II*\x00\x08\x00\x00\x00\x03\x00\x1a\x01\x05\x00\x00\x00\x00\x00"
 | 
				
			||||||
        b"\x00\x00\x00\x00\x1b\x01\x05\x00\x00\x00\x00\x00\x00\x00\x00\x00"
 | 
					        b"\x00\x00\x00\x00\x1b\x01\x05\x00\x00\x00\x00\x00\x00\x00\x00\x00"
 | 
				
			||||||
| 
						 | 
					@ -409,7 +410,7 @@ def test_empty_values():
 | 
				
			||||||
    assert 33432 in info
 | 
					    assert 33432 in info
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_photoshop_info(tmp_path):
 | 
					def test_photoshop_info(tmp_path: Path) -> None:
 | 
				
			||||||
    with Image.open("Tests/images/issue_2278.tif") as im:
 | 
					    with Image.open("Tests/images/issue_2278.tif") as im:
 | 
				
			||||||
        assert len(im.tag_v2[34377]) == 70
 | 
					        assert len(im.tag_v2[34377]) == 70
 | 
				
			||||||
        assert isinstance(im.tag_v2[34377], bytes)
 | 
					        assert isinstance(im.tag_v2[34377], bytes)
 | 
				
			||||||
| 
						 | 
					@ -420,7 +421,7 @@ def test_photoshop_info(tmp_path):
 | 
				
			||||||
        assert isinstance(reloaded.tag_v2[34377], bytes)
 | 
					        assert isinstance(reloaded.tag_v2[34377], bytes)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_too_many_entries():
 | 
					def test_too_many_entries() -> None:
 | 
				
			||||||
    ifd = TiffImagePlugin.ImageFileDirectory_v2()
 | 
					    ifd = TiffImagePlugin.ImageFileDirectory_v2()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    #    277: ("SamplesPerPixel", SHORT, 1),
 | 
					    #    277: ("SamplesPerPixel", SHORT, 1),
 | 
				
			||||||
| 
						 | 
					@ -432,7 +433,7 @@ def test_too_many_entries():
 | 
				
			||||||
        assert ifd[277] == 4
 | 
					        assert ifd[277] == 4
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_tag_group_data():
 | 
					def test_tag_group_data() -> None:
 | 
				
			||||||
    base_ifd = TiffImagePlugin.ImageFileDirectory_v2()
 | 
					    base_ifd = TiffImagePlugin.ImageFileDirectory_v2()
 | 
				
			||||||
    interop_ifd = TiffImagePlugin.ImageFileDirectory_v2(group=40965)
 | 
					    interop_ifd = TiffImagePlugin.ImageFileDirectory_v2(group=40965)
 | 
				
			||||||
    for ifd in (base_ifd, interop_ifd):
 | 
					    for ifd in (base_ifd, interop_ifd):
 | 
				
			||||||
| 
						 | 
					@ -446,7 +447,7 @@ def test_tag_group_data():
 | 
				
			||||||
    assert base_ifd.tagtype[2] != interop_ifd.tagtype[256]
 | 
					    assert base_ifd.tagtype[2] != interop_ifd.tagtype[256]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_empty_subifd(tmp_path):
 | 
					def test_empty_subifd(tmp_path: Path) -> None:
 | 
				
			||||||
    out = str(tmp_path / "temp.jpg")
 | 
					    out = str(tmp_path / "temp.jpg")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    im = hopper()
 | 
					    im = hopper()
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -4,6 +4,7 @@ import io
 | 
				
			||||||
import re
 | 
					import re
 | 
				
			||||||
import sys
 | 
					import sys
 | 
				
			||||||
import warnings
 | 
					import warnings
 | 
				
			||||||
 | 
					from pathlib import Path
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import pytest
 | 
					import pytest
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -26,7 +27,7 @@ except ImportError:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class TestUnsupportedWebp:
 | 
					class TestUnsupportedWebp:
 | 
				
			||||||
    def test_unsupported(self):
 | 
					    def test_unsupported(self) -> None:
 | 
				
			||||||
        if HAVE_WEBP:
 | 
					        if HAVE_WEBP:
 | 
				
			||||||
            WebPImagePlugin.SUPPORTED = False
 | 
					            WebPImagePlugin.SUPPORTED = False
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -42,15 +43,15 @@ class TestUnsupportedWebp:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@skip_unless_feature("webp")
 | 
					@skip_unless_feature("webp")
 | 
				
			||||||
class TestFileWebp:
 | 
					class TestFileWebp:
 | 
				
			||||||
    def setup_method(self):
 | 
					    def setup_method(self) -> None:
 | 
				
			||||||
        self.rgb_mode = "RGB"
 | 
					        self.rgb_mode = "RGB"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_version(self):
 | 
					    def test_version(self) -> None:
 | 
				
			||||||
        _webp.WebPDecoderVersion()
 | 
					        _webp.WebPDecoderVersion()
 | 
				
			||||||
        _webp.WebPDecoderBuggyAlpha()
 | 
					        _webp.WebPDecoderBuggyAlpha()
 | 
				
			||||||
        assert re.search(r"\d+\.\d+\.\d+$", features.version_module("webp"))
 | 
					        assert re.search(r"\d+\.\d+\.\d+$", features.version_module("webp"))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_read_rgb(self):
 | 
					    def test_read_rgb(self) -> None:
 | 
				
			||||||
        """
 | 
					        """
 | 
				
			||||||
        Can we read a RGB mode WebP file without error?
 | 
					        Can we read a RGB mode WebP file without error?
 | 
				
			||||||
        Does it have the bits we expect?
 | 
					        Does it have the bits we expect?
 | 
				
			||||||
| 
						 | 
					@ -67,7 +68,7 @@ class TestFileWebp:
 | 
				
			||||||
            # dwebp -ppm ../../Tests/images/hopper.webp -o hopper_webp_bits.ppm
 | 
					            # dwebp -ppm ../../Tests/images/hopper.webp -o hopper_webp_bits.ppm
 | 
				
			||||||
            assert_image_similar_tofile(image, "Tests/images/hopper_webp_bits.ppm", 1.0)
 | 
					            assert_image_similar_tofile(image, "Tests/images/hopper_webp_bits.ppm", 1.0)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def _roundtrip(self, tmp_path, mode, epsilon, args={}):
 | 
					    def _roundtrip(self, tmp_path: Path, mode, epsilon, args={}) -> None:
 | 
				
			||||||
        temp_file = str(tmp_path / "temp.webp")
 | 
					        temp_file = str(tmp_path / "temp.webp")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        hopper(mode).save(temp_file, **args)
 | 
					        hopper(mode).save(temp_file, **args)
 | 
				
			||||||
| 
						 | 
					@ -93,7 +94,7 @@ class TestFileWebp:
 | 
				
			||||||
                target = target.convert(self.rgb_mode)
 | 
					                target = target.convert(self.rgb_mode)
 | 
				
			||||||
            assert_image_similar(image, target, epsilon)
 | 
					            assert_image_similar(image, target, epsilon)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_write_rgb(self, tmp_path):
 | 
					    def test_write_rgb(self, tmp_path: Path) -> None:
 | 
				
			||||||
        """
 | 
					        """
 | 
				
			||||||
        Can we write a RGB mode file to webp without error?
 | 
					        Can we write a RGB mode file to webp without error?
 | 
				
			||||||
        Does it have the bits we expect?
 | 
					        Does it have the bits we expect?
 | 
				
			||||||
| 
						 | 
					@ -101,7 +102,7 @@ class TestFileWebp:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        self._roundtrip(tmp_path, self.rgb_mode, 12.5)
 | 
					        self._roundtrip(tmp_path, self.rgb_mode, 12.5)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_write_method(self, tmp_path):
 | 
					    def test_write_method(self, tmp_path: Path) -> None:
 | 
				
			||||||
        self._roundtrip(tmp_path, self.rgb_mode, 12.0, {"method": 6})
 | 
					        self._roundtrip(tmp_path, self.rgb_mode, 12.0, {"method": 6})
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        buffer_no_args = io.BytesIO()
 | 
					        buffer_no_args = io.BytesIO()
 | 
				
			||||||
| 
						 | 
					@ -112,7 +113,7 @@ class TestFileWebp:
 | 
				
			||||||
        assert buffer_no_args.getbuffer() != buffer_method.getbuffer()
 | 
					        assert buffer_no_args.getbuffer() != buffer_method.getbuffer()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    @skip_unless_feature("webp_anim")
 | 
					    @skip_unless_feature("webp_anim")
 | 
				
			||||||
    def test_save_all(self, tmp_path):
 | 
					    def test_save_all(self, tmp_path: Path) -> None:
 | 
				
			||||||
        temp_file = str(tmp_path / "temp.webp")
 | 
					        temp_file = str(tmp_path / "temp.webp")
 | 
				
			||||||
        im = Image.new("RGB", (1, 1))
 | 
					        im = Image.new("RGB", (1, 1))
 | 
				
			||||||
        im2 = Image.new("RGB", (1, 1), "#f00")
 | 
					        im2 = Image.new("RGB", (1, 1), "#f00")
 | 
				
			||||||
| 
						 | 
					@ -124,14 +125,14 @@ class TestFileWebp:
 | 
				
			||||||
            reloaded.seek(1)
 | 
					            reloaded.seek(1)
 | 
				
			||||||
            assert_image_similar(im2, reloaded, 1)
 | 
					            assert_image_similar(im2, reloaded, 1)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_icc_profile(self, tmp_path):
 | 
					    def test_icc_profile(self, tmp_path: Path) -> None:
 | 
				
			||||||
        self._roundtrip(tmp_path, self.rgb_mode, 12.5, {"icc_profile": None})
 | 
					        self._roundtrip(tmp_path, self.rgb_mode, 12.5, {"icc_profile": None})
 | 
				
			||||||
        if _webp.HAVE_WEBPANIM:
 | 
					        if _webp.HAVE_WEBPANIM:
 | 
				
			||||||
            self._roundtrip(
 | 
					            self._roundtrip(
 | 
				
			||||||
                tmp_path, self.rgb_mode, 12.5, {"icc_profile": None, "save_all": True}
 | 
					                tmp_path, self.rgb_mode, 12.5, {"icc_profile": None, "save_all": True}
 | 
				
			||||||
            )
 | 
					            )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_write_unsupported_mode_L(self, tmp_path):
 | 
					    def test_write_unsupported_mode_L(self, tmp_path: Path) -> None:
 | 
				
			||||||
        """
 | 
					        """
 | 
				
			||||||
        Saving a black-and-white file to WebP format should work, and be
 | 
					        Saving a black-and-white file to WebP format should work, and be
 | 
				
			||||||
        similar to the original file.
 | 
					        similar to the original file.
 | 
				
			||||||
| 
						 | 
					@ -139,7 +140,7 @@ class TestFileWebp:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        self._roundtrip(tmp_path, "L", 10.0)
 | 
					        self._roundtrip(tmp_path, "L", 10.0)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_write_unsupported_mode_P(self, tmp_path):
 | 
					    def test_write_unsupported_mode_P(self, tmp_path: Path) -> None:
 | 
				
			||||||
        """
 | 
					        """
 | 
				
			||||||
        Saving a palette-based file to WebP format should work, and be
 | 
					        Saving a palette-based file to WebP format should work, and be
 | 
				
			||||||
        similar to the original file.
 | 
					        similar to the original file.
 | 
				
			||||||
| 
						 | 
					@ -148,14 +149,14 @@ class TestFileWebp:
 | 
				
			||||||
        self._roundtrip(tmp_path, "P", 50.0)
 | 
					        self._roundtrip(tmp_path, "P", 50.0)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    @pytest.mark.skipif(sys.maxsize <= 2**32, reason="Requires 64-bit system")
 | 
					    @pytest.mark.skipif(sys.maxsize <= 2**32, reason="Requires 64-bit system")
 | 
				
			||||||
    def test_write_encoding_error_message(self, tmp_path):
 | 
					    def test_write_encoding_error_message(self, tmp_path: Path) -> None:
 | 
				
			||||||
        temp_file = str(tmp_path / "temp.webp")
 | 
					        temp_file = str(tmp_path / "temp.webp")
 | 
				
			||||||
        im = Image.new("RGB", (15000, 15000))
 | 
					        im = Image.new("RGB", (15000, 15000))
 | 
				
			||||||
        with pytest.raises(ValueError) as e:
 | 
					        with pytest.raises(ValueError) as e:
 | 
				
			||||||
            im.save(temp_file, method=0)
 | 
					            im.save(temp_file, method=0)
 | 
				
			||||||
        assert str(e.value) == "encoding error 6"
 | 
					        assert str(e.value) == "encoding error 6"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_WebPEncode_with_invalid_args(self):
 | 
					    def test_WebPEncode_with_invalid_args(self) -> None:
 | 
				
			||||||
        """
 | 
					        """
 | 
				
			||||||
        Calling encoder functions with no arguments should result in an error.
 | 
					        Calling encoder functions with no arguments should result in an error.
 | 
				
			||||||
        """
 | 
					        """
 | 
				
			||||||
| 
						 | 
					@ -166,7 +167,7 @@ class TestFileWebp:
 | 
				
			||||||
        with pytest.raises(TypeError):
 | 
					        with pytest.raises(TypeError):
 | 
				
			||||||
            _webp.WebPEncode()
 | 
					            _webp.WebPEncode()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_WebPDecode_with_invalid_args(self):
 | 
					    def test_WebPDecode_with_invalid_args(self) -> None:
 | 
				
			||||||
        """
 | 
					        """
 | 
				
			||||||
        Calling decoder functions with no arguments should result in an error.
 | 
					        Calling decoder functions with no arguments should result in an error.
 | 
				
			||||||
        """
 | 
					        """
 | 
				
			||||||
| 
						 | 
					@ -177,14 +178,14 @@ class TestFileWebp:
 | 
				
			||||||
        with pytest.raises(TypeError):
 | 
					        with pytest.raises(TypeError):
 | 
				
			||||||
            _webp.WebPDecode()
 | 
					            _webp.WebPDecode()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_no_resource_warning(self, tmp_path):
 | 
					    def test_no_resource_warning(self, tmp_path: Path) -> None:
 | 
				
			||||||
        file_path = "Tests/images/hopper.webp"
 | 
					        file_path = "Tests/images/hopper.webp"
 | 
				
			||||||
        with Image.open(file_path) as image:
 | 
					        with Image.open(file_path) as image:
 | 
				
			||||||
            temp_file = str(tmp_path / "temp.webp")
 | 
					            temp_file = str(tmp_path / "temp.webp")
 | 
				
			||||||
            with warnings.catch_warnings():
 | 
					            with warnings.catch_warnings():
 | 
				
			||||||
                image.save(temp_file)
 | 
					                image.save(temp_file)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_file_pointer_could_be_reused(self):
 | 
					    def test_file_pointer_could_be_reused(self) -> None:
 | 
				
			||||||
        file_path = "Tests/images/hopper.webp"
 | 
					        file_path = "Tests/images/hopper.webp"
 | 
				
			||||||
        with open(file_path, "rb") as blob:
 | 
					        with open(file_path, "rb") as blob:
 | 
				
			||||||
            Image.open(blob).load()
 | 
					            Image.open(blob).load()
 | 
				
			||||||
| 
						 | 
					@ -195,14 +196,14 @@ class TestFileWebp:
 | 
				
			||||||
        (0, (0,), (-1, 0, 1, 2), (253, 254, 255, 256)),
 | 
					        (0, (0,), (-1, 0, 1, 2), (253, 254, 255, 256)),
 | 
				
			||||||
    )
 | 
					    )
 | 
				
			||||||
    @skip_unless_feature("webp_anim")
 | 
					    @skip_unless_feature("webp_anim")
 | 
				
			||||||
    def test_invalid_background(self, background, tmp_path):
 | 
					    def test_invalid_background(self, background, tmp_path: Path) -> None:
 | 
				
			||||||
        temp_file = str(tmp_path / "temp.webp")
 | 
					        temp_file = str(tmp_path / "temp.webp")
 | 
				
			||||||
        im = hopper()
 | 
					        im = hopper()
 | 
				
			||||||
        with pytest.raises(OSError):
 | 
					        with pytest.raises(OSError):
 | 
				
			||||||
            im.save(temp_file, save_all=True, append_images=[im], background=background)
 | 
					            im.save(temp_file, save_all=True, append_images=[im], background=background)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    @skip_unless_feature("webp_anim")
 | 
					    @skip_unless_feature("webp_anim")
 | 
				
			||||||
    def test_background_from_gif(self, tmp_path):
 | 
					    def test_background_from_gif(self, tmp_path: Path) -> None:
 | 
				
			||||||
        # Save L mode GIF with background
 | 
					        # Save L mode GIF with background
 | 
				
			||||||
        with Image.open("Tests/images/no_palette_with_background.gif") as im:
 | 
					        with Image.open("Tests/images/no_palette_with_background.gif") as im:
 | 
				
			||||||
            out_webp = str(tmp_path / "temp.webp")
 | 
					            out_webp = str(tmp_path / "temp.webp")
 | 
				
			||||||
| 
						 | 
					@ -227,7 +228,7 @@ class TestFileWebp:
 | 
				
			||||||
        assert difference < 5
 | 
					        assert difference < 5
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    @skip_unless_feature("webp_anim")
 | 
					    @skip_unless_feature("webp_anim")
 | 
				
			||||||
    def test_duration(self, tmp_path):
 | 
					    def test_duration(self, tmp_path: Path) -> None:
 | 
				
			||||||
        with Image.open("Tests/images/dispose_bgnd.gif") as im:
 | 
					        with Image.open("Tests/images/dispose_bgnd.gif") as im:
 | 
				
			||||||
            assert im.info["duration"] == 1000
 | 
					            assert im.info["duration"] == 1000
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -238,7 +239,7 @@ class TestFileWebp:
 | 
				
			||||||
            reloaded.load()
 | 
					            reloaded.load()
 | 
				
			||||||
            assert reloaded.info["duration"] == 1000
 | 
					            assert reloaded.info["duration"] == 1000
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_roundtrip_rgba_palette(self, tmp_path):
 | 
					    def test_roundtrip_rgba_palette(self, tmp_path: Path) -> None:
 | 
				
			||||||
        temp_file = str(tmp_path / "temp.webp")
 | 
					        temp_file = str(tmp_path / "temp.webp")
 | 
				
			||||||
        im = Image.new("RGBA", (1, 1)).convert("P")
 | 
					        im = Image.new("RGBA", (1, 1)).convert("P")
 | 
				
			||||||
        assert im.mode == "P"
 | 
					        assert im.mode == "P"
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,5 +1,7 @@
 | 
				
			||||||
from __future__ import annotations
 | 
					from __future__ import annotations
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					from pathlib import Path
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import pytest
 | 
					import pytest
 | 
				
			||||||
 | 
					
 | 
				
			||||||
from PIL import Image
 | 
					from PIL import Image
 | 
				
			||||||
| 
						 | 
					@ -14,12 +16,12 @@ from .helper import (
 | 
				
			||||||
_webp = pytest.importorskip("PIL._webp", reason="WebP support not installed")
 | 
					_webp = pytest.importorskip("PIL._webp", reason="WebP support not installed")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def setup_module():
 | 
					def setup_module() -> None:
 | 
				
			||||||
    if _webp.WebPDecoderBuggyAlpha():
 | 
					    if _webp.WebPDecoderBuggyAlpha():
 | 
				
			||||||
        pytest.skip("Buggy early version of WebP installed, not testing transparency")
 | 
					        pytest.skip("Buggy early version of WebP installed, not testing transparency")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_read_rgba():
 | 
					def test_read_rgba() -> None:
 | 
				
			||||||
    """
 | 
					    """
 | 
				
			||||||
    Can we read an RGBA mode file without error?
 | 
					    Can we read an RGBA mode file without error?
 | 
				
			||||||
    Does it have the bits we expect?
 | 
					    Does it have the bits we expect?
 | 
				
			||||||
| 
						 | 
					@ -39,7 +41,7 @@ def test_read_rgba():
 | 
				
			||||||
        assert_image_similar_tofile(image, "Tests/images/transparent.png", 20.0)
 | 
					        assert_image_similar_tofile(image, "Tests/images/transparent.png", 20.0)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_write_lossless_rgb(tmp_path):
 | 
					def test_write_lossless_rgb(tmp_path: Path) -> None:
 | 
				
			||||||
    """
 | 
					    """
 | 
				
			||||||
    Can we write an RGBA mode file with lossless compression without error?
 | 
					    Can we write an RGBA mode file with lossless compression without error?
 | 
				
			||||||
    Does it have the bits we expect?
 | 
					    Does it have the bits we expect?
 | 
				
			||||||
| 
						 | 
					@ -68,7 +70,7 @@ def test_write_lossless_rgb(tmp_path):
 | 
				
			||||||
        assert_image_equal(image, pil_image)
 | 
					        assert_image_equal(image, pil_image)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_write_rgba(tmp_path):
 | 
					def test_write_rgba(tmp_path: Path) -> None:
 | 
				
			||||||
    """
 | 
					    """
 | 
				
			||||||
    Can we write a RGBA mode file to WebP without error.
 | 
					    Can we write a RGBA mode file to WebP without error.
 | 
				
			||||||
    Does it have the bits we expect?
 | 
					    Does it have the bits we expect?
 | 
				
			||||||
| 
						 | 
					@ -99,7 +101,7 @@ def test_write_rgba(tmp_path):
 | 
				
			||||||
            assert_image_similar(image, pil_image, 1.0)
 | 
					            assert_image_similar(image, pil_image, 1.0)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_keep_rgb_values_when_transparent(tmp_path):
 | 
					def test_keep_rgb_values_when_transparent(tmp_path: Path) -> None:
 | 
				
			||||||
    """
 | 
					    """
 | 
				
			||||||
    Saving transparent pixels should retain their original RGB values
 | 
					    Saving transparent pixels should retain their original RGB values
 | 
				
			||||||
    when using the "exact" parameter.
 | 
					    when using the "exact" parameter.
 | 
				
			||||||
| 
						 | 
					@ -128,7 +130,7 @@ def test_keep_rgb_values_when_transparent(tmp_path):
 | 
				
			||||||
        assert_image_equal(reloaded.convert("RGB"), image)
 | 
					        assert_image_equal(reloaded.convert("RGB"), image)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_write_unsupported_mode_PA(tmp_path):
 | 
					def test_write_unsupported_mode_PA(tmp_path: Path) -> None:
 | 
				
			||||||
    """
 | 
					    """
 | 
				
			||||||
    Saving a palette-based file with transparency to WebP format
 | 
					    Saving a palette-based file with transparency to WebP format
 | 
				
			||||||
    should work, and be similar to the original file.
 | 
					    should work, and be similar to the original file.
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,5 +1,7 @@
 | 
				
			||||||
from __future__ import annotations
 | 
					from __future__ import annotations
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					from pathlib import Path
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import pytest
 | 
					import pytest
 | 
				
			||||||
from packaging.version import parse as parse_version
 | 
					from packaging.version import parse as parse_version
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -18,7 +20,7 @@ pytestmark = [
 | 
				
			||||||
]
 | 
					]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_n_frames():
 | 
					def test_n_frames() -> None:
 | 
				
			||||||
    """Ensure that WebP format sets n_frames and is_animated attributes correctly."""
 | 
					    """Ensure that WebP format sets n_frames and is_animated attributes correctly."""
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    with Image.open("Tests/images/hopper.webp") as im:
 | 
					    with Image.open("Tests/images/hopper.webp") as im:
 | 
				
			||||||
| 
						 | 
					@ -30,7 +32,7 @@ def test_n_frames():
 | 
				
			||||||
        assert im.is_animated
 | 
					        assert im.is_animated
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_write_animation_L(tmp_path):
 | 
					def test_write_animation_L(tmp_path: Path) -> None:
 | 
				
			||||||
    """
 | 
					    """
 | 
				
			||||||
    Convert an animated GIF to animated WebP, then compare the frame count, and first
 | 
					    Convert an animated GIF to animated WebP, then compare the frame count, and first
 | 
				
			||||||
    and last frames to ensure they're visually similar.
 | 
					    and last frames to ensure they're visually similar.
 | 
				
			||||||
| 
						 | 
					@ -60,13 +62,13 @@ def test_write_animation_L(tmp_path):
 | 
				
			||||||
            assert_image_similar(im, orig.convert("RGBA"), 32.9)
 | 
					            assert_image_similar(im, orig.convert("RGBA"), 32.9)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_write_animation_RGB(tmp_path):
 | 
					def test_write_animation_RGB(tmp_path: Path) -> None:
 | 
				
			||||||
    """
 | 
					    """
 | 
				
			||||||
    Write an animated WebP from RGB frames, and ensure the frames
 | 
					    Write an animated WebP from RGB frames, and ensure the frames
 | 
				
			||||||
    are visually similar to the originals.
 | 
					    are visually similar to the originals.
 | 
				
			||||||
    """
 | 
					    """
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def check(temp_file):
 | 
					    def check(temp_file) -> None:
 | 
				
			||||||
        with Image.open(temp_file) as im:
 | 
					        with Image.open(temp_file) as im:
 | 
				
			||||||
            assert im.n_frames == 2
 | 
					            assert im.n_frames == 2
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -105,7 +107,7 @@ def test_write_animation_RGB(tmp_path):
 | 
				
			||||||
            check(temp_file2)
 | 
					            check(temp_file2)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_timestamp_and_duration(tmp_path):
 | 
					def test_timestamp_and_duration(tmp_path: Path) -> None:
 | 
				
			||||||
    """
 | 
					    """
 | 
				
			||||||
    Try passing a list of durations, and make sure the encoded
 | 
					    Try passing a list of durations, and make sure the encoded
 | 
				
			||||||
    timestamps and durations are correct.
 | 
					    timestamps and durations are correct.
 | 
				
			||||||
| 
						 | 
					@ -136,7 +138,7 @@ def test_timestamp_and_duration(tmp_path):
 | 
				
			||||||
            ts += durations[frame]
 | 
					            ts += durations[frame]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_float_duration(tmp_path):
 | 
					def test_float_duration(tmp_path: Path) -> None:
 | 
				
			||||||
    temp_file = str(tmp_path / "temp.webp")
 | 
					    temp_file = str(tmp_path / "temp.webp")
 | 
				
			||||||
    with Image.open("Tests/images/iss634.apng") as im:
 | 
					    with Image.open("Tests/images/iss634.apng") as im:
 | 
				
			||||||
        assert im.info["duration"] == 70.0
 | 
					        assert im.info["duration"] == 70.0
 | 
				
			||||||
| 
						 | 
					@ -148,7 +150,7 @@ def test_float_duration(tmp_path):
 | 
				
			||||||
        assert reloaded.info["duration"] == 70
 | 
					        assert reloaded.info["duration"] == 70
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_seeking(tmp_path):
 | 
					def test_seeking(tmp_path: Path) -> None:
 | 
				
			||||||
    """
 | 
					    """
 | 
				
			||||||
    Create an animated WebP file, and then try seeking through frames in reverse-order,
 | 
					    Create an animated WebP file, and then try seeking through frames in reverse-order,
 | 
				
			||||||
    verifying the timestamps and durations are correct.
 | 
					    verifying the timestamps and durations are correct.
 | 
				
			||||||
| 
						 | 
					@ -179,7 +181,7 @@ def test_seeking(tmp_path):
 | 
				
			||||||
            ts -= dur
 | 
					            ts -= dur
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_seek_errors():
 | 
					def test_seek_errors() -> None:
 | 
				
			||||||
    with Image.open("Tests/images/iss634.webp") as im:
 | 
					    with Image.open("Tests/images/iss634.webp") as im:
 | 
				
			||||||
        with pytest.raises(EOFError):
 | 
					        with pytest.raises(EOFError):
 | 
				
			||||||
            im.seek(-1)
 | 
					            im.seek(-1)
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,6 +1,7 @@
 | 
				
			||||||
from __future__ import annotations
 | 
					from __future__ import annotations
 | 
				
			||||||
 | 
					
 | 
				
			||||||
from io import BytesIO
 | 
					from io import BytesIO
 | 
				
			||||||
 | 
					from pathlib import Path
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import pytest
 | 
					import pytest
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -19,7 +20,7 @@ except ImportError:
 | 
				
			||||||
    ElementTree = None
 | 
					    ElementTree = None
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_read_exif_metadata():
 | 
					def test_read_exif_metadata() -> None:
 | 
				
			||||||
    file_path = "Tests/images/flower.webp"
 | 
					    file_path = "Tests/images/flower.webp"
 | 
				
			||||||
    with Image.open(file_path) as image:
 | 
					    with Image.open(file_path) as image:
 | 
				
			||||||
        assert image.format == "WEBP"
 | 
					        assert image.format == "WEBP"
 | 
				
			||||||
| 
						 | 
					@ -37,7 +38,7 @@ def test_read_exif_metadata():
 | 
				
			||||||
            assert exif_data == expected_exif
 | 
					            assert exif_data == expected_exif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_read_exif_metadata_without_prefix():
 | 
					def test_read_exif_metadata_without_prefix() -> None:
 | 
				
			||||||
    with Image.open("Tests/images/flower2.webp") as im:
 | 
					    with Image.open("Tests/images/flower2.webp") as im:
 | 
				
			||||||
        # Assert prefix is not present
 | 
					        # Assert prefix is not present
 | 
				
			||||||
        assert im.info["exif"][:6] != b"Exif\x00\x00"
 | 
					        assert im.info["exif"][:6] != b"Exif\x00\x00"
 | 
				
			||||||
| 
						 | 
					@ -49,7 +50,7 @@ def test_read_exif_metadata_without_prefix():
 | 
				
			||||||
@mark_if_feature_version(
 | 
					@mark_if_feature_version(
 | 
				
			||||||
    pytest.mark.valgrind_known_error, "libjpeg_turbo", "2.0", reason="Known Failing"
 | 
					    pytest.mark.valgrind_known_error, "libjpeg_turbo", "2.0", reason="Known Failing"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
def test_write_exif_metadata():
 | 
					def test_write_exif_metadata() -> None:
 | 
				
			||||||
    file_path = "Tests/images/flower.jpg"
 | 
					    file_path = "Tests/images/flower.jpg"
 | 
				
			||||||
    test_buffer = BytesIO()
 | 
					    test_buffer = BytesIO()
 | 
				
			||||||
    with Image.open(file_path) as image:
 | 
					    with Image.open(file_path) as image:
 | 
				
			||||||
| 
						 | 
					@ -63,7 +64,7 @@ def test_write_exif_metadata():
 | 
				
			||||||
    assert webp_exif == expected_exif[6:], "WebP EXIF didn't match"
 | 
					    assert webp_exif == expected_exif[6:], "WebP EXIF didn't match"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_read_icc_profile():
 | 
					def test_read_icc_profile() -> None:
 | 
				
			||||||
    file_path = "Tests/images/flower2.webp"
 | 
					    file_path = "Tests/images/flower2.webp"
 | 
				
			||||||
    with Image.open(file_path) as image:
 | 
					    with Image.open(file_path) as image:
 | 
				
			||||||
        assert image.format == "WEBP"
 | 
					        assert image.format == "WEBP"
 | 
				
			||||||
| 
						 | 
					@ -80,7 +81,7 @@ def test_read_icc_profile():
 | 
				
			||||||
@mark_if_feature_version(
 | 
					@mark_if_feature_version(
 | 
				
			||||||
    pytest.mark.valgrind_known_error, "libjpeg_turbo", "2.0", reason="Known Failing"
 | 
					    pytest.mark.valgrind_known_error, "libjpeg_turbo", "2.0", reason="Known Failing"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
def test_write_icc_metadata():
 | 
					def test_write_icc_metadata() -> None:
 | 
				
			||||||
    file_path = "Tests/images/flower2.jpg"
 | 
					    file_path = "Tests/images/flower2.jpg"
 | 
				
			||||||
    test_buffer = BytesIO()
 | 
					    test_buffer = BytesIO()
 | 
				
			||||||
    with Image.open(file_path) as image:
 | 
					    with Image.open(file_path) as image:
 | 
				
			||||||
| 
						 | 
					@ -100,7 +101,7 @@ def test_write_icc_metadata():
 | 
				
			||||||
@mark_if_feature_version(
 | 
					@mark_if_feature_version(
 | 
				
			||||||
    pytest.mark.valgrind_known_error, "libjpeg_turbo", "2.0", reason="Known Failing"
 | 
					    pytest.mark.valgrind_known_error, "libjpeg_turbo", "2.0", reason="Known Failing"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
def test_read_no_exif():
 | 
					def test_read_no_exif() -> None:
 | 
				
			||||||
    file_path = "Tests/images/flower.jpg"
 | 
					    file_path = "Tests/images/flower.jpg"
 | 
				
			||||||
    test_buffer = BytesIO()
 | 
					    test_buffer = BytesIO()
 | 
				
			||||||
    with Image.open(file_path) as image:
 | 
					    with Image.open(file_path) as image:
 | 
				
			||||||
| 
						 | 
					@ -113,7 +114,7 @@ def test_read_no_exif():
 | 
				
			||||||
        assert not webp_image._getexif()
 | 
					        assert not webp_image._getexif()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_getxmp():
 | 
					def test_getxmp() -> None:
 | 
				
			||||||
    with Image.open("Tests/images/flower.webp") as im:
 | 
					    with Image.open("Tests/images/flower.webp") as im:
 | 
				
			||||||
        assert "xmp" not in im.info
 | 
					        assert "xmp" not in im.info
 | 
				
			||||||
        assert im.getxmp() == {}
 | 
					        assert im.getxmp() == {}
 | 
				
			||||||
| 
						 | 
					@ -133,7 +134,7 @@ def test_getxmp():
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@skip_unless_feature("webp_anim")
 | 
					@skip_unless_feature("webp_anim")
 | 
				
			||||||
def test_write_animated_metadata(tmp_path):
 | 
					def test_write_animated_metadata(tmp_path: Path) -> None:
 | 
				
			||||||
    iccp_data = b"<iccp_data>"
 | 
					    iccp_data = b"<iccp_data>"
 | 
				
			||||||
    exif_data = b"<exif_data>"
 | 
					    exif_data = b"<exif_data>"
 | 
				
			||||||
    xmp_data = b"<xmp_data>"
 | 
					    xmp_data = b"<xmp_data>"
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,5 +1,7 @@
 | 
				
			||||||
from __future__ import annotations
 | 
					from __future__ import annotations
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					from pathlib import Path
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import pytest
 | 
					import pytest
 | 
				
			||||||
 | 
					
 | 
				
			||||||
from PIL import Image, WmfImagePlugin
 | 
					from PIL import Image, WmfImagePlugin
 | 
				
			||||||
| 
						 | 
					@ -7,7 +9,7 @@ from PIL import Image, WmfImagePlugin
 | 
				
			||||||
from .helper import assert_image_similar_tofile, hopper
 | 
					from .helper import assert_image_similar_tofile, hopper
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_load_raw():
 | 
					def test_load_raw() -> None:
 | 
				
			||||||
    # Test basic EMF open and rendering
 | 
					    # Test basic EMF open and rendering
 | 
				
			||||||
    with Image.open("Tests/images/drawing.emf") as im:
 | 
					    with Image.open("Tests/images/drawing.emf") as im:
 | 
				
			||||||
        if hasattr(Image.core, "drawwmf"):
 | 
					        if hasattr(Image.core, "drawwmf"):
 | 
				
			||||||
| 
						 | 
					@ -25,17 +27,17 @@ def test_load_raw():
 | 
				
			||||||
            assert_image_similar_tofile(im, "Tests/images/drawing_wmf_ref.png", 2.0)
 | 
					            assert_image_similar_tofile(im, "Tests/images/drawing_wmf_ref.png", 2.0)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_load():
 | 
					def test_load() -> None:
 | 
				
			||||||
    with Image.open("Tests/images/drawing.emf") as im:
 | 
					    with Image.open("Tests/images/drawing.emf") as im:
 | 
				
			||||||
        if hasattr(Image.core, "drawwmf"):
 | 
					        if hasattr(Image.core, "drawwmf"):
 | 
				
			||||||
            assert im.load()[0, 0] == (255, 255, 255)
 | 
					            assert im.load()[0, 0] == (255, 255, 255)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_register_handler(tmp_path):
 | 
					def test_register_handler(tmp_path: Path) -> None:
 | 
				
			||||||
    class TestHandler:
 | 
					    class TestHandler:
 | 
				
			||||||
        methodCalled = False
 | 
					        methodCalled = False
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        def save(self, im, fp, filename):
 | 
					        def save(self, im, fp, filename) -> None:
 | 
				
			||||||
            self.methodCalled = True
 | 
					            self.methodCalled = True
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    handler = TestHandler()
 | 
					    handler = TestHandler()
 | 
				
			||||||
| 
						 | 
					@ -51,12 +53,12 @@ def test_register_handler(tmp_path):
 | 
				
			||||||
    WmfImagePlugin.register_handler(original_handler)
 | 
					    WmfImagePlugin.register_handler(original_handler)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_load_float_dpi():
 | 
					def test_load_float_dpi() -> None:
 | 
				
			||||||
    with Image.open("Tests/images/drawing.emf") as im:
 | 
					    with Image.open("Tests/images/drawing.emf") as im:
 | 
				
			||||||
        assert im.info["dpi"] == 1423.7668161434979
 | 
					        assert im.info["dpi"] == 1423.7668161434979
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_load_set_dpi():
 | 
					def test_load_set_dpi() -> None:
 | 
				
			||||||
    with Image.open("Tests/images/drawing.wmf") as im:
 | 
					    with Image.open("Tests/images/drawing.wmf") as im:
 | 
				
			||||||
        assert im.size == (82, 82)
 | 
					        assert im.size == (82, 82)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -68,7 +70,7 @@ def test_load_set_dpi():
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@pytest.mark.parametrize("ext", (".wmf", ".emf"))
 | 
					@pytest.mark.parametrize("ext", (".wmf", ".emf"))
 | 
				
			||||||
def test_save(ext, tmp_path):
 | 
					def test_save(ext, tmp_path: Path) -> None:
 | 
				
			||||||
    im = hopper()
 | 
					    im = hopper()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    tmpfile = str(tmp_path / ("temp" + ext))
 | 
					    tmpfile = str(tmp_path / ("temp" + ext))
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,6 +1,7 @@
 | 
				
			||||||
from __future__ import annotations
 | 
					from __future__ import annotations
 | 
				
			||||||
 | 
					
 | 
				
			||||||
from io import BytesIO
 | 
					from io import BytesIO
 | 
				
			||||||
 | 
					from pathlib import Path
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import pytest
 | 
					import pytest
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -32,14 +33,14 @@ static char basic_bits[] = {
 | 
				
			||||||
"""
 | 
					"""
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_pil151():
 | 
					def test_pil151() -> None:
 | 
				
			||||||
    with Image.open(BytesIO(PIL151)) as im:
 | 
					    with Image.open(BytesIO(PIL151)) as im:
 | 
				
			||||||
        im.load()
 | 
					        im.load()
 | 
				
			||||||
        assert im.mode == "1"
 | 
					        assert im.mode == "1"
 | 
				
			||||||
        assert im.size == (32, 32)
 | 
					        assert im.size == (32, 32)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_open():
 | 
					def test_open() -> None:
 | 
				
			||||||
    # Arrange
 | 
					    # Arrange
 | 
				
			||||||
    # Created with `convert hopper.png hopper.xbm`
 | 
					    # Created with `convert hopper.png hopper.xbm`
 | 
				
			||||||
    filename = "Tests/images/hopper.xbm"
 | 
					    filename = "Tests/images/hopper.xbm"
 | 
				
			||||||
| 
						 | 
					@ -51,7 +52,7 @@ def test_open():
 | 
				
			||||||
        assert im.size == (128, 128)
 | 
					        assert im.size == (128, 128)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_open_filename_with_underscore():
 | 
					def test_open_filename_with_underscore() -> None:
 | 
				
			||||||
    # Arrange
 | 
					    # Arrange
 | 
				
			||||||
    # Created with `convert hopper.png hopper_underscore.xbm`
 | 
					    # Created with `convert hopper.png hopper_underscore.xbm`
 | 
				
			||||||
    filename = "Tests/images/hopper_underscore.xbm"
 | 
					    filename = "Tests/images/hopper_underscore.xbm"
 | 
				
			||||||
| 
						 | 
					@ -63,14 +64,14 @@ def test_open_filename_with_underscore():
 | 
				
			||||||
        assert im.size == (128, 128)
 | 
					        assert im.size == (128, 128)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_invalid_file():
 | 
					def test_invalid_file() -> None:
 | 
				
			||||||
    invalid_file = "Tests/images/flower.jpg"
 | 
					    invalid_file = "Tests/images/flower.jpg"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    with pytest.raises(SyntaxError):
 | 
					    with pytest.raises(SyntaxError):
 | 
				
			||||||
        XbmImagePlugin.XbmImageFile(invalid_file)
 | 
					        XbmImagePlugin.XbmImageFile(invalid_file)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_save_wrong_mode(tmp_path):
 | 
					def test_save_wrong_mode(tmp_path: Path) -> None:
 | 
				
			||||||
    im = hopper()
 | 
					    im = hopper()
 | 
				
			||||||
    out = str(tmp_path / "temp.xbm")
 | 
					    out = str(tmp_path / "temp.xbm")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -78,7 +79,7 @@ def test_save_wrong_mode(tmp_path):
 | 
				
			||||||
        im.save(out)
 | 
					        im.save(out)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_hotspot(tmp_path):
 | 
					def test_hotspot(tmp_path: Path) -> None:
 | 
				
			||||||
    im = hopper("1")
 | 
					    im = hopper("1")
 | 
				
			||||||
    out = str(tmp_path / "temp.xbm")
 | 
					    out = str(tmp_path / "temp.xbm")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -21,7 +21,7 @@ def tuple_to_ints(tp):
 | 
				
			||||||
    return int(x * 255.0), int(y * 255.0), int(z * 255.0)
 | 
					    return int(x * 255.0), int(y * 255.0), int(z * 255.0)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_sanity():
 | 
					def test_sanity() -> None:
 | 
				
			||||||
    Image.new("HSV", (100, 100))
 | 
					    Image.new("HSV", (100, 100))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -78,7 +78,7 @@ def to_rgb_colorsys(im):
 | 
				
			||||||
    return to_xxx_colorsys(im, colorsys.hsv_to_rgb, "RGB")
 | 
					    return to_xxx_colorsys(im, colorsys.hsv_to_rgb, "RGB")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_wedge():
 | 
					def test_wedge() -> None:
 | 
				
			||||||
    src = wedge().resize((3 * 32, 32), Image.Resampling.BILINEAR)
 | 
					    src = wedge().resize((3 * 32, 32), Image.Resampling.BILINEAR)
 | 
				
			||||||
    im = src.convert("HSV")
 | 
					    im = src.convert("HSV")
 | 
				
			||||||
    comparable = to_hsv_colorsys(src)
 | 
					    comparable = to_hsv_colorsys(src)
 | 
				
			||||||
| 
						 | 
					@ -110,7 +110,7 @@ def test_wedge():
 | 
				
			||||||
    )
 | 
					    )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_convert():
 | 
					def test_convert() -> None:
 | 
				
			||||||
    im = hopper("RGB").convert("HSV")
 | 
					    im = hopper("RGB").convert("HSV")
 | 
				
			||||||
    comparable = to_hsv_colorsys(hopper("RGB"))
 | 
					    comparable = to_hsv_colorsys(hopper("RGB"))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -128,7 +128,7 @@ def test_convert():
 | 
				
			||||||
    )
 | 
					    )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_hsv_to_rgb():
 | 
					def test_hsv_to_rgb() -> None:
 | 
				
			||||||
    comparable = to_hsv_colorsys(hopper("RGB"))
 | 
					    comparable = to_hsv_colorsys(hopper("RGB"))
 | 
				
			||||||
    converted = comparable.convert("RGB")
 | 
					    converted = comparable.convert("RGB")
 | 
				
			||||||
    comparable = to_rgb_colorsys(comparable)
 | 
					    comparable = to_rgb_colorsys(comparable)
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -7,6 +7,7 @@ import shutil
 | 
				
			||||||
import sys
 | 
					import sys
 | 
				
			||||||
import tempfile
 | 
					import tempfile
 | 
				
			||||||
import warnings
 | 
					import warnings
 | 
				
			||||||
 | 
					from pathlib import Path
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import pytest
 | 
					import pytest
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -60,19 +61,19 @@ class TestImage:
 | 
				
			||||||
            "HSV",
 | 
					            "HSV",
 | 
				
			||||||
        ),
 | 
					        ),
 | 
				
			||||||
    )
 | 
					    )
 | 
				
			||||||
    def test_image_modes_success(self, mode):
 | 
					    def test_image_modes_success(self, mode) -> None:
 | 
				
			||||||
        Image.new(mode, (1, 1))
 | 
					        Image.new(mode, (1, 1))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    @pytest.mark.parametrize("mode", ("", "bad", "very very long"))
 | 
					    @pytest.mark.parametrize("mode", ("", "bad", "very very long"))
 | 
				
			||||||
    def test_image_modes_fail(self, mode):
 | 
					    def test_image_modes_fail(self, mode) -> None:
 | 
				
			||||||
        with pytest.raises(ValueError) as e:
 | 
					        with pytest.raises(ValueError) as e:
 | 
				
			||||||
            Image.new(mode, (1, 1))
 | 
					            Image.new(mode, (1, 1))
 | 
				
			||||||
        assert str(e.value) == "unrecognized image mode"
 | 
					        assert str(e.value) == "unrecognized image mode"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_exception_inheritance(self):
 | 
					    def test_exception_inheritance(self) -> None:
 | 
				
			||||||
        assert issubclass(UnidentifiedImageError, OSError)
 | 
					        assert issubclass(UnidentifiedImageError, OSError)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_sanity(self):
 | 
					    def test_sanity(self) -> None:
 | 
				
			||||||
        im = Image.new("L", (100, 100))
 | 
					        im = Image.new("L", (100, 100))
 | 
				
			||||||
        assert repr(im)[:45] == "<PIL.Image.Image image mode=L size=100x100 at"
 | 
					        assert repr(im)[:45] == "<PIL.Image.Image image mode=L size=100x100 at"
 | 
				
			||||||
        assert im.mode == "L"
 | 
					        assert im.mode == "L"
 | 
				
			||||||
| 
						 | 
					@ -97,9 +98,9 @@ class TestImage:
 | 
				
			||||||
        # with pytest.raises(MemoryError):
 | 
					        # with pytest.raises(MemoryError):
 | 
				
			||||||
        #   Image.new("L", (1000000, 1000000))
 | 
					        #   Image.new("L", (1000000, 1000000))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_repr_pretty(self):
 | 
					    def test_repr_pretty(self) -> None:
 | 
				
			||||||
        class Pretty:
 | 
					        class Pretty:
 | 
				
			||||||
            def text(self, text):
 | 
					            def text(self, text) -> None:
 | 
				
			||||||
                self.pretty_output = text
 | 
					                self.pretty_output = text
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        im = Image.new("L", (100, 100))
 | 
					        im = Image.new("L", (100, 100))
 | 
				
			||||||
| 
						 | 
					@ -108,7 +109,7 @@ class TestImage:
 | 
				
			||||||
        im._repr_pretty_(p, None)
 | 
					        im._repr_pretty_(p, None)
 | 
				
			||||||
        assert p.pretty_output == "<PIL.Image.Image image mode=L size=100x100>"
 | 
					        assert p.pretty_output == "<PIL.Image.Image image mode=L size=100x100>"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_open_formats(self):
 | 
					    def test_open_formats(self) -> None:
 | 
				
			||||||
        PNGFILE = "Tests/images/hopper.png"
 | 
					        PNGFILE = "Tests/images/hopper.png"
 | 
				
			||||||
        JPGFILE = "Tests/images/hopper.jpg"
 | 
					        JPGFILE = "Tests/images/hopper.jpg"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -130,7 +131,7 @@ class TestImage:
 | 
				
			||||||
                assert im.mode == "RGB"
 | 
					                assert im.mode == "RGB"
 | 
				
			||||||
                assert im.size == (128, 128)
 | 
					                assert im.size == (128, 128)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_width_height(self):
 | 
					    def test_width_height(self) -> None:
 | 
				
			||||||
        im = Image.new("RGB", (1, 2))
 | 
					        im = Image.new("RGB", (1, 2))
 | 
				
			||||||
        assert im.width == 1
 | 
					        assert im.width == 1
 | 
				
			||||||
        assert im.height == 2
 | 
					        assert im.height == 2
 | 
				
			||||||
| 
						 | 
					@ -138,29 +139,29 @@ class TestImage:
 | 
				
			||||||
        with pytest.raises(AttributeError):
 | 
					        with pytest.raises(AttributeError):
 | 
				
			||||||
            im.size = (3, 4)
 | 
					            im.size = (3, 4)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_set_mode(self):
 | 
					    def test_set_mode(self) -> None:
 | 
				
			||||||
        im = Image.new("RGB", (1, 1))
 | 
					        im = Image.new("RGB", (1, 1))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        with pytest.raises(AttributeError):
 | 
					        with pytest.raises(AttributeError):
 | 
				
			||||||
            im.mode = "P"
 | 
					            im.mode = "P"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_invalid_image(self):
 | 
					    def test_invalid_image(self) -> None:
 | 
				
			||||||
        im = io.BytesIO(b"")
 | 
					        im = io.BytesIO(b"")
 | 
				
			||||||
        with pytest.raises(UnidentifiedImageError):
 | 
					        with pytest.raises(UnidentifiedImageError):
 | 
				
			||||||
            with Image.open(im):
 | 
					            with Image.open(im):
 | 
				
			||||||
                pass
 | 
					                pass
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_bad_mode(self):
 | 
					    def test_bad_mode(self) -> None:
 | 
				
			||||||
        with pytest.raises(ValueError):
 | 
					        with pytest.raises(ValueError):
 | 
				
			||||||
            with Image.open("filename", "bad mode"):
 | 
					            with Image.open("filename", "bad mode"):
 | 
				
			||||||
                pass
 | 
					                pass
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_stringio(self):
 | 
					    def test_stringio(self) -> None:
 | 
				
			||||||
        with pytest.raises(ValueError):
 | 
					        with pytest.raises(ValueError):
 | 
				
			||||||
            with Image.open(io.StringIO()):
 | 
					            with Image.open(io.StringIO()):
 | 
				
			||||||
                pass
 | 
					                pass
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_pathlib(self, tmp_path):
 | 
					    def test_pathlib(self, tmp_path: Path) -> None:
 | 
				
			||||||
        from PIL.Image import Path
 | 
					        from PIL.Image import Path
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        with Image.open(Path("Tests/images/multipage-mmap.tiff")) as im:
 | 
					        with Image.open(Path("Tests/images/multipage-mmap.tiff")) as im:
 | 
				
			||||||
| 
						 | 
					@ -179,11 +180,11 @@ class TestImage:
 | 
				
			||||||
                    os.remove(temp_file)
 | 
					                    os.remove(temp_file)
 | 
				
			||||||
                im.save(Path(temp_file))
 | 
					                im.save(Path(temp_file))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_fp_name(self, tmp_path):
 | 
					    def test_fp_name(self, tmp_path: Path) -> None:
 | 
				
			||||||
        temp_file = str(tmp_path / "temp.jpg")
 | 
					        temp_file = str(tmp_path / "temp.jpg")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        class FP:
 | 
					        class FP:
 | 
				
			||||||
            def write(self, b):
 | 
					            def write(self, b) -> None:
 | 
				
			||||||
                pass
 | 
					                pass
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        fp = FP()
 | 
					        fp = FP()
 | 
				
			||||||
| 
						 | 
					@ -192,7 +193,7 @@ class TestImage:
 | 
				
			||||||
        im = hopper()
 | 
					        im = hopper()
 | 
				
			||||||
        im.save(fp)
 | 
					        im.save(fp)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_tempfile(self):
 | 
					    def test_tempfile(self) -> None:
 | 
				
			||||||
        # see #1460, pathlib support breaks tempfile.TemporaryFile on py27
 | 
					        # see #1460, pathlib support breaks tempfile.TemporaryFile on py27
 | 
				
			||||||
        # Will error out on save on 3.0.0
 | 
					        # Will error out on save on 3.0.0
 | 
				
			||||||
        im = hopper()
 | 
					        im = hopper()
 | 
				
			||||||
| 
						 | 
					@ -201,13 +202,13 @@ class TestImage:
 | 
				
			||||||
            fp.seek(0)
 | 
					            fp.seek(0)
 | 
				
			||||||
            assert_image_similar_tofile(im, fp, 20)
 | 
					            assert_image_similar_tofile(im, fp, 20)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_unknown_extension(self, tmp_path):
 | 
					    def test_unknown_extension(self, tmp_path: Path) -> None:
 | 
				
			||||||
        im = hopper()
 | 
					        im = hopper()
 | 
				
			||||||
        temp_file = str(tmp_path / "temp.unknown")
 | 
					        temp_file = str(tmp_path / "temp.unknown")
 | 
				
			||||||
        with pytest.raises(ValueError):
 | 
					        with pytest.raises(ValueError):
 | 
				
			||||||
            im.save(temp_file)
 | 
					            im.save(temp_file)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_internals(self):
 | 
					    def test_internals(self) -> None:
 | 
				
			||||||
        im = Image.new("L", (100, 100))
 | 
					        im = Image.new("L", (100, 100))
 | 
				
			||||||
        im.readonly = 1
 | 
					        im.readonly = 1
 | 
				
			||||||
        im._copy()
 | 
					        im._copy()
 | 
				
			||||||
| 
						 | 
					@ -222,7 +223,7 @@ class TestImage:
 | 
				
			||||||
        sys.platform == "cygwin",
 | 
					        sys.platform == "cygwin",
 | 
				
			||||||
        reason="Test requires opening an mmaped file for writing",
 | 
					        reason="Test requires opening an mmaped file for writing",
 | 
				
			||||||
    )
 | 
					    )
 | 
				
			||||||
    def test_readonly_save(self, tmp_path):
 | 
					    def test_readonly_save(self, tmp_path: Path) -> None:
 | 
				
			||||||
        temp_file = str(tmp_path / "temp.bmp")
 | 
					        temp_file = str(tmp_path / "temp.bmp")
 | 
				
			||||||
        shutil.copy("Tests/images/rgb32bf-rgba.bmp", temp_file)
 | 
					        shutil.copy("Tests/images/rgb32bf-rgba.bmp", temp_file)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -230,7 +231,7 @@ class TestImage:
 | 
				
			||||||
            assert im.readonly
 | 
					            assert im.readonly
 | 
				
			||||||
            im.save(temp_file)
 | 
					            im.save(temp_file)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_dump(self, tmp_path):
 | 
					    def test_dump(self, tmp_path: Path) -> None:
 | 
				
			||||||
        im = Image.new("L", (10, 10))
 | 
					        im = Image.new("L", (10, 10))
 | 
				
			||||||
        im._dump(str(tmp_path / "temp_L.ppm"))
 | 
					        im._dump(str(tmp_path / "temp_L.ppm"))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -241,7 +242,7 @@ class TestImage:
 | 
				
			||||||
        with pytest.raises(ValueError):
 | 
					        with pytest.raises(ValueError):
 | 
				
			||||||
            im._dump(str(tmp_path / "temp_HSV.ppm"))
 | 
					            im._dump(str(tmp_path / "temp_HSV.ppm"))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_comparison_with_other_type(self):
 | 
					    def test_comparison_with_other_type(self) -> None:
 | 
				
			||||||
        # Arrange
 | 
					        # Arrange
 | 
				
			||||||
        item = Image.new("RGB", (25, 25), "#000")
 | 
					        item = Image.new("RGB", (25, 25), "#000")
 | 
				
			||||||
        num = 12
 | 
					        num = 12
 | 
				
			||||||
| 
						 | 
					@ -251,7 +252,7 @@ class TestImage:
 | 
				
			||||||
        assert item is not None
 | 
					        assert item is not None
 | 
				
			||||||
        assert item != num
 | 
					        assert item != num
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_expand_x(self):
 | 
					    def test_expand_x(self) -> None:
 | 
				
			||||||
        # Arrange
 | 
					        # Arrange
 | 
				
			||||||
        im = hopper()
 | 
					        im = hopper()
 | 
				
			||||||
        orig_size = im.size
 | 
					        orig_size = im.size
 | 
				
			||||||
| 
						 | 
					@ -264,7 +265,7 @@ class TestImage:
 | 
				
			||||||
        assert im.size[0] == orig_size[0] + 2 * xmargin
 | 
					        assert im.size[0] == orig_size[0] + 2 * xmargin
 | 
				
			||||||
        assert im.size[1] == orig_size[1] + 2 * xmargin
 | 
					        assert im.size[1] == orig_size[1] + 2 * xmargin
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_expand_xy(self):
 | 
					    def test_expand_xy(self) -> None:
 | 
				
			||||||
        # Arrange
 | 
					        # Arrange
 | 
				
			||||||
        im = hopper()
 | 
					        im = hopper()
 | 
				
			||||||
        orig_size = im.size
 | 
					        orig_size = im.size
 | 
				
			||||||
| 
						 | 
					@ -278,12 +279,12 @@ class TestImage:
 | 
				
			||||||
        assert im.size[0] == orig_size[0] + 2 * xmargin
 | 
					        assert im.size[0] == orig_size[0] + 2 * xmargin
 | 
				
			||||||
        assert im.size[1] == orig_size[1] + 2 * ymargin
 | 
					        assert im.size[1] == orig_size[1] + 2 * ymargin
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_getbands(self):
 | 
					    def test_getbands(self) -> None:
 | 
				
			||||||
        # Assert
 | 
					        # Assert
 | 
				
			||||||
        assert hopper("RGB").getbands() == ("R", "G", "B")
 | 
					        assert hopper("RGB").getbands() == ("R", "G", "B")
 | 
				
			||||||
        assert hopper("YCbCr").getbands() == ("Y", "Cb", "Cr")
 | 
					        assert hopper("YCbCr").getbands() == ("Y", "Cb", "Cr")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_getchannel_wrong_params(self):
 | 
					    def test_getchannel_wrong_params(self) -> None:
 | 
				
			||||||
        im = hopper()
 | 
					        im = hopper()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        with pytest.raises(ValueError):
 | 
					        with pytest.raises(ValueError):
 | 
				
			||||||
| 
						 | 
					@ -295,7 +296,7 @@ class TestImage:
 | 
				
			||||||
        with pytest.raises(ValueError):
 | 
					        with pytest.raises(ValueError):
 | 
				
			||||||
            im.getchannel("1")
 | 
					            im.getchannel("1")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_getchannel(self):
 | 
					    def test_getchannel(self) -> None:
 | 
				
			||||||
        im = hopper("YCbCr")
 | 
					        im = hopper("YCbCr")
 | 
				
			||||||
        Y, Cb, Cr = im.split()
 | 
					        Y, Cb, Cr = im.split()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -306,7 +307,7 @@ class TestImage:
 | 
				
			||||||
        assert_image_equal(Cr, im.getchannel(2))
 | 
					        assert_image_equal(Cr, im.getchannel(2))
 | 
				
			||||||
        assert_image_equal(Cr, im.getchannel("Cr"))
 | 
					        assert_image_equal(Cr, im.getchannel("Cr"))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_getbbox(self):
 | 
					    def test_getbbox(self) -> None:
 | 
				
			||||||
        # Arrange
 | 
					        # Arrange
 | 
				
			||||||
        im = hopper()
 | 
					        im = hopper()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -316,7 +317,7 @@ class TestImage:
 | 
				
			||||||
        # Assert
 | 
					        # Assert
 | 
				
			||||||
        assert bbox == (0, 0, 128, 128)
 | 
					        assert bbox == (0, 0, 128, 128)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_ne(self):
 | 
					    def test_ne(self) -> None:
 | 
				
			||||||
        # Arrange
 | 
					        # Arrange
 | 
				
			||||||
        im1 = Image.new("RGB", (25, 25), "black")
 | 
					        im1 = Image.new("RGB", (25, 25), "black")
 | 
				
			||||||
        im2 = Image.new("RGB", (25, 25), "white")
 | 
					        im2 = Image.new("RGB", (25, 25), "white")
 | 
				
			||||||
| 
						 | 
					@ -324,7 +325,7 @@ class TestImage:
 | 
				
			||||||
        # Act / Assert
 | 
					        # Act / Assert
 | 
				
			||||||
        assert im1 != im2
 | 
					        assert im1 != im2
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_alpha_composite(self):
 | 
					    def test_alpha_composite(self) -> None:
 | 
				
			||||||
        # https://stackoverflow.com/questions/3374878
 | 
					        # https://stackoverflow.com/questions/3374878
 | 
				
			||||||
        # Arrange
 | 
					        # Arrange
 | 
				
			||||||
        expected_colors = sorted(
 | 
					        expected_colors = sorted(
 | 
				
			||||||
| 
						 | 
					@ -355,7 +356,7 @@ class TestImage:
 | 
				
			||||||
        img_colors = sorted(img.getcolors())
 | 
					        img_colors = sorted(img.getcolors())
 | 
				
			||||||
        assert img_colors == expected_colors
 | 
					        assert img_colors == expected_colors
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_alpha_inplace(self):
 | 
					    def test_alpha_inplace(self) -> None:
 | 
				
			||||||
        src = Image.new("RGBA", (128, 128), "blue")
 | 
					        src = Image.new("RGBA", (128, 128), "blue")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        over = Image.new("RGBA", (128, 128), "red")
 | 
					        over = Image.new("RGBA", (128, 128), "red")
 | 
				
			||||||
| 
						 | 
					@ -407,7 +408,7 @@ class TestImage:
 | 
				
			||||||
        with pytest.raises(ValueError):
 | 
					        with pytest.raises(ValueError):
 | 
				
			||||||
            source.alpha_composite(over, (0, 0), (0, -1))
 | 
					            source.alpha_composite(over, (0, 0), (0, -1))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_register_open_duplicates(self):
 | 
					    def test_register_open_duplicates(self) -> None:
 | 
				
			||||||
        # Arrange
 | 
					        # Arrange
 | 
				
			||||||
        factory, accept = Image.OPEN["JPEG"]
 | 
					        factory, accept = Image.OPEN["JPEG"]
 | 
				
			||||||
        id_length = len(Image.ID)
 | 
					        id_length = len(Image.ID)
 | 
				
			||||||
| 
						 | 
					@ -418,7 +419,7 @@ class TestImage:
 | 
				
			||||||
        # Assert
 | 
					        # Assert
 | 
				
			||||||
        assert len(Image.ID) == id_length
 | 
					        assert len(Image.ID) == id_length
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_registered_extensions_uninitialized(self):
 | 
					    def test_registered_extensions_uninitialized(self) -> None:
 | 
				
			||||||
        # Arrange
 | 
					        # Arrange
 | 
				
			||||||
        Image._initialized = 0
 | 
					        Image._initialized = 0
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -428,7 +429,7 @@ class TestImage:
 | 
				
			||||||
        # Assert
 | 
					        # Assert
 | 
				
			||||||
        assert Image._initialized == 2
 | 
					        assert Image._initialized == 2
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_registered_extensions(self):
 | 
					    def test_registered_extensions(self) -> None:
 | 
				
			||||||
        # Arrange
 | 
					        # Arrange
 | 
				
			||||||
        # Open an image to trigger plugin registration
 | 
					        # Open an image to trigger plugin registration
 | 
				
			||||||
        with Image.open("Tests/images/rgb.jpg"):
 | 
					        with Image.open("Tests/images/rgb.jpg"):
 | 
				
			||||||
| 
						 | 
					@ -442,7 +443,7 @@ class TestImage:
 | 
				
			||||||
        for ext in [".cur", ".icns", ".tif", ".tiff"]:
 | 
					        for ext in [".cur", ".icns", ".tif", ".tiff"]:
 | 
				
			||||||
            assert ext in extensions
 | 
					            assert ext in extensions
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_effect_mandelbrot(self):
 | 
					    def test_effect_mandelbrot(self) -> None:
 | 
				
			||||||
        # Arrange
 | 
					        # Arrange
 | 
				
			||||||
        size = (512, 512)
 | 
					        size = (512, 512)
 | 
				
			||||||
        extent = (-3, -2.5, 2, 2.5)
 | 
					        extent = (-3, -2.5, 2, 2.5)
 | 
				
			||||||
| 
						 | 
					@ -455,7 +456,7 @@ class TestImage:
 | 
				
			||||||
        assert im.size == (512, 512)
 | 
					        assert im.size == (512, 512)
 | 
				
			||||||
        assert_image_equal_tofile(im, "Tests/images/effect_mandelbrot.png")
 | 
					        assert_image_equal_tofile(im, "Tests/images/effect_mandelbrot.png")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_effect_mandelbrot_bad_arguments(self):
 | 
					    def test_effect_mandelbrot_bad_arguments(self) -> None:
 | 
				
			||||||
        # Arrange
 | 
					        # Arrange
 | 
				
			||||||
        size = (512, 512)
 | 
					        size = (512, 512)
 | 
				
			||||||
        # Get coordinates the wrong way round:
 | 
					        # Get coordinates the wrong way round:
 | 
				
			||||||
| 
						 | 
					@ -467,7 +468,7 @@ class TestImage:
 | 
				
			||||||
        with pytest.raises(ValueError):
 | 
					        with pytest.raises(ValueError):
 | 
				
			||||||
            Image.effect_mandelbrot(size, extent, quality)
 | 
					            Image.effect_mandelbrot(size, extent, quality)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_effect_noise(self):
 | 
					    def test_effect_noise(self) -> None:
 | 
				
			||||||
        # Arrange
 | 
					        # Arrange
 | 
				
			||||||
        size = (100, 100)
 | 
					        size = (100, 100)
 | 
				
			||||||
        sigma = 128
 | 
					        sigma = 128
 | 
				
			||||||
| 
						 | 
					@ -485,7 +486,7 @@ class TestImage:
 | 
				
			||||||
        p4 = im.getpixel((0, 4))
 | 
					        p4 = im.getpixel((0, 4))
 | 
				
			||||||
        assert_not_all_same([p0, p1, p2, p3, p4])
 | 
					        assert_not_all_same([p0, p1, p2, p3, p4])
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_effect_spread(self):
 | 
					    def test_effect_spread(self) -> None:
 | 
				
			||||||
        # Arrange
 | 
					        # Arrange
 | 
				
			||||||
        im = hopper()
 | 
					        im = hopper()
 | 
				
			||||||
        distance = 10
 | 
					        distance = 10
 | 
				
			||||||
| 
						 | 
					@ -497,7 +498,7 @@ class TestImage:
 | 
				
			||||||
        assert im.size == (128, 128)
 | 
					        assert im.size == (128, 128)
 | 
				
			||||||
        assert_image_similar_tofile(im2, "Tests/images/effect_spread.png", 110)
 | 
					        assert_image_similar_tofile(im2, "Tests/images/effect_spread.png", 110)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_effect_spread_zero(self):
 | 
					    def test_effect_spread_zero(self) -> None:
 | 
				
			||||||
        # Arrange
 | 
					        # Arrange
 | 
				
			||||||
        im = hopper()
 | 
					        im = hopper()
 | 
				
			||||||
        distance = 0
 | 
					        distance = 0
 | 
				
			||||||
| 
						 | 
					@ -508,7 +509,7 @@ class TestImage:
 | 
				
			||||||
        # Assert
 | 
					        # Assert
 | 
				
			||||||
        assert_image_equal(im, im2)
 | 
					        assert_image_equal(im, im2)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_check_size(self):
 | 
					    def test_check_size(self) -> None:
 | 
				
			||||||
        # Checking that the _check_size function throws value errors when we want it to
 | 
					        # Checking that the _check_size function throws value errors when we want it to
 | 
				
			||||||
        with pytest.raises(ValueError):
 | 
					        with pytest.raises(ValueError):
 | 
				
			||||||
            Image.new("RGB", 0)  # not a tuple
 | 
					            Image.new("RGB", 0)  # not a tuple
 | 
				
			||||||
| 
						 | 
					@ -537,10 +538,10 @@ class TestImage:
 | 
				
			||||||
        "PILLOW_VALGRIND_TEST" in os.environ, reason="Valgrind is slower"
 | 
					        "PILLOW_VALGRIND_TEST" in os.environ, reason="Valgrind is slower"
 | 
				
			||||||
    )
 | 
					    )
 | 
				
			||||||
    @pytest.mark.parametrize("size", ((0, 100000000), (100000000, 0)))
 | 
					    @pytest.mark.parametrize("size", ((0, 100000000), (100000000, 0)))
 | 
				
			||||||
    def test_empty_image(self, size):
 | 
					    def test_empty_image(self, size) -> None:
 | 
				
			||||||
        Image.new("RGB", size)
 | 
					        Image.new("RGB", size)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_storage_neg(self):
 | 
					    def test_storage_neg(self) -> None:
 | 
				
			||||||
        # Storage.c accepted negative values for xsize, ysize.  Was
 | 
					        # Storage.c accepted negative values for xsize, ysize.  Was
 | 
				
			||||||
        # test_neg_ppm, but the core function for that has been
 | 
					        # test_neg_ppm, but the core function for that has been
 | 
				
			||||||
        # removed Calling directly into core to test the error in
 | 
					        # removed Calling directly into core to test the error in
 | 
				
			||||||
| 
						 | 
					@ -549,13 +550,13 @@ class TestImage:
 | 
				
			||||||
        with pytest.raises(ValueError):
 | 
					        with pytest.raises(ValueError):
 | 
				
			||||||
            Image.core.fill("RGB", (2, -2), (0, 0, 0))
 | 
					            Image.core.fill("RGB", (2, -2), (0, 0, 0))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_one_item_tuple(self):
 | 
					    def test_one_item_tuple(self) -> None:
 | 
				
			||||||
        for mode in ("I", "F", "L"):
 | 
					        for mode in ("I", "F", "L"):
 | 
				
			||||||
            im = Image.new(mode, (100, 100), (5,))
 | 
					            im = Image.new(mode, (100, 100), (5,))
 | 
				
			||||||
            px = im.load()
 | 
					            px = im.load()
 | 
				
			||||||
            assert px[0, 0] == 5
 | 
					            assert px[0, 0] == 5
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_linear_gradient_wrong_mode(self):
 | 
					    def test_linear_gradient_wrong_mode(self) -> None:
 | 
				
			||||||
        # Arrange
 | 
					        # Arrange
 | 
				
			||||||
        wrong_mode = "RGB"
 | 
					        wrong_mode = "RGB"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -564,7 +565,7 @@ class TestImage:
 | 
				
			||||||
            Image.linear_gradient(wrong_mode)
 | 
					            Image.linear_gradient(wrong_mode)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    @pytest.mark.parametrize("mode", ("L", "P", "I", "F"))
 | 
					    @pytest.mark.parametrize("mode", ("L", "P", "I", "F"))
 | 
				
			||||||
    def test_linear_gradient(self, mode):
 | 
					    def test_linear_gradient(self, mode) -> None:
 | 
				
			||||||
        # Arrange
 | 
					        # Arrange
 | 
				
			||||||
        target_file = "Tests/images/linear_gradient.png"
 | 
					        target_file = "Tests/images/linear_gradient.png"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -580,7 +581,7 @@ class TestImage:
 | 
				
			||||||
            target = target.convert(mode)
 | 
					            target = target.convert(mode)
 | 
				
			||||||
        assert_image_equal(im, target)
 | 
					        assert_image_equal(im, target)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_radial_gradient_wrong_mode(self):
 | 
					    def test_radial_gradient_wrong_mode(self) -> None:
 | 
				
			||||||
        # Arrange
 | 
					        # Arrange
 | 
				
			||||||
        wrong_mode = "RGB"
 | 
					        wrong_mode = "RGB"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -589,7 +590,7 @@ class TestImage:
 | 
				
			||||||
            Image.radial_gradient(wrong_mode)
 | 
					            Image.radial_gradient(wrong_mode)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    @pytest.mark.parametrize("mode", ("L", "P", "I", "F"))
 | 
					    @pytest.mark.parametrize("mode", ("L", "P", "I", "F"))
 | 
				
			||||||
    def test_radial_gradient(self, mode):
 | 
					    def test_radial_gradient(self, mode) -> None:
 | 
				
			||||||
        # Arrange
 | 
					        # Arrange
 | 
				
			||||||
        target_file = "Tests/images/radial_gradient.png"
 | 
					        target_file = "Tests/images/radial_gradient.png"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -605,7 +606,7 @@ class TestImage:
 | 
				
			||||||
            target = target.convert(mode)
 | 
					            target = target.convert(mode)
 | 
				
			||||||
        assert_image_equal(im, target)
 | 
					        assert_image_equal(im, target)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_register_extensions(self):
 | 
					    def test_register_extensions(self) -> None:
 | 
				
			||||||
        test_format = "a"
 | 
					        test_format = "a"
 | 
				
			||||||
        exts = ["b", "c"]
 | 
					        exts = ["b", "c"]
 | 
				
			||||||
        for ext in exts:
 | 
					        for ext in exts:
 | 
				
			||||||
| 
						 | 
					@ -621,7 +622,7 @@ class TestImage:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        assert ext_individual == ext_multiple
 | 
					        assert ext_individual == ext_multiple
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_remap_palette(self):
 | 
					    def test_remap_palette(self) -> None:
 | 
				
			||||||
        # Test identity transform
 | 
					        # Test identity transform
 | 
				
			||||||
        with Image.open("Tests/images/hopper.gif") as im:
 | 
					        with Image.open("Tests/images/hopper.gif") as im:
 | 
				
			||||||
            assert_image_equal(im, im.remap_palette(list(range(256))))
 | 
					            assert_image_equal(im, im.remap_palette(list(range(256))))
 | 
				
			||||||
| 
						 | 
					@ -640,7 +641,7 @@ class TestImage:
 | 
				
			||||||
            with pytest.raises(ValueError):
 | 
					            with pytest.raises(ValueError):
 | 
				
			||||||
                im.remap_palette(None)
 | 
					                im.remap_palette(None)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_remap_palette_transparency(self):
 | 
					    def test_remap_palette_transparency(self) -> None:
 | 
				
			||||||
        im = Image.new("P", (1, 2), (0, 0, 0))
 | 
					        im = Image.new("P", (1, 2), (0, 0, 0))
 | 
				
			||||||
        im.putpixel((0, 1), (255, 0, 0))
 | 
					        im.putpixel((0, 1), (255, 0, 0))
 | 
				
			||||||
        im.info["transparency"] = 0
 | 
					        im.info["transparency"] = 0
 | 
				
			||||||
| 
						 | 
					@ -655,7 +656,7 @@ class TestImage:
 | 
				
			||||||
        im_remapped = im.remap_palette([1, 0])
 | 
					        im_remapped = im.remap_palette([1, 0])
 | 
				
			||||||
        assert "transparency" not in im_remapped.info
 | 
					        assert "transparency" not in im_remapped.info
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test__new(self):
 | 
					    def test__new(self) -> None:
 | 
				
			||||||
        im = hopper("RGB")
 | 
					        im = hopper("RGB")
 | 
				
			||||||
        im_p = hopper("P")
 | 
					        im_p = hopper("P")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -664,7 +665,7 @@ class TestImage:
 | 
				
			||||||
        blank_p.palette = None
 | 
					        blank_p.palette = None
 | 
				
			||||||
        blank_pa.palette = None
 | 
					        blank_pa.palette = None
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        def _make_new(base_image, image, palette_result=None):
 | 
					        def _make_new(base_image, image, palette_result=None) -> None:
 | 
				
			||||||
            new_image = base_image._new(image.im)
 | 
					            new_image = base_image._new(image.im)
 | 
				
			||||||
            assert new_image.mode == image.mode
 | 
					            assert new_image.mode == image.mode
 | 
				
			||||||
            assert new_image.size == image.size
 | 
					            assert new_image.size == image.size
 | 
				
			||||||
| 
						 | 
					@ -679,7 +680,7 @@ class TestImage:
 | 
				
			||||||
        _make_new(im, blank_p, ImagePalette.ImagePalette())
 | 
					        _make_new(im, blank_p, ImagePalette.ImagePalette())
 | 
				
			||||||
        _make_new(im, blank_pa, ImagePalette.ImagePalette())
 | 
					        _make_new(im, blank_pa, ImagePalette.ImagePalette())
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_p_from_rgb_rgba(self):
 | 
					    def test_p_from_rgb_rgba(self) -> None:
 | 
				
			||||||
        for mode, color in [
 | 
					        for mode, color in [
 | 
				
			||||||
            ("RGB", "#DDEEFF"),
 | 
					            ("RGB", "#DDEEFF"),
 | 
				
			||||||
            ("RGB", (221, 238, 255)),
 | 
					            ("RGB", (221, 238, 255)),
 | 
				
			||||||
| 
						 | 
					@ -689,7 +690,7 @@ class TestImage:
 | 
				
			||||||
            expected = Image.new(mode, (100, 100), color)
 | 
					            expected = Image.new(mode, (100, 100), color)
 | 
				
			||||||
            assert_image_equal(im.convert(mode), expected)
 | 
					            assert_image_equal(im.convert(mode), expected)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_no_resource_warning_on_save(self, tmp_path):
 | 
					    def test_no_resource_warning_on_save(self, tmp_path: Path) -> None:
 | 
				
			||||||
        # https://github.com/python-pillow/Pillow/issues/835
 | 
					        # https://github.com/python-pillow/Pillow/issues/835
 | 
				
			||||||
        # Arrange
 | 
					        # Arrange
 | 
				
			||||||
        test_file = "Tests/images/hopper.png"
 | 
					        test_file = "Tests/images/hopper.png"
 | 
				
			||||||
| 
						 | 
					@ -700,7 +701,7 @@ class TestImage:
 | 
				
			||||||
            with warnings.catch_warnings():
 | 
					            with warnings.catch_warnings():
 | 
				
			||||||
                im.save(temp_file)
 | 
					                im.save(temp_file)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_no_new_file_on_error(self, tmp_path):
 | 
					    def test_no_new_file_on_error(self, tmp_path: Path) -> None:
 | 
				
			||||||
        temp_file = str(tmp_path / "temp.jpg")
 | 
					        temp_file = str(tmp_path / "temp.jpg")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        im = Image.new("RGB", (0, 0))
 | 
					        im = Image.new("RGB", (0, 0))
 | 
				
			||||||
| 
						 | 
					@ -709,10 +710,10 @@ class TestImage:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        assert not os.path.exists(temp_file)
 | 
					        assert not os.path.exists(temp_file)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_load_on_nonexclusive_multiframe(self):
 | 
					    def test_load_on_nonexclusive_multiframe(self) -> None:
 | 
				
			||||||
        with open("Tests/images/frozenpond.mpo", "rb") as fp:
 | 
					        with open("Tests/images/frozenpond.mpo", "rb") as fp:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            def act(fp):
 | 
					            def act(fp) -> None:
 | 
				
			||||||
                im = Image.open(fp)
 | 
					                im = Image.open(fp)
 | 
				
			||||||
                im.load()
 | 
					                im.load()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -723,7 +724,7 @@ class TestImage:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            assert not fp.closed
 | 
					            assert not fp.closed
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_empty_exif(self):
 | 
					    def test_empty_exif(self) -> None:
 | 
				
			||||||
        with Image.open("Tests/images/exif.png") as im:
 | 
					        with Image.open("Tests/images/exif.png") as im:
 | 
				
			||||||
            exif = im.getexif()
 | 
					            exif = im.getexif()
 | 
				
			||||||
        assert dict(exif)
 | 
					        assert dict(exif)
 | 
				
			||||||
| 
						 | 
					@ -739,7 +740,7 @@ class TestImage:
 | 
				
			||||||
    @mark_if_feature_version(
 | 
					    @mark_if_feature_version(
 | 
				
			||||||
        pytest.mark.valgrind_known_error, "libjpeg_turbo", "2.0", reason="Known Failing"
 | 
					        pytest.mark.valgrind_known_error, "libjpeg_turbo", "2.0", reason="Known Failing"
 | 
				
			||||||
    )
 | 
					    )
 | 
				
			||||||
    def test_exif_jpeg(self, tmp_path):
 | 
					    def test_exif_jpeg(self, tmp_path: Path) -> None:
 | 
				
			||||||
        with Image.open("Tests/images/exif-72dpi-int.jpg") as im:  # Little endian
 | 
					        with Image.open("Tests/images/exif-72dpi-int.jpg") as im:  # Little endian
 | 
				
			||||||
            exif = im.getexif()
 | 
					            exif = im.getexif()
 | 
				
			||||||
            assert 258 not in exif
 | 
					            assert 258 not in exif
 | 
				
			||||||
| 
						 | 
					@ -785,7 +786,7 @@ class TestImage:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    @skip_unless_feature("webp")
 | 
					    @skip_unless_feature("webp")
 | 
				
			||||||
    @skip_unless_feature("webp_anim")
 | 
					    @skip_unless_feature("webp_anim")
 | 
				
			||||||
    def test_exif_webp(self, tmp_path):
 | 
					    def test_exif_webp(self, tmp_path: Path) -> None:
 | 
				
			||||||
        with Image.open("Tests/images/hopper.webp") as im:
 | 
					        with Image.open("Tests/images/hopper.webp") as im:
 | 
				
			||||||
            exif = im.getexif()
 | 
					            exif = im.getexif()
 | 
				
			||||||
            assert exif == {}
 | 
					            assert exif == {}
 | 
				
			||||||
| 
						 | 
					@ -795,7 +796,7 @@ class TestImage:
 | 
				
			||||||
            exif[40963] = 455
 | 
					            exif[40963] = 455
 | 
				
			||||||
            exif[305] = "Pillow test"
 | 
					            exif[305] = "Pillow test"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            def check_exif():
 | 
					            def check_exif() -> None:
 | 
				
			||||||
                with Image.open(out) as reloaded:
 | 
					                with Image.open(out) as reloaded:
 | 
				
			||||||
                    reloaded_exif = reloaded.getexif()
 | 
					                    reloaded_exif = reloaded.getexif()
 | 
				
			||||||
                    assert reloaded_exif[258] == 8
 | 
					                    assert reloaded_exif[258] == 8
 | 
				
			||||||
| 
						 | 
					@ -807,7 +808,7 @@ class TestImage:
 | 
				
			||||||
            im.save(out, exif=exif, save_all=True)
 | 
					            im.save(out, exif=exif, save_all=True)
 | 
				
			||||||
            check_exif()
 | 
					            check_exif()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_exif_png(self, tmp_path):
 | 
					    def test_exif_png(self, tmp_path: Path) -> None:
 | 
				
			||||||
        with Image.open("Tests/images/exif.png") as im:
 | 
					        with Image.open("Tests/images/exif.png") as im:
 | 
				
			||||||
            exif = im.getexif()
 | 
					            exif = im.getexif()
 | 
				
			||||||
            assert exif == {274: 1}
 | 
					            assert exif == {274: 1}
 | 
				
			||||||
| 
						 | 
					@ -823,7 +824,7 @@ class TestImage:
 | 
				
			||||||
            reloaded_exif = reloaded.getexif()
 | 
					            reloaded_exif = reloaded.getexif()
 | 
				
			||||||
            assert reloaded_exif == {258: 8, 40963: 455, 305: "Pillow test"}
 | 
					            assert reloaded_exif == {258: 8, 40963: 455, 305: "Pillow test"}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_exif_interop(self):
 | 
					    def test_exif_interop(self) -> None:
 | 
				
			||||||
        with Image.open("Tests/images/flower.jpg") as im:
 | 
					        with Image.open("Tests/images/flower.jpg") as im:
 | 
				
			||||||
            exif = im.getexif()
 | 
					            exif = im.getexif()
 | 
				
			||||||
            assert exif.get_ifd(0xA005) == {
 | 
					            assert exif.get_ifd(0xA005) == {
 | 
				
			||||||
| 
						 | 
					@ -837,7 +838,7 @@ class TestImage:
 | 
				
			||||||
            reloaded_exif.load(exif.tobytes())
 | 
					            reloaded_exif.load(exif.tobytes())
 | 
				
			||||||
            assert reloaded_exif.get_ifd(0xA005) == exif.get_ifd(0xA005)
 | 
					            assert reloaded_exif.get_ifd(0xA005) == exif.get_ifd(0xA005)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_exif_ifd1(self):
 | 
					    def test_exif_ifd1(self) -> None:
 | 
				
			||||||
        with Image.open("Tests/images/flower.jpg") as im:
 | 
					        with Image.open("Tests/images/flower.jpg") as im:
 | 
				
			||||||
            exif = im.getexif()
 | 
					            exif = im.getexif()
 | 
				
			||||||
            assert exif.get_ifd(ExifTags.IFD.IFD1) == {
 | 
					            assert exif.get_ifd(ExifTags.IFD.IFD1) == {
 | 
				
			||||||
| 
						 | 
					@ -849,7 +850,7 @@ class TestImage:
 | 
				
			||||||
                283: 180.0,
 | 
					                283: 180.0,
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_exif_ifd(self):
 | 
					    def test_exif_ifd(self) -> None:
 | 
				
			||||||
        with Image.open("Tests/images/flower.jpg") as im:
 | 
					        with Image.open("Tests/images/flower.jpg") as im:
 | 
				
			||||||
            exif = im.getexif()
 | 
					            exif = im.getexif()
 | 
				
			||||||
        del exif.get_ifd(0x8769)[0xA005]
 | 
					        del exif.get_ifd(0x8769)[0xA005]
 | 
				
			||||||
| 
						 | 
					@ -858,7 +859,7 @@ class TestImage:
 | 
				
			||||||
        reloaded_exif.load(exif.tobytes())
 | 
					        reloaded_exif.load(exif.tobytes())
 | 
				
			||||||
        assert reloaded_exif.get_ifd(0x8769) == exif.get_ifd(0x8769)
 | 
					        assert reloaded_exif.get_ifd(0x8769) == exif.get_ifd(0x8769)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_exif_load_from_fp(self):
 | 
					    def test_exif_load_from_fp(self) -> None:
 | 
				
			||||||
        with Image.open("Tests/images/flower.jpg") as im:
 | 
					        with Image.open("Tests/images/flower.jpg") as im:
 | 
				
			||||||
            data = im.info["exif"]
 | 
					            data = im.info["exif"]
 | 
				
			||||||
            if data.startswith(b"Exif\x00\x00"):
 | 
					            if data.startswith(b"Exif\x00\x00"):
 | 
				
			||||||
| 
						 | 
					@ -879,7 +880,7 @@ class TestImage:
 | 
				
			||||||
                34665: 196,
 | 
					                34665: 196,
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_exif_hide_offsets(self):
 | 
					    def test_exif_hide_offsets(self) -> None:
 | 
				
			||||||
        with Image.open("Tests/images/flower.jpg") as im:
 | 
					        with Image.open("Tests/images/flower.jpg") as im:
 | 
				
			||||||
            exif = im.getexif()
 | 
					            exif = im.getexif()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -905,18 +906,18 @@ class TestImage:
 | 
				
			||||||
                assert exif.get_ifd(0xA005)
 | 
					                assert exif.get_ifd(0xA005)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    @pytest.mark.parametrize("size", ((1, 0), (0, 1), (0, 0)))
 | 
					    @pytest.mark.parametrize("size", ((1, 0), (0, 1), (0, 0)))
 | 
				
			||||||
    def test_zero_tobytes(self, size):
 | 
					    def test_zero_tobytes(self, size) -> None:
 | 
				
			||||||
        im = Image.new("RGB", size)
 | 
					        im = Image.new("RGB", size)
 | 
				
			||||||
        assert im.tobytes() == b""
 | 
					        assert im.tobytes() == b""
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    @pytest.mark.parametrize("size", ((1, 0), (0, 1), (0, 0)))
 | 
					    @pytest.mark.parametrize("size", ((1, 0), (0, 1), (0, 0)))
 | 
				
			||||||
    def test_zero_frombytes(self, size):
 | 
					    def test_zero_frombytes(self, size) -> None:
 | 
				
			||||||
        Image.frombytes("RGB", size, b"")
 | 
					        Image.frombytes("RGB", size, b"")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        im = Image.new("RGB", size)
 | 
					        im = Image.new("RGB", size)
 | 
				
			||||||
        im.frombytes(b"")
 | 
					        im.frombytes(b"")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_has_transparency_data(self):
 | 
					    def test_has_transparency_data(self) -> None:
 | 
				
			||||||
        for mode in ("1", "L", "P", "RGB"):
 | 
					        for mode in ("1", "L", "P", "RGB"):
 | 
				
			||||||
            im = Image.new(mode, (1, 1))
 | 
					            im = Image.new(mode, (1, 1))
 | 
				
			||||||
            assert not im.has_transparency_data
 | 
					            assert not im.has_transparency_data
 | 
				
			||||||
| 
						 | 
					@ -941,7 +942,7 @@ class TestImage:
 | 
				
			||||||
        assert im.palette.mode == "RGBA"
 | 
					        assert im.palette.mode == "RGBA"
 | 
				
			||||||
        assert im.has_transparency_data
 | 
					        assert im.has_transparency_data
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_apply_transparency(self):
 | 
					    def test_apply_transparency(self) -> None:
 | 
				
			||||||
        im = Image.new("P", (1, 1))
 | 
					        im = Image.new("P", (1, 1))
 | 
				
			||||||
        im.putpalette((0, 0, 0, 1, 1, 1))
 | 
					        im.putpalette((0, 0, 0, 1, 1, 1))
 | 
				
			||||||
        assert im.palette.colors == {(0, 0, 0): 0, (1, 1, 1): 1}
 | 
					        assert im.palette.colors == {(0, 0, 0): 0, (1, 1, 1): 1}
 | 
				
			||||||
| 
						 | 
					@ -970,7 +971,7 @@ class TestImage:
 | 
				
			||||||
            im.apply_transparency()
 | 
					            im.apply_transparency()
 | 
				
			||||||
            assert im.palette.colors[(27, 35, 6, 214)] == 24
 | 
					            assert im.palette.colors[(27, 35, 6, 214)] == 24
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_constants(self):
 | 
					    def test_constants(self) -> None:
 | 
				
			||||||
        for enum in (
 | 
					        for enum in (
 | 
				
			||||||
            Image.Transpose,
 | 
					            Image.Transpose,
 | 
				
			||||||
            Image.Transform,
 | 
					            Image.Transform,
 | 
				
			||||||
| 
						 | 
					@ -995,7 +996,7 @@ class TestImage:
 | 
				
			||||||
            "01r_00.pcx",
 | 
					            "01r_00.pcx",
 | 
				
			||||||
        ],
 | 
					        ],
 | 
				
			||||||
    )
 | 
					    )
 | 
				
			||||||
    def test_overrun(self, path):
 | 
					    def test_overrun(self, path) -> None:
 | 
				
			||||||
        """For overrun completeness, test as:
 | 
					        """For overrun completeness, test as:
 | 
				
			||||||
        valgrind pytest -qq Tests/test_image.py::TestImage::test_overrun | grep decode.c
 | 
					        valgrind pytest -qq Tests/test_image.py::TestImage::test_overrun | grep decode.c
 | 
				
			||||||
        """
 | 
					        """
 | 
				
			||||||
| 
						 | 
					@ -1009,7 +1010,7 @@ class TestImage:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                assert buffer_overrun or truncated
 | 
					                assert buffer_overrun or truncated
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_fli_overrun2(self):
 | 
					    def test_fli_overrun2(self) -> None:
 | 
				
			||||||
        with Image.open("Tests/images/fli_overrun2.bin") as im:
 | 
					        with Image.open("Tests/images/fli_overrun2.bin") as im:
 | 
				
			||||||
            try:
 | 
					            try:
 | 
				
			||||||
                im.seek(1)
 | 
					                im.seek(1)
 | 
				
			||||||
| 
						 | 
					@ -1017,12 +1018,12 @@ class TestImage:
 | 
				
			||||||
            except OSError as e:
 | 
					            except OSError as e:
 | 
				
			||||||
                assert str(e) == "buffer overrun when reading image file"
 | 
					                assert str(e) == "buffer overrun when reading image file"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_exit_fp(self):
 | 
					    def test_exit_fp(self) -> None:
 | 
				
			||||||
        with Image.new("L", (1, 1)) as im:
 | 
					        with Image.new("L", (1, 1)) as im:
 | 
				
			||||||
            pass
 | 
					            pass
 | 
				
			||||||
        assert not hasattr(im, "fp")
 | 
					        assert not hasattr(im, "fp")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_close_graceful(self, caplog):
 | 
					    def test_close_graceful(self, caplog) -> None:
 | 
				
			||||||
        with Image.open("Tests/images/hopper.jpg") as im:
 | 
					        with Image.open("Tests/images/hopper.jpg") as im:
 | 
				
			||||||
            copy = im.copy()
 | 
					            copy = im.copy()
 | 
				
			||||||
            with caplog.at_level(logging.DEBUG):
 | 
					            with caplog.at_level(logging.DEBUG):
 | 
				
			||||||
| 
						 | 
					@ -1043,7 +1044,7 @@ def mock_encode(*args):
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class TestRegistry:
 | 
					class TestRegistry:
 | 
				
			||||||
    def test_encode_registry(self):
 | 
					    def test_encode_registry(self) -> None:
 | 
				
			||||||
        Image.register_encoder("MOCK", mock_encode)
 | 
					        Image.register_encoder("MOCK", mock_encode)
 | 
				
			||||||
        assert "MOCK" in Image.ENCODERS
 | 
					        assert "MOCK" in Image.ENCODERS
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1052,6 +1053,6 @@ class TestRegistry:
 | 
				
			||||||
        assert isinstance(enc, MockEncoder)
 | 
					        assert isinstance(enc, MockEncoder)
 | 
				
			||||||
        assert enc.args == ("RGB", "args", "extra")
 | 
					        assert enc.args == ("RGB", "args", "extra")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_encode_registry_fail(self):
 | 
					    def test_encode_registry_fail(self) -> None:
 | 
				
			||||||
        with pytest.raises(OSError):
 | 
					        with pytest.raises(OSError):
 | 
				
			||||||
            Image._getencoder("RGB", "DoesNotExist", ("args",), extra=("extra",))
 | 
					            Image._getencoder("RGB", "DoesNotExist", ("args",), extra=("extra",))
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -35,16 +35,16 @@ class AccessTest:
 | 
				
			||||||
    _need_cffi_access = False
 | 
					    _need_cffi_access = False
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    @classmethod
 | 
					    @classmethod
 | 
				
			||||||
    def setup_class(cls):
 | 
					    def setup_class(cls) -> None:
 | 
				
			||||||
        Image.USE_CFFI_ACCESS = cls._need_cffi_access
 | 
					        Image.USE_CFFI_ACCESS = cls._need_cffi_access
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    @classmethod
 | 
					    @classmethod
 | 
				
			||||||
    def teardown_class(cls):
 | 
					    def teardown_class(cls) -> None:
 | 
				
			||||||
        Image.USE_CFFI_ACCESS = cls._init_cffi_access
 | 
					        Image.USE_CFFI_ACCESS = cls._init_cffi_access
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class TestImagePutPixel(AccessTest):
 | 
					class TestImagePutPixel(AccessTest):
 | 
				
			||||||
    def test_sanity(self):
 | 
					    def test_sanity(self) -> None:
 | 
				
			||||||
        im1 = hopper()
 | 
					        im1 = hopper()
 | 
				
			||||||
        im2 = Image.new(im1.mode, im1.size, 0)
 | 
					        im2 = Image.new(im1.mode, im1.size, 0)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -81,7 +81,7 @@ class TestImagePutPixel(AccessTest):
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        assert_image_equal(im1, im2)
 | 
					        assert_image_equal(im1, im2)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_sanity_negative_index(self):
 | 
					    def test_sanity_negative_index(self) -> None:
 | 
				
			||||||
        im1 = hopper()
 | 
					        im1 = hopper()
 | 
				
			||||||
        im2 = Image.new(im1.mode, im1.size, 0)
 | 
					        im2 = Image.new(im1.mode, im1.size, 0)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -119,7 +119,7 @@ class TestImagePutPixel(AccessTest):
 | 
				
			||||||
        assert_image_equal(im1, im2)
 | 
					        assert_image_equal(im1, im2)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    @pytest.mark.skipif(numpy is None, reason="NumPy not installed")
 | 
					    @pytest.mark.skipif(numpy is None, reason="NumPy not installed")
 | 
				
			||||||
    def test_numpy(self):
 | 
					    def test_numpy(self) -> None:
 | 
				
			||||||
        im = hopper()
 | 
					        im = hopper()
 | 
				
			||||||
        pix = im.load()
 | 
					        pix = im.load()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -138,7 +138,7 @@ class TestImageGetPixel(AccessTest):
 | 
				
			||||||
            return (16, 32, 49)
 | 
					            return (16, 32, 49)
 | 
				
			||||||
        return tuple(range(1, bands + 1))
 | 
					        return tuple(range(1, bands + 1))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def check(self, mode, expected_color=None):
 | 
					    def check(self, mode, expected_color=None) -> None:
 | 
				
			||||||
        if self._need_cffi_access and mode.startswith("BGR;"):
 | 
					        if self._need_cffi_access and mode.startswith("BGR;"):
 | 
				
			||||||
            pytest.skip("Support not added to deprecated module for BGR;* modes")
 | 
					            pytest.skip("Support not added to deprecated module for BGR;* modes")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -222,10 +222,10 @@ class TestImageGetPixel(AccessTest):
 | 
				
			||||||
            "YCbCr",
 | 
					            "YCbCr",
 | 
				
			||||||
        ),
 | 
					        ),
 | 
				
			||||||
    )
 | 
					    )
 | 
				
			||||||
    def test_basic(self, mode):
 | 
					    def test_basic(self, mode) -> None:
 | 
				
			||||||
        self.check(mode)
 | 
					        self.check(mode)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_list(self):
 | 
					    def test_list(self) -> None:
 | 
				
			||||||
        im = hopper()
 | 
					        im = hopper()
 | 
				
			||||||
        assert im.getpixel([0, 0]) == (20, 20, 70)
 | 
					        assert im.getpixel([0, 0]) == (20, 20, 70)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -233,14 +233,14 @@ class TestImageGetPixel(AccessTest):
 | 
				
			||||||
    @pytest.mark.parametrize(
 | 
					    @pytest.mark.parametrize(
 | 
				
			||||||
        "expected_color", (2**15 - 1, 2**15, 2**15 + 1, 2**16 - 1)
 | 
					        "expected_color", (2**15 - 1, 2**15, 2**15 + 1, 2**16 - 1)
 | 
				
			||||||
    )
 | 
					    )
 | 
				
			||||||
    def test_signedness(self, mode, expected_color):
 | 
					    def test_signedness(self, mode, expected_color) -> None:
 | 
				
			||||||
        # see https://github.com/python-pillow/Pillow/issues/452
 | 
					        # see https://github.com/python-pillow/Pillow/issues/452
 | 
				
			||||||
        # pixelaccess is using signed int* instead of uint*
 | 
					        # pixelaccess is using signed int* instead of uint*
 | 
				
			||||||
        self.check(mode, expected_color)
 | 
					        self.check(mode, expected_color)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    @pytest.mark.parametrize("mode", ("P", "PA"))
 | 
					    @pytest.mark.parametrize("mode", ("P", "PA"))
 | 
				
			||||||
    @pytest.mark.parametrize("color", ((255, 0, 0), (255, 0, 0, 255)))
 | 
					    @pytest.mark.parametrize("color", ((255, 0, 0), (255, 0, 0, 255)))
 | 
				
			||||||
    def test_p_putpixel_rgb_rgba(self, mode, color):
 | 
					    def test_p_putpixel_rgb_rgba(self, mode, color) -> None:
 | 
				
			||||||
        im = Image.new(mode, (1, 1))
 | 
					        im = Image.new(mode, (1, 1))
 | 
				
			||||||
        im.putpixel((0, 0), color)
 | 
					        im.putpixel((0, 0), color)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -264,7 +264,7 @@ class TestCffiGetPixel(TestImageGetPixel):
 | 
				
			||||||
class TestCffi(AccessTest):
 | 
					class TestCffi(AccessTest):
 | 
				
			||||||
    _need_cffi_access = True
 | 
					    _need_cffi_access = True
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def _test_get_access(self, im):
 | 
					    def _test_get_access(self, im) -> None:
 | 
				
			||||||
        """Do we get the same thing as the old pixel access
 | 
					        """Do we get the same thing as the old pixel access
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        Using private interfaces, forcing a capi access and
 | 
					        Using private interfaces, forcing a capi access and
 | 
				
			||||||
| 
						 | 
					@ -282,7 +282,7 @@ class TestCffi(AccessTest):
 | 
				
			||||||
        with pytest.raises(ValueError):
 | 
					        with pytest.raises(ValueError):
 | 
				
			||||||
            access[(access.xsize + 1, access.ysize + 1)]
 | 
					            access[(access.xsize + 1, access.ysize + 1)]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_get_vs_c(self):
 | 
					    def test_get_vs_c(self) -> None:
 | 
				
			||||||
        with pytest.warns(DeprecationWarning):
 | 
					        with pytest.warns(DeprecationWarning):
 | 
				
			||||||
            rgb = hopper("RGB")
 | 
					            rgb = hopper("RGB")
 | 
				
			||||||
            rgb.load()
 | 
					            rgb.load()
 | 
				
			||||||
| 
						 | 
					@ -301,7 +301,7 @@ class TestCffi(AccessTest):
 | 
				
			||||||
        # im = Image.new('I;32B', (10, 10), 2**10)
 | 
					        # im = Image.new('I;32B', (10, 10), 2**10)
 | 
				
			||||||
        # self._test_get_access(im)
 | 
					        # self._test_get_access(im)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def _test_set_access(self, im, color):
 | 
					    def _test_set_access(self, im, color) -> None:
 | 
				
			||||||
        """Are we writing the correct bits into the image?
 | 
					        """Are we writing the correct bits into the image?
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        Using private interfaces, forcing a capi access and
 | 
					        Using private interfaces, forcing a capi access and
 | 
				
			||||||
| 
						 | 
					@ -322,7 +322,7 @@ class TestCffi(AccessTest):
 | 
				
			||||||
        with pytest.raises(ValueError):
 | 
					        with pytest.raises(ValueError):
 | 
				
			||||||
            access[(0, 0)] = color
 | 
					            access[(0, 0)] = color
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_set_vs_c(self):
 | 
					    def test_set_vs_c(self) -> None:
 | 
				
			||||||
        rgb = hopper("RGB")
 | 
					        rgb = hopper("RGB")
 | 
				
			||||||
        with pytest.warns(DeprecationWarning):
 | 
					        with pytest.warns(DeprecationWarning):
 | 
				
			||||||
            rgb.load()
 | 
					            rgb.load()
 | 
				
			||||||
| 
						 | 
					@ -345,11 +345,11 @@ class TestCffi(AccessTest):
 | 
				
			||||||
        # self._test_set_access(im, 2**13-1)
 | 
					        # self._test_set_access(im, 2**13-1)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    @pytest.mark.filterwarnings("ignore::DeprecationWarning")
 | 
					    @pytest.mark.filterwarnings("ignore::DeprecationWarning")
 | 
				
			||||||
    def test_not_implemented(self):
 | 
					    def test_not_implemented(self) -> None:
 | 
				
			||||||
        assert PyAccess.new(hopper("BGR;15")) is None
 | 
					        assert PyAccess.new(hopper("BGR;15")) is None
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    # ref https://github.com/python-pillow/Pillow/pull/2009
 | 
					    # ref https://github.com/python-pillow/Pillow/pull/2009
 | 
				
			||||||
    def test_reference_counting(self):
 | 
					    def test_reference_counting(self) -> None:
 | 
				
			||||||
        size = 10
 | 
					        size = 10
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        for _ in range(10):
 | 
					        for _ in range(10):
 | 
				
			||||||
| 
						 | 
					@ -361,7 +361,7 @@ class TestCffi(AccessTest):
 | 
				
			||||||
                assert px[i, 0] == 0
 | 
					                assert px[i, 0] == 0
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    @pytest.mark.parametrize("mode", ("P", "PA"))
 | 
					    @pytest.mark.parametrize("mode", ("P", "PA"))
 | 
				
			||||||
    def test_p_putpixel_rgb_rgba(self, mode):
 | 
					    def test_p_putpixel_rgb_rgba(self, mode) -> None:
 | 
				
			||||||
        for color in ((255, 0, 0), (255, 0, 0, 127 if mode == "PA" else 255)):
 | 
					        for color in ((255, 0, 0), (255, 0, 0, 127 if mode == "PA" else 255)):
 | 
				
			||||||
            im = Image.new(mode, (1, 1))
 | 
					            im = Image.new(mode, (1, 1))
 | 
				
			||||||
            with pytest.warns(DeprecationWarning):
 | 
					            with pytest.warns(DeprecationWarning):
 | 
				
			||||||
| 
						 | 
					@ -379,7 +379,7 @@ class TestImagePutPixelError(AccessTest):
 | 
				
			||||||
    INVALID_TYPES = ["foo", 1.0, None]
 | 
					    INVALID_TYPES = ["foo", 1.0, None]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    @pytest.mark.parametrize("mode", IMAGE_MODES1)
 | 
					    @pytest.mark.parametrize("mode", IMAGE_MODES1)
 | 
				
			||||||
    def test_putpixel_type_error1(self, mode):
 | 
					    def test_putpixel_type_error1(self, mode) -> None:
 | 
				
			||||||
        im = hopper(mode)
 | 
					        im = hopper(mode)
 | 
				
			||||||
        for v in self.INVALID_TYPES:
 | 
					        for v in self.INVALID_TYPES:
 | 
				
			||||||
            with pytest.raises(TypeError, match="color must be int or tuple"):
 | 
					            with pytest.raises(TypeError, match="color must be int or tuple"):
 | 
				
			||||||
| 
						 | 
					@ -402,14 +402,14 @@ class TestImagePutPixelError(AccessTest):
 | 
				
			||||||
            ),
 | 
					            ),
 | 
				
			||||||
        ),
 | 
					        ),
 | 
				
			||||||
    )
 | 
					    )
 | 
				
			||||||
    def test_putpixel_invalid_number_of_bands(self, mode, band_numbers, match):
 | 
					    def test_putpixel_invalid_number_of_bands(self, mode, band_numbers, match) -> None:
 | 
				
			||||||
        im = hopper(mode)
 | 
					        im = hopper(mode)
 | 
				
			||||||
        for band_number in band_numbers:
 | 
					        for band_number in band_numbers:
 | 
				
			||||||
            with pytest.raises(TypeError, match=match):
 | 
					            with pytest.raises(TypeError, match=match):
 | 
				
			||||||
                im.putpixel((0, 0), (0,) * band_number)
 | 
					                im.putpixel((0, 0), (0,) * band_number)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    @pytest.mark.parametrize("mode", IMAGE_MODES2)
 | 
					    @pytest.mark.parametrize("mode", IMAGE_MODES2)
 | 
				
			||||||
    def test_putpixel_type_error2(self, mode):
 | 
					    def test_putpixel_type_error2(self, mode) -> None:
 | 
				
			||||||
        im = hopper(mode)
 | 
					        im = hopper(mode)
 | 
				
			||||||
        for v in self.INVALID_TYPES:
 | 
					        for v in self.INVALID_TYPES:
 | 
				
			||||||
            with pytest.raises(
 | 
					            with pytest.raises(
 | 
				
			||||||
| 
						 | 
					@ -418,7 +418,7 @@ class TestImagePutPixelError(AccessTest):
 | 
				
			||||||
                im.putpixel((0, 0), v)
 | 
					                im.putpixel((0, 0), v)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    @pytest.mark.parametrize("mode", IMAGE_MODES1 + IMAGE_MODES2)
 | 
					    @pytest.mark.parametrize("mode", IMAGE_MODES1 + IMAGE_MODES2)
 | 
				
			||||||
    def test_putpixel_overflow_error(self, mode):
 | 
					    def test_putpixel_overflow_error(self, mode) -> None:
 | 
				
			||||||
        im = hopper(mode)
 | 
					        im = hopper(mode)
 | 
				
			||||||
        with pytest.raises(OverflowError):
 | 
					        with pytest.raises(OverflowError):
 | 
				
			||||||
            im.putpixel((0, 0), 2**80)
 | 
					            im.putpixel((0, 0), 2**80)
 | 
				
			||||||
| 
						 | 
					@ -427,7 +427,7 @@ class TestImagePutPixelError(AccessTest):
 | 
				
			||||||
class TestEmbeddable:
 | 
					class TestEmbeddable:
 | 
				
			||||||
    @pytest.mark.xfail(reason="failing test")
 | 
					    @pytest.mark.xfail(reason="failing test")
 | 
				
			||||||
    @pytest.mark.skipif(not is_win32(), reason="requires Windows")
 | 
					    @pytest.mark.skipif(not is_win32(), reason="requires Windows")
 | 
				
			||||||
    def test_embeddable(self):
 | 
					    def test_embeddable(self) -> None:
 | 
				
			||||||
        import ctypes
 | 
					        import ctypes
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        from setuptools.command.build_ext import new_compiler
 | 
					        from setuptools.command.build_ext import new_compiler
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -12,12 +12,12 @@ numpy = pytest.importorskip("numpy", reason="NumPy not installed")
 | 
				
			||||||
im = hopper().resize((128, 100))
 | 
					im = hopper().resize((128, 100))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_toarray():
 | 
					def test_toarray() -> None:
 | 
				
			||||||
    def test(mode):
 | 
					    def test(mode):
 | 
				
			||||||
        ai = numpy.array(im.convert(mode))
 | 
					        ai = numpy.array(im.convert(mode))
 | 
				
			||||||
        return ai.shape, ai.dtype.str, ai.nbytes
 | 
					        return ai.shape, ai.dtype.str, ai.nbytes
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_with_dtype(dtype):
 | 
					    def test_with_dtype(dtype) -> None:
 | 
				
			||||||
        ai = numpy.array(im, dtype=dtype)
 | 
					        ai = numpy.array(im, dtype=dtype)
 | 
				
			||||||
        assert ai.dtype == dtype
 | 
					        assert ai.dtype == dtype
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -46,11 +46,11 @@ def test_toarray():
 | 
				
			||||||
                numpy.array(im_truncated)
 | 
					                numpy.array(im_truncated)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_fromarray():
 | 
					def test_fromarray() -> None:
 | 
				
			||||||
    class Wrapper:
 | 
					    class Wrapper:
 | 
				
			||||||
        """Class with API matching Image.fromarray"""
 | 
					        """Class with API matching Image.fromarray"""
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        def __init__(self, img, arr_params):
 | 
					        def __init__(self, img, arr_params) -> None:
 | 
				
			||||||
            self.img = img
 | 
					            self.img = img
 | 
				
			||||||
            self.__array_interface__ = arr_params
 | 
					            self.__array_interface__ = arr_params
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -89,7 +89,7 @@ def test_fromarray():
 | 
				
			||||||
        Image.fromarray(wrapped)
 | 
					        Image.fromarray(wrapped)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_fromarray_palette():
 | 
					def test_fromarray_palette() -> None:
 | 
				
			||||||
    # Arrange
 | 
					    # Arrange
 | 
				
			||||||
    i = im.convert("L")
 | 
					    i = im.convert("L")
 | 
				
			||||||
    a = numpy.array(i)
 | 
					    a = numpy.array(i)
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -19,7 +19,7 @@ def draft_roundtrip(in_mode, in_size, req_mode, req_size):
 | 
				
			||||||
    return im
 | 
					    return im
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_size():
 | 
					def test_size() -> None:
 | 
				
			||||||
    for in_size, req_size, out_size in [
 | 
					    for in_size, req_size, out_size in [
 | 
				
			||||||
        ((435, 361), (2048, 2048), (435, 361)),  # bigger
 | 
					        ((435, 361), (2048, 2048), (435, 361)),  # bigger
 | 
				
			||||||
        ((435, 361), (435, 361), (435, 361)),  # same
 | 
					        ((435, 361), (435, 361), (435, 361)),  # same
 | 
				
			||||||
| 
						 | 
					@ -48,7 +48,7 @@ def test_size():
 | 
				
			||||||
        assert im.size == out_size
 | 
					        assert im.size == out_size
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_mode():
 | 
					def test_mode() -> None:
 | 
				
			||||||
    for in_mode, req_mode, out_mode in [
 | 
					    for in_mode, req_mode, out_mode in [
 | 
				
			||||||
        ("RGB", "1", "RGB"),
 | 
					        ("RGB", "1", "RGB"),
 | 
				
			||||||
        ("RGB", "L", "L"),
 | 
					        ("RGB", "L", "L"),
 | 
				
			||||||
| 
						 | 
					@ -68,7 +68,7 @@ def test_mode():
 | 
				
			||||||
        assert im.mode == out_mode
 | 
					        assert im.mode == out_mode
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_several_drafts():
 | 
					def test_several_drafts() -> None:
 | 
				
			||||||
    im = draft_roundtrip("L", (128, 128), None, (64, 64))
 | 
					    im = draft_roundtrip("L", (128, 128), None, (64, 64))
 | 
				
			||||||
    im.draft(None, (64, 64))
 | 
					    im.draft(None, (64, 64))
 | 
				
			||||||
    im.load()
 | 
					    im.load()
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -3,7 +3,7 @@ from __future__ import annotations
 | 
				
			||||||
from .helper import hopper
 | 
					from .helper import hopper
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_entropy():
 | 
					def test_entropy() -> None:
 | 
				
			||||||
    def entropy(mode):
 | 
					    def entropy(mode):
 | 
				
			||||||
        return hopper(mode).entropy()
 | 
					        return hopper(mode).entropy()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -36,7 +36,7 @@ from .helper import assert_image_equal, hopper
 | 
				
			||||||
    ),
 | 
					    ),
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
@pytest.mark.parametrize("mode", ("L", "I", "RGB", "CMYK"))
 | 
					@pytest.mark.parametrize("mode", ("L", "I", "RGB", "CMYK"))
 | 
				
			||||||
def test_sanity(filter_to_apply, mode):
 | 
					def test_sanity(filter_to_apply, mode) -> None:
 | 
				
			||||||
    im = hopper(mode)
 | 
					    im = hopper(mode)
 | 
				
			||||||
    if mode != "I" or isinstance(filter_to_apply, ImageFilter.BuiltinFilter):
 | 
					    if mode != "I" or isinstance(filter_to_apply, ImageFilter.BuiltinFilter):
 | 
				
			||||||
        out = im.filter(filter_to_apply)
 | 
					        out = im.filter(filter_to_apply)
 | 
				
			||||||
| 
						 | 
					@ -45,7 +45,7 @@ def test_sanity(filter_to_apply, mode):
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@pytest.mark.parametrize("mode", ("L", "I", "RGB", "CMYK"))
 | 
					@pytest.mark.parametrize("mode", ("L", "I", "RGB", "CMYK"))
 | 
				
			||||||
def test_sanity_error(mode):
 | 
					def test_sanity_error(mode) -> None:
 | 
				
			||||||
    with pytest.raises(TypeError):
 | 
					    with pytest.raises(TypeError):
 | 
				
			||||||
        im = hopper(mode)
 | 
					        im = hopper(mode)
 | 
				
			||||||
        im.filter("hello")
 | 
					        im.filter("hello")
 | 
				
			||||||
| 
						 | 
					@ -53,7 +53,7 @@ def test_sanity_error(mode):
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# crashes on small images
 | 
					# crashes on small images
 | 
				
			||||||
@pytest.mark.parametrize("size", ((1, 1), (2, 2), (3, 3)))
 | 
					@pytest.mark.parametrize("size", ((1, 1), (2, 2), (3, 3)))
 | 
				
			||||||
def test_crash(size):
 | 
					def test_crash(size) -> None:
 | 
				
			||||||
    im = Image.new("RGB", size)
 | 
					    im = Image.new("RGB", size)
 | 
				
			||||||
    im.filter(ImageFilter.SMOOTH)
 | 
					    im.filter(ImageFilter.SMOOTH)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -67,7 +67,7 @@ def test_crash(size):
 | 
				
			||||||
        ("RGB", ((4, 0, 0), (0, 0, 0))),
 | 
					        ("RGB", ((4, 0, 0), (0, 0, 0))),
 | 
				
			||||||
    ),
 | 
					    ),
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
def test_modefilter(mode, expected):
 | 
					def test_modefilter(mode, expected) -> None:
 | 
				
			||||||
    im = Image.new(mode, (3, 3), None)
 | 
					    im = Image.new(mode, (3, 3), None)
 | 
				
			||||||
    im.putdata(list(range(9)))
 | 
					    im.putdata(list(range(9)))
 | 
				
			||||||
    # image is:
 | 
					    # image is:
 | 
				
			||||||
| 
						 | 
					@ -90,7 +90,7 @@ def test_modefilter(mode, expected):
 | 
				
			||||||
        ("F", (0.0, 4.0, 8.0)),
 | 
					        ("F", (0.0, 4.0, 8.0)),
 | 
				
			||||||
    ),
 | 
					    ),
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
def test_rankfilter(mode, expected):
 | 
					def test_rankfilter(mode, expected) -> None:
 | 
				
			||||||
    im = Image.new(mode, (3, 3), None)
 | 
					    im = Image.new(mode, (3, 3), None)
 | 
				
			||||||
    im.putdata(list(range(9)))
 | 
					    im.putdata(list(range(9)))
 | 
				
			||||||
    # image is:
 | 
					    # image is:
 | 
				
			||||||
| 
						 | 
					@ -106,7 +106,7 @@ def test_rankfilter(mode, expected):
 | 
				
			||||||
@pytest.mark.parametrize(
 | 
					@pytest.mark.parametrize(
 | 
				
			||||||
    "filter", (ImageFilter.MinFilter, ImageFilter.MedianFilter, ImageFilter.MaxFilter)
 | 
					    "filter", (ImageFilter.MinFilter, ImageFilter.MedianFilter, ImageFilter.MaxFilter)
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
def test_rankfilter_error(filter):
 | 
					def test_rankfilter_error(filter) -> None:
 | 
				
			||||||
    with pytest.raises(ValueError):
 | 
					    with pytest.raises(ValueError):
 | 
				
			||||||
        im = Image.new("P", (3, 3), None)
 | 
					        im = Image.new("P", (3, 3), None)
 | 
				
			||||||
        im.putdata(list(range(9)))
 | 
					        im.putdata(list(range(9)))
 | 
				
			||||||
| 
						 | 
					@ -117,27 +117,27 @@ def test_rankfilter_error(filter):
 | 
				
			||||||
        im.filter(filter).getpixel((1, 1))
 | 
					        im.filter(filter).getpixel((1, 1))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_rankfilter_properties():
 | 
					def test_rankfilter_properties() -> None:
 | 
				
			||||||
    rankfilter = ImageFilter.RankFilter(1, 2)
 | 
					    rankfilter = ImageFilter.RankFilter(1, 2)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    assert rankfilter.size == 1
 | 
					    assert rankfilter.size == 1
 | 
				
			||||||
    assert rankfilter.rank == 2
 | 
					    assert rankfilter.rank == 2
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_builtinfilter_p():
 | 
					def test_builtinfilter_p() -> None:
 | 
				
			||||||
    builtin_filter = ImageFilter.BuiltinFilter()
 | 
					    builtin_filter = ImageFilter.BuiltinFilter()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    with pytest.raises(ValueError):
 | 
					    with pytest.raises(ValueError):
 | 
				
			||||||
        builtin_filter.filter(hopper("P"))
 | 
					        builtin_filter.filter(hopper("P"))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_kernel_not_enough_coefficients():
 | 
					def test_kernel_not_enough_coefficients() -> None:
 | 
				
			||||||
    with pytest.raises(ValueError):
 | 
					    with pytest.raises(ValueError):
 | 
				
			||||||
        ImageFilter.Kernel((3, 3), (0, 0))
 | 
					        ImageFilter.Kernel((3, 3), (0, 0))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@pytest.mark.parametrize("mode", ("L", "LA", "I", "RGB", "CMYK"))
 | 
					@pytest.mark.parametrize("mode", ("L", "LA", "I", "RGB", "CMYK"))
 | 
				
			||||||
def test_consistency_3x3(mode):
 | 
					def test_consistency_3x3(mode) -> None:
 | 
				
			||||||
    with Image.open("Tests/images/hopper.bmp") as source:
 | 
					    with Image.open("Tests/images/hopper.bmp") as source:
 | 
				
			||||||
        reference_name = "hopper_emboss"
 | 
					        reference_name = "hopper_emboss"
 | 
				
			||||||
        reference_name += "_I.png" if mode == "I" else ".bmp"
 | 
					        reference_name += "_I.png" if mode == "I" else ".bmp"
 | 
				
			||||||
| 
						 | 
					@ -163,7 +163,7 @@ def test_consistency_3x3(mode):
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@pytest.mark.parametrize("mode", ("L", "LA", "I", "RGB", "CMYK"))
 | 
					@pytest.mark.parametrize("mode", ("L", "LA", "I", "RGB", "CMYK"))
 | 
				
			||||||
def test_consistency_5x5(mode):
 | 
					def test_consistency_5x5(mode) -> None:
 | 
				
			||||||
    with Image.open("Tests/images/hopper.bmp") as source:
 | 
					    with Image.open("Tests/images/hopper.bmp") as source:
 | 
				
			||||||
        reference_name = "hopper_emboss_more"
 | 
					        reference_name = "hopper_emboss_more"
 | 
				
			||||||
        reference_name += "_I.png" if mode == "I" else ".bmp"
 | 
					        reference_name += "_I.png" if mode == "I" else ".bmp"
 | 
				
			||||||
| 
						 | 
					@ -199,7 +199,7 @@ def test_consistency_5x5(mode):
 | 
				
			||||||
        (2, -2),
 | 
					        (2, -2),
 | 
				
			||||||
    ),
 | 
					    ),
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
def test_invalid_box_blur_filter(radius):
 | 
					def test_invalid_box_blur_filter(radius) -> None:
 | 
				
			||||||
    with pytest.raises(ValueError):
 | 
					    with pytest.raises(ValueError):
 | 
				
			||||||
        ImageFilter.BoxBlur(radius)
 | 
					        ImageFilter.BoxBlur(radius)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -5,7 +5,7 @@ from PIL import Image
 | 
				
			||||||
from .helper import hopper
 | 
					from .helper import hopper
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_extrema():
 | 
					def test_extrema() -> None:
 | 
				
			||||||
    def extrema(mode):
 | 
					    def extrema(mode):
 | 
				
			||||||
        return hopper(mode).getextrema()
 | 
					        return hopper(mode).getextrema()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -20,7 +20,7 @@ def test_extrema():
 | 
				
			||||||
    assert extrema("I;16") == (1, 255)
 | 
					    assert extrema("I;16") == (1, 255)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_true_16():
 | 
					def test_true_16() -> None:
 | 
				
			||||||
    with Image.open("Tests/images/16_bit_noise.tif") as im:
 | 
					    with Image.open("Tests/images/16_bit_noise.tif") as im:
 | 
				
			||||||
        assert im.mode == "I;16"
 | 
					        assert im.mode == "I;16"
 | 
				
			||||||
        extrema = im.getextrema()
 | 
					        extrema = im.getextrema()
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -5,7 +5,7 @@ from PIL import Image
 | 
				
			||||||
from .helper import hopper
 | 
					from .helper import hopper
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_palette():
 | 
					def test_palette() -> None:
 | 
				
			||||||
    def palette(mode):
 | 
					    def palette(mode):
 | 
				
			||||||
        p = hopper(mode).getpalette()
 | 
					        p = hopper(mode).getpalette()
 | 
				
			||||||
        if p:
 | 
					        if p:
 | 
				
			||||||
| 
						 | 
					@ -23,7 +23,7 @@ def test_palette():
 | 
				
			||||||
    assert palette("YCbCr") is None
 | 
					    assert palette("YCbCr") is None
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_palette_rawmode():
 | 
					def test_palette_rawmode() -> None:
 | 
				
			||||||
    im = Image.new("P", (1, 1))
 | 
					    im = Image.new("P", (1, 1))
 | 
				
			||||||
    im.putpalette((1, 2, 3))
 | 
					    im.putpalette((1, 2, 3))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -10,14 +10,14 @@ from PIL import Image
 | 
				
			||||||
from .helper import hopper
 | 
					from .helper import hopper
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_sanity():
 | 
					def test_sanity() -> None:
 | 
				
			||||||
    im = hopper()
 | 
					    im = hopper()
 | 
				
			||||||
    pix = im.load()
 | 
					    pix = im.load()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    assert pix[0, 0] == (20, 20, 70)
 | 
					    assert pix[0, 0] == (20, 20, 70)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_close():
 | 
					def test_close() -> None:
 | 
				
			||||||
    im = Image.open("Tests/images/hopper.gif")
 | 
					    im = Image.open("Tests/images/hopper.gif")
 | 
				
			||||||
    im.close()
 | 
					    im.close()
 | 
				
			||||||
    with pytest.raises(ValueError):
 | 
					    with pytest.raises(ValueError):
 | 
				
			||||||
| 
						 | 
					@ -26,7 +26,7 @@ def test_close():
 | 
				
			||||||
        im.getpixel((0, 0))
 | 
					        im.getpixel((0, 0))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_close_after_load(caplog):
 | 
					def test_close_after_load(caplog) -> None:
 | 
				
			||||||
    im = Image.open("Tests/images/hopper.gif")
 | 
					    im = Image.open("Tests/images/hopper.gif")
 | 
				
			||||||
    im.load()
 | 
					    im.load()
 | 
				
			||||||
    with caplog.at_level(logging.DEBUG):
 | 
					    with caplog.at_level(logging.DEBUG):
 | 
				
			||||||
| 
						 | 
					@ -34,7 +34,7 @@ def test_close_after_load(caplog):
 | 
				
			||||||
    assert len(caplog.records) == 0
 | 
					    assert len(caplog.records) == 0
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_contextmanager():
 | 
					def test_contextmanager() -> None:
 | 
				
			||||||
    fn = None
 | 
					    fn = None
 | 
				
			||||||
    with Image.open("Tests/images/hopper.gif") as im:
 | 
					    with Image.open("Tests/images/hopper.gif") as im:
 | 
				
			||||||
        fn = im.fp.fileno()
 | 
					        fn = im.fp.fileno()
 | 
				
			||||||
| 
						 | 
					@ -44,7 +44,7 @@ def test_contextmanager():
 | 
				
			||||||
        os.fstat(fn)
 | 
					        os.fstat(fn)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_contextmanager_non_exclusive_fp():
 | 
					def test_contextmanager_non_exclusive_fp() -> None:
 | 
				
			||||||
    with open("Tests/images/hopper.gif", "rb") as fp:
 | 
					    with open("Tests/images/hopper.gif", "rb") as fp:
 | 
				
			||||||
        with Image.open(fp):
 | 
					        with Image.open(fp):
 | 
				
			||||||
            pass
 | 
					            pass
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -7,7 +7,7 @@ from PIL import Image, ImageMode
 | 
				
			||||||
from .helper import hopper
 | 
					from .helper import hopper
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_sanity():
 | 
					def test_sanity() -> None:
 | 
				
			||||||
    with hopper() as im:
 | 
					    with hopper() as im:
 | 
				
			||||||
        im.mode
 | 
					        im.mode
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -69,7 +69,7 @@ def test_sanity():
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
def test_properties(
 | 
					def test_properties(
 | 
				
			||||||
    mode, expected_base, expected_type, expected_bands, expected_band_names
 | 
					    mode, expected_base, expected_type, expected_bands, expected_band_names
 | 
				
			||||||
):
 | 
					) -> None:
 | 
				
			||||||
    assert Image.getmodebase(mode) == expected_base
 | 
					    assert Image.getmodebase(mode) == expected_base
 | 
				
			||||||
    assert Image.getmodetype(mode) == expected_type
 | 
					    assert Image.getmodetype(mode) == expected_type
 | 
				
			||||||
    assert Image.getmodebands(mode) == expected_bands
 | 
					    assert Image.getmodebands(mode) == expected_bands
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -11,7 +11,7 @@ class TestImagingPaste:
 | 
				
			||||||
    masks = {}
 | 
					    masks = {}
 | 
				
			||||||
    size = 128
 | 
					    size = 128
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def assert_9points_image(self, im, expected):
 | 
					    def assert_9points_image(self, im, expected) -> None:
 | 
				
			||||||
        expected = [
 | 
					        expected = [
 | 
				
			||||||
            point[0] if im.mode == "L" else point[: len(im.mode)] for point in expected
 | 
					            point[0] if im.mode == "L" else point[: len(im.mode)] for point in expected
 | 
				
			||||||
        ]
 | 
					        ]
 | 
				
			||||||
| 
						 | 
					@ -29,7 +29,7 @@ class TestImagingPaste:
 | 
				
			||||||
        ]
 | 
					        ]
 | 
				
			||||||
        assert actual == expected
 | 
					        assert actual == expected
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def assert_9points_paste(self, im, im2, mask, expected):
 | 
					    def assert_9points_paste(self, im, im2, mask, expected) -> None:
 | 
				
			||||||
        im3 = im.copy()
 | 
					        im3 = im.copy()
 | 
				
			||||||
        im3.paste(im2, (0, 0), mask)
 | 
					        im3.paste(im2, (0, 0), mask)
 | 
				
			||||||
        self.assert_9points_image(im3, expected)
 | 
					        self.assert_9points_image(im3, expected)
 | 
				
			||||||
| 
						 | 
					@ -106,7 +106,7 @@ class TestImagingPaste:
 | 
				
			||||||
        )
 | 
					        )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    @pytest.mark.parametrize("mode", ["RGBA", "RGB", "L"])
 | 
					    @pytest.mark.parametrize("mode", ["RGBA", "RGB", "L"])
 | 
				
			||||||
    def test_image_solid(self, mode):
 | 
					    def test_image_solid(self, mode) -> None:
 | 
				
			||||||
        im = Image.new(mode, (200, 200), "red")
 | 
					        im = Image.new(mode, (200, 200), "red")
 | 
				
			||||||
        im2 = getattr(self, "gradient_" + mode)
 | 
					        im2 = getattr(self, "gradient_" + mode)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -116,7 +116,7 @@ class TestImagingPaste:
 | 
				
			||||||
        assert_image_equal(im, im2)
 | 
					        assert_image_equal(im, im2)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    @pytest.mark.parametrize("mode", ["RGBA", "RGB", "L"])
 | 
					    @pytest.mark.parametrize("mode", ["RGBA", "RGB", "L"])
 | 
				
			||||||
    def test_image_mask_1(self, mode):
 | 
					    def test_image_mask_1(self, mode) -> None:
 | 
				
			||||||
        im = Image.new(mode, (200, 200), "white")
 | 
					        im = Image.new(mode, (200, 200), "white")
 | 
				
			||||||
        im2 = getattr(self, "gradient_" + mode)
 | 
					        im2 = getattr(self, "gradient_" + mode)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -138,7 +138,7 @@ class TestImagingPaste:
 | 
				
			||||||
        )
 | 
					        )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    @pytest.mark.parametrize("mode", ["RGBA", "RGB", "L"])
 | 
					    @pytest.mark.parametrize("mode", ["RGBA", "RGB", "L"])
 | 
				
			||||||
    def test_image_mask_L(self, mode):
 | 
					    def test_image_mask_L(self, mode) -> None:
 | 
				
			||||||
        im = Image.new(mode, (200, 200), "white")
 | 
					        im = Image.new(mode, (200, 200), "white")
 | 
				
			||||||
        im2 = getattr(self, "gradient_" + mode)
 | 
					        im2 = getattr(self, "gradient_" + mode)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -160,7 +160,7 @@ class TestImagingPaste:
 | 
				
			||||||
        )
 | 
					        )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    @pytest.mark.parametrize("mode", ["RGBA", "RGB", "L"])
 | 
					    @pytest.mark.parametrize("mode", ["RGBA", "RGB", "L"])
 | 
				
			||||||
    def test_image_mask_LA(self, mode):
 | 
					    def test_image_mask_LA(self, mode) -> None:
 | 
				
			||||||
        im = Image.new(mode, (200, 200), "white")
 | 
					        im = Image.new(mode, (200, 200), "white")
 | 
				
			||||||
        im2 = getattr(self, "gradient_" + mode)
 | 
					        im2 = getattr(self, "gradient_" + mode)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -182,7 +182,7 @@ class TestImagingPaste:
 | 
				
			||||||
        )
 | 
					        )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    @pytest.mark.parametrize("mode", ["RGBA", "RGB", "L"])
 | 
					    @pytest.mark.parametrize("mode", ["RGBA", "RGB", "L"])
 | 
				
			||||||
    def test_image_mask_RGBA(self, mode):
 | 
					    def test_image_mask_RGBA(self, mode) -> None:
 | 
				
			||||||
        im = Image.new(mode, (200, 200), "white")
 | 
					        im = Image.new(mode, (200, 200), "white")
 | 
				
			||||||
        im2 = getattr(self, "gradient_" + mode)
 | 
					        im2 = getattr(self, "gradient_" + mode)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -204,7 +204,7 @@ class TestImagingPaste:
 | 
				
			||||||
        )
 | 
					        )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    @pytest.mark.parametrize("mode", ["RGBA", "RGB", "L"])
 | 
					    @pytest.mark.parametrize("mode", ["RGBA", "RGB", "L"])
 | 
				
			||||||
    def test_image_mask_RGBa(self, mode):
 | 
					    def test_image_mask_RGBa(self, mode) -> None:
 | 
				
			||||||
        im = Image.new(mode, (200, 200), "white")
 | 
					        im = Image.new(mode, (200, 200), "white")
 | 
				
			||||||
        im2 = getattr(self, "gradient_" + mode)
 | 
					        im2 = getattr(self, "gradient_" + mode)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -226,7 +226,7 @@ class TestImagingPaste:
 | 
				
			||||||
        )
 | 
					        )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    @pytest.mark.parametrize("mode", ["RGBA", "RGB", "L"])
 | 
					    @pytest.mark.parametrize("mode", ["RGBA", "RGB", "L"])
 | 
				
			||||||
    def test_color_solid(self, mode):
 | 
					    def test_color_solid(self, mode) -> None:
 | 
				
			||||||
        im = Image.new(mode, (200, 200), "black")
 | 
					        im = Image.new(mode, (200, 200), "black")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        rect = (12, 23, 128 + 12, 128 + 23)
 | 
					        rect = (12, 23, 128 + 12, 128 + 23)
 | 
				
			||||||
| 
						 | 
					@ -239,7 +239,7 @@ class TestImagingPaste:
 | 
				
			||||||
            assert sum(head[:255]) == 0
 | 
					            assert sum(head[:255]) == 0
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    @pytest.mark.parametrize("mode", ["RGBA", "RGB", "L"])
 | 
					    @pytest.mark.parametrize("mode", ["RGBA", "RGB", "L"])
 | 
				
			||||||
    def test_color_mask_1(self, mode):
 | 
					    def test_color_mask_1(self, mode) -> None:
 | 
				
			||||||
        im = Image.new(mode, (200, 200), (50, 60, 70, 80)[: len(mode)])
 | 
					        im = Image.new(mode, (200, 200), (50, 60, 70, 80)[: len(mode)])
 | 
				
			||||||
        color = (10, 20, 30, 40)[: len(mode)]
 | 
					        color = (10, 20, 30, 40)[: len(mode)]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -261,7 +261,7 @@ class TestImagingPaste:
 | 
				
			||||||
        )
 | 
					        )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    @pytest.mark.parametrize("mode", ["RGBA", "RGB", "L"])
 | 
					    @pytest.mark.parametrize("mode", ["RGBA", "RGB", "L"])
 | 
				
			||||||
    def test_color_mask_L(self, mode):
 | 
					    def test_color_mask_L(self, mode) -> None:
 | 
				
			||||||
        im = getattr(self, "gradient_" + mode).copy()
 | 
					        im = getattr(self, "gradient_" + mode).copy()
 | 
				
			||||||
        color = "white"
 | 
					        color = "white"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -283,7 +283,7 @@ class TestImagingPaste:
 | 
				
			||||||
        )
 | 
					        )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    @pytest.mark.parametrize("mode", ["RGBA", "RGB", "L"])
 | 
					    @pytest.mark.parametrize("mode", ["RGBA", "RGB", "L"])
 | 
				
			||||||
    def test_color_mask_RGBA(self, mode):
 | 
					    def test_color_mask_RGBA(self, mode) -> None:
 | 
				
			||||||
        im = getattr(self, "gradient_" + mode).copy()
 | 
					        im = getattr(self, "gradient_" + mode).copy()
 | 
				
			||||||
        color = "white"
 | 
					        color = "white"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -305,7 +305,7 @@ class TestImagingPaste:
 | 
				
			||||||
        )
 | 
					        )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    @pytest.mark.parametrize("mode", ["RGBA", "RGB", "L"])
 | 
					    @pytest.mark.parametrize("mode", ["RGBA", "RGB", "L"])
 | 
				
			||||||
    def test_color_mask_RGBa(self, mode):
 | 
					    def test_color_mask_RGBa(self, mode) -> None:
 | 
				
			||||||
        im = getattr(self, "gradient_" + mode).copy()
 | 
					        im = getattr(self, "gradient_" + mode).copy()
 | 
				
			||||||
        color = "white"
 | 
					        color = "white"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -326,7 +326,7 @@ class TestImagingPaste:
 | 
				
			||||||
            ],
 | 
					            ],
 | 
				
			||||||
        )
 | 
					        )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_different_sizes(self):
 | 
					    def test_different_sizes(self) -> None:
 | 
				
			||||||
        im = Image.new("RGB", (100, 100))
 | 
					        im = Image.new("RGB", (100, 100))
 | 
				
			||||||
        im2 = Image.new("RGB", (50, 50))
 | 
					        im2 = Image.new("RGB", (50, 50))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -10,7 +10,7 @@ from PIL import Image
 | 
				
			||||||
from .helper import assert_image_equal, hopper
 | 
					from .helper import assert_image_equal, hopper
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_sanity():
 | 
					def test_sanity() -> None:
 | 
				
			||||||
    im1 = hopper()
 | 
					    im1 = hopper()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    data = list(im1.getdata())
 | 
					    data = list(im1.getdata())
 | 
				
			||||||
| 
						 | 
					@ -29,7 +29,7 @@ def test_sanity():
 | 
				
			||||||
    assert_image_equal(im1, im2)
 | 
					    assert_image_equal(im1, im2)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_long_integers():
 | 
					def test_long_integers() -> None:
 | 
				
			||||||
    # see bug-200802-systemerror
 | 
					    # see bug-200802-systemerror
 | 
				
			||||||
    def put(value):
 | 
					    def put(value):
 | 
				
			||||||
        im = Image.new("RGBA", (1, 1))
 | 
					        im = Image.new("RGBA", (1, 1))
 | 
				
			||||||
| 
						 | 
					@ -46,19 +46,19 @@ def test_long_integers():
 | 
				
			||||||
        assert put(sys.maxsize) == (255, 255, 255, 127)
 | 
					        assert put(sys.maxsize) == (255, 255, 255, 127)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_pypy_performance():
 | 
					def test_pypy_performance() -> None:
 | 
				
			||||||
    im = Image.new("L", (256, 256))
 | 
					    im = Image.new("L", (256, 256))
 | 
				
			||||||
    im.putdata(list(range(256)) * 256)
 | 
					    im.putdata(list(range(256)) * 256)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_mode_with_L_with_float():
 | 
					def test_mode_with_L_with_float() -> None:
 | 
				
			||||||
    im = Image.new("L", (1, 1), 0)
 | 
					    im = Image.new("L", (1, 1), 0)
 | 
				
			||||||
    im.putdata([2.0])
 | 
					    im.putdata([2.0])
 | 
				
			||||||
    assert im.getpixel((0, 0)) == 2
 | 
					    assert im.getpixel((0, 0)) == 2
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@pytest.mark.parametrize("mode", ("I", "I;16", "I;16L", "I;16B"))
 | 
					@pytest.mark.parametrize("mode", ("I", "I;16", "I;16L", "I;16B"))
 | 
				
			||||||
def test_mode_i(mode):
 | 
					def test_mode_i(mode) -> None:
 | 
				
			||||||
    src = hopper("L")
 | 
					    src = hopper("L")
 | 
				
			||||||
    data = list(src.getdata())
 | 
					    data = list(src.getdata())
 | 
				
			||||||
    im = Image.new(mode, src.size, 0)
 | 
					    im = Image.new(mode, src.size, 0)
 | 
				
			||||||
| 
						 | 
					@ -68,7 +68,7 @@ def test_mode_i(mode):
 | 
				
			||||||
    assert list(im.getdata()) == target
 | 
					    assert list(im.getdata()) == target
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_mode_F():
 | 
					def test_mode_F() -> None:
 | 
				
			||||||
    src = hopper("L")
 | 
					    src = hopper("L")
 | 
				
			||||||
    data = list(src.getdata())
 | 
					    data = list(src.getdata())
 | 
				
			||||||
    im = Image.new("F", src.size, 0)
 | 
					    im = Image.new("F", src.size, 0)
 | 
				
			||||||
| 
						 | 
					@ -79,7 +79,7 @@ def test_mode_F():
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@pytest.mark.parametrize("mode", ("BGR;15", "BGR;16", "BGR;24"))
 | 
					@pytest.mark.parametrize("mode", ("BGR;15", "BGR;16", "BGR;24"))
 | 
				
			||||||
def test_mode_BGR(mode):
 | 
					def test_mode_BGR(mode) -> None:
 | 
				
			||||||
    data = [(16, 32, 49), (32, 32, 98)]
 | 
					    data = [(16, 32, 49), (32, 32, 98)]
 | 
				
			||||||
    im = Image.new(mode, (1, 2))
 | 
					    im = Image.new(mode, (1, 2))
 | 
				
			||||||
    im.putdata(data)
 | 
					    im.putdata(data)
 | 
				
			||||||
| 
						 | 
					@ -87,7 +87,7 @@ def test_mode_BGR(mode):
 | 
				
			||||||
    assert list(im.getdata()) == data
 | 
					    assert list(im.getdata()) == data
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_array_B():
 | 
					def test_array_B() -> None:
 | 
				
			||||||
    # shouldn't segfault
 | 
					    # shouldn't segfault
 | 
				
			||||||
    # see https://github.com/python-pillow/Pillow/issues/1008
 | 
					    # see https://github.com/python-pillow/Pillow/issues/1008
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -98,7 +98,7 @@ def test_array_B():
 | 
				
			||||||
    assert len(im.getdata()) == len(arr)
 | 
					    assert len(im.getdata()) == len(arr)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_array_F():
 | 
					def test_array_F() -> None:
 | 
				
			||||||
    # shouldn't segfault
 | 
					    # shouldn't segfault
 | 
				
			||||||
    # see https://github.com/python-pillow/Pillow/issues/1008
 | 
					    # see https://github.com/python-pillow/Pillow/issues/1008
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -109,7 +109,7 @@ def test_array_F():
 | 
				
			||||||
    assert len(im.getdata()) == len(arr)
 | 
					    assert len(im.getdata()) == len(arr)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_not_flattened():
 | 
					def test_not_flattened() -> None:
 | 
				
			||||||
    im = Image.new("L", (1, 1))
 | 
					    im = Image.new("L", (1, 1))
 | 
				
			||||||
    with pytest.raises(TypeError):
 | 
					    with pytest.raises(TypeError):
 | 
				
			||||||
        im.putdata([[0]])
 | 
					        im.putdata([[0]])
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -7,7 +7,7 @@ from PIL import Image, ImagePalette
 | 
				
			||||||
from .helper import assert_image_equal, assert_image_equal_tofile, hopper
 | 
					from .helper import assert_image_equal, assert_image_equal_tofile, hopper
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_putpalette():
 | 
					def test_putpalette() -> None:
 | 
				
			||||||
    def palette(mode):
 | 
					    def palette(mode):
 | 
				
			||||||
        im = hopper(mode).copy()
 | 
					        im = hopper(mode).copy()
 | 
				
			||||||
        im.putpalette(list(range(256)) * 3)
 | 
					        im.putpalette(list(range(256)) * 3)
 | 
				
			||||||
| 
						 | 
					@ -43,7 +43,7 @@ def test_putpalette():
 | 
				
			||||||
        im.putpalette(list(range(256)) * 3)
 | 
					        im.putpalette(list(range(256)) * 3)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_imagepalette():
 | 
					def test_imagepalette() -> None:
 | 
				
			||||||
    im = hopper("P")
 | 
					    im = hopper("P")
 | 
				
			||||||
    im.putpalette(ImagePalette.negative())
 | 
					    im.putpalette(ImagePalette.negative())
 | 
				
			||||||
    assert_image_equal_tofile(im.convert("RGB"), "Tests/images/palette_negative.png")
 | 
					    assert_image_equal_tofile(im.convert("RGB"), "Tests/images/palette_negative.png")
 | 
				
			||||||
| 
						 | 
					@ -57,7 +57,7 @@ def test_imagepalette():
 | 
				
			||||||
    assert_image_equal_tofile(im.convert("RGB"), "Tests/images/palette_wedge.png")
 | 
					    assert_image_equal_tofile(im.convert("RGB"), "Tests/images/palette_wedge.png")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_putpalette_with_alpha_values():
 | 
					def test_putpalette_with_alpha_values() -> None:
 | 
				
			||||||
    with Image.open("Tests/images/transparent.gif") as im:
 | 
					    with Image.open("Tests/images/transparent.gif") as im:
 | 
				
			||||||
        expected = im.convert("RGBA")
 | 
					        expected = im.convert("RGBA")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -81,19 +81,19 @@ def test_putpalette_with_alpha_values():
 | 
				
			||||||
        ("RGBAX", (1, 2, 3, 4, 0)),
 | 
					        ("RGBAX", (1, 2, 3, 4, 0)),
 | 
				
			||||||
    ),
 | 
					    ),
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
def test_rgba_palette(mode, palette):
 | 
					def test_rgba_palette(mode, palette) -> None:
 | 
				
			||||||
    im = Image.new("P", (1, 1))
 | 
					    im = Image.new("P", (1, 1))
 | 
				
			||||||
    im.putpalette(palette, mode)
 | 
					    im.putpalette(palette, mode)
 | 
				
			||||||
    assert im.getpalette() == [1, 2, 3]
 | 
					    assert im.getpalette() == [1, 2, 3]
 | 
				
			||||||
    assert im.palette.colors == {(1, 2, 3, 4): 0}
 | 
					    assert im.palette.colors == {(1, 2, 3, 4): 0}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_empty_palette():
 | 
					def test_empty_palette() -> None:
 | 
				
			||||||
    im = Image.new("P", (1, 1))
 | 
					    im = Image.new("P", (1, 1))
 | 
				
			||||||
    assert im.getpalette() == []
 | 
					    assert im.getpalette() == []
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_undefined_palette_index():
 | 
					def test_undefined_palette_index() -> None:
 | 
				
			||||||
    im = Image.new("P", (1, 1), 3)
 | 
					    im = Image.new("P", (1, 1), 3)
 | 
				
			||||||
    im.putpalette((1, 2, 3))
 | 
					    im.putpalette((1, 2, 3))
 | 
				
			||||||
    assert im.convert("RGB").getpixel((0, 0)) == (0, 0, 0)
 | 
					    assert im.convert("RGB").getpixel((0, 0)) == (0, 0, 0)
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -48,7 +48,7 @@ gradients_image.load()
 | 
				
			||||||
        ((1, 3), (10, 4)),
 | 
					        ((1, 3), (10, 4)),
 | 
				
			||||||
    ),
 | 
					    ),
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
def test_args_factor(size, expected):
 | 
					def test_args_factor(size, expected) -> None:
 | 
				
			||||||
    im = Image.new("L", (10, 10))
 | 
					    im = Image.new("L", (10, 10))
 | 
				
			||||||
    assert expected == im.reduce(size).size
 | 
					    assert expected == im.reduce(size).size
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -56,7 +56,7 @@ def test_args_factor(size, expected):
 | 
				
			||||||
@pytest.mark.parametrize(
 | 
					@pytest.mark.parametrize(
 | 
				
			||||||
    "size, expected_error", ((0, ValueError), (2.0, TypeError), ((0, 10), ValueError))
 | 
					    "size, expected_error", ((0, ValueError), (2.0, TypeError), ((0, 10), ValueError))
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
def test_args_factor_error(size, expected_error):
 | 
					def test_args_factor_error(size, expected_error) -> None:
 | 
				
			||||||
    im = Image.new("L", (10, 10))
 | 
					    im = Image.new("L", (10, 10))
 | 
				
			||||||
    with pytest.raises(expected_error):
 | 
					    with pytest.raises(expected_error):
 | 
				
			||||||
        im.reduce(size)
 | 
					        im.reduce(size)
 | 
				
			||||||
| 
						 | 
					@ -69,7 +69,7 @@ def test_args_factor_error(size, expected_error):
 | 
				
			||||||
        ((5, 5, 6, 6), (1, 1)),
 | 
					        ((5, 5, 6, 6), (1, 1)),
 | 
				
			||||||
    ),
 | 
					    ),
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
def test_args_box(size, expected):
 | 
					def test_args_box(size, expected) -> None:
 | 
				
			||||||
    im = Image.new("L", (10, 10))
 | 
					    im = Image.new("L", (10, 10))
 | 
				
			||||||
    assert expected == im.reduce(2, size).size
 | 
					    assert expected == im.reduce(2, size).size
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -86,14 +86,14 @@ def test_args_box(size, expected):
 | 
				
			||||||
        ((5, 0, 5, 10), ValueError),
 | 
					        ((5, 0, 5, 10), ValueError),
 | 
				
			||||||
    ),
 | 
					    ),
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
def test_args_box_error(size, expected_error):
 | 
					def test_args_box_error(size, expected_error) -> None:
 | 
				
			||||||
    im = Image.new("L", (10, 10))
 | 
					    im = Image.new("L", (10, 10))
 | 
				
			||||||
    with pytest.raises(expected_error):
 | 
					    with pytest.raises(expected_error):
 | 
				
			||||||
        im.reduce(2, size).size
 | 
					        im.reduce(2, size).size
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@pytest.mark.parametrize("mode", ("P", "1", "I;16"))
 | 
					@pytest.mark.parametrize("mode", ("P", "1", "I;16"))
 | 
				
			||||||
def test_unsupported_modes(mode):
 | 
					def test_unsupported_modes(mode) -> None:
 | 
				
			||||||
    im = Image.new("P", (10, 10))
 | 
					    im = Image.new("P", (10, 10))
 | 
				
			||||||
    with pytest.raises(ValueError):
 | 
					    with pytest.raises(ValueError):
 | 
				
			||||||
        im.reduce(3)
 | 
					        im.reduce(3)
 | 
				
			||||||
| 
						 | 
					@ -119,14 +119,16 @@ def get_image(mode):
 | 
				
			||||||
    return im.crop((0, 0, im.width, im.height - 5))
 | 
					    return im.crop((0, 0, im.width, im.height - 5))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def compare_reduce_with_box(im, factor):
 | 
					def compare_reduce_with_box(im, factor) -> None:
 | 
				
			||||||
    box = (11, 13, 146, 164)
 | 
					    box = (11, 13, 146, 164)
 | 
				
			||||||
    reduced = im.reduce(factor, box=box)
 | 
					    reduced = im.reduce(factor, box=box)
 | 
				
			||||||
    reference = im.crop(box).reduce(factor)
 | 
					    reference = im.crop(box).reduce(factor)
 | 
				
			||||||
    assert reduced == reference
 | 
					    assert reduced == reference
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def compare_reduce_with_reference(im, factor, average_diff=0.4, max_diff=1):
 | 
					def compare_reduce_with_reference(
 | 
				
			||||||
 | 
					    im, factor, average_diff: float = 0.4, max_diff: int = 1
 | 
				
			||||||
 | 
					) -> None:
 | 
				
			||||||
    """Image.reduce() should look very similar to Image.resize(BOX).
 | 
					    """Image.reduce() should look very similar to Image.resize(BOX).
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    A reference image is compiled from a large source area
 | 
					    A reference image is compiled from a large source area
 | 
				
			||||||
| 
						 | 
					@ -171,7 +173,7 @@ def compare_reduce_with_reference(im, factor, average_diff=0.4, max_diff=1):
 | 
				
			||||||
    assert_compare_images(reduced, reference, average_diff, max_diff)
 | 
					    assert_compare_images(reduced, reference, average_diff, max_diff)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def assert_compare_images(a, b, max_average_diff, max_diff=255):
 | 
					def assert_compare_images(a, b, max_average_diff, max_diff: int = 255) -> None:
 | 
				
			||||||
    assert a.mode == b.mode, f"got mode {repr(a.mode)}, expected {repr(b.mode)}"
 | 
					    assert a.mode == b.mode, f"got mode {repr(a.mode)}, expected {repr(b.mode)}"
 | 
				
			||||||
    assert a.size == b.size, f"got size {repr(a.size)}, expected {repr(b.size)}"
 | 
					    assert a.size == b.size, f"got size {repr(a.size)}, expected {repr(b.size)}"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -199,20 +201,20 @@ def assert_compare_images(a, b, max_average_diff, max_diff=255):
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@pytest.mark.parametrize("factor", remarkable_factors)
 | 
					@pytest.mark.parametrize("factor", remarkable_factors)
 | 
				
			||||||
def test_mode_L(factor):
 | 
					def test_mode_L(factor) -> None:
 | 
				
			||||||
    im = get_image("L")
 | 
					    im = get_image("L")
 | 
				
			||||||
    compare_reduce_with_reference(im, factor)
 | 
					    compare_reduce_with_reference(im, factor)
 | 
				
			||||||
    compare_reduce_with_box(im, factor)
 | 
					    compare_reduce_with_box(im, factor)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@pytest.mark.parametrize("factor", remarkable_factors)
 | 
					@pytest.mark.parametrize("factor", remarkable_factors)
 | 
				
			||||||
def test_mode_LA(factor):
 | 
					def test_mode_LA(factor) -> None:
 | 
				
			||||||
    im = get_image("LA")
 | 
					    im = get_image("LA")
 | 
				
			||||||
    compare_reduce_with_reference(im, factor, 0.8, 5)
 | 
					    compare_reduce_with_reference(im, factor, 0.8, 5)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@pytest.mark.parametrize("factor", remarkable_factors)
 | 
					@pytest.mark.parametrize("factor", remarkable_factors)
 | 
				
			||||||
def test_mode_LA_opaque(factor):
 | 
					def test_mode_LA_opaque(factor) -> None:
 | 
				
			||||||
    im = get_image("LA")
 | 
					    im = get_image("LA")
 | 
				
			||||||
    # With opaque alpha, an error should be way smaller.
 | 
					    # With opaque alpha, an error should be way smaller.
 | 
				
			||||||
    im.putalpha(Image.new("L", im.size, 255))
 | 
					    im.putalpha(Image.new("L", im.size, 255))
 | 
				
			||||||
| 
						 | 
					@ -221,27 +223,27 @@ def test_mode_LA_opaque(factor):
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@pytest.mark.parametrize("factor", remarkable_factors)
 | 
					@pytest.mark.parametrize("factor", remarkable_factors)
 | 
				
			||||||
def test_mode_La(factor):
 | 
					def test_mode_La(factor) -> None:
 | 
				
			||||||
    im = get_image("La")
 | 
					    im = get_image("La")
 | 
				
			||||||
    compare_reduce_with_reference(im, factor)
 | 
					    compare_reduce_with_reference(im, factor)
 | 
				
			||||||
    compare_reduce_with_box(im, factor)
 | 
					    compare_reduce_with_box(im, factor)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@pytest.mark.parametrize("factor", remarkable_factors)
 | 
					@pytest.mark.parametrize("factor", remarkable_factors)
 | 
				
			||||||
def test_mode_RGB(factor):
 | 
					def test_mode_RGB(factor) -> None:
 | 
				
			||||||
    im = get_image("RGB")
 | 
					    im = get_image("RGB")
 | 
				
			||||||
    compare_reduce_with_reference(im, factor)
 | 
					    compare_reduce_with_reference(im, factor)
 | 
				
			||||||
    compare_reduce_with_box(im, factor)
 | 
					    compare_reduce_with_box(im, factor)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@pytest.mark.parametrize("factor", remarkable_factors)
 | 
					@pytest.mark.parametrize("factor", remarkable_factors)
 | 
				
			||||||
def test_mode_RGBA(factor):
 | 
					def test_mode_RGBA(factor) -> None:
 | 
				
			||||||
    im = get_image("RGBA")
 | 
					    im = get_image("RGBA")
 | 
				
			||||||
    compare_reduce_with_reference(im, factor, 0.8, 5)
 | 
					    compare_reduce_with_reference(im, factor, 0.8, 5)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@pytest.mark.parametrize("factor", remarkable_factors)
 | 
					@pytest.mark.parametrize("factor", remarkable_factors)
 | 
				
			||||||
def test_mode_RGBA_opaque(factor):
 | 
					def test_mode_RGBA_opaque(factor) -> None:
 | 
				
			||||||
    im = get_image("RGBA")
 | 
					    im = get_image("RGBA")
 | 
				
			||||||
    # With opaque alpha, an error should be way smaller.
 | 
					    # With opaque alpha, an error should be way smaller.
 | 
				
			||||||
    im.putalpha(Image.new("L", im.size, 255))
 | 
					    im.putalpha(Image.new("L", im.size, 255))
 | 
				
			||||||
| 
						 | 
					@ -250,27 +252,27 @@ def test_mode_RGBA_opaque(factor):
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@pytest.mark.parametrize("factor", remarkable_factors)
 | 
					@pytest.mark.parametrize("factor", remarkable_factors)
 | 
				
			||||||
def test_mode_RGBa(factor):
 | 
					def test_mode_RGBa(factor) -> None:
 | 
				
			||||||
    im = get_image("RGBa")
 | 
					    im = get_image("RGBa")
 | 
				
			||||||
    compare_reduce_with_reference(im, factor)
 | 
					    compare_reduce_with_reference(im, factor)
 | 
				
			||||||
    compare_reduce_with_box(im, factor)
 | 
					    compare_reduce_with_box(im, factor)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@pytest.mark.parametrize("factor", remarkable_factors)
 | 
					@pytest.mark.parametrize("factor", remarkable_factors)
 | 
				
			||||||
def test_mode_I(factor):
 | 
					def test_mode_I(factor) -> None:
 | 
				
			||||||
    im = get_image("I")
 | 
					    im = get_image("I")
 | 
				
			||||||
    compare_reduce_with_reference(im, factor)
 | 
					    compare_reduce_with_reference(im, factor)
 | 
				
			||||||
    compare_reduce_with_box(im, factor)
 | 
					    compare_reduce_with_box(im, factor)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@pytest.mark.parametrize("factor", remarkable_factors)
 | 
					@pytest.mark.parametrize("factor", remarkable_factors)
 | 
				
			||||||
def test_mode_F(factor):
 | 
					def test_mode_F(factor) -> None:
 | 
				
			||||||
    im = get_image("F")
 | 
					    im = get_image("F")
 | 
				
			||||||
    compare_reduce_with_reference(im, factor, 0, 0)
 | 
					    compare_reduce_with_reference(im, factor, 0, 0)
 | 
				
			||||||
    compare_reduce_with_box(im, factor)
 | 
					    compare_reduce_with_box(im, factor)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@skip_unless_feature("jpg_2000")
 | 
					@skip_unless_feature("jpg_2000")
 | 
				
			||||||
def test_jpeg2k():
 | 
					def test_jpeg2k() -> None:
 | 
				
			||||||
    with Image.open("Tests/images/test-card-lossless.jp2") as im:
 | 
					    with Image.open("Tests/images/test-card-lossless.jp2") as im:
 | 
				
			||||||
        assert im.reduce(2).size == (320, 240)
 | 
					        assert im.reduce(2).size == (320, 240)
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -16,7 +16,7 @@ from .helper import (
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class TestImagingResampleVulnerability:
 | 
					class TestImagingResampleVulnerability:
 | 
				
			||||||
    # see https://github.com/python-pillow/Pillow/issues/1710
 | 
					    # see https://github.com/python-pillow/Pillow/issues/1710
 | 
				
			||||||
    def test_overflow(self):
 | 
					    def test_overflow(self) -> None:
 | 
				
			||||||
        im = hopper("L")
 | 
					        im = hopper("L")
 | 
				
			||||||
        size_too_large = 0x100000008 // 4
 | 
					        size_too_large = 0x100000008 // 4
 | 
				
			||||||
        size_normal = 1000  # unimportant
 | 
					        size_normal = 1000  # unimportant
 | 
				
			||||||
| 
						 | 
					@ -28,7 +28,7 @@ class TestImagingResampleVulnerability:
 | 
				
			||||||
                # any resampling filter will do here
 | 
					                # any resampling filter will do here
 | 
				
			||||||
                im.im.resize((xsize, ysize), Image.Resampling.BILINEAR)
 | 
					                im.im.resize((xsize, ysize), Image.Resampling.BILINEAR)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_invalid_size(self):
 | 
					    def test_invalid_size(self) -> None:
 | 
				
			||||||
        im = hopper()
 | 
					        im = hopper()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        # Should not crash
 | 
					        # Should not crash
 | 
				
			||||||
| 
						 | 
					@ -40,7 +40,7 @@ class TestImagingResampleVulnerability:
 | 
				
			||||||
        with pytest.raises(ValueError):
 | 
					        with pytest.raises(ValueError):
 | 
				
			||||||
            im.resize((100, -100))
 | 
					            im.resize((100, -100))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_modify_after_resizing(self):
 | 
					    def test_modify_after_resizing(self) -> None:
 | 
				
			||||||
        im = hopper("RGB")
 | 
					        im = hopper("RGB")
 | 
				
			||||||
        # get copy with same size
 | 
					        # get copy with same size
 | 
				
			||||||
        copy = im.resize(im.size)
 | 
					        copy = im.resize(im.size)
 | 
				
			||||||
| 
						 | 
					@ -83,7 +83,7 @@ class TestImagingCoreResampleAccuracy:
 | 
				
			||||||
                s_px[size[0] - x - 1, y] = 255 - val
 | 
					                s_px[size[0] - x - 1, y] = 255 - val
 | 
				
			||||||
        return sample
 | 
					        return sample
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def check_case(self, case, sample):
 | 
					    def check_case(self, case, sample) -> None:
 | 
				
			||||||
        s_px = sample.load()
 | 
					        s_px = sample.load()
 | 
				
			||||||
        c_px = case.load()
 | 
					        c_px = case.load()
 | 
				
			||||||
        for y in range(case.size[1]):
 | 
					        for y in range(case.size[1]):
 | 
				
			||||||
| 
						 | 
					@ -103,7 +103,7 @@ class TestImagingCoreResampleAccuracy:
 | 
				
			||||||
        )
 | 
					        )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    @pytest.mark.parametrize("mode", ("RGBX", "RGB", "La", "L"))
 | 
					    @pytest.mark.parametrize("mode", ("RGBX", "RGB", "La", "L"))
 | 
				
			||||||
    def test_reduce_box(self, mode):
 | 
					    def test_reduce_box(self, mode) -> None:
 | 
				
			||||||
        case = self.make_case(mode, (8, 8), 0xE1)
 | 
					        case = self.make_case(mode, (8, 8), 0xE1)
 | 
				
			||||||
        case = case.resize((4, 4), Image.Resampling.BOX)
 | 
					        case = case.resize((4, 4), Image.Resampling.BOX)
 | 
				
			||||||
        # fmt: off
 | 
					        # fmt: off
 | 
				
			||||||
| 
						 | 
					@ -114,7 +114,7 @@ class TestImagingCoreResampleAccuracy:
 | 
				
			||||||
            self.check_case(channel, self.make_sample(data, (4, 4)))
 | 
					            self.check_case(channel, self.make_sample(data, (4, 4)))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    @pytest.mark.parametrize("mode", ("RGBX", "RGB", "La", "L"))
 | 
					    @pytest.mark.parametrize("mode", ("RGBX", "RGB", "La", "L"))
 | 
				
			||||||
    def test_reduce_bilinear(self, mode):
 | 
					    def test_reduce_bilinear(self, mode) -> None:
 | 
				
			||||||
        case = self.make_case(mode, (8, 8), 0xE1)
 | 
					        case = self.make_case(mode, (8, 8), 0xE1)
 | 
				
			||||||
        case = case.resize((4, 4), Image.Resampling.BILINEAR)
 | 
					        case = case.resize((4, 4), Image.Resampling.BILINEAR)
 | 
				
			||||||
        # fmt: off
 | 
					        # fmt: off
 | 
				
			||||||
| 
						 | 
					@ -125,7 +125,7 @@ class TestImagingCoreResampleAccuracy:
 | 
				
			||||||
            self.check_case(channel, self.make_sample(data, (4, 4)))
 | 
					            self.check_case(channel, self.make_sample(data, (4, 4)))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    @pytest.mark.parametrize("mode", ("RGBX", "RGB", "La", "L"))
 | 
					    @pytest.mark.parametrize("mode", ("RGBX", "RGB", "La", "L"))
 | 
				
			||||||
    def test_reduce_hamming(self, mode):
 | 
					    def test_reduce_hamming(self, mode) -> None:
 | 
				
			||||||
        case = self.make_case(mode, (8, 8), 0xE1)
 | 
					        case = self.make_case(mode, (8, 8), 0xE1)
 | 
				
			||||||
        case = case.resize((4, 4), Image.Resampling.HAMMING)
 | 
					        case = case.resize((4, 4), Image.Resampling.HAMMING)
 | 
				
			||||||
        # fmt: off
 | 
					        # fmt: off
 | 
				
			||||||
| 
						 | 
					@ -136,7 +136,7 @@ class TestImagingCoreResampleAccuracy:
 | 
				
			||||||
            self.check_case(channel, self.make_sample(data, (4, 4)))
 | 
					            self.check_case(channel, self.make_sample(data, (4, 4)))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    @pytest.mark.parametrize("mode", ("RGBX", "RGB", "La", "L"))
 | 
					    @pytest.mark.parametrize("mode", ("RGBX", "RGB", "La", "L"))
 | 
				
			||||||
    def test_reduce_bicubic(self, mode):
 | 
					    def test_reduce_bicubic(self, mode) -> None:
 | 
				
			||||||
        case = self.make_case(mode, (12, 12), 0xE1)
 | 
					        case = self.make_case(mode, (12, 12), 0xE1)
 | 
				
			||||||
        case = case.resize((6, 6), Image.Resampling.BICUBIC)
 | 
					        case = case.resize((6, 6), Image.Resampling.BICUBIC)
 | 
				
			||||||
        # fmt: off
 | 
					        # fmt: off
 | 
				
			||||||
| 
						 | 
					@ -148,7 +148,7 @@ class TestImagingCoreResampleAccuracy:
 | 
				
			||||||
            self.check_case(channel, self.make_sample(data, (6, 6)))
 | 
					            self.check_case(channel, self.make_sample(data, (6, 6)))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    @pytest.mark.parametrize("mode", ("RGBX", "RGB", "La", "L"))
 | 
					    @pytest.mark.parametrize("mode", ("RGBX", "RGB", "La", "L"))
 | 
				
			||||||
    def test_reduce_lanczos(self, mode):
 | 
					    def test_reduce_lanczos(self, mode) -> None:
 | 
				
			||||||
        case = self.make_case(mode, (16, 16), 0xE1)
 | 
					        case = self.make_case(mode, (16, 16), 0xE1)
 | 
				
			||||||
        case = case.resize((8, 8), Image.Resampling.LANCZOS)
 | 
					        case = case.resize((8, 8), Image.Resampling.LANCZOS)
 | 
				
			||||||
        # fmt: off
 | 
					        # fmt: off
 | 
				
			||||||
| 
						 | 
					@ -161,7 +161,7 @@ class TestImagingCoreResampleAccuracy:
 | 
				
			||||||
            self.check_case(channel, self.make_sample(data, (8, 8)))
 | 
					            self.check_case(channel, self.make_sample(data, (8, 8)))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    @pytest.mark.parametrize("mode", ("RGBX", "RGB", "La", "L"))
 | 
					    @pytest.mark.parametrize("mode", ("RGBX", "RGB", "La", "L"))
 | 
				
			||||||
    def test_enlarge_box(self, mode):
 | 
					    def test_enlarge_box(self, mode) -> None:
 | 
				
			||||||
        case = self.make_case(mode, (2, 2), 0xE1)
 | 
					        case = self.make_case(mode, (2, 2), 0xE1)
 | 
				
			||||||
        case = case.resize((4, 4), Image.Resampling.BOX)
 | 
					        case = case.resize((4, 4), Image.Resampling.BOX)
 | 
				
			||||||
        # fmt: off
 | 
					        # fmt: off
 | 
				
			||||||
| 
						 | 
					@ -172,7 +172,7 @@ class TestImagingCoreResampleAccuracy:
 | 
				
			||||||
            self.check_case(channel, self.make_sample(data, (4, 4)))
 | 
					            self.check_case(channel, self.make_sample(data, (4, 4)))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    @pytest.mark.parametrize("mode", ("RGBX", "RGB", "La", "L"))
 | 
					    @pytest.mark.parametrize("mode", ("RGBX", "RGB", "La", "L"))
 | 
				
			||||||
    def test_enlarge_bilinear(self, mode):
 | 
					    def test_enlarge_bilinear(self, mode) -> None:
 | 
				
			||||||
        case = self.make_case(mode, (2, 2), 0xE1)
 | 
					        case = self.make_case(mode, (2, 2), 0xE1)
 | 
				
			||||||
        case = case.resize((4, 4), Image.Resampling.BILINEAR)
 | 
					        case = case.resize((4, 4), Image.Resampling.BILINEAR)
 | 
				
			||||||
        # fmt: off
 | 
					        # fmt: off
 | 
				
			||||||
| 
						 | 
					@ -183,7 +183,7 @@ class TestImagingCoreResampleAccuracy:
 | 
				
			||||||
            self.check_case(channel, self.make_sample(data, (4, 4)))
 | 
					            self.check_case(channel, self.make_sample(data, (4, 4)))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    @pytest.mark.parametrize("mode", ("RGBX", "RGB", "La", "L"))
 | 
					    @pytest.mark.parametrize("mode", ("RGBX", "RGB", "La", "L"))
 | 
				
			||||||
    def test_enlarge_hamming(self, mode):
 | 
					    def test_enlarge_hamming(self, mode) -> None:
 | 
				
			||||||
        case = self.make_case(mode, (2, 2), 0xE1)
 | 
					        case = self.make_case(mode, (2, 2), 0xE1)
 | 
				
			||||||
        case = case.resize((4, 4), Image.Resampling.HAMMING)
 | 
					        case = case.resize((4, 4), Image.Resampling.HAMMING)
 | 
				
			||||||
        # fmt: off
 | 
					        # fmt: off
 | 
				
			||||||
| 
						 | 
					@ -194,7 +194,7 @@ class TestImagingCoreResampleAccuracy:
 | 
				
			||||||
            self.check_case(channel, self.make_sample(data, (4, 4)))
 | 
					            self.check_case(channel, self.make_sample(data, (4, 4)))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    @pytest.mark.parametrize("mode", ("RGBX", "RGB", "La", "L"))
 | 
					    @pytest.mark.parametrize("mode", ("RGBX", "RGB", "La", "L"))
 | 
				
			||||||
    def test_enlarge_bicubic(self, mode):
 | 
					    def test_enlarge_bicubic(self, mode) -> None:
 | 
				
			||||||
        case = self.make_case(mode, (4, 4), 0xE1)
 | 
					        case = self.make_case(mode, (4, 4), 0xE1)
 | 
				
			||||||
        case = case.resize((8, 8), Image.Resampling.BICUBIC)
 | 
					        case = case.resize((8, 8), Image.Resampling.BICUBIC)
 | 
				
			||||||
        # fmt: off
 | 
					        # fmt: off
 | 
				
			||||||
| 
						 | 
					@ -207,7 +207,7 @@ class TestImagingCoreResampleAccuracy:
 | 
				
			||||||
            self.check_case(channel, self.make_sample(data, (8, 8)))
 | 
					            self.check_case(channel, self.make_sample(data, (8, 8)))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    @pytest.mark.parametrize("mode", ("RGBX", "RGB", "La", "L"))
 | 
					    @pytest.mark.parametrize("mode", ("RGBX", "RGB", "La", "L"))
 | 
				
			||||||
    def test_enlarge_lanczos(self, mode):
 | 
					    def test_enlarge_lanczos(self, mode) -> None:
 | 
				
			||||||
        case = self.make_case(mode, (6, 6), 0xE1)
 | 
					        case = self.make_case(mode, (6, 6), 0xE1)
 | 
				
			||||||
        case = case.resize((12, 12), Image.Resampling.LANCZOS)
 | 
					        case = case.resize((12, 12), Image.Resampling.LANCZOS)
 | 
				
			||||||
        data = (
 | 
					        data = (
 | 
				
			||||||
| 
						 | 
					@ -221,7 +221,7 @@ class TestImagingCoreResampleAccuracy:
 | 
				
			||||||
        for channel in case.split():
 | 
					        for channel in case.split():
 | 
				
			||||||
            self.check_case(channel, self.make_sample(data, (12, 12)))
 | 
					            self.check_case(channel, self.make_sample(data, (12, 12)))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_box_filter_correct_range(self):
 | 
					    def test_box_filter_correct_range(self) -> None:
 | 
				
			||||||
        im = Image.new("RGB", (8, 8), "#1688ff").resize(
 | 
					        im = Image.new("RGB", (8, 8), "#1688ff").resize(
 | 
				
			||||||
            (100, 100), Image.Resampling.BOX
 | 
					            (100, 100), Image.Resampling.BOX
 | 
				
			||||||
        )
 | 
					        )
 | 
				
			||||||
| 
						 | 
					@ -234,7 +234,7 @@ class TestCoreResampleConsistency:
 | 
				
			||||||
        im = Image.new(mode, (512, 9), fill)
 | 
					        im = Image.new(mode, (512, 9), fill)
 | 
				
			||||||
        return im.resize((9, 512), Image.Resampling.LANCZOS), im.load()[0, 0]
 | 
					        return im.resize((9, 512), Image.Resampling.LANCZOS), im.load()[0, 0]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def run_case(self, case):
 | 
					    def run_case(self, case) -> None:
 | 
				
			||||||
        channel, color = case
 | 
					        channel, color = case
 | 
				
			||||||
        px = channel.load()
 | 
					        px = channel.load()
 | 
				
			||||||
        for x in range(channel.size[0]):
 | 
					        for x in range(channel.size[0]):
 | 
				
			||||||
| 
						 | 
					@ -243,7 +243,7 @@ class TestCoreResampleConsistency:
 | 
				
			||||||
                    message = f"{px[x, y]} != {color} for pixel {(x, y)}"
 | 
					                    message = f"{px[x, y]} != {color} for pixel {(x, y)}"
 | 
				
			||||||
                    assert px[x, y] == color, message
 | 
					                    assert px[x, y] == color, message
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_8u(self):
 | 
					    def test_8u(self) -> None:
 | 
				
			||||||
        im, color = self.make_case("RGB", (0, 64, 255))
 | 
					        im, color = self.make_case("RGB", (0, 64, 255))
 | 
				
			||||||
        r, g, b = im.split()
 | 
					        r, g, b = im.split()
 | 
				
			||||||
        self.run_case((r, color[0]))
 | 
					        self.run_case((r, color[0]))
 | 
				
			||||||
| 
						 | 
					@ -251,13 +251,13 @@ class TestCoreResampleConsistency:
 | 
				
			||||||
        self.run_case((b, color[2]))
 | 
					        self.run_case((b, color[2]))
 | 
				
			||||||
        self.run_case(self.make_case("L", 12))
 | 
					        self.run_case(self.make_case("L", 12))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_32i(self):
 | 
					    def test_32i(self) -> None:
 | 
				
			||||||
        self.run_case(self.make_case("I", 12))
 | 
					        self.run_case(self.make_case("I", 12))
 | 
				
			||||||
        self.run_case(self.make_case("I", 0x7FFFFFFF))
 | 
					        self.run_case(self.make_case("I", 0x7FFFFFFF))
 | 
				
			||||||
        self.run_case(self.make_case("I", -12))
 | 
					        self.run_case(self.make_case("I", -12))
 | 
				
			||||||
        self.run_case(self.make_case("I", -1 << 31))
 | 
					        self.run_case(self.make_case("I", -1 << 31))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_32f(self):
 | 
					    def test_32f(self) -> None:
 | 
				
			||||||
        self.run_case(self.make_case("F", 1))
 | 
					        self.run_case(self.make_case("F", 1))
 | 
				
			||||||
        self.run_case(self.make_case("F", 3.40282306074e38))
 | 
					        self.run_case(self.make_case("F", 3.40282306074e38))
 | 
				
			||||||
        self.run_case(self.make_case("F", 1.175494e-38))
 | 
					        self.run_case(self.make_case("F", 1.175494e-38))
 | 
				
			||||||
| 
						 | 
					@ -275,7 +275,7 @@ class TestCoreResampleAlphaCorrect:
 | 
				
			||||||
                px[x, y] = tuple(pix)
 | 
					                px[x, y] = tuple(pix)
 | 
				
			||||||
        return i
 | 
					        return i
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def run_levels_case(self, i):
 | 
					    def run_levels_case(self, i) -> None:
 | 
				
			||||||
        px = i.load()
 | 
					        px = i.load()
 | 
				
			||||||
        for y in range(i.size[1]):
 | 
					        for y in range(i.size[1]):
 | 
				
			||||||
            used_colors = {px[x, y][0] for x in range(i.size[0])}
 | 
					            used_colors = {px[x, y][0] for x in range(i.size[0])}
 | 
				
			||||||
| 
						 | 
					@ -285,7 +285,7 @@ class TestCoreResampleAlphaCorrect:
 | 
				
			||||||
            )
 | 
					            )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    @pytest.mark.xfail(reason="Current implementation isn't precise enough")
 | 
					    @pytest.mark.xfail(reason="Current implementation isn't precise enough")
 | 
				
			||||||
    def test_levels_rgba(self):
 | 
					    def test_levels_rgba(self) -> None:
 | 
				
			||||||
        case = self.make_levels_case("RGBA")
 | 
					        case = self.make_levels_case("RGBA")
 | 
				
			||||||
        self.run_levels_case(case.resize((512, 32), Image.Resampling.BOX))
 | 
					        self.run_levels_case(case.resize((512, 32), Image.Resampling.BOX))
 | 
				
			||||||
        self.run_levels_case(case.resize((512, 32), Image.Resampling.BILINEAR))
 | 
					        self.run_levels_case(case.resize((512, 32), Image.Resampling.BILINEAR))
 | 
				
			||||||
| 
						 | 
					@ -294,7 +294,7 @@ class TestCoreResampleAlphaCorrect:
 | 
				
			||||||
        self.run_levels_case(case.resize((512, 32), Image.Resampling.LANCZOS))
 | 
					        self.run_levels_case(case.resize((512, 32), Image.Resampling.LANCZOS))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    @pytest.mark.xfail(reason="Current implementation isn't precise enough")
 | 
					    @pytest.mark.xfail(reason="Current implementation isn't precise enough")
 | 
				
			||||||
    def test_levels_la(self):
 | 
					    def test_levels_la(self) -> None:
 | 
				
			||||||
        case = self.make_levels_case("LA")
 | 
					        case = self.make_levels_case("LA")
 | 
				
			||||||
        self.run_levels_case(case.resize((512, 32), Image.Resampling.BOX))
 | 
					        self.run_levels_case(case.resize((512, 32), Image.Resampling.BOX))
 | 
				
			||||||
        self.run_levels_case(case.resize((512, 32), Image.Resampling.BILINEAR))
 | 
					        self.run_levels_case(case.resize((512, 32), Image.Resampling.BILINEAR))
 | 
				
			||||||
| 
						 | 
					@ -312,7 +312,7 @@ class TestCoreResampleAlphaCorrect:
 | 
				
			||||||
                px[x + xdiv4, y + ydiv4] = clean_pixel
 | 
					                px[x + xdiv4, y + ydiv4] = clean_pixel
 | 
				
			||||||
        return i
 | 
					        return i
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def run_dirty_case(self, i, clean_pixel):
 | 
					    def run_dirty_case(self, i, clean_pixel) -> None:
 | 
				
			||||||
        px = i.load()
 | 
					        px = i.load()
 | 
				
			||||||
        for y in range(i.size[1]):
 | 
					        for y in range(i.size[1]):
 | 
				
			||||||
            for x in range(i.size[0]):
 | 
					            for x in range(i.size[0]):
 | 
				
			||||||
| 
						 | 
					@ -323,7 +323,7 @@ class TestCoreResampleAlphaCorrect:
 | 
				
			||||||
                    )
 | 
					                    )
 | 
				
			||||||
                    assert px[x, y][:3] == clean_pixel, message
 | 
					                    assert px[x, y][:3] == clean_pixel, message
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_dirty_pixels_rgba(self):
 | 
					    def test_dirty_pixels_rgba(self) -> None:
 | 
				
			||||||
        case = self.make_dirty_case("RGBA", (255, 255, 0, 128), (0, 0, 255, 0))
 | 
					        case = self.make_dirty_case("RGBA", (255, 255, 0, 128), (0, 0, 255, 0))
 | 
				
			||||||
        self.run_dirty_case(case.resize((20, 20), Image.Resampling.BOX), (255, 255, 0))
 | 
					        self.run_dirty_case(case.resize((20, 20), Image.Resampling.BOX), (255, 255, 0))
 | 
				
			||||||
        self.run_dirty_case(
 | 
					        self.run_dirty_case(
 | 
				
			||||||
| 
						 | 
					@ -339,7 +339,7 @@ class TestCoreResampleAlphaCorrect:
 | 
				
			||||||
            case.resize((20, 20), Image.Resampling.LANCZOS), (255, 255, 0)
 | 
					            case.resize((20, 20), Image.Resampling.LANCZOS), (255, 255, 0)
 | 
				
			||||||
        )
 | 
					        )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_dirty_pixels_la(self):
 | 
					    def test_dirty_pixels_la(self) -> None:
 | 
				
			||||||
        case = self.make_dirty_case("LA", (255, 128), (0, 0))
 | 
					        case = self.make_dirty_case("LA", (255, 128), (0, 0))
 | 
				
			||||||
        self.run_dirty_case(case.resize((20, 20), Image.Resampling.BOX), (255,))
 | 
					        self.run_dirty_case(case.resize((20, 20), Image.Resampling.BOX), (255,))
 | 
				
			||||||
        self.run_dirty_case(case.resize((20, 20), Image.Resampling.BILINEAR), (255,))
 | 
					        self.run_dirty_case(case.resize((20, 20), Image.Resampling.BILINEAR), (255,))
 | 
				
			||||||
| 
						 | 
					@ -355,22 +355,22 @@ class TestCoreResamplePasses:
 | 
				
			||||||
        yield
 | 
					        yield
 | 
				
			||||||
        assert Image.core.get_stats()["new_count"] - count == diff
 | 
					        assert Image.core.get_stats()["new_count"] - count == diff
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_horizontal(self):
 | 
					    def test_horizontal(self) -> None:
 | 
				
			||||||
        im = hopper("L")
 | 
					        im = hopper("L")
 | 
				
			||||||
        with self.count(1):
 | 
					        with self.count(1):
 | 
				
			||||||
            im.resize((im.size[0] - 10, im.size[1]), Image.Resampling.BILINEAR)
 | 
					            im.resize((im.size[0] - 10, im.size[1]), Image.Resampling.BILINEAR)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_vertical(self):
 | 
					    def test_vertical(self) -> None:
 | 
				
			||||||
        im = hopper("L")
 | 
					        im = hopper("L")
 | 
				
			||||||
        with self.count(1):
 | 
					        with self.count(1):
 | 
				
			||||||
            im.resize((im.size[0], im.size[1] - 10), Image.Resampling.BILINEAR)
 | 
					            im.resize((im.size[0], im.size[1] - 10), Image.Resampling.BILINEAR)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_both(self):
 | 
					    def test_both(self) -> None:
 | 
				
			||||||
        im = hopper("L")
 | 
					        im = hopper("L")
 | 
				
			||||||
        with self.count(2):
 | 
					        with self.count(2):
 | 
				
			||||||
            im.resize((im.size[0] - 10, im.size[1] - 10), Image.Resampling.BILINEAR)
 | 
					            im.resize((im.size[0] - 10, im.size[1] - 10), Image.Resampling.BILINEAR)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_box_horizontal(self):
 | 
					    def test_box_horizontal(self) -> None:
 | 
				
			||||||
        im = hopper("L")
 | 
					        im = hopper("L")
 | 
				
			||||||
        box = (20, 0, im.size[0] - 20, im.size[1])
 | 
					        box = (20, 0, im.size[0] - 20, im.size[1])
 | 
				
			||||||
        with self.count(1):
 | 
					        with self.count(1):
 | 
				
			||||||
| 
						 | 
					@ -380,7 +380,7 @@ class TestCoreResamplePasses:
 | 
				
			||||||
            cropped = im.crop(box).resize(im.size, Image.Resampling.BILINEAR)
 | 
					            cropped = im.crop(box).resize(im.size, Image.Resampling.BILINEAR)
 | 
				
			||||||
        assert_image_similar(with_box, cropped, 0.1)
 | 
					        assert_image_similar(with_box, cropped, 0.1)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_box_vertical(self):
 | 
					    def test_box_vertical(self) -> None:
 | 
				
			||||||
        im = hopper("L")
 | 
					        im = hopper("L")
 | 
				
			||||||
        box = (0, 20, im.size[0], im.size[1] - 20)
 | 
					        box = (0, 20, im.size[0], im.size[1] - 20)
 | 
				
			||||||
        with self.count(1):
 | 
					        with self.count(1):
 | 
				
			||||||
| 
						 | 
					@ -392,7 +392,7 @@ class TestCoreResamplePasses:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class TestCoreResampleCoefficients:
 | 
					class TestCoreResampleCoefficients:
 | 
				
			||||||
    def test_reduce(self):
 | 
					    def test_reduce(self) -> None:
 | 
				
			||||||
        test_color = 254
 | 
					        test_color = 254
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        for size in range(400000, 400010, 2):
 | 
					        for size in range(400000, 400010, 2):
 | 
				
			||||||
| 
						 | 
					@ -404,7 +404,7 @@ class TestCoreResampleCoefficients:
 | 
				
			||||||
            if px[2, 0] != test_color // 2:
 | 
					            if px[2, 0] != test_color // 2:
 | 
				
			||||||
                assert test_color // 2 == px[2, 0]
 | 
					                assert test_color // 2 == px[2, 0]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_non_zero_coefficients(self):
 | 
					    def test_non_zero_coefficients(self) -> None:
 | 
				
			||||||
        # regression test for the wrong coefficients calculation
 | 
					        # regression test for the wrong coefficients calculation
 | 
				
			||||||
        # due to bug https://github.com/python-pillow/Pillow/issues/2161
 | 
					        # due to bug https://github.com/python-pillow/Pillow/issues/2161
 | 
				
			||||||
        im = Image.new("RGBA", (1280, 1280), (0x20, 0x40, 0x60, 0xFF))
 | 
					        im = Image.new("RGBA", (1280, 1280), (0x20, 0x40, 0x60, 0xFF))
 | 
				
			||||||
| 
						 | 
					@ -432,7 +432,7 @@ class TestCoreResampleBox:
 | 
				
			||||||
            Image.Resampling.LANCZOS,
 | 
					            Image.Resampling.LANCZOS,
 | 
				
			||||||
        ),
 | 
					        ),
 | 
				
			||||||
    )
 | 
					    )
 | 
				
			||||||
    def test_wrong_arguments(self, resample):
 | 
					    def test_wrong_arguments(self, resample) -> None:
 | 
				
			||||||
        im = hopper()
 | 
					        im = hopper()
 | 
				
			||||||
        im.resize((32, 32), resample, (0, 0, im.width, im.height))
 | 
					        im.resize((32, 32), resample, (0, 0, im.width, im.height))
 | 
				
			||||||
        im.resize((32, 32), resample, (20, 20, im.width, im.height))
 | 
					        im.resize((32, 32), resample, (20, 20, im.width, im.height))
 | 
				
			||||||
| 
						 | 
					@ -478,7 +478,7 @@ class TestCoreResampleBox:
 | 
				
			||||||
    @mark_if_feature_version(
 | 
					    @mark_if_feature_version(
 | 
				
			||||||
        pytest.mark.valgrind_known_error, "libjpeg_turbo", "2.0", reason="Known Failing"
 | 
					        pytest.mark.valgrind_known_error, "libjpeg_turbo", "2.0", reason="Known Failing"
 | 
				
			||||||
    )
 | 
					    )
 | 
				
			||||||
    def test_tiles(self):
 | 
					    def test_tiles(self) -> None:
 | 
				
			||||||
        with Image.open("Tests/images/flower.jpg") as im:
 | 
					        with Image.open("Tests/images/flower.jpg") as im:
 | 
				
			||||||
            assert im.size == (480, 360)
 | 
					            assert im.size == (480, 360)
 | 
				
			||||||
            dst_size = (251, 188)
 | 
					            dst_size = (251, 188)
 | 
				
			||||||
| 
						 | 
					@ -491,7 +491,7 @@ class TestCoreResampleBox:
 | 
				
			||||||
    @mark_if_feature_version(
 | 
					    @mark_if_feature_version(
 | 
				
			||||||
        pytest.mark.valgrind_known_error, "libjpeg_turbo", "2.0", reason="Known Failing"
 | 
					        pytest.mark.valgrind_known_error, "libjpeg_turbo", "2.0", reason="Known Failing"
 | 
				
			||||||
    )
 | 
					    )
 | 
				
			||||||
    def test_subsample(self):
 | 
					    def test_subsample(self) -> None:
 | 
				
			||||||
        # This test shows advantages of the subpixel resizing
 | 
					        # This test shows advantages of the subpixel resizing
 | 
				
			||||||
        # after supersampling (e.g. during JPEG decoding).
 | 
					        # after supersampling (e.g. during JPEG decoding).
 | 
				
			||||||
        with Image.open("Tests/images/flower.jpg") as im:
 | 
					        with Image.open("Tests/images/flower.jpg") as im:
 | 
				
			||||||
| 
						 | 
					@ -518,14 +518,14 @@ class TestCoreResampleBox:
 | 
				
			||||||
    @pytest.mark.parametrize(
 | 
					    @pytest.mark.parametrize(
 | 
				
			||||||
        "resample", (Image.Resampling.NEAREST, Image.Resampling.BILINEAR)
 | 
					        "resample", (Image.Resampling.NEAREST, Image.Resampling.BILINEAR)
 | 
				
			||||||
    )
 | 
					    )
 | 
				
			||||||
    def test_formats(self, mode, resample):
 | 
					    def test_formats(self, mode, resample) -> None:
 | 
				
			||||||
        im = hopper(mode)
 | 
					        im = hopper(mode)
 | 
				
			||||||
        box = (20, 20, im.size[0] - 20, im.size[1] - 20)
 | 
					        box = (20, 20, im.size[0] - 20, im.size[1] - 20)
 | 
				
			||||||
        with_box = im.resize((32, 32), resample, box)
 | 
					        with_box = im.resize((32, 32), resample, box)
 | 
				
			||||||
        cropped = im.crop(box).resize((32, 32), resample)
 | 
					        cropped = im.crop(box).resize((32, 32), resample)
 | 
				
			||||||
        assert_image_similar(cropped, with_box, 0.4)
 | 
					        assert_image_similar(cropped, with_box, 0.4)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_passthrough(self):
 | 
					    def test_passthrough(self) -> None:
 | 
				
			||||||
        # When no resize is required
 | 
					        # When no resize is required
 | 
				
			||||||
        im = hopper()
 | 
					        im = hopper()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -539,7 +539,7 @@ class TestCoreResampleBox:
 | 
				
			||||||
            assert res.size == size
 | 
					            assert res.size == size
 | 
				
			||||||
            assert_image_equal(res, im.crop(box), f">>> {size} {box}")
 | 
					            assert_image_equal(res, im.crop(box), f">>> {size} {box}")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_no_passthrough(self):
 | 
					    def test_no_passthrough(self) -> None:
 | 
				
			||||||
        # When resize is required
 | 
					        # When resize is required
 | 
				
			||||||
        im = hopper()
 | 
					        im = hopper()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -558,7 +558,7 @@ class TestCoreResampleBox:
 | 
				
			||||||
    @pytest.mark.parametrize(
 | 
					    @pytest.mark.parametrize(
 | 
				
			||||||
        "flt", (Image.Resampling.NEAREST, Image.Resampling.BICUBIC)
 | 
					        "flt", (Image.Resampling.NEAREST, Image.Resampling.BICUBIC)
 | 
				
			||||||
    )
 | 
					    )
 | 
				
			||||||
    def test_skip_horizontal(self, flt):
 | 
					    def test_skip_horizontal(self, flt) -> None:
 | 
				
			||||||
        # Can skip resize for one dimension
 | 
					        # Can skip resize for one dimension
 | 
				
			||||||
        im = hopper()
 | 
					        im = hopper()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -581,7 +581,7 @@ class TestCoreResampleBox:
 | 
				
			||||||
    @pytest.mark.parametrize(
 | 
					    @pytest.mark.parametrize(
 | 
				
			||||||
        "flt", (Image.Resampling.NEAREST, Image.Resampling.BICUBIC)
 | 
					        "flt", (Image.Resampling.NEAREST, Image.Resampling.BICUBIC)
 | 
				
			||||||
    )
 | 
					    )
 | 
				
			||||||
    def test_skip_vertical(self, flt):
 | 
					    def test_skip_vertical(self, flt) -> None:
 | 
				
			||||||
        # Can skip resize for one dimension
 | 
					        # Can skip resize for one dimension
 | 
				
			||||||
        im = hopper()
 | 
					        im = hopper()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -12,7 +12,7 @@ from .helper import (
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def rotate(im, mode, angle, center=None, translate=None):
 | 
					def rotate(im, mode, angle, center=None, translate=None) -> None:
 | 
				
			||||||
    out = im.rotate(angle, center=center, translate=translate)
 | 
					    out = im.rotate(angle, center=center, translate=translate)
 | 
				
			||||||
    assert out.mode == mode
 | 
					    assert out.mode == mode
 | 
				
			||||||
    assert out.size == im.size  # default rotate clips output
 | 
					    assert out.size == im.size  # default rotate clips output
 | 
				
			||||||
| 
						 | 
					@ -27,13 +27,13 @@ def rotate(im, mode, angle, center=None, translate=None):
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@pytest.mark.parametrize("mode", ("1", "P", "L", "RGB", "I", "F"))
 | 
					@pytest.mark.parametrize("mode", ("1", "P", "L", "RGB", "I", "F"))
 | 
				
			||||||
def test_mode(mode):
 | 
					def test_mode(mode) -> None:
 | 
				
			||||||
    im = hopper(mode)
 | 
					    im = hopper(mode)
 | 
				
			||||||
    rotate(im, mode, 45)
 | 
					    rotate(im, mode, 45)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@pytest.mark.parametrize("angle", (0, 90, 180, 270))
 | 
					@pytest.mark.parametrize("angle", (0, 90, 180, 270))
 | 
				
			||||||
def test_angle(angle):
 | 
					def test_angle(angle) -> None:
 | 
				
			||||||
    with Image.open("Tests/images/test-card.png") as im:
 | 
					    with Image.open("Tests/images/test-card.png") as im:
 | 
				
			||||||
        rotate(im, im.mode, angle)
 | 
					        rotate(im, im.mode, angle)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -42,12 +42,12 @@ def test_angle(angle):
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@pytest.mark.parametrize("angle", (0, 45, 90, 180, 270))
 | 
					@pytest.mark.parametrize("angle", (0, 45, 90, 180, 270))
 | 
				
			||||||
def test_zero(angle):
 | 
					def test_zero(angle) -> None:
 | 
				
			||||||
    im = Image.new("RGB", (0, 0))
 | 
					    im = Image.new("RGB", (0, 0))
 | 
				
			||||||
    rotate(im, im.mode, angle)
 | 
					    rotate(im, im.mode, angle)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_resample():
 | 
					def test_resample() -> None:
 | 
				
			||||||
    # Target image creation, inspected by eye.
 | 
					    # Target image creation, inspected by eye.
 | 
				
			||||||
    # >>> im = Image.open('Tests/images/hopper.ppm')
 | 
					    # >>> im = Image.open('Tests/images/hopper.ppm')
 | 
				
			||||||
    # >>> im = im.rotate(45, resample=Image.Resampling.BICUBIC, expand=True)
 | 
					    # >>> im = im.rotate(45, resample=Image.Resampling.BICUBIC, expand=True)
 | 
				
			||||||
| 
						 | 
					@ -64,7 +64,7 @@ def test_resample():
 | 
				
			||||||
            assert_image_similar(im, target, epsilon)
 | 
					            assert_image_similar(im, target, epsilon)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_center_0():
 | 
					def test_center_0() -> None:
 | 
				
			||||||
    im = hopper()
 | 
					    im = hopper()
 | 
				
			||||||
    im = im.rotate(45, center=(0, 0), resample=Image.Resampling.BICUBIC)
 | 
					    im = im.rotate(45, center=(0, 0), resample=Image.Resampling.BICUBIC)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -75,7 +75,7 @@ def test_center_0():
 | 
				
			||||||
    assert_image_similar(im, target, 15)
 | 
					    assert_image_similar(im, target, 15)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_center_14():
 | 
					def test_center_14() -> None:
 | 
				
			||||||
    im = hopper()
 | 
					    im = hopper()
 | 
				
			||||||
    im = im.rotate(45, center=(14, 14), resample=Image.Resampling.BICUBIC)
 | 
					    im = im.rotate(45, center=(14, 14), resample=Image.Resampling.BICUBIC)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -86,7 +86,7 @@ def test_center_14():
 | 
				
			||||||
        assert_image_similar(im, target, 10)
 | 
					        assert_image_similar(im, target, 10)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_translate():
 | 
					def test_translate() -> None:
 | 
				
			||||||
    im = hopper()
 | 
					    im = hopper()
 | 
				
			||||||
    with Image.open("Tests/images/hopper_45.png") as target:
 | 
					    with Image.open("Tests/images/hopper_45.png") as target:
 | 
				
			||||||
        target_origin = (target.size[1] / 2 - 64) - 5
 | 
					        target_origin = (target.size[1] / 2 - 64) - 5
 | 
				
			||||||
| 
						 | 
					@ -99,7 +99,7 @@ def test_translate():
 | 
				
			||||||
    assert_image_similar(im, target, 1)
 | 
					    assert_image_similar(im, target, 1)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_fastpath_center():
 | 
					def test_fastpath_center() -> None:
 | 
				
			||||||
    # if the center is -1,-1 and we rotate by 90<=x<=270 the
 | 
					    # if the center is -1,-1 and we rotate by 90<=x<=270 the
 | 
				
			||||||
    # resulting image should be black
 | 
					    # resulting image should be black
 | 
				
			||||||
    for angle in (90, 180, 270):
 | 
					    for angle in (90, 180, 270):
 | 
				
			||||||
| 
						 | 
					@ -107,7 +107,7 @@ def test_fastpath_center():
 | 
				
			||||||
        assert_image_equal(im, Image.new("RGB", im.size, "black"))
 | 
					        assert_image_equal(im, Image.new("RGB", im.size, "black"))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_fastpath_translate():
 | 
					def test_fastpath_translate() -> None:
 | 
				
			||||||
    # if we post-translate by -128
 | 
					    # if we post-translate by -128
 | 
				
			||||||
    # resulting image should be black
 | 
					    # resulting image should be black
 | 
				
			||||||
    for angle in (0, 90, 180, 270):
 | 
					    for angle in (0, 90, 180, 270):
 | 
				
			||||||
| 
						 | 
					@ -115,26 +115,26 @@ def test_fastpath_translate():
 | 
				
			||||||
        assert_image_equal(im, Image.new("RGB", im.size, "black"))
 | 
					        assert_image_equal(im, Image.new("RGB", im.size, "black"))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_center():
 | 
					def test_center() -> None:
 | 
				
			||||||
    im = hopper()
 | 
					    im = hopper()
 | 
				
			||||||
    rotate(im, im.mode, 45, center=(0, 0))
 | 
					    rotate(im, im.mode, 45, center=(0, 0))
 | 
				
			||||||
    rotate(im, im.mode, 45, translate=(im.size[0] / 2, 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))
 | 
					    rotate(im, im.mode, 45, center=(0, 0), translate=(im.size[0] / 2, 0))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_rotate_no_fill():
 | 
					def test_rotate_no_fill() -> None:
 | 
				
			||||||
    im = Image.new("RGB", (100, 100), "green")
 | 
					    im = Image.new("RGB", (100, 100), "green")
 | 
				
			||||||
    im = im.rotate(45)
 | 
					    im = im.rotate(45)
 | 
				
			||||||
    assert_image_equal_tofile(im, "Tests/images/rotate_45_no_fill.png")
 | 
					    assert_image_equal_tofile(im, "Tests/images/rotate_45_no_fill.png")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_rotate_with_fill():
 | 
					def test_rotate_with_fill() -> None:
 | 
				
			||||||
    im = Image.new("RGB", (100, 100), "green")
 | 
					    im = Image.new("RGB", (100, 100), "green")
 | 
				
			||||||
    im = im.rotate(45, fillcolor="white")
 | 
					    im = im.rotate(45, fillcolor="white")
 | 
				
			||||||
    assert_image_equal_tofile(im, "Tests/images/rotate_45_with_fill.png")
 | 
					    assert_image_equal_tofile(im, "Tests/images/rotate_45_with_fill.png")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_alpha_rotate_no_fill():
 | 
					def test_alpha_rotate_no_fill() -> None:
 | 
				
			||||||
    # Alpha images are handled differently internally
 | 
					    # Alpha images are handled differently internally
 | 
				
			||||||
    im = Image.new("RGBA", (10, 10), "green")
 | 
					    im = Image.new("RGBA", (10, 10), "green")
 | 
				
			||||||
    im = im.rotate(45, expand=1)
 | 
					    im = im.rotate(45, expand=1)
 | 
				
			||||||
| 
						 | 
					@ -142,7 +142,7 @@ def test_alpha_rotate_no_fill():
 | 
				
			||||||
    assert corner == (0, 0, 0, 0)
 | 
					    assert corner == (0, 0, 0, 0)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_alpha_rotate_with_fill():
 | 
					def test_alpha_rotate_with_fill() -> None:
 | 
				
			||||||
    # Alpha images are handled differently internally
 | 
					    # Alpha images are handled differently internally
 | 
				
			||||||
    im = Image.new("RGBA", (10, 10), "green")
 | 
					    im = Image.new("RGBA", (10, 10), "green")
 | 
				
			||||||
    im = im.rotate(45, expand=1, fillcolor=(255, 0, 0, 255))
 | 
					    im = im.rotate(45, expand=1, fillcolor=(255, 0, 0, 255))
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -14,14 +14,14 @@ from .helper import (
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_sanity():
 | 
					def test_sanity() -> None:
 | 
				
			||||||
    im = hopper()
 | 
					    im = hopper()
 | 
				
			||||||
    assert im.thumbnail((100, 100)) is None
 | 
					    assert im.thumbnail((100, 100)) is None
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    assert im.size == (100, 100)
 | 
					    assert im.size == (100, 100)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_aspect():
 | 
					def test_aspect() -> None:
 | 
				
			||||||
    im = Image.new("L", (128, 128))
 | 
					    im = Image.new("L", (128, 128))
 | 
				
			||||||
    im.thumbnail((100, 100))
 | 
					    im.thumbnail((100, 100))
 | 
				
			||||||
    assert im.size == (100, 100)
 | 
					    assert im.size == (100, 100)
 | 
				
			||||||
| 
						 | 
					@ -67,19 +67,19 @@ def test_aspect():
 | 
				
			||||||
    assert im.size == (75, 23)  # ratio is 3.260869565217
 | 
					    assert im.size == (75, 23)  # ratio is 3.260869565217
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_division_by_zero():
 | 
					def test_division_by_zero() -> None:
 | 
				
			||||||
    im = Image.new("L", (200, 2))
 | 
					    im = Image.new("L", (200, 2))
 | 
				
			||||||
    im.thumbnail((75, 75))
 | 
					    im.thumbnail((75, 75))
 | 
				
			||||||
    assert im.size == (75, 1)
 | 
					    assert im.size == (75, 1)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_float():
 | 
					def test_float() -> None:
 | 
				
			||||||
    im = Image.new("L", (128, 128))
 | 
					    im = Image.new("L", (128, 128))
 | 
				
			||||||
    im.thumbnail((99.9, 99.9))
 | 
					    im.thumbnail((99.9, 99.9))
 | 
				
			||||||
    assert im.size == (99, 99)
 | 
					    assert im.size == (99, 99)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_no_resize():
 | 
					def test_no_resize() -> None:
 | 
				
			||||||
    # Check that draft() can resize the image to the destination size
 | 
					    # Check that draft() can resize the image to the destination size
 | 
				
			||||||
    with Image.open("Tests/images/hopper.jpg") as im:
 | 
					    with Image.open("Tests/images/hopper.jpg") as im:
 | 
				
			||||||
        im.draft(None, (64, 64))
 | 
					        im.draft(None, (64, 64))
 | 
				
			||||||
| 
						 | 
					@ -92,7 +92,7 @@ def test_no_resize():
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@skip_unless_feature("libtiff")
 | 
					@skip_unless_feature("libtiff")
 | 
				
			||||||
def test_load_first():
 | 
					def test_load_first() -> None:
 | 
				
			||||||
    # load() may change the size of the image
 | 
					    # load() may change the size of the image
 | 
				
			||||||
    # Test that thumbnail() is calling it before performing size calculations
 | 
					    # Test that thumbnail() is calling it before performing size calculations
 | 
				
			||||||
    with Image.open("Tests/images/g4_orientation_5.tif") as im:
 | 
					    with Image.open("Tests/images/g4_orientation_5.tif") as im:
 | 
				
			||||||
| 
						 | 
					@ -106,7 +106,7 @@ def test_load_first():
 | 
				
			||||||
        assert im.size == (590, 88)
 | 
					        assert im.size == (590, 88)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_load_first_unless_jpeg():
 | 
					def test_load_first_unless_jpeg() -> None:
 | 
				
			||||||
    # Test that thumbnail() still uses draft() for JPEG
 | 
					    # Test that thumbnail() still uses draft() for JPEG
 | 
				
			||||||
    with Image.open("Tests/images/hopper.jpg") as im:
 | 
					    with Image.open("Tests/images/hopper.jpg") as im:
 | 
				
			||||||
        draft = im.draft
 | 
					        draft = im.draft
 | 
				
			||||||
| 
						 | 
					@ -124,7 +124,7 @@ def test_load_first_unless_jpeg():
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# valgrind test is failing with memory allocated in libjpeg
 | 
					# valgrind test is failing with memory allocated in libjpeg
 | 
				
			||||||
@pytest.mark.valgrind_known_error(reason="Known Failing")
 | 
					@pytest.mark.valgrind_known_error(reason="Known Failing")
 | 
				
			||||||
def test_DCT_scaling_edges():
 | 
					def test_DCT_scaling_edges() -> None:
 | 
				
			||||||
    # Make an image with red borders and size (N * 8) + 1 to cross DCT grid
 | 
					    # Make an image with red borders and size (N * 8) + 1 to cross DCT grid
 | 
				
			||||||
    im = Image.new("RGB", (257, 257), "red")
 | 
					    im = Image.new("RGB", (257, 257), "red")
 | 
				
			||||||
    im.paste(Image.new("RGB", (235, 235)), (11, 11))
 | 
					    im.paste(Image.new("RGB", (235, 235)), (11, 11))
 | 
				
			||||||
| 
						 | 
					@ -138,7 +138,7 @@ def test_DCT_scaling_edges():
 | 
				
			||||||
    assert_image_similar(thumb, ref, 1.5)
 | 
					    assert_image_similar(thumb, ref, 1.5)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_reducing_gap_values():
 | 
					def test_reducing_gap_values() -> None:
 | 
				
			||||||
    im = hopper()
 | 
					    im = hopper()
 | 
				
			||||||
    im.thumbnail((18, 18), Image.Resampling.BICUBIC)
 | 
					    im.thumbnail((18, 18), Image.Resampling.BICUBIC)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -155,7 +155,7 @@ def test_reducing_gap_values():
 | 
				
			||||||
    assert_image_similar(ref, im, 3.5)
 | 
					    assert_image_similar(ref, im, 3.5)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_reducing_gap_for_DCT_scaling():
 | 
					def test_reducing_gap_for_DCT_scaling() -> None:
 | 
				
			||||||
    with Image.open("Tests/images/hopper.jpg") as ref:
 | 
					    with Image.open("Tests/images/hopper.jpg") as ref:
 | 
				
			||||||
        # thumbnail should call draft with reducing_gap scale
 | 
					        # thumbnail should call draft with reducing_gap scale
 | 
				
			||||||
        ref.draft(None, (18 * 3, 18 * 3))
 | 
					        ref.draft(None, (18 * 3, 18 * 3))
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -10,7 +10,7 @@ from .helper import assert_image_equal, assert_image_similar, hopper
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class TestImageTransform:
 | 
					class TestImageTransform:
 | 
				
			||||||
    def test_sanity(self):
 | 
					    def test_sanity(self) -> None:
 | 
				
			||||||
        im = hopper()
 | 
					        im = hopper()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        for transform in (
 | 
					        for transform in (
 | 
				
			||||||
| 
						 | 
					@ -31,7 +31,7 @@ class TestImageTransform:
 | 
				
			||||||
        ):
 | 
					        ):
 | 
				
			||||||
            assert_image_equal(im, im.transform(im.size, transform))
 | 
					            assert_image_equal(im, im.transform(im.size, transform))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_info(self):
 | 
					    def test_info(self) -> None:
 | 
				
			||||||
        comment = b"File written by Adobe Photoshop\xa8 4.0"
 | 
					        comment = b"File written by Adobe Photoshop\xa8 4.0"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        with Image.open("Tests/images/hopper.gif") as im:
 | 
					        with Image.open("Tests/images/hopper.gif") as im:
 | 
				
			||||||
| 
						 | 
					@ -41,14 +41,14 @@ class TestImageTransform:
 | 
				
			||||||
            new_im = im.transform((100, 100), transform)
 | 
					            new_im = im.transform((100, 100), transform)
 | 
				
			||||||
        assert new_im.info["comment"] == comment
 | 
					        assert new_im.info["comment"] == comment
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_palette(self):
 | 
					    def test_palette(self) -> None:
 | 
				
			||||||
        with Image.open("Tests/images/hopper.gif") as im:
 | 
					        with Image.open("Tests/images/hopper.gif") as im:
 | 
				
			||||||
            transformed = im.transform(
 | 
					            transformed = im.transform(
 | 
				
			||||||
                im.size, Image.Transform.AFFINE, [1, 0, 0, 0, 1, 0]
 | 
					                im.size, Image.Transform.AFFINE, [1, 0, 0, 0, 1, 0]
 | 
				
			||||||
            )
 | 
					            )
 | 
				
			||||||
            assert im.palette.palette == transformed.palette.palette
 | 
					            assert im.palette.palette == transformed.palette.palette
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_extent(self):
 | 
					    def test_extent(self) -> None:
 | 
				
			||||||
        im = hopper("RGB")
 | 
					        im = hopper("RGB")
 | 
				
			||||||
        (w, h) = im.size
 | 
					        (w, h) = im.size
 | 
				
			||||||
        transformed = im.transform(
 | 
					        transformed = im.transform(
 | 
				
			||||||
| 
						 | 
					@ -63,7 +63,7 @@ class TestImageTransform:
 | 
				
			||||||
        # undone -- precision?
 | 
					        # undone -- precision?
 | 
				
			||||||
        assert_image_similar(transformed, scaled, 23)
 | 
					        assert_image_similar(transformed, scaled, 23)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_quad(self):
 | 
					    def test_quad(self) -> None:
 | 
				
			||||||
        # one simple quad transform, equivalent to scale & crop upper left quad
 | 
					        # one simple quad transform, equivalent to scale & crop upper left quad
 | 
				
			||||||
        im = hopper("RGB")
 | 
					        im = hopper("RGB")
 | 
				
			||||||
        (w, h) = im.size
 | 
					        (w, h) = im.size
 | 
				
			||||||
| 
						 | 
					@ -91,7 +91,7 @@ class TestImageTransform:
 | 
				
			||||||
            ("LA", (76, 0)),
 | 
					            ("LA", (76, 0)),
 | 
				
			||||||
        ),
 | 
					        ),
 | 
				
			||||||
    )
 | 
					    )
 | 
				
			||||||
    def test_fill(self, mode, expected_pixel):
 | 
					    def test_fill(self, mode, expected_pixel) -> None:
 | 
				
			||||||
        im = hopper(mode)
 | 
					        im = hopper(mode)
 | 
				
			||||||
        (w, h) = im.size
 | 
					        (w, h) = im.size
 | 
				
			||||||
        transformed = im.transform(
 | 
					        transformed = im.transform(
 | 
				
			||||||
| 
						 | 
					@ -103,7 +103,7 @@ class TestImageTransform:
 | 
				
			||||||
        )
 | 
					        )
 | 
				
			||||||
        assert transformed.getpixel((w - 1, h - 1)) == expected_pixel
 | 
					        assert transformed.getpixel((w - 1, h - 1)) == expected_pixel
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_mesh(self):
 | 
					    def test_mesh(self) -> None:
 | 
				
			||||||
        # this should be a checkerboard of halfsized hoppers in ul, lr
 | 
					        # this should be a checkerboard of halfsized hoppers in ul, lr
 | 
				
			||||||
        im = hopper("RGBA")
 | 
					        im = hopper("RGBA")
 | 
				
			||||||
        (w, h) = im.size
 | 
					        (w, h) = im.size
 | 
				
			||||||
| 
						 | 
					@ -142,7 +142,7 @@ class TestImageTransform:
 | 
				
			||||||
        assert_image_equal(blank, transformed.crop((w // 2, 0, w, h // 2)))
 | 
					        assert_image_equal(blank, transformed.crop((w // 2, 0, w, h // 2)))
 | 
				
			||||||
        assert_image_equal(blank, transformed.crop((0, h // 2, w // 2, h)))
 | 
					        assert_image_equal(blank, transformed.crop((0, h // 2, w // 2, h)))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def _test_alpha_premult(self, op):
 | 
					    def _test_alpha_premult(self, op) -> None:
 | 
				
			||||||
        # create image with half white, half black,
 | 
					        # create image with half white, half black,
 | 
				
			||||||
        # with the black half transparent.
 | 
					        # with the black half transparent.
 | 
				
			||||||
        # do op,
 | 
					        # do op,
 | 
				
			||||||
| 
						 | 
					@ -158,13 +158,13 @@ class TestImageTransform:
 | 
				
			||||||
        hist = im_background.histogram()
 | 
					        hist = im_background.histogram()
 | 
				
			||||||
        assert 40 * 10 == hist[-1]
 | 
					        assert 40 * 10 == hist[-1]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_alpha_premult_resize(self):
 | 
					    def test_alpha_premult_resize(self) -> None:
 | 
				
			||||||
        def op(im, sz):
 | 
					        def op(im, sz):
 | 
				
			||||||
            return im.resize(sz, Image.Resampling.BILINEAR)
 | 
					            return im.resize(sz, Image.Resampling.BILINEAR)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        self._test_alpha_premult(op)
 | 
					        self._test_alpha_premult(op)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_alpha_premult_transform(self):
 | 
					    def test_alpha_premult_transform(self) -> None:
 | 
				
			||||||
        def op(im, sz):
 | 
					        def op(im, sz):
 | 
				
			||||||
            (w, h) = im.size
 | 
					            (w, h) = im.size
 | 
				
			||||||
            return im.transform(
 | 
					            return im.transform(
 | 
				
			||||||
| 
						 | 
					@ -173,7 +173,7 @@ class TestImageTransform:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        self._test_alpha_premult(op)
 | 
					        self._test_alpha_premult(op)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def _test_nearest(self, op, mode):
 | 
					    def _test_nearest(self, op, mode) -> None:
 | 
				
			||||||
        # create white image with half transparent,
 | 
					        # create white image with half transparent,
 | 
				
			||||||
        # do op,
 | 
					        # do op,
 | 
				
			||||||
        # the image should remain white with half transparent
 | 
					        # the image should remain white with half transparent
 | 
				
			||||||
| 
						 | 
					@ -196,14 +196,14 @@ class TestImageTransform:
 | 
				
			||||||
        )
 | 
					        )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    @pytest.mark.parametrize("mode", ("RGBA", "LA"))
 | 
					    @pytest.mark.parametrize("mode", ("RGBA", "LA"))
 | 
				
			||||||
    def test_nearest_resize(self, mode):
 | 
					    def test_nearest_resize(self, mode) -> None:
 | 
				
			||||||
        def op(im, sz):
 | 
					        def op(im, sz):
 | 
				
			||||||
            return im.resize(sz, Image.Resampling.NEAREST)
 | 
					            return im.resize(sz, Image.Resampling.NEAREST)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        self._test_nearest(op, mode)
 | 
					        self._test_nearest(op, mode)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    @pytest.mark.parametrize("mode", ("RGBA", "LA"))
 | 
					    @pytest.mark.parametrize("mode", ("RGBA", "LA"))
 | 
				
			||||||
    def test_nearest_transform(self, mode):
 | 
					    def test_nearest_transform(self, mode) -> None:
 | 
				
			||||||
        def op(im, sz):
 | 
					        def op(im, sz):
 | 
				
			||||||
            (w, h) = im.size
 | 
					            (w, h) = im.size
 | 
				
			||||||
            return im.transform(
 | 
					            return im.transform(
 | 
				
			||||||
| 
						 | 
					@ -212,7 +212,7 @@ class TestImageTransform:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        self._test_nearest(op, mode)
 | 
					        self._test_nearest(op, mode)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_blank_fill(self):
 | 
					    def test_blank_fill(self) -> None:
 | 
				
			||||||
        # attempting to hit
 | 
					        # attempting to hit
 | 
				
			||||||
        # https://github.com/python-pillow/Pillow/issues/254 reported
 | 
					        # https://github.com/python-pillow/Pillow/issues/254 reported
 | 
				
			||||||
        #
 | 
					        #
 | 
				
			||||||
| 
						 | 
					@ -234,13 +234,13 @@ class TestImageTransform:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        self.test_mesh()
 | 
					        self.test_mesh()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_missing_method_data(self):
 | 
					    def test_missing_method_data(self) -> None:
 | 
				
			||||||
        with hopper() as im:
 | 
					        with hopper() as im:
 | 
				
			||||||
            with pytest.raises(ValueError):
 | 
					            with pytest.raises(ValueError):
 | 
				
			||||||
                im.transform((100, 100), None)
 | 
					                im.transform((100, 100), None)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    @pytest.mark.parametrize("resample", (Image.Resampling.BOX, "unknown"))
 | 
					    @pytest.mark.parametrize("resample", (Image.Resampling.BOX, "unknown"))
 | 
				
			||||||
    def test_unknown_resampling_filter(self, resample):
 | 
					    def test_unknown_resampling_filter(self, resample) -> None:
 | 
				
			||||||
        with hopper() as im:
 | 
					        with hopper() as im:
 | 
				
			||||||
            (w, h) = im.size
 | 
					            (w, h) = im.size
 | 
				
			||||||
            with pytest.raises(ValueError):
 | 
					            with pytest.raises(ValueError):
 | 
				
			||||||
| 
						 | 
					@ -263,7 +263,7 @@ class TestImageTransformAffine:
 | 
				
			||||||
            (270, Image.Transpose.ROTATE_270),
 | 
					            (270, Image.Transpose.ROTATE_270),
 | 
				
			||||||
        ),
 | 
					        ),
 | 
				
			||||||
    )
 | 
					    )
 | 
				
			||||||
    def test_rotate(self, deg, transpose):
 | 
					    def test_rotate(self, deg, transpose) -> None:
 | 
				
			||||||
        im = self._test_image()
 | 
					        im = self._test_image()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        angle = -math.radians(deg)
 | 
					        angle = -math.radians(deg)
 | 
				
			||||||
| 
						 | 
					@ -313,7 +313,7 @@ class TestImageTransformAffine:
 | 
				
			||||||
            (Image.Resampling.BICUBIC, 1),
 | 
					            (Image.Resampling.BICUBIC, 1),
 | 
				
			||||||
        ),
 | 
					        ),
 | 
				
			||||||
    )
 | 
					    )
 | 
				
			||||||
    def test_resize(self, scale, epsilon_scale, resample, epsilon):
 | 
					    def test_resize(self, scale, epsilon_scale, resample, epsilon) -> None:
 | 
				
			||||||
        im = self._test_image()
 | 
					        im = self._test_image()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        size_up = int(round(im.width * scale)), int(round(im.height * scale))
 | 
					        size_up = int(round(im.width * scale)), int(round(im.height * scale))
 | 
				
			||||||
| 
						 | 
					@ -342,7 +342,7 @@ class TestImageTransformAffine:
 | 
				
			||||||
            (Image.Resampling.BICUBIC, 1),
 | 
					            (Image.Resampling.BICUBIC, 1),
 | 
				
			||||||
        ),
 | 
					        ),
 | 
				
			||||||
    )
 | 
					    )
 | 
				
			||||||
    def test_translate(self, x, y, epsilon_scale, resample, epsilon):
 | 
					    def test_translate(self, x, y, epsilon_scale, resample, epsilon) -> None:
 | 
				
			||||||
        im = self._test_image()
 | 
					        im = self._test_image()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        size_up = int(round(im.width + x)), int(round(im.height + y))
 | 
					        size_up = int(round(im.width + x)), int(round(im.height + y))
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -15,7 +15,7 @@ WHITE = (255, 255, 255)
 | 
				
			||||||
GRAY = 128
 | 
					GRAY = 128
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_sanity():
 | 
					def test_sanity() -> None:
 | 
				
			||||||
    im = hopper("L")
 | 
					    im = hopper("L")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    ImageChops.constant(im, 128)
 | 
					    ImageChops.constant(im, 128)
 | 
				
			||||||
| 
						 | 
					@ -48,7 +48,7 @@ def test_sanity():
 | 
				
			||||||
    ImageChops.offset(im, 10, 20)
 | 
					    ImageChops.offset(im, 10, 20)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_add():
 | 
					def test_add() -> None:
 | 
				
			||||||
    # Arrange
 | 
					    # Arrange
 | 
				
			||||||
    with Image.open("Tests/images/imagedraw_ellipse_RGB.png") as im1:
 | 
					    with Image.open("Tests/images/imagedraw_ellipse_RGB.png") as im1:
 | 
				
			||||||
        with Image.open("Tests/images/imagedraw_floodfill_RGB.png") as im2:
 | 
					        with Image.open("Tests/images/imagedraw_floodfill_RGB.png") as im2:
 | 
				
			||||||
| 
						 | 
					@ -60,7 +60,7 @@ def test_add():
 | 
				
			||||||
    assert new.getpixel((50, 50)) == ORANGE
 | 
					    assert new.getpixel((50, 50)) == ORANGE
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_add_scale_offset():
 | 
					def test_add_scale_offset() -> None:
 | 
				
			||||||
    # Arrange
 | 
					    # Arrange
 | 
				
			||||||
    with Image.open("Tests/images/imagedraw_ellipse_RGB.png") as im1:
 | 
					    with Image.open("Tests/images/imagedraw_ellipse_RGB.png") as im1:
 | 
				
			||||||
        with Image.open("Tests/images/imagedraw_floodfill_RGB.png") as im2:
 | 
					        with Image.open("Tests/images/imagedraw_floodfill_RGB.png") as im2:
 | 
				
			||||||
| 
						 | 
					@ -72,7 +72,7 @@ def test_add_scale_offset():
 | 
				
			||||||
    assert new.getpixel((50, 50)) == (202, 151, 100)
 | 
					    assert new.getpixel((50, 50)) == (202, 151, 100)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_add_clip():
 | 
					def test_add_clip() -> None:
 | 
				
			||||||
    # Arrange
 | 
					    # Arrange
 | 
				
			||||||
    im = hopper()
 | 
					    im = hopper()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -83,7 +83,7 @@ def test_add_clip():
 | 
				
			||||||
    assert new.getpixel((50, 50)) == (255, 255, 254)
 | 
					    assert new.getpixel((50, 50)) == (255, 255, 254)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_add_modulo():
 | 
					def test_add_modulo() -> None:
 | 
				
			||||||
    # Arrange
 | 
					    # Arrange
 | 
				
			||||||
    with Image.open("Tests/images/imagedraw_ellipse_RGB.png") as im1:
 | 
					    with Image.open("Tests/images/imagedraw_ellipse_RGB.png") as im1:
 | 
				
			||||||
        with Image.open("Tests/images/imagedraw_floodfill_RGB.png") as im2:
 | 
					        with Image.open("Tests/images/imagedraw_floodfill_RGB.png") as im2:
 | 
				
			||||||
| 
						 | 
					@ -95,7 +95,7 @@ def test_add_modulo():
 | 
				
			||||||
    assert new.getpixel((50, 50)) == ORANGE
 | 
					    assert new.getpixel((50, 50)) == ORANGE
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_add_modulo_no_clip():
 | 
					def test_add_modulo_no_clip() -> None:
 | 
				
			||||||
    # Arrange
 | 
					    # Arrange
 | 
				
			||||||
    im = hopper()
 | 
					    im = hopper()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -106,7 +106,7 @@ def test_add_modulo_no_clip():
 | 
				
			||||||
    assert new.getpixel((50, 50)) == (224, 76, 254)
 | 
					    assert new.getpixel((50, 50)) == (224, 76, 254)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_blend():
 | 
					def test_blend() -> None:
 | 
				
			||||||
    # Arrange
 | 
					    # Arrange
 | 
				
			||||||
    with Image.open("Tests/images/imagedraw_ellipse_RGB.png") as im1:
 | 
					    with Image.open("Tests/images/imagedraw_ellipse_RGB.png") as im1:
 | 
				
			||||||
        with Image.open("Tests/images/imagedraw_floodfill_RGB.png") as im2:
 | 
					        with Image.open("Tests/images/imagedraw_floodfill_RGB.png") as im2:
 | 
				
			||||||
| 
						 | 
					@ -118,7 +118,7 @@ def test_blend():
 | 
				
			||||||
    assert new.getpixel((50, 50)) == BROWN
 | 
					    assert new.getpixel((50, 50)) == BROWN
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_constant():
 | 
					def test_constant() -> None:
 | 
				
			||||||
    # Arrange
 | 
					    # Arrange
 | 
				
			||||||
    im = Image.new("RGB", (20, 10))
 | 
					    im = Image.new("RGB", (20, 10))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -131,7 +131,7 @@ def test_constant():
 | 
				
			||||||
    assert new.getpixel((19, 9)) == GRAY
 | 
					    assert new.getpixel((19, 9)) == GRAY
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_darker_image():
 | 
					def test_darker_image() -> None:
 | 
				
			||||||
    # Arrange
 | 
					    # Arrange
 | 
				
			||||||
    with Image.open("Tests/images/imagedraw_chord_RGB.png") as im1:
 | 
					    with Image.open("Tests/images/imagedraw_chord_RGB.png") as im1:
 | 
				
			||||||
        with Image.open("Tests/images/imagedraw_outline_chord_RGB.png") as im2:
 | 
					        with Image.open("Tests/images/imagedraw_outline_chord_RGB.png") as im2:
 | 
				
			||||||
| 
						 | 
					@ -142,7 +142,7 @@ def test_darker_image():
 | 
				
			||||||
            assert_image_equal(new, im2)
 | 
					            assert_image_equal(new, im2)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_darker_pixel():
 | 
					def test_darker_pixel() -> None:
 | 
				
			||||||
    # Arrange
 | 
					    # Arrange
 | 
				
			||||||
    im1 = hopper()
 | 
					    im1 = hopper()
 | 
				
			||||||
    with Image.open("Tests/images/imagedraw_chord_RGB.png") as im2:
 | 
					    with Image.open("Tests/images/imagedraw_chord_RGB.png") as im2:
 | 
				
			||||||
| 
						 | 
					@ -153,7 +153,7 @@ def test_darker_pixel():
 | 
				
			||||||
    assert new.getpixel((50, 50)) == (240, 166, 0)
 | 
					    assert new.getpixel((50, 50)) == (240, 166, 0)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_difference():
 | 
					def test_difference() -> None:
 | 
				
			||||||
    # Arrange
 | 
					    # Arrange
 | 
				
			||||||
    with Image.open("Tests/images/imagedraw_arc_end_le_start.png") as im1:
 | 
					    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:
 | 
					        with Image.open("Tests/images/imagedraw_arc_no_loops.png") as im2:
 | 
				
			||||||
| 
						 | 
					@ -164,7 +164,7 @@ def test_difference():
 | 
				
			||||||
    assert new.getbbox() == (25, 25, 76, 76)
 | 
					    assert new.getbbox() == (25, 25, 76, 76)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_difference_pixel():
 | 
					def test_difference_pixel() -> None:
 | 
				
			||||||
    # Arrange
 | 
					    # Arrange
 | 
				
			||||||
    im1 = hopper()
 | 
					    im1 = hopper()
 | 
				
			||||||
    with Image.open("Tests/images/imagedraw_polygon_kite_RGB.png") as im2:
 | 
					    with Image.open("Tests/images/imagedraw_polygon_kite_RGB.png") as im2:
 | 
				
			||||||
| 
						 | 
					@ -175,7 +175,7 @@ def test_difference_pixel():
 | 
				
			||||||
    assert new.getpixel((50, 50)) == (240, 166, 128)
 | 
					    assert new.getpixel((50, 50)) == (240, 166, 128)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_duplicate():
 | 
					def test_duplicate() -> None:
 | 
				
			||||||
    # Arrange
 | 
					    # Arrange
 | 
				
			||||||
    im = hopper()
 | 
					    im = hopper()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -186,7 +186,7 @@ def test_duplicate():
 | 
				
			||||||
    assert_image_equal(new, im)
 | 
					    assert_image_equal(new, im)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_invert():
 | 
					def test_invert() -> None:
 | 
				
			||||||
    # Arrange
 | 
					    # Arrange
 | 
				
			||||||
    with Image.open("Tests/images/imagedraw_floodfill_RGB.png") as im:
 | 
					    with Image.open("Tests/images/imagedraw_floodfill_RGB.png") as im:
 | 
				
			||||||
        # Act
 | 
					        # Act
 | 
				
			||||||
| 
						 | 
					@ -198,7 +198,7 @@ def test_invert():
 | 
				
			||||||
    assert new.getpixel((50, 50)) == CYAN
 | 
					    assert new.getpixel((50, 50)) == CYAN
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_lighter_image():
 | 
					def test_lighter_image() -> None:
 | 
				
			||||||
    # Arrange
 | 
					    # Arrange
 | 
				
			||||||
    with Image.open("Tests/images/imagedraw_chord_RGB.png") as im1:
 | 
					    with Image.open("Tests/images/imagedraw_chord_RGB.png") as im1:
 | 
				
			||||||
        with Image.open("Tests/images/imagedraw_outline_chord_RGB.png") as im2:
 | 
					        with Image.open("Tests/images/imagedraw_outline_chord_RGB.png") as im2:
 | 
				
			||||||
| 
						 | 
					@ -209,7 +209,7 @@ def test_lighter_image():
 | 
				
			||||||
        assert_image_equal(new, im1)
 | 
					        assert_image_equal(new, im1)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_lighter_pixel():
 | 
					def test_lighter_pixel() -> None:
 | 
				
			||||||
    # Arrange
 | 
					    # Arrange
 | 
				
			||||||
    im1 = hopper()
 | 
					    im1 = hopper()
 | 
				
			||||||
    with Image.open("Tests/images/imagedraw_chord_RGB.png") as im2:
 | 
					    with Image.open("Tests/images/imagedraw_chord_RGB.png") as im2:
 | 
				
			||||||
| 
						 | 
					@ -220,7 +220,7 @@ def test_lighter_pixel():
 | 
				
			||||||
    assert new.getpixel((50, 50)) == (255, 255, 127)
 | 
					    assert new.getpixel((50, 50)) == (255, 255, 127)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_multiply_black():
 | 
					def test_multiply_black() -> None:
 | 
				
			||||||
    """If you multiply an image with a solid black image,
 | 
					    """If you multiply an image with a solid black image,
 | 
				
			||||||
    the result is black."""
 | 
					    the result is black."""
 | 
				
			||||||
    # Arrange
 | 
					    # Arrange
 | 
				
			||||||
| 
						 | 
					@ -234,7 +234,7 @@ def test_multiply_black():
 | 
				
			||||||
    assert_image_equal(new, black)
 | 
					    assert_image_equal(new, black)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_multiply_green():
 | 
					def test_multiply_green() -> None:
 | 
				
			||||||
    # Arrange
 | 
					    # Arrange
 | 
				
			||||||
    with Image.open("Tests/images/imagedraw_floodfill_RGB.png") as im:
 | 
					    with Image.open("Tests/images/imagedraw_floodfill_RGB.png") as im:
 | 
				
			||||||
        green = Image.new("RGB", im.size, "green")
 | 
					        green = Image.new("RGB", im.size, "green")
 | 
				
			||||||
| 
						 | 
					@ -248,7 +248,7 @@ def test_multiply_green():
 | 
				
			||||||
    assert new.getpixel((50, 50)) == BLACK
 | 
					    assert new.getpixel((50, 50)) == BLACK
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_multiply_white():
 | 
					def test_multiply_white() -> None:
 | 
				
			||||||
    """If you multiply with a solid white image, the image is unaffected."""
 | 
					    """If you multiply with a solid white image, the image is unaffected."""
 | 
				
			||||||
    # Arrange
 | 
					    # Arrange
 | 
				
			||||||
    im1 = hopper()
 | 
					    im1 = hopper()
 | 
				
			||||||
| 
						 | 
					@ -261,7 +261,7 @@ def test_multiply_white():
 | 
				
			||||||
    assert_image_equal(new, im1)
 | 
					    assert_image_equal(new, im1)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_offset():
 | 
					def test_offset() -> None:
 | 
				
			||||||
    # Arrange
 | 
					    # Arrange
 | 
				
			||||||
    xoffset = 45
 | 
					    xoffset = 45
 | 
				
			||||||
    yoffset = 20
 | 
					    yoffset = 20
 | 
				
			||||||
| 
						 | 
					@ -278,7 +278,7 @@ def test_offset():
 | 
				
			||||||
        assert ImageChops.offset(im, xoffset) == ImageChops.offset(im, xoffset, xoffset)
 | 
					        assert ImageChops.offset(im, xoffset) == ImageChops.offset(im, xoffset, xoffset)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_screen():
 | 
					def test_screen() -> None:
 | 
				
			||||||
    # Arrange
 | 
					    # Arrange
 | 
				
			||||||
    with Image.open("Tests/images/imagedraw_ellipse_RGB.png") as im1:
 | 
					    with Image.open("Tests/images/imagedraw_ellipse_RGB.png") as im1:
 | 
				
			||||||
        with Image.open("Tests/images/imagedraw_floodfill_RGB.png") as im2:
 | 
					        with Image.open("Tests/images/imagedraw_floodfill_RGB.png") as im2:
 | 
				
			||||||
| 
						 | 
					@ -290,7 +290,7 @@ def test_screen():
 | 
				
			||||||
    assert new.getpixel((50, 50)) == ORANGE
 | 
					    assert new.getpixel((50, 50)) == ORANGE
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_subtract():
 | 
					def test_subtract() -> None:
 | 
				
			||||||
    # Arrange
 | 
					    # Arrange
 | 
				
			||||||
    with Image.open("Tests/images/imagedraw_chord_RGB.png") as im1:
 | 
					    with Image.open("Tests/images/imagedraw_chord_RGB.png") as im1:
 | 
				
			||||||
        with Image.open("Tests/images/imagedraw_outline_chord_RGB.png") as im2:
 | 
					        with Image.open("Tests/images/imagedraw_outline_chord_RGB.png") as im2:
 | 
				
			||||||
| 
						 | 
					@ -303,7 +303,7 @@ def test_subtract():
 | 
				
			||||||
    assert new.getpixel((50, 52)) == BLACK
 | 
					    assert new.getpixel((50, 52)) == BLACK
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_subtract_scale_offset():
 | 
					def test_subtract_scale_offset() -> None:
 | 
				
			||||||
    # Arrange
 | 
					    # Arrange
 | 
				
			||||||
    with Image.open("Tests/images/imagedraw_chord_RGB.png") as im1:
 | 
					    with Image.open("Tests/images/imagedraw_chord_RGB.png") as im1:
 | 
				
			||||||
        with Image.open("Tests/images/imagedraw_outline_chord_RGB.png") as im2:
 | 
					        with Image.open("Tests/images/imagedraw_outline_chord_RGB.png") as im2:
 | 
				
			||||||
| 
						 | 
					@ -315,7 +315,7 @@ def test_subtract_scale_offset():
 | 
				
			||||||
    assert new.getpixel((50, 50)) == (100, 202, 100)
 | 
					    assert new.getpixel((50, 50)) == (100, 202, 100)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_subtract_clip():
 | 
					def test_subtract_clip() -> None:
 | 
				
			||||||
    # Arrange
 | 
					    # Arrange
 | 
				
			||||||
    im1 = hopper()
 | 
					    im1 = hopper()
 | 
				
			||||||
    with Image.open("Tests/images/imagedraw_chord_RGB.png") as im2:
 | 
					    with Image.open("Tests/images/imagedraw_chord_RGB.png") as im2:
 | 
				
			||||||
| 
						 | 
					@ -326,7 +326,7 @@ def test_subtract_clip():
 | 
				
			||||||
    assert new.getpixel((50, 50)) == (0, 0, 127)
 | 
					    assert new.getpixel((50, 50)) == (0, 0, 127)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_subtract_modulo():
 | 
					def test_subtract_modulo() -> None:
 | 
				
			||||||
    # Arrange
 | 
					    # Arrange
 | 
				
			||||||
    with Image.open("Tests/images/imagedraw_chord_RGB.png") as im1:
 | 
					    with Image.open("Tests/images/imagedraw_chord_RGB.png") as im1:
 | 
				
			||||||
        with Image.open("Tests/images/imagedraw_outline_chord_RGB.png") as im2:
 | 
					        with Image.open("Tests/images/imagedraw_outline_chord_RGB.png") as im2:
 | 
				
			||||||
| 
						 | 
					@ -339,7 +339,7 @@ def test_subtract_modulo():
 | 
				
			||||||
    assert new.getpixel((50, 52)) == BLACK
 | 
					    assert new.getpixel((50, 52)) == BLACK
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_subtract_modulo_no_clip():
 | 
					def test_subtract_modulo_no_clip() -> None:
 | 
				
			||||||
    # Arrange
 | 
					    # Arrange
 | 
				
			||||||
    im1 = hopper()
 | 
					    im1 = hopper()
 | 
				
			||||||
    with Image.open("Tests/images/imagedraw_chord_RGB.png") as im2:
 | 
					    with Image.open("Tests/images/imagedraw_chord_RGB.png") as im2:
 | 
				
			||||||
| 
						 | 
					@ -350,7 +350,7 @@ def test_subtract_modulo_no_clip():
 | 
				
			||||||
    assert new.getpixel((50, 50)) == (241, 167, 127)
 | 
					    assert new.getpixel((50, 50)) == (241, 167, 127)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_soft_light():
 | 
					def test_soft_light() -> None:
 | 
				
			||||||
    # Arrange
 | 
					    # Arrange
 | 
				
			||||||
    with Image.open("Tests/images/hopper.png") as im1:
 | 
					    with Image.open("Tests/images/hopper.png") as im1:
 | 
				
			||||||
        with Image.open("Tests/images/hopper-XYZ.png") as im2:
 | 
					        with Image.open("Tests/images/hopper-XYZ.png") as im2:
 | 
				
			||||||
| 
						 | 
					@ -362,7 +362,7 @@ def test_soft_light():
 | 
				
			||||||
    assert new.getpixel((15, 100)) == (1, 1, 3)
 | 
					    assert new.getpixel((15, 100)) == (1, 1, 3)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_hard_light():
 | 
					def test_hard_light() -> None:
 | 
				
			||||||
    # Arrange
 | 
					    # Arrange
 | 
				
			||||||
    with Image.open("Tests/images/hopper.png") as im1:
 | 
					    with Image.open("Tests/images/hopper.png") as im1:
 | 
				
			||||||
        with Image.open("Tests/images/hopper-XYZ.png") as im2:
 | 
					        with Image.open("Tests/images/hopper-XYZ.png") as im2:
 | 
				
			||||||
| 
						 | 
					@ -374,7 +374,7 @@ def test_hard_light():
 | 
				
			||||||
    assert new.getpixel((15, 100)) == (1, 1, 2)
 | 
					    assert new.getpixel((15, 100)) == (1, 1, 2)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_overlay():
 | 
					def test_overlay() -> None:
 | 
				
			||||||
    # Arrange
 | 
					    # Arrange
 | 
				
			||||||
    with Image.open("Tests/images/hopper.png") as im1:
 | 
					    with Image.open("Tests/images/hopper.png") as im1:
 | 
				
			||||||
        with Image.open("Tests/images/hopper-XYZ.png") as im2:
 | 
					        with Image.open("Tests/images/hopper-XYZ.png") as im2:
 | 
				
			||||||
| 
						 | 
					@ -386,7 +386,7 @@ def test_overlay():
 | 
				
			||||||
    assert new.getpixel((15, 100)) == (1, 1, 2)
 | 
					    assert new.getpixel((15, 100)) == (1, 1, 2)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_logical():
 | 
					def test_logical() -> None:
 | 
				
			||||||
    def table(op, a, b):
 | 
					    def table(op, a, b):
 | 
				
			||||||
        out = []
 | 
					        out = []
 | 
				
			||||||
        for x in (a, b):
 | 
					        for x in (a, b):
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -5,6 +5,7 @@ import os
 | 
				
			||||||
import re
 | 
					import re
 | 
				
			||||||
import shutil
 | 
					import shutil
 | 
				
			||||||
from io import BytesIO
 | 
					from io import BytesIO
 | 
				
			||||||
 | 
					from pathlib import Path
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import pytest
 | 
					import pytest
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -32,7 +33,7 @@ SRGB = "Tests/icc/sRGB_IEC61966-2-1_black_scaled.icc"
 | 
				
			||||||
HAVE_PROFILE = os.path.exists(SRGB)
 | 
					HAVE_PROFILE = os.path.exists(SRGB)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def setup_module():
 | 
					def setup_module() -> None:
 | 
				
			||||||
    try:
 | 
					    try:
 | 
				
			||||||
        from PIL import ImageCms
 | 
					        from PIL import ImageCms
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -42,12 +43,12 @@ def setup_module():
 | 
				
			||||||
        pytest.skip(str(v))
 | 
					        pytest.skip(str(v))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def skip_missing():
 | 
					def skip_missing() -> None:
 | 
				
			||||||
    if not HAVE_PROFILE:
 | 
					    if not HAVE_PROFILE:
 | 
				
			||||||
        pytest.skip("SRGB profile not available")
 | 
					        pytest.skip("SRGB profile not available")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_sanity():
 | 
					def test_sanity() -> None:
 | 
				
			||||||
    # basic smoke test.
 | 
					    # basic smoke test.
 | 
				
			||||||
    # this mostly follows the cms_test outline.
 | 
					    # this mostly follows the cms_test outline.
 | 
				
			||||||
    with pytest.warns(DeprecationWarning):
 | 
					    with pytest.warns(DeprecationWarning):
 | 
				
			||||||
| 
						 | 
					@ -91,7 +92,7 @@ def test_sanity():
 | 
				
			||||||
    hopper().point(t)
 | 
					    hopper().point(t)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_flags():
 | 
					def test_flags() -> None:
 | 
				
			||||||
    assert ImageCms.Flags.NONE == 0
 | 
					    assert ImageCms.Flags.NONE == 0
 | 
				
			||||||
    assert ImageCms.Flags.GRIDPOINTS(0) == ImageCms.Flags.NONE
 | 
					    assert ImageCms.Flags.GRIDPOINTS(0) == ImageCms.Flags.NONE
 | 
				
			||||||
    assert ImageCms.Flags.GRIDPOINTS(256) == ImageCms.Flags.NONE
 | 
					    assert ImageCms.Flags.GRIDPOINTS(256) == ImageCms.Flags.NONE
 | 
				
			||||||
| 
						 | 
					@ -101,7 +102,7 @@ def test_flags():
 | 
				
			||||||
    assert ImageCms.Flags.GRIDPOINTS(511) == ImageCms.Flags.GRIDPOINTS(255)
 | 
					    assert ImageCms.Flags.GRIDPOINTS(511) == ImageCms.Flags.GRIDPOINTS(255)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_name():
 | 
					def test_name() -> None:
 | 
				
			||||||
    skip_missing()
 | 
					    skip_missing()
 | 
				
			||||||
    # get profile information for file
 | 
					    # get profile information for file
 | 
				
			||||||
    assert (
 | 
					    assert (
 | 
				
			||||||
| 
						 | 
					@ -110,7 +111,7 @@ def test_name():
 | 
				
			||||||
    )
 | 
					    )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_info():
 | 
					def test_info() -> None:
 | 
				
			||||||
    skip_missing()
 | 
					    skip_missing()
 | 
				
			||||||
    assert ImageCms.getProfileInfo(SRGB).splitlines() == [
 | 
					    assert ImageCms.getProfileInfo(SRGB).splitlines() == [
 | 
				
			||||||
        "sRGB IEC61966-2-1 black scaled",
 | 
					        "sRGB IEC61966-2-1 black scaled",
 | 
				
			||||||
| 
						 | 
					@ -120,7 +121,7 @@ def test_info():
 | 
				
			||||||
    ]
 | 
					    ]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_copyright():
 | 
					def test_copyright() -> None:
 | 
				
			||||||
    skip_missing()
 | 
					    skip_missing()
 | 
				
			||||||
    assert (
 | 
					    assert (
 | 
				
			||||||
        ImageCms.getProfileCopyright(SRGB).strip()
 | 
					        ImageCms.getProfileCopyright(SRGB).strip()
 | 
				
			||||||
| 
						 | 
					@ -128,12 +129,12 @@ def test_copyright():
 | 
				
			||||||
    )
 | 
					    )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_manufacturer():
 | 
					def test_manufacturer() -> None:
 | 
				
			||||||
    skip_missing()
 | 
					    skip_missing()
 | 
				
			||||||
    assert ImageCms.getProfileManufacturer(SRGB).strip() == ""
 | 
					    assert ImageCms.getProfileManufacturer(SRGB).strip() == ""
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_model():
 | 
					def test_model() -> None:
 | 
				
			||||||
    skip_missing()
 | 
					    skip_missing()
 | 
				
			||||||
    assert (
 | 
					    assert (
 | 
				
			||||||
        ImageCms.getProfileModel(SRGB).strip()
 | 
					        ImageCms.getProfileModel(SRGB).strip()
 | 
				
			||||||
| 
						 | 
					@ -141,14 +142,14 @@ def test_model():
 | 
				
			||||||
    )
 | 
					    )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_description():
 | 
					def test_description() -> None:
 | 
				
			||||||
    skip_missing()
 | 
					    skip_missing()
 | 
				
			||||||
    assert (
 | 
					    assert (
 | 
				
			||||||
        ImageCms.getProfileDescription(SRGB).strip() == "sRGB IEC61966-2-1 black scaled"
 | 
					        ImageCms.getProfileDescription(SRGB).strip() == "sRGB IEC61966-2-1 black scaled"
 | 
				
			||||||
    )
 | 
					    )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_intent():
 | 
					def test_intent() -> None:
 | 
				
			||||||
    skip_missing()
 | 
					    skip_missing()
 | 
				
			||||||
    assert ImageCms.getDefaultIntent(SRGB) == 0
 | 
					    assert ImageCms.getDefaultIntent(SRGB) == 0
 | 
				
			||||||
    support = ImageCms.isIntentSupported(
 | 
					    support = ImageCms.isIntentSupported(
 | 
				
			||||||
| 
						 | 
					@ -157,7 +158,7 @@ def test_intent():
 | 
				
			||||||
    assert support == 1
 | 
					    assert support == 1
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_profile_object():
 | 
					def test_profile_object() -> None:
 | 
				
			||||||
    # same, using profile object
 | 
					    # same, using profile object
 | 
				
			||||||
    p = ImageCms.createProfile("sRGB")
 | 
					    p = ImageCms.createProfile("sRGB")
 | 
				
			||||||
    # assert ImageCms.getProfileName(p).strip() == "sRGB built-in - (lcms internal)"
 | 
					    # assert ImageCms.getProfileName(p).strip() == "sRGB built-in - (lcms internal)"
 | 
				
			||||||
| 
						 | 
					@ -170,7 +171,7 @@ def test_profile_object():
 | 
				
			||||||
    assert support == 1
 | 
					    assert support == 1
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_extensions():
 | 
					def test_extensions() -> None:
 | 
				
			||||||
    # extensions
 | 
					    # extensions
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    with Image.open("Tests/images/rgb.jpg") as i:
 | 
					    with Image.open("Tests/images/rgb.jpg") as i:
 | 
				
			||||||
| 
						 | 
					@ -181,7 +182,7 @@ def test_extensions():
 | 
				
			||||||
    )
 | 
					    )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_exceptions():
 | 
					def test_exceptions() -> None:
 | 
				
			||||||
    # Test mode mismatch
 | 
					    # Test mode mismatch
 | 
				
			||||||
    psRGB = ImageCms.createProfile("sRGB")
 | 
					    psRGB = ImageCms.createProfile("sRGB")
 | 
				
			||||||
    pLab = ImageCms.createProfile("LAB")
 | 
					    pLab = ImageCms.createProfile("LAB")
 | 
				
			||||||
| 
						 | 
					@ -207,17 +208,17 @@ def test_exceptions():
 | 
				
			||||||
        ImageCms.isIntentSupported(SRGB, None, None)
 | 
					        ImageCms.isIntentSupported(SRGB, None, None)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_display_profile():
 | 
					def test_display_profile() -> None:
 | 
				
			||||||
    # try fetching the profile for the current display device
 | 
					    # try fetching the profile for the current display device
 | 
				
			||||||
    ImageCms.get_display_profile()
 | 
					    ImageCms.get_display_profile()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_lab_color_profile():
 | 
					def test_lab_color_profile() -> None:
 | 
				
			||||||
    ImageCms.createProfile("LAB", 5000)
 | 
					    ImageCms.createProfile("LAB", 5000)
 | 
				
			||||||
    ImageCms.createProfile("LAB", 6500)
 | 
					    ImageCms.createProfile("LAB", 6500)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_unsupported_color_space():
 | 
					def test_unsupported_color_space() -> None:
 | 
				
			||||||
    with pytest.raises(
 | 
					    with pytest.raises(
 | 
				
			||||||
        ImageCms.PyCMSError,
 | 
					        ImageCms.PyCMSError,
 | 
				
			||||||
        match=re.escape(
 | 
					        match=re.escape(
 | 
				
			||||||
| 
						 | 
					@ -227,7 +228,7 @@ def test_unsupported_color_space():
 | 
				
			||||||
        ImageCms.createProfile("unsupported")
 | 
					        ImageCms.createProfile("unsupported")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_invalid_color_temperature():
 | 
					def test_invalid_color_temperature() -> None:
 | 
				
			||||||
    with pytest.raises(
 | 
					    with pytest.raises(
 | 
				
			||||||
        ImageCms.PyCMSError,
 | 
					        ImageCms.PyCMSError,
 | 
				
			||||||
        match='Color temperature must be numeric, "invalid" not valid',
 | 
					        match='Color temperature must be numeric, "invalid" not valid',
 | 
				
			||||||
| 
						 | 
					@ -236,7 +237,7 @@ def test_invalid_color_temperature():
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@pytest.mark.parametrize("flag", ("my string", -1))
 | 
					@pytest.mark.parametrize("flag", ("my string", -1))
 | 
				
			||||||
def test_invalid_flag(flag):
 | 
					def test_invalid_flag(flag) -> None:
 | 
				
			||||||
    with hopper() as im:
 | 
					    with hopper() as im:
 | 
				
			||||||
        with pytest.raises(
 | 
					        with pytest.raises(
 | 
				
			||||||
            ImageCms.PyCMSError, match="flags must be an integer between 0 and "
 | 
					            ImageCms.PyCMSError, match="flags must be an integer between 0 and "
 | 
				
			||||||
| 
						 | 
					@ -244,7 +245,7 @@ def test_invalid_flag(flag):
 | 
				
			||||||
            ImageCms.profileToProfile(im, "foo", "bar", flags=flag)
 | 
					            ImageCms.profileToProfile(im, "foo", "bar", flags=flag)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_simple_lab():
 | 
					def test_simple_lab() -> None:
 | 
				
			||||||
    i = Image.new("RGB", (10, 10), (128, 128, 128))
 | 
					    i = Image.new("RGB", (10, 10), (128, 128, 128))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    psRGB = ImageCms.createProfile("sRGB")
 | 
					    psRGB = ImageCms.createProfile("sRGB")
 | 
				
			||||||
| 
						 | 
					@ -268,7 +269,7 @@ def test_simple_lab():
 | 
				
			||||||
    assert list(b_data) == [128] * 100
 | 
					    assert list(b_data) == [128] * 100
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_lab_color():
 | 
					def test_lab_color() -> None:
 | 
				
			||||||
    psRGB = ImageCms.createProfile("sRGB")
 | 
					    psRGB = ImageCms.createProfile("sRGB")
 | 
				
			||||||
    pLab = ImageCms.createProfile("LAB")
 | 
					    pLab = ImageCms.createProfile("LAB")
 | 
				
			||||||
    t = ImageCms.buildTransform(psRGB, pLab, "RGB", "LAB")
 | 
					    t = ImageCms.buildTransform(psRGB, pLab, "RGB", "LAB")
 | 
				
			||||||
| 
						 | 
					@ -283,7 +284,7 @@ def test_lab_color():
 | 
				
			||||||
    assert_image_similar_tofile(i, "Tests/images/hopper.Lab.tif", 3.5)
 | 
					    assert_image_similar_tofile(i, "Tests/images/hopper.Lab.tif", 3.5)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_lab_srgb():
 | 
					def test_lab_srgb() -> None:
 | 
				
			||||||
    psRGB = ImageCms.createProfile("sRGB")
 | 
					    psRGB = ImageCms.createProfile("sRGB")
 | 
				
			||||||
    pLab = ImageCms.createProfile("LAB")
 | 
					    pLab = ImageCms.createProfile("LAB")
 | 
				
			||||||
    t = ImageCms.buildTransform(pLab, psRGB, "LAB", "RGB")
 | 
					    t = ImageCms.buildTransform(pLab, psRGB, "LAB", "RGB")
 | 
				
			||||||
| 
						 | 
					@ -300,7 +301,7 @@ def test_lab_srgb():
 | 
				
			||||||
    assert "sRGB" in ImageCms.getProfileDescription(profile)
 | 
					    assert "sRGB" in ImageCms.getProfileDescription(profile)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_lab_roundtrip():
 | 
					def test_lab_roundtrip() -> None:
 | 
				
			||||||
    # check to see if we're at least internally consistent.
 | 
					    # check to see if we're at least internally consistent.
 | 
				
			||||||
    psRGB = ImageCms.createProfile("sRGB")
 | 
					    psRGB = ImageCms.createProfile("sRGB")
 | 
				
			||||||
    pLab = ImageCms.createProfile("LAB")
 | 
					    pLab = ImageCms.createProfile("LAB")
 | 
				
			||||||
| 
						 | 
					@ -317,7 +318,7 @@ def test_lab_roundtrip():
 | 
				
			||||||
    assert_image_similar(hopper(), out, 2)
 | 
					    assert_image_similar(hopper(), out, 2)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_profile_tobytes():
 | 
					def test_profile_tobytes() -> None:
 | 
				
			||||||
    with Image.open("Tests/images/rgb.jpg") as i:
 | 
					    with Image.open("Tests/images/rgb.jpg") as i:
 | 
				
			||||||
        p = ImageCms.getOpenProfile(BytesIO(i.info["icc_profile"]))
 | 
					        p = ImageCms.getOpenProfile(BytesIO(i.info["icc_profile"]))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -329,12 +330,12 @@ def test_profile_tobytes():
 | 
				
			||||||
    assert ImageCms.getProfileDescription(p) == ImageCms.getProfileDescription(p2)
 | 
					    assert ImageCms.getProfileDescription(p) == ImageCms.getProfileDescription(p2)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_extended_information():
 | 
					def test_extended_information() -> None:
 | 
				
			||||||
    skip_missing()
 | 
					    skip_missing()
 | 
				
			||||||
    o = ImageCms.getOpenProfile(SRGB)
 | 
					    o = ImageCms.getOpenProfile(SRGB)
 | 
				
			||||||
    p = o.profile
 | 
					    p = o.profile
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def assert_truncated_tuple_equal(tup1, tup2, digits=10):
 | 
					    def assert_truncated_tuple_equal(tup1, tup2, digits: int = 10) -> None:
 | 
				
			||||||
        # Helper function to reduce precision of tuples of floats
 | 
					        # Helper function to reduce precision of tuples of floats
 | 
				
			||||||
        # recursively and then check equality.
 | 
					        # recursively and then check equality.
 | 
				
			||||||
        power = 10**digits
 | 
					        power = 10**digits
 | 
				
			||||||
| 
						 | 
					@ -476,7 +477,7 @@ def test_extended_information():
 | 
				
			||||||
    assert p.xcolor_space == "RGB "
 | 
					    assert p.xcolor_space == "RGB "
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_non_ascii_path(tmp_path):
 | 
					def test_non_ascii_path(tmp_path: Path) -> None:
 | 
				
			||||||
    skip_missing()
 | 
					    skip_missing()
 | 
				
			||||||
    tempfile = str(tmp_path / ("temp_" + chr(128) + ".icc"))
 | 
					    tempfile = str(tmp_path / ("temp_" + chr(128) + ".icc"))
 | 
				
			||||||
    try:
 | 
					    try:
 | 
				
			||||||
| 
						 | 
					@ -489,7 +490,7 @@ def test_non_ascii_path(tmp_path):
 | 
				
			||||||
    assert p.model == "IEC 61966-2-1 Default RGB Colour Space - sRGB"
 | 
					    assert p.model == "IEC 61966-2-1 Default RGB Colour Space - sRGB"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_profile_typesafety():
 | 
					def test_profile_typesafety() -> None:
 | 
				
			||||||
    """Profile init type safety
 | 
					    """Profile init type safety
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    prepatch, these would segfault, postpatch they should emit a typeerror
 | 
					    prepatch, these would segfault, postpatch they should emit a typeerror
 | 
				
			||||||
| 
						 | 
					@ -501,7 +502,7 @@ def test_profile_typesafety():
 | 
				
			||||||
        ImageCms.ImageCmsProfile(1).tobytes()
 | 
					        ImageCms.ImageCmsProfile(1).tobytes()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def assert_aux_channel_preserved(mode, transform_in_place, preserved_channel):
 | 
					def assert_aux_channel_preserved(mode, transform_in_place, preserved_channel) -> None:
 | 
				
			||||||
    def create_test_image():
 | 
					    def create_test_image():
 | 
				
			||||||
        # set up test image with something interesting in the tested aux channel.
 | 
					        # set up test image with something interesting in the tested aux channel.
 | 
				
			||||||
        # fmt: off
 | 
					        # fmt: off
 | 
				
			||||||
| 
						 | 
					@ -556,31 +557,31 @@ def assert_aux_channel_preserved(mode, transform_in_place, preserved_channel):
 | 
				
			||||||
    assert_image_equal(source_image_aux, result_image_aux)
 | 
					    assert_image_equal(source_image_aux, result_image_aux)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_preserve_auxiliary_channels_rgba():
 | 
					def test_preserve_auxiliary_channels_rgba() -> None:
 | 
				
			||||||
    assert_aux_channel_preserved(
 | 
					    assert_aux_channel_preserved(
 | 
				
			||||||
        mode="RGBA", transform_in_place=False, preserved_channel="A"
 | 
					        mode="RGBA", transform_in_place=False, preserved_channel="A"
 | 
				
			||||||
    )
 | 
					    )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_preserve_auxiliary_channels_rgba_in_place():
 | 
					def test_preserve_auxiliary_channels_rgba_in_place() -> None:
 | 
				
			||||||
    assert_aux_channel_preserved(
 | 
					    assert_aux_channel_preserved(
 | 
				
			||||||
        mode="RGBA", transform_in_place=True, preserved_channel="A"
 | 
					        mode="RGBA", transform_in_place=True, preserved_channel="A"
 | 
				
			||||||
    )
 | 
					    )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_preserve_auxiliary_channels_rgbx():
 | 
					def test_preserve_auxiliary_channels_rgbx() -> None:
 | 
				
			||||||
    assert_aux_channel_preserved(
 | 
					    assert_aux_channel_preserved(
 | 
				
			||||||
        mode="RGBX", transform_in_place=False, preserved_channel="X"
 | 
					        mode="RGBX", transform_in_place=False, preserved_channel="X"
 | 
				
			||||||
    )
 | 
					    )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_preserve_auxiliary_channels_rgbx_in_place():
 | 
					def test_preserve_auxiliary_channels_rgbx_in_place() -> None:
 | 
				
			||||||
    assert_aux_channel_preserved(
 | 
					    assert_aux_channel_preserved(
 | 
				
			||||||
        mode="RGBX", transform_in_place=True, preserved_channel="X"
 | 
					        mode="RGBX", transform_in_place=True, preserved_channel="X"
 | 
				
			||||||
    )
 | 
					    )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_auxiliary_channels_isolated():
 | 
					def test_auxiliary_channels_isolated() -> None:
 | 
				
			||||||
    # test data in aux channels does not affect non-aux channels
 | 
					    # test data in aux channels does not affect non-aux channels
 | 
				
			||||||
    aux_channel_formats = [
 | 
					    aux_channel_formats = [
 | 
				
			||||||
        # format, profile, color-only format, source test image
 | 
					        # format, profile, color-only format, source test image
 | 
				
			||||||
| 
						 | 
					@ -630,7 +631,7 @@ def test_auxiliary_channels_isolated():
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@pytest.mark.parametrize("mode", ("RGB", "RGBA", "RGBX"))
 | 
					@pytest.mark.parametrize("mode", ("RGB", "RGBA", "RGBX"))
 | 
				
			||||||
def test_rgb_lab(mode):
 | 
					def test_rgb_lab(mode) -> None:
 | 
				
			||||||
    im = Image.new(mode, (1, 1))
 | 
					    im = Image.new(mode, (1, 1))
 | 
				
			||||||
    converted_im = im.convert("LAB")
 | 
					    converted_im = im.convert("LAB")
 | 
				
			||||||
    assert converted_im.getpixel((0, 0)) == (0, 128, 128)
 | 
					    assert converted_im.getpixel((0, 0)) == (0, 128, 128)
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -5,7 +5,7 @@ import pytest
 | 
				
			||||||
from PIL import Image, ImageColor
 | 
					from PIL import Image, ImageColor
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_hash():
 | 
					def test_hash() -> None:
 | 
				
			||||||
    # short 3 components
 | 
					    # short 3 components
 | 
				
			||||||
    assert (255, 0, 0) == ImageColor.getrgb("#f00")
 | 
					    assert (255, 0, 0) == ImageColor.getrgb("#f00")
 | 
				
			||||||
    assert (0, 255, 0) == ImageColor.getrgb("#0f0")
 | 
					    assert (0, 255, 0) == ImageColor.getrgb("#0f0")
 | 
				
			||||||
| 
						 | 
					@ -57,7 +57,7 @@ def test_hash():
 | 
				
			||||||
        ImageColor.getrgb("#f00000 ")
 | 
					        ImageColor.getrgb("#f00000 ")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_colormap():
 | 
					def test_colormap() -> None:
 | 
				
			||||||
    assert (0, 0, 0) == ImageColor.getrgb("black")
 | 
					    assert (0, 0, 0) == ImageColor.getrgb("black")
 | 
				
			||||||
    assert (255, 255, 255) == ImageColor.getrgb("white")
 | 
					    assert (255, 255, 255) == ImageColor.getrgb("white")
 | 
				
			||||||
    assert (255, 255, 255) == ImageColor.getrgb("WHITE")
 | 
					    assert (255, 255, 255) == ImageColor.getrgb("WHITE")
 | 
				
			||||||
| 
						 | 
					@ -66,7 +66,7 @@ def test_colormap():
 | 
				
			||||||
        ImageColor.getrgb("black ")
 | 
					        ImageColor.getrgb("black ")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_functions():
 | 
					def test_functions() -> None:
 | 
				
			||||||
    # rgb numbers
 | 
					    # rgb numbers
 | 
				
			||||||
    assert (255, 0, 0) == ImageColor.getrgb("rgb(255,0,0)")
 | 
					    assert (255, 0, 0) == ImageColor.getrgb("rgb(255,0,0)")
 | 
				
			||||||
    assert (0, 255, 0) == ImageColor.getrgb("rgb(0,255,0)")
 | 
					    assert (0, 255, 0) == ImageColor.getrgb("rgb(0,255,0)")
 | 
				
			||||||
| 
						 | 
					@ -160,7 +160,7 @@ def test_functions():
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# look for rounding errors (based on code by Tim Hatch)
 | 
					# look for rounding errors (based on code by Tim Hatch)
 | 
				
			||||||
def test_rounding_errors():
 | 
					def test_rounding_errors() -> None:
 | 
				
			||||||
    for color in ImageColor.colormap:
 | 
					    for color in ImageColor.colormap:
 | 
				
			||||||
        expected = Image.new("RGB", (1, 1), color).convert("L").getpixel((0, 0))
 | 
					        expected = Image.new("RGB", (1, 1), color).convert("L").getpixel((0, 0))
 | 
				
			||||||
        actual = ImageColor.getcolor(color, "L")
 | 
					        actual = ImageColor.getcolor(color, "L")
 | 
				
			||||||
| 
						 | 
					@ -195,11 +195,11 @@ def test_rounding_errors():
 | 
				
			||||||
    Image.new("LA", (1, 1), "white")
 | 
					    Image.new("LA", (1, 1), "white")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_color_hsv():
 | 
					def test_color_hsv() -> None:
 | 
				
			||||||
    assert (170, 255, 255) == ImageColor.getcolor("hsv(240, 100%, 100%)", "HSV")
 | 
					    assert (170, 255, 255) == ImageColor.getcolor("hsv(240, 100%, 100%)", "HSV")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_color_too_long():
 | 
					def test_color_too_long() -> None:
 | 
				
			||||||
    # Arrange
 | 
					    # Arrange
 | 
				
			||||||
    color_too_long = "hsl(" + "1" * 40 + "," + "1" * 40 + "%," + "1" * 40 + "%)"
 | 
					    color_too_long = "hsl(" + "1" * 40 + "," + "1" * 40 + "%," + "1" * 40 + "%)"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -47,7 +47,7 @@ KITE_POINTS = (
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_sanity():
 | 
					def test_sanity() -> None:
 | 
				
			||||||
    im = hopper("RGB").copy()
 | 
					    im = hopper("RGB").copy()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    draw = ImageDraw.ImageDraw(im)
 | 
					    draw = ImageDraw.ImageDraw(im)
 | 
				
			||||||
| 
						 | 
					@ -59,13 +59,13 @@ def test_sanity():
 | 
				
			||||||
    draw.rectangle(list(range(4)))
 | 
					    draw.rectangle(list(range(4)))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_valueerror():
 | 
					def test_valueerror() -> None:
 | 
				
			||||||
    with Image.open("Tests/images/chi.gif") as im:
 | 
					    with Image.open("Tests/images/chi.gif") as im:
 | 
				
			||||||
        draw = ImageDraw.Draw(im)
 | 
					        draw = ImageDraw.Draw(im)
 | 
				
			||||||
        draw.line((0, 0), fill=(0, 0, 0))
 | 
					        draw.line((0, 0), fill=(0, 0, 0))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_mode_mismatch():
 | 
					def test_mode_mismatch() -> None:
 | 
				
			||||||
    im = hopper("RGB").copy()
 | 
					    im = hopper("RGB").copy()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    with pytest.raises(ValueError):
 | 
					    with pytest.raises(ValueError):
 | 
				
			||||||
| 
						 | 
					@ -74,7 +74,7 @@ def test_mode_mismatch():
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@pytest.mark.parametrize("bbox", BBOX)
 | 
					@pytest.mark.parametrize("bbox", BBOX)
 | 
				
			||||||
@pytest.mark.parametrize("start, end", ((0, 180), (0.5, 180.4)))
 | 
					@pytest.mark.parametrize("start, end", ((0, 180), (0.5, 180.4)))
 | 
				
			||||||
def test_arc(bbox, start, end):
 | 
					def test_arc(bbox, start, end) -> None:
 | 
				
			||||||
    # Arrange
 | 
					    # Arrange
 | 
				
			||||||
    im = Image.new("RGB", (W, H))
 | 
					    im = Image.new("RGB", (W, H))
 | 
				
			||||||
    draw = ImageDraw.Draw(im)
 | 
					    draw = ImageDraw.Draw(im)
 | 
				
			||||||
| 
						 | 
					@ -87,7 +87,7 @@ def test_arc(bbox, start, end):
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@pytest.mark.parametrize("bbox", BBOX)
 | 
					@pytest.mark.parametrize("bbox", BBOX)
 | 
				
			||||||
def test_arc_end_le_start(bbox):
 | 
					def test_arc_end_le_start(bbox) -> None:
 | 
				
			||||||
    # Arrange
 | 
					    # Arrange
 | 
				
			||||||
    im = Image.new("RGB", (W, H))
 | 
					    im = Image.new("RGB", (W, H))
 | 
				
			||||||
    draw = ImageDraw.Draw(im)
 | 
					    draw = ImageDraw.Draw(im)
 | 
				
			||||||
| 
						 | 
					@ -102,7 +102,7 @@ def test_arc_end_le_start(bbox):
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@pytest.mark.parametrize("bbox", BBOX)
 | 
					@pytest.mark.parametrize("bbox", BBOX)
 | 
				
			||||||
def test_arc_no_loops(bbox):
 | 
					def test_arc_no_loops(bbox) -> None:
 | 
				
			||||||
    # No need to go in loops
 | 
					    # No need to go in loops
 | 
				
			||||||
    # Arrange
 | 
					    # Arrange
 | 
				
			||||||
    im = Image.new("RGB", (W, H))
 | 
					    im = Image.new("RGB", (W, H))
 | 
				
			||||||
| 
						 | 
					@ -118,7 +118,7 @@ def test_arc_no_loops(bbox):
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@pytest.mark.parametrize("bbox", BBOX)
 | 
					@pytest.mark.parametrize("bbox", BBOX)
 | 
				
			||||||
def test_arc_width(bbox):
 | 
					def test_arc_width(bbox) -> None:
 | 
				
			||||||
    # Arrange
 | 
					    # Arrange
 | 
				
			||||||
    im = Image.new("RGB", (W, H))
 | 
					    im = Image.new("RGB", (W, H))
 | 
				
			||||||
    draw = ImageDraw.Draw(im)
 | 
					    draw = ImageDraw.Draw(im)
 | 
				
			||||||
| 
						 | 
					@ -131,7 +131,7 @@ def test_arc_width(bbox):
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@pytest.mark.parametrize("bbox", BBOX)
 | 
					@pytest.mark.parametrize("bbox", BBOX)
 | 
				
			||||||
def test_arc_width_pieslice_large(bbox):
 | 
					def test_arc_width_pieslice_large(bbox) -> None:
 | 
				
			||||||
    # Tests an arc with a large enough width that it is a pieslice
 | 
					    # Tests an arc with a large enough width that it is a pieslice
 | 
				
			||||||
    # Arrange
 | 
					    # Arrange
 | 
				
			||||||
    im = Image.new("RGB", (W, H))
 | 
					    im = Image.new("RGB", (W, H))
 | 
				
			||||||
| 
						 | 
					@ -145,7 +145,7 @@ def test_arc_width_pieslice_large(bbox):
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@pytest.mark.parametrize("bbox", BBOX)
 | 
					@pytest.mark.parametrize("bbox", BBOX)
 | 
				
			||||||
def test_arc_width_fill(bbox):
 | 
					def test_arc_width_fill(bbox) -> None:
 | 
				
			||||||
    # Arrange
 | 
					    # Arrange
 | 
				
			||||||
    im = Image.new("RGB", (W, H))
 | 
					    im = Image.new("RGB", (W, H))
 | 
				
			||||||
    draw = ImageDraw.Draw(im)
 | 
					    draw = ImageDraw.Draw(im)
 | 
				
			||||||
| 
						 | 
					@ -158,7 +158,7 @@ def test_arc_width_fill(bbox):
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@pytest.mark.parametrize("bbox", BBOX)
 | 
					@pytest.mark.parametrize("bbox", BBOX)
 | 
				
			||||||
def test_arc_width_non_whole_angle(bbox):
 | 
					def test_arc_width_non_whole_angle(bbox) -> None:
 | 
				
			||||||
    # Arrange
 | 
					    # Arrange
 | 
				
			||||||
    im = Image.new("RGB", (W, H))
 | 
					    im = Image.new("RGB", (W, H))
 | 
				
			||||||
    draw = ImageDraw.Draw(im)
 | 
					    draw = ImageDraw.Draw(im)
 | 
				
			||||||
| 
						 | 
					@ -171,7 +171,7 @@ def test_arc_width_non_whole_angle(bbox):
 | 
				
			||||||
    assert_image_similar_tofile(im, expected, 1)
 | 
					    assert_image_similar_tofile(im, expected, 1)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_arc_high():
 | 
					def test_arc_high() -> None:
 | 
				
			||||||
    # Arrange
 | 
					    # Arrange
 | 
				
			||||||
    im = Image.new("RGB", (200, 200))
 | 
					    im = Image.new("RGB", (200, 200))
 | 
				
			||||||
    draw = ImageDraw.Draw(im)
 | 
					    draw = ImageDraw.Draw(im)
 | 
				
			||||||
| 
						 | 
					@ -184,7 +184,7 @@ def test_arc_high():
 | 
				
			||||||
    assert_image_equal_tofile(im, "Tests/images/imagedraw_arc_high.png")
 | 
					    assert_image_equal_tofile(im, "Tests/images/imagedraw_arc_high.png")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_bitmap():
 | 
					def test_bitmap() -> None:
 | 
				
			||||||
    # Arrange
 | 
					    # Arrange
 | 
				
			||||||
    im = Image.new("RGB", (W, H))
 | 
					    im = Image.new("RGB", (W, H))
 | 
				
			||||||
    draw = ImageDraw.Draw(im)
 | 
					    draw = ImageDraw.Draw(im)
 | 
				
			||||||
| 
						 | 
					@ -200,7 +200,7 @@ def test_bitmap():
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@pytest.mark.parametrize("mode", ("RGB", "L"))
 | 
					@pytest.mark.parametrize("mode", ("RGB", "L"))
 | 
				
			||||||
@pytest.mark.parametrize("bbox", BBOX)
 | 
					@pytest.mark.parametrize("bbox", BBOX)
 | 
				
			||||||
def test_chord(mode, bbox):
 | 
					def test_chord(mode, bbox) -> None:
 | 
				
			||||||
    # Arrange
 | 
					    # Arrange
 | 
				
			||||||
    im = Image.new(mode, (W, H))
 | 
					    im = Image.new(mode, (W, H))
 | 
				
			||||||
    draw = ImageDraw.Draw(im)
 | 
					    draw = ImageDraw.Draw(im)
 | 
				
			||||||
| 
						 | 
					@ -214,7 +214,7 @@ def test_chord(mode, bbox):
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@pytest.mark.parametrize("bbox", BBOX)
 | 
					@pytest.mark.parametrize("bbox", BBOX)
 | 
				
			||||||
def test_chord_width(bbox):
 | 
					def test_chord_width(bbox) -> None:
 | 
				
			||||||
    # Arrange
 | 
					    # Arrange
 | 
				
			||||||
    im = Image.new("RGB", (W, H))
 | 
					    im = Image.new("RGB", (W, H))
 | 
				
			||||||
    draw = ImageDraw.Draw(im)
 | 
					    draw = ImageDraw.Draw(im)
 | 
				
			||||||
| 
						 | 
					@ -227,7 +227,7 @@ def test_chord_width(bbox):
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@pytest.mark.parametrize("bbox", BBOX)
 | 
					@pytest.mark.parametrize("bbox", BBOX)
 | 
				
			||||||
def test_chord_width_fill(bbox):
 | 
					def test_chord_width_fill(bbox) -> None:
 | 
				
			||||||
    # Arrange
 | 
					    # Arrange
 | 
				
			||||||
    im = Image.new("RGB", (W, H))
 | 
					    im = Image.new("RGB", (W, H))
 | 
				
			||||||
    draw = ImageDraw.Draw(im)
 | 
					    draw = ImageDraw.Draw(im)
 | 
				
			||||||
| 
						 | 
					@ -240,7 +240,7 @@ def test_chord_width_fill(bbox):
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@pytest.mark.parametrize("bbox", BBOX)
 | 
					@pytest.mark.parametrize("bbox", BBOX)
 | 
				
			||||||
def test_chord_zero_width(bbox):
 | 
					def test_chord_zero_width(bbox) -> None:
 | 
				
			||||||
    # Arrange
 | 
					    # Arrange
 | 
				
			||||||
    im = Image.new("RGB", (W, H))
 | 
					    im = Image.new("RGB", (W, H))
 | 
				
			||||||
    draw = ImageDraw.Draw(im)
 | 
					    draw = ImageDraw.Draw(im)
 | 
				
			||||||
| 
						 | 
					@ -252,7 +252,7 @@ def test_chord_zero_width(bbox):
 | 
				
			||||||
    assert_image_equal_tofile(im, "Tests/images/imagedraw_chord_zero_width.png")
 | 
					    assert_image_equal_tofile(im, "Tests/images/imagedraw_chord_zero_width.png")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_chord_too_fat():
 | 
					def test_chord_too_fat() -> None:
 | 
				
			||||||
    # Arrange
 | 
					    # Arrange
 | 
				
			||||||
    im = Image.new("RGB", (100, 100))
 | 
					    im = Image.new("RGB", (100, 100))
 | 
				
			||||||
    draw = ImageDraw.Draw(im)
 | 
					    draw = ImageDraw.Draw(im)
 | 
				
			||||||
| 
						 | 
					@ -266,7 +266,7 @@ def test_chord_too_fat():
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@pytest.mark.parametrize("mode", ("RGB", "L"))
 | 
					@pytest.mark.parametrize("mode", ("RGB", "L"))
 | 
				
			||||||
@pytest.mark.parametrize("bbox", BBOX)
 | 
					@pytest.mark.parametrize("bbox", BBOX)
 | 
				
			||||||
def test_ellipse(mode, bbox):
 | 
					def test_ellipse(mode, bbox) -> None:
 | 
				
			||||||
    # Arrange
 | 
					    # Arrange
 | 
				
			||||||
    im = Image.new(mode, (W, H))
 | 
					    im = Image.new(mode, (W, H))
 | 
				
			||||||
    draw = ImageDraw.Draw(im)
 | 
					    draw = ImageDraw.Draw(im)
 | 
				
			||||||
| 
						 | 
					@ -280,7 +280,7 @@ def test_ellipse(mode, bbox):
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@pytest.mark.parametrize("bbox", BBOX)
 | 
					@pytest.mark.parametrize("bbox", BBOX)
 | 
				
			||||||
def test_ellipse_translucent(bbox):
 | 
					def test_ellipse_translucent(bbox) -> None:
 | 
				
			||||||
    # Arrange
 | 
					    # Arrange
 | 
				
			||||||
    im = Image.new("RGB", (W, H))
 | 
					    im = Image.new("RGB", (W, H))
 | 
				
			||||||
    draw = ImageDraw.Draw(im, "RGBA")
 | 
					    draw = ImageDraw.Draw(im, "RGBA")
 | 
				
			||||||
| 
						 | 
					@ -293,7 +293,7 @@ def test_ellipse_translucent(bbox):
 | 
				
			||||||
    assert_image_similar_tofile(im, expected, 1)
 | 
					    assert_image_similar_tofile(im, expected, 1)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_ellipse_edge():
 | 
					def test_ellipse_edge() -> None:
 | 
				
			||||||
    # Arrange
 | 
					    # Arrange
 | 
				
			||||||
    im = Image.new("RGB", (W, H))
 | 
					    im = Image.new("RGB", (W, H))
 | 
				
			||||||
    draw = ImageDraw.Draw(im)
 | 
					    draw = ImageDraw.Draw(im)
 | 
				
			||||||
| 
						 | 
					@ -305,7 +305,7 @@ def test_ellipse_edge():
 | 
				
			||||||
    assert_image_similar_tofile(im, "Tests/images/imagedraw_ellipse_edge.png", 1)
 | 
					    assert_image_similar_tofile(im, "Tests/images/imagedraw_ellipse_edge.png", 1)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_ellipse_symmetric():
 | 
					def test_ellipse_symmetric() -> None:
 | 
				
			||||||
    for width, bbox in (
 | 
					    for width, bbox in (
 | 
				
			||||||
        (100, (24, 24, 75, 75)),
 | 
					        (100, (24, 24, 75, 75)),
 | 
				
			||||||
        (101, (25, 25, 75, 75)),
 | 
					        (101, (25, 25, 75, 75)),
 | 
				
			||||||
| 
						 | 
					@ -317,7 +317,7 @@ def test_ellipse_symmetric():
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@pytest.mark.parametrize("bbox", BBOX)
 | 
					@pytest.mark.parametrize("bbox", BBOX)
 | 
				
			||||||
def test_ellipse_width(bbox):
 | 
					def test_ellipse_width(bbox) -> None:
 | 
				
			||||||
    # Arrange
 | 
					    # Arrange
 | 
				
			||||||
    im = Image.new("RGB", (W, H))
 | 
					    im = Image.new("RGB", (W, H))
 | 
				
			||||||
    draw = ImageDraw.Draw(im)
 | 
					    draw = ImageDraw.Draw(im)
 | 
				
			||||||
| 
						 | 
					@ -329,7 +329,7 @@ def test_ellipse_width(bbox):
 | 
				
			||||||
    assert_image_similar_tofile(im, "Tests/images/imagedraw_ellipse_width.png", 1)
 | 
					    assert_image_similar_tofile(im, "Tests/images/imagedraw_ellipse_width.png", 1)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_ellipse_width_large():
 | 
					def test_ellipse_width_large() -> None:
 | 
				
			||||||
    # Arrange
 | 
					    # Arrange
 | 
				
			||||||
    im = Image.new("RGB", (500, 500))
 | 
					    im = Image.new("RGB", (500, 500))
 | 
				
			||||||
    draw = ImageDraw.Draw(im)
 | 
					    draw = ImageDraw.Draw(im)
 | 
				
			||||||
| 
						 | 
					@ -342,7 +342,7 @@ def test_ellipse_width_large():
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@pytest.mark.parametrize("bbox", BBOX)
 | 
					@pytest.mark.parametrize("bbox", BBOX)
 | 
				
			||||||
def test_ellipse_width_fill(bbox):
 | 
					def test_ellipse_width_fill(bbox) -> None:
 | 
				
			||||||
    # Arrange
 | 
					    # Arrange
 | 
				
			||||||
    im = Image.new("RGB", (W, H))
 | 
					    im = Image.new("RGB", (W, H))
 | 
				
			||||||
    draw = ImageDraw.Draw(im)
 | 
					    draw = ImageDraw.Draw(im)
 | 
				
			||||||
| 
						 | 
					@ -355,7 +355,7 @@ def test_ellipse_width_fill(bbox):
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@pytest.mark.parametrize("bbox", BBOX)
 | 
					@pytest.mark.parametrize("bbox", BBOX)
 | 
				
			||||||
def test_ellipse_zero_width(bbox):
 | 
					def test_ellipse_zero_width(bbox) -> None:
 | 
				
			||||||
    # Arrange
 | 
					    # Arrange
 | 
				
			||||||
    im = Image.new("RGB", (W, H))
 | 
					    im = Image.new("RGB", (W, H))
 | 
				
			||||||
    draw = ImageDraw.Draw(im)
 | 
					    draw = ImageDraw.Draw(im)
 | 
				
			||||||
| 
						 | 
					@ -394,13 +394,13 @@ def ellipse_various_sizes_helper(filled):
 | 
				
			||||||
    return im
 | 
					    return im
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_ellipse_various_sizes():
 | 
					def test_ellipse_various_sizes() -> None:
 | 
				
			||||||
    im = ellipse_various_sizes_helper(False)
 | 
					    im = ellipse_various_sizes_helper(False)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    assert_image_equal_tofile(im, "Tests/images/imagedraw_ellipse_various_sizes.png")
 | 
					    assert_image_equal_tofile(im, "Tests/images/imagedraw_ellipse_various_sizes.png")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_ellipse_various_sizes_filled():
 | 
					def test_ellipse_various_sizes_filled() -> None:
 | 
				
			||||||
    im = ellipse_various_sizes_helper(True)
 | 
					    im = ellipse_various_sizes_helper(True)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    assert_image_equal_tofile(
 | 
					    assert_image_equal_tofile(
 | 
				
			||||||
| 
						 | 
					@ -409,7 +409,7 @@ def test_ellipse_various_sizes_filled():
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@pytest.mark.parametrize("points", POINTS)
 | 
					@pytest.mark.parametrize("points", POINTS)
 | 
				
			||||||
def test_line(points):
 | 
					def test_line(points) -> None:
 | 
				
			||||||
    # Arrange
 | 
					    # Arrange
 | 
				
			||||||
    im = Image.new("RGB", (W, H))
 | 
					    im = Image.new("RGB", (W, H))
 | 
				
			||||||
    draw = ImageDraw.Draw(im)
 | 
					    draw = ImageDraw.Draw(im)
 | 
				
			||||||
| 
						 | 
					@ -421,7 +421,7 @@ def test_line(points):
 | 
				
			||||||
    assert_image_equal_tofile(im, "Tests/images/imagedraw_line.png")
 | 
					    assert_image_equal_tofile(im, "Tests/images/imagedraw_line.png")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_shape1():
 | 
					def test_shape1() -> None:
 | 
				
			||||||
    # Arrange
 | 
					    # Arrange
 | 
				
			||||||
    im = Image.new("RGB", (100, 100), "white")
 | 
					    im = Image.new("RGB", (100, 100), "white")
 | 
				
			||||||
    draw = ImageDraw.Draw(im)
 | 
					    draw = ImageDraw.Draw(im)
 | 
				
			||||||
| 
						 | 
					@ -442,7 +442,7 @@ def test_shape1():
 | 
				
			||||||
    assert_image_equal_tofile(im, "Tests/images/imagedraw_shape1.png")
 | 
					    assert_image_equal_tofile(im, "Tests/images/imagedraw_shape1.png")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_shape2():
 | 
					def test_shape2() -> None:
 | 
				
			||||||
    # Arrange
 | 
					    # Arrange
 | 
				
			||||||
    im = Image.new("RGB", (100, 100), "white")
 | 
					    im = Image.new("RGB", (100, 100), "white")
 | 
				
			||||||
    draw = ImageDraw.Draw(im)
 | 
					    draw = ImageDraw.Draw(im)
 | 
				
			||||||
| 
						 | 
					@ -463,7 +463,7 @@ def test_shape2():
 | 
				
			||||||
    assert_image_equal_tofile(im, "Tests/images/imagedraw_shape2.png")
 | 
					    assert_image_equal_tofile(im, "Tests/images/imagedraw_shape2.png")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_transform():
 | 
					def test_transform() -> None:
 | 
				
			||||||
    # Arrange
 | 
					    # Arrange
 | 
				
			||||||
    im = Image.new("RGB", (100, 100), "white")
 | 
					    im = Image.new("RGB", (100, 100), "white")
 | 
				
			||||||
    expected = im.copy()
 | 
					    expected = im.copy()
 | 
				
			||||||
| 
						 | 
					@ -482,7 +482,7 @@ def test_transform():
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@pytest.mark.parametrize("bbox", BBOX)
 | 
					@pytest.mark.parametrize("bbox", BBOX)
 | 
				
			||||||
@pytest.mark.parametrize("start, end", ((-92, 46), (-92.2, 46.2)))
 | 
					@pytest.mark.parametrize("start, end", ((-92, 46), (-92.2, 46.2)))
 | 
				
			||||||
def test_pieslice(bbox, start, end):
 | 
					def test_pieslice(bbox, start, end) -> None:
 | 
				
			||||||
    # Arrange
 | 
					    # Arrange
 | 
				
			||||||
    im = Image.new("RGB", (W, H))
 | 
					    im = Image.new("RGB", (W, H))
 | 
				
			||||||
    draw = ImageDraw.Draw(im)
 | 
					    draw = ImageDraw.Draw(im)
 | 
				
			||||||
| 
						 | 
					@ -495,7 +495,7 @@ def test_pieslice(bbox, start, end):
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@pytest.mark.parametrize("bbox", BBOX)
 | 
					@pytest.mark.parametrize("bbox", BBOX)
 | 
				
			||||||
def test_pieslice_width(bbox):
 | 
					def test_pieslice_width(bbox) -> None:
 | 
				
			||||||
    # Arrange
 | 
					    # Arrange
 | 
				
			||||||
    im = Image.new("RGB", (W, H))
 | 
					    im = Image.new("RGB", (W, H))
 | 
				
			||||||
    draw = ImageDraw.Draw(im)
 | 
					    draw = ImageDraw.Draw(im)
 | 
				
			||||||
| 
						 | 
					@ -508,7 +508,7 @@ def test_pieslice_width(bbox):
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@pytest.mark.parametrize("bbox", BBOX)
 | 
					@pytest.mark.parametrize("bbox", BBOX)
 | 
				
			||||||
def test_pieslice_width_fill(bbox):
 | 
					def test_pieslice_width_fill(bbox) -> None:
 | 
				
			||||||
    # Arrange
 | 
					    # Arrange
 | 
				
			||||||
    im = Image.new("RGB", (W, H))
 | 
					    im = Image.new("RGB", (W, H))
 | 
				
			||||||
    draw = ImageDraw.Draw(im)
 | 
					    draw = ImageDraw.Draw(im)
 | 
				
			||||||
| 
						 | 
					@ -522,7 +522,7 @@ def test_pieslice_width_fill(bbox):
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@pytest.mark.parametrize("bbox", BBOX)
 | 
					@pytest.mark.parametrize("bbox", BBOX)
 | 
				
			||||||
def test_pieslice_zero_width(bbox):
 | 
					def test_pieslice_zero_width(bbox) -> None:
 | 
				
			||||||
    # Arrange
 | 
					    # Arrange
 | 
				
			||||||
    im = Image.new("RGB", (W, H))
 | 
					    im = Image.new("RGB", (W, H))
 | 
				
			||||||
    draw = ImageDraw.Draw(im)
 | 
					    draw = ImageDraw.Draw(im)
 | 
				
			||||||
| 
						 | 
					@ -534,7 +534,7 @@ def test_pieslice_zero_width(bbox):
 | 
				
			||||||
    assert_image_equal_tofile(im, "Tests/images/imagedraw_pieslice_zero_width.png")
 | 
					    assert_image_equal_tofile(im, "Tests/images/imagedraw_pieslice_zero_width.png")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_pieslice_wide():
 | 
					def test_pieslice_wide() -> None:
 | 
				
			||||||
    # Arrange
 | 
					    # Arrange
 | 
				
			||||||
    im = Image.new("RGB", (200, 100))
 | 
					    im = Image.new("RGB", (200, 100))
 | 
				
			||||||
    draw = ImageDraw.Draw(im)
 | 
					    draw = ImageDraw.Draw(im)
 | 
				
			||||||
| 
						 | 
					@ -546,7 +546,7 @@ def test_pieslice_wide():
 | 
				
			||||||
    assert_image_equal_tofile(im, "Tests/images/imagedraw_pieslice_wide.png")
 | 
					    assert_image_equal_tofile(im, "Tests/images/imagedraw_pieslice_wide.png")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_pieslice_no_spikes():
 | 
					def test_pieslice_no_spikes() -> None:
 | 
				
			||||||
    im = Image.new("RGB", (161, 161), "white")
 | 
					    im = Image.new("RGB", (161, 161), "white")
 | 
				
			||||||
    draw = ImageDraw.Draw(im)
 | 
					    draw = ImageDraw.Draw(im)
 | 
				
			||||||
    cxs = (
 | 
					    cxs = (
 | 
				
			||||||
| 
						 | 
					@ -577,7 +577,7 @@ def test_pieslice_no_spikes():
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@pytest.mark.parametrize("points", POINTS)
 | 
					@pytest.mark.parametrize("points", POINTS)
 | 
				
			||||||
def test_point(points):
 | 
					def test_point(points) -> None:
 | 
				
			||||||
    # Arrange
 | 
					    # Arrange
 | 
				
			||||||
    im = Image.new("RGB", (W, H))
 | 
					    im = Image.new("RGB", (W, H))
 | 
				
			||||||
    draw = ImageDraw.Draw(im)
 | 
					    draw = ImageDraw.Draw(im)
 | 
				
			||||||
| 
						 | 
					@ -589,7 +589,7 @@ def test_point(points):
 | 
				
			||||||
    assert_image_equal_tofile(im, "Tests/images/imagedraw_point.png")
 | 
					    assert_image_equal_tofile(im, "Tests/images/imagedraw_point.png")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_point_I16():
 | 
					def test_point_I16() -> None:
 | 
				
			||||||
    # Arrange
 | 
					    # Arrange
 | 
				
			||||||
    im = Image.new("I;16", (1, 1))
 | 
					    im = Image.new("I;16", (1, 1))
 | 
				
			||||||
    draw = ImageDraw.Draw(im)
 | 
					    draw = ImageDraw.Draw(im)
 | 
				
			||||||
| 
						 | 
					@ -602,7 +602,7 @@ def test_point_I16():
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@pytest.mark.parametrize("points", POINTS)
 | 
					@pytest.mark.parametrize("points", POINTS)
 | 
				
			||||||
def test_polygon(points):
 | 
					def test_polygon(points) -> None:
 | 
				
			||||||
    # Arrange
 | 
					    # Arrange
 | 
				
			||||||
    im = Image.new("RGB", (W, H))
 | 
					    im = Image.new("RGB", (W, H))
 | 
				
			||||||
    draw = ImageDraw.Draw(im)
 | 
					    draw = ImageDraw.Draw(im)
 | 
				
			||||||
| 
						 | 
					@ -616,7 +616,7 @@ def test_polygon(points):
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@pytest.mark.parametrize("mode", ("RGB", "L"))
 | 
					@pytest.mark.parametrize("mode", ("RGB", "L"))
 | 
				
			||||||
@pytest.mark.parametrize("kite_points", KITE_POINTS)
 | 
					@pytest.mark.parametrize("kite_points", KITE_POINTS)
 | 
				
			||||||
def test_polygon_kite(mode, kite_points):
 | 
					def test_polygon_kite(mode, kite_points) -> None:
 | 
				
			||||||
    # Test drawing lines of different gradients (dx>dy, dy>dx) and
 | 
					    # Test drawing lines of different gradients (dx>dy, dy>dx) and
 | 
				
			||||||
    # vertical (dx==0) and horizontal (dy==0) lines
 | 
					    # vertical (dx==0) and horizontal (dy==0) lines
 | 
				
			||||||
    # Arrange
 | 
					    # Arrange
 | 
				
			||||||
| 
						 | 
					@ -631,7 +631,7 @@ def test_polygon_kite(mode, kite_points):
 | 
				
			||||||
    assert_image_equal_tofile(im, expected)
 | 
					    assert_image_equal_tofile(im, expected)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_polygon_1px_high():
 | 
					def test_polygon_1px_high() -> None:
 | 
				
			||||||
    # Test drawing a 1px high polygon
 | 
					    # Test drawing a 1px high polygon
 | 
				
			||||||
    # Arrange
 | 
					    # Arrange
 | 
				
			||||||
    im = Image.new("RGB", (3, 3))
 | 
					    im = Image.new("RGB", (3, 3))
 | 
				
			||||||
| 
						 | 
					@ -645,7 +645,7 @@ def test_polygon_1px_high():
 | 
				
			||||||
    assert_image_equal_tofile(im, expected)
 | 
					    assert_image_equal_tofile(im, expected)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_polygon_1px_high_translucent():
 | 
					def test_polygon_1px_high_translucent() -> None:
 | 
				
			||||||
    # Test drawing a translucent 1px high polygon
 | 
					    # Test drawing a translucent 1px high polygon
 | 
				
			||||||
    # Arrange
 | 
					    # Arrange
 | 
				
			||||||
    im = Image.new("RGB", (4, 3))
 | 
					    im = Image.new("RGB", (4, 3))
 | 
				
			||||||
| 
						 | 
					@ -659,7 +659,7 @@ def test_polygon_1px_high_translucent():
 | 
				
			||||||
    assert_image_equal_tofile(im, expected)
 | 
					    assert_image_equal_tofile(im, expected)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_polygon_translucent():
 | 
					def test_polygon_translucent() -> None:
 | 
				
			||||||
    # Arrange
 | 
					    # Arrange
 | 
				
			||||||
    im = Image.new("RGB", (W, H))
 | 
					    im = Image.new("RGB", (W, H))
 | 
				
			||||||
    draw = ImageDraw.Draw(im, "RGBA")
 | 
					    draw = ImageDraw.Draw(im, "RGBA")
 | 
				
			||||||
| 
						 | 
					@ -673,7 +673,7 @@ def test_polygon_translucent():
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@pytest.mark.parametrize("bbox", BBOX)
 | 
					@pytest.mark.parametrize("bbox", BBOX)
 | 
				
			||||||
def test_rectangle(bbox):
 | 
					def test_rectangle(bbox) -> None:
 | 
				
			||||||
    # Arrange
 | 
					    # Arrange
 | 
				
			||||||
    im = Image.new("RGB", (W, H))
 | 
					    im = Image.new("RGB", (W, H))
 | 
				
			||||||
    draw = ImageDraw.Draw(im)
 | 
					    draw = ImageDraw.Draw(im)
 | 
				
			||||||
| 
						 | 
					@ -685,7 +685,7 @@ def test_rectangle(bbox):
 | 
				
			||||||
    assert_image_equal_tofile(im, "Tests/images/imagedraw_rectangle.png")
 | 
					    assert_image_equal_tofile(im, "Tests/images/imagedraw_rectangle.png")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_big_rectangle():
 | 
					def test_big_rectangle() -> None:
 | 
				
			||||||
    # Test drawing a rectangle bigger than the image
 | 
					    # Test drawing a rectangle bigger than the image
 | 
				
			||||||
    # Arrange
 | 
					    # Arrange
 | 
				
			||||||
    im = Image.new("RGB", (W, H))
 | 
					    im = Image.new("RGB", (W, H))
 | 
				
			||||||
| 
						 | 
					@ -700,7 +700,7 @@ def test_big_rectangle():
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@pytest.mark.parametrize("bbox", BBOX)
 | 
					@pytest.mark.parametrize("bbox", BBOX)
 | 
				
			||||||
def test_rectangle_width(bbox):
 | 
					def test_rectangle_width(bbox) -> None:
 | 
				
			||||||
    # Arrange
 | 
					    # Arrange
 | 
				
			||||||
    im = Image.new("RGB", (W, H))
 | 
					    im = Image.new("RGB", (W, H))
 | 
				
			||||||
    draw = ImageDraw.Draw(im)
 | 
					    draw = ImageDraw.Draw(im)
 | 
				
			||||||
| 
						 | 
					@ -714,7 +714,7 @@ def test_rectangle_width(bbox):
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@pytest.mark.parametrize("bbox", BBOX)
 | 
					@pytest.mark.parametrize("bbox", BBOX)
 | 
				
			||||||
def test_rectangle_width_fill(bbox):
 | 
					def test_rectangle_width_fill(bbox) -> None:
 | 
				
			||||||
    # Arrange
 | 
					    # Arrange
 | 
				
			||||||
    im = Image.new("RGB", (W, H))
 | 
					    im = Image.new("RGB", (W, H))
 | 
				
			||||||
    draw = ImageDraw.Draw(im)
 | 
					    draw = ImageDraw.Draw(im)
 | 
				
			||||||
| 
						 | 
					@ -728,7 +728,7 @@ def test_rectangle_width_fill(bbox):
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@pytest.mark.parametrize("bbox", BBOX)
 | 
					@pytest.mark.parametrize("bbox", BBOX)
 | 
				
			||||||
def test_rectangle_zero_width(bbox):
 | 
					def test_rectangle_zero_width(bbox) -> None:
 | 
				
			||||||
    # Arrange
 | 
					    # Arrange
 | 
				
			||||||
    im = Image.new("RGB", (W, H))
 | 
					    im = Image.new("RGB", (W, H))
 | 
				
			||||||
    draw = ImageDraw.Draw(im)
 | 
					    draw = ImageDraw.Draw(im)
 | 
				
			||||||
| 
						 | 
					@ -741,7 +741,7 @@ def test_rectangle_zero_width(bbox):
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@pytest.mark.parametrize("bbox", BBOX)
 | 
					@pytest.mark.parametrize("bbox", BBOX)
 | 
				
			||||||
def test_rectangle_I16(bbox):
 | 
					def test_rectangle_I16(bbox) -> None:
 | 
				
			||||||
    # Arrange
 | 
					    # Arrange
 | 
				
			||||||
    im = Image.new("I;16", (W, H))
 | 
					    im = Image.new("I;16", (W, H))
 | 
				
			||||||
    draw = ImageDraw.Draw(im)
 | 
					    draw = ImageDraw.Draw(im)
 | 
				
			||||||
| 
						 | 
					@ -754,7 +754,7 @@ def test_rectangle_I16(bbox):
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@pytest.mark.parametrize("bbox", BBOX)
 | 
					@pytest.mark.parametrize("bbox", BBOX)
 | 
				
			||||||
def test_rectangle_translucent_outline(bbox):
 | 
					def test_rectangle_translucent_outline(bbox) -> None:
 | 
				
			||||||
    # Arrange
 | 
					    # Arrange
 | 
				
			||||||
    im = Image.new("RGB", (W, H))
 | 
					    im = Image.new("RGB", (W, H))
 | 
				
			||||||
    draw = ImageDraw.Draw(im, "RGBA")
 | 
					    draw = ImageDraw.Draw(im, "RGBA")
 | 
				
			||||||
| 
						 | 
					@ -772,7 +772,7 @@ def test_rectangle_translucent_outline(bbox):
 | 
				
			||||||
    "xy",
 | 
					    "xy",
 | 
				
			||||||
    [(10, 20, 190, 180), ([10, 20], [190, 180]), ((10, 20), (190, 180))],
 | 
					    [(10, 20, 190, 180), ([10, 20], [190, 180]), ((10, 20), (190, 180))],
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
def test_rounded_rectangle(xy):
 | 
					def test_rounded_rectangle(xy) -> None:
 | 
				
			||||||
    # Arrange
 | 
					    # Arrange
 | 
				
			||||||
    im = Image.new("RGB", (200, 200))
 | 
					    im = Image.new("RGB", (200, 200))
 | 
				
			||||||
    draw = ImageDraw.Draw(im)
 | 
					    draw = ImageDraw.Draw(im)
 | 
				
			||||||
| 
						 | 
					@ -788,7 +788,9 @@ def test_rounded_rectangle(xy):
 | 
				
			||||||
@pytest.mark.parametrize("top_right", (True, False))
 | 
					@pytest.mark.parametrize("top_right", (True, False))
 | 
				
			||||||
@pytest.mark.parametrize("bottom_right", (True, False))
 | 
					@pytest.mark.parametrize("bottom_right", (True, False))
 | 
				
			||||||
@pytest.mark.parametrize("bottom_left", (True, False))
 | 
					@pytest.mark.parametrize("bottom_left", (True, False))
 | 
				
			||||||
def test_rounded_rectangle_corners(top_left, top_right, bottom_right, bottom_left):
 | 
					def test_rounded_rectangle_corners(
 | 
				
			||||||
 | 
					    top_left, top_right, bottom_right, bottom_left
 | 
				
			||||||
 | 
					) -> None:
 | 
				
			||||||
    corners = (top_left, top_right, bottom_right, bottom_left)
 | 
					    corners = (top_left, top_right, bottom_right, bottom_left)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    # Arrange
 | 
					    # Arrange
 | 
				
			||||||
| 
						 | 
					@ -822,7 +824,7 @@ def test_rounded_rectangle_corners(top_left, top_right, bottom_right, bottom_lef
 | 
				
			||||||
        ((10, 20, 190, 181), 85, "height"),
 | 
					        ((10, 20, 190, 181), 85, "height"),
 | 
				
			||||||
    ],
 | 
					    ],
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
def test_rounded_rectangle_non_integer_radius(xy, radius, type):
 | 
					def test_rounded_rectangle_non_integer_radius(xy, radius, type) -> None:
 | 
				
			||||||
    # Arrange
 | 
					    # Arrange
 | 
				
			||||||
    im = Image.new("RGB", (200, 200))
 | 
					    im = Image.new("RGB", (200, 200))
 | 
				
			||||||
    draw = ImageDraw.Draw(im)
 | 
					    draw = ImageDraw.Draw(im)
 | 
				
			||||||
| 
						 | 
					@ -838,7 +840,7 @@ def test_rounded_rectangle_non_integer_radius(xy, radius, type):
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@pytest.mark.parametrize("bbox", BBOX)
 | 
					@pytest.mark.parametrize("bbox", BBOX)
 | 
				
			||||||
def test_rounded_rectangle_zero_radius(bbox):
 | 
					def test_rounded_rectangle_zero_radius(bbox) -> None:
 | 
				
			||||||
    # Arrange
 | 
					    # Arrange
 | 
				
			||||||
    im = Image.new("RGB", (W, H))
 | 
					    im = Image.new("RGB", (W, H))
 | 
				
			||||||
    draw = ImageDraw.Draw(im)
 | 
					    draw = ImageDraw.Draw(im)
 | 
				
			||||||
| 
						 | 
					@ -860,7 +862,7 @@ def test_rounded_rectangle_zero_radius(bbox):
 | 
				
			||||||
        ((20, 20, 80, 80), "both"),
 | 
					        ((20, 20, 80, 80), "both"),
 | 
				
			||||||
    ],
 | 
					    ],
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
def test_rounded_rectangle_translucent(xy, suffix):
 | 
					def test_rounded_rectangle_translucent(xy, suffix) -> None:
 | 
				
			||||||
    # Arrange
 | 
					    # Arrange
 | 
				
			||||||
    im = Image.new("RGB", (W, H))
 | 
					    im = Image.new("RGB", (W, H))
 | 
				
			||||||
    draw = ImageDraw.Draw(im, "RGBA")
 | 
					    draw = ImageDraw.Draw(im, "RGBA")
 | 
				
			||||||
| 
						 | 
					@ -877,7 +879,7 @@ def test_rounded_rectangle_translucent(xy, suffix):
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@pytest.mark.parametrize("bbox", BBOX)
 | 
					@pytest.mark.parametrize("bbox", BBOX)
 | 
				
			||||||
def test_floodfill(bbox):
 | 
					def test_floodfill(bbox) -> None:
 | 
				
			||||||
    red = ImageColor.getrgb("red")
 | 
					    red = ImageColor.getrgb("red")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    for mode, value in [("L", 1), ("RGBA", (255, 0, 0, 0)), ("RGB", red)]:
 | 
					    for mode, value in [("L", 1), ("RGBA", (255, 0, 0, 0)), ("RGB", red)]:
 | 
				
			||||||
| 
						 | 
					@ -910,7 +912,7 @@ def test_floodfill(bbox):
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@pytest.mark.parametrize("bbox", BBOX)
 | 
					@pytest.mark.parametrize("bbox", BBOX)
 | 
				
			||||||
def test_floodfill_border(bbox):
 | 
					def test_floodfill_border(bbox) -> None:
 | 
				
			||||||
    # floodfill() is experimental
 | 
					    # floodfill() is experimental
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    # Arrange
 | 
					    # Arrange
 | 
				
			||||||
| 
						 | 
					@ -932,7 +934,7 @@ def test_floodfill_border(bbox):
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@pytest.mark.parametrize("bbox", BBOX)
 | 
					@pytest.mark.parametrize("bbox", BBOX)
 | 
				
			||||||
def test_floodfill_thresh(bbox):
 | 
					def test_floodfill_thresh(bbox) -> None:
 | 
				
			||||||
    # floodfill() is experimental
 | 
					    # floodfill() is experimental
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    # Arrange
 | 
					    # Arrange
 | 
				
			||||||
| 
						 | 
					@ -948,7 +950,7 @@ def test_floodfill_thresh(bbox):
 | 
				
			||||||
    assert_image_equal_tofile(im, "Tests/images/imagedraw_floodfill2.png")
 | 
					    assert_image_equal_tofile(im, "Tests/images/imagedraw_floodfill2.png")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_floodfill_not_negative():
 | 
					def test_floodfill_not_negative() -> None:
 | 
				
			||||||
    # floodfill() is experimental
 | 
					    # floodfill() is experimental
 | 
				
			||||||
    # Test that floodfill does not extend into negative coordinates
 | 
					    # Test that floodfill does not extend into negative coordinates
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -976,7 +978,7 @@ def create_base_image_draw(
 | 
				
			||||||
    return img, ImageDraw.Draw(img)
 | 
					    return img, ImageDraw.Draw(img)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_square():
 | 
					def test_square() -> None:
 | 
				
			||||||
    expected = os.path.join(IMAGES_PATH, "square.png")
 | 
					    expected = os.path.join(IMAGES_PATH, "square.png")
 | 
				
			||||||
    img, draw = create_base_image_draw((10, 10))
 | 
					    img, draw = create_base_image_draw((10, 10))
 | 
				
			||||||
    draw.polygon([(2, 2), (2, 7), (7, 7), (7, 2)], BLACK)
 | 
					    draw.polygon([(2, 2), (2, 7), (7, 7), (7, 2)], BLACK)
 | 
				
			||||||
| 
						 | 
					@ -989,7 +991,7 @@ def test_square():
 | 
				
			||||||
    assert_image_equal_tofile(img, expected, "square as normal rectangle failed")
 | 
					    assert_image_equal_tofile(img, expected, "square as normal rectangle failed")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_triangle_right():
 | 
					def test_triangle_right() -> None:
 | 
				
			||||||
    img, draw = create_base_image_draw((20, 20))
 | 
					    img, draw = create_base_image_draw((20, 20))
 | 
				
			||||||
    draw.polygon([(3, 5), (17, 5), (10, 12)], BLACK)
 | 
					    draw.polygon([(3, 5), (17, 5), (10, 12)], BLACK)
 | 
				
			||||||
    assert_image_equal_tofile(
 | 
					    assert_image_equal_tofile(
 | 
				
			||||||
| 
						 | 
					@ -1001,7 +1003,7 @@ def test_triangle_right():
 | 
				
			||||||
    "fill, suffix",
 | 
					    "fill, suffix",
 | 
				
			||||||
    ((BLACK, "width"), (None, "width_no_fill")),
 | 
					    ((BLACK, "width"), (None, "width_no_fill")),
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
def test_triangle_right_width(fill, suffix):
 | 
					def test_triangle_right_width(fill, suffix) -> None:
 | 
				
			||||||
    img, draw = create_base_image_draw((100, 100))
 | 
					    img, draw = create_base_image_draw((100, 100))
 | 
				
			||||||
    draw.polygon([(15, 25), (85, 25), (50, 60)], fill, WHITE, width=5)
 | 
					    draw.polygon([(15, 25), (85, 25), (50, 60)], fill, WHITE, width=5)
 | 
				
			||||||
    assert_image_equal_tofile(
 | 
					    assert_image_equal_tofile(
 | 
				
			||||||
| 
						 | 
					@ -1009,7 +1011,7 @@ def test_triangle_right_width(fill, suffix):
 | 
				
			||||||
    )
 | 
					    )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_line_horizontal():
 | 
					def test_line_horizontal() -> None:
 | 
				
			||||||
    img, draw = create_base_image_draw((20, 20))
 | 
					    img, draw = create_base_image_draw((20, 20))
 | 
				
			||||||
    draw.line((5, 5, 14, 5), BLACK, 2)
 | 
					    draw.line((5, 5, 14, 5), BLACK, 2)
 | 
				
			||||||
    assert_image_equal_tofile(
 | 
					    assert_image_equal_tofile(
 | 
				
			||||||
| 
						 | 
					@ -1047,7 +1049,7 @@ def test_line_horizontal():
 | 
				
			||||||
    )
 | 
					    )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_line_h_s1_w2():
 | 
					def test_line_h_s1_w2() -> None:
 | 
				
			||||||
    pytest.skip("failing")
 | 
					    pytest.skip("failing")
 | 
				
			||||||
    img, draw = create_base_image_draw((20, 20))
 | 
					    img, draw = create_base_image_draw((20, 20))
 | 
				
			||||||
    draw.line((5, 5, 14, 6), BLACK, 2)
 | 
					    draw.line((5, 5, 14, 6), BLACK, 2)
 | 
				
			||||||
| 
						 | 
					@ -1058,7 +1060,7 @@ def test_line_h_s1_w2():
 | 
				
			||||||
    )
 | 
					    )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_line_vertical():
 | 
					def test_line_vertical() -> None:
 | 
				
			||||||
    img, draw = create_base_image_draw((20, 20))
 | 
					    img, draw = create_base_image_draw((20, 20))
 | 
				
			||||||
    draw.line((5, 5, 5, 14), BLACK, 2)
 | 
					    draw.line((5, 5, 5, 14), BLACK, 2)
 | 
				
			||||||
    assert_image_equal_tofile(
 | 
					    assert_image_equal_tofile(
 | 
				
			||||||
| 
						 | 
					@ -1104,7 +1106,7 @@ def test_line_vertical():
 | 
				
			||||||
    )
 | 
					    )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_line_oblique_45():
 | 
					def test_line_oblique_45() -> None:
 | 
				
			||||||
    expected = os.path.join(IMAGES_PATH, "line_oblique_45_w3px_a.png")
 | 
					    expected = os.path.join(IMAGES_PATH, "line_oblique_45_w3px_a.png")
 | 
				
			||||||
    img, draw = create_base_image_draw((20, 20))
 | 
					    img, draw = create_base_image_draw((20, 20))
 | 
				
			||||||
    draw.line((5, 5, 14, 14), BLACK, 3)
 | 
					    draw.line((5, 5, 14, 14), BLACK, 3)
 | 
				
			||||||
| 
						 | 
					@ -1126,7 +1128,7 @@ def test_line_oblique_45():
 | 
				
			||||||
    )
 | 
					    )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_wide_line_dot():
 | 
					def test_wide_line_dot() -> None:
 | 
				
			||||||
    # Test drawing a wide "line" from one point to another just draws a single point
 | 
					    # Test drawing a wide "line" from one point to another just draws a single point
 | 
				
			||||||
    # Arrange
 | 
					    # Arrange
 | 
				
			||||||
    im = Image.new("RGB", (W, H))
 | 
					    im = Image.new("RGB", (W, H))
 | 
				
			||||||
| 
						 | 
					@ -1139,7 +1141,7 @@ def test_wide_line_dot():
 | 
				
			||||||
    assert_image_similar_tofile(im, "Tests/images/imagedraw_wide_line_dot.png", 1)
 | 
					    assert_image_similar_tofile(im, "Tests/images/imagedraw_wide_line_dot.png", 1)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_wide_line_larger_than_int():
 | 
					def test_wide_line_larger_than_int() -> None:
 | 
				
			||||||
    # Arrange
 | 
					    # Arrange
 | 
				
			||||||
    im = Image.new("RGB", (W, H))
 | 
					    im = Image.new("RGB", (W, H))
 | 
				
			||||||
    draw = ImageDraw.Draw(im)
 | 
					    draw = ImageDraw.Draw(im)
 | 
				
			||||||
| 
						 | 
					@ -1233,7 +1235,7 @@ def test_wide_line_larger_than_int():
 | 
				
			||||||
        ],
 | 
					        ],
 | 
				
			||||||
    ],
 | 
					    ],
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
def test_line_joint(xy):
 | 
					def test_line_joint(xy) -> None:
 | 
				
			||||||
    im = Image.new("RGB", (500, 325))
 | 
					    im = Image.new("RGB", (500, 325))
 | 
				
			||||||
    draw = ImageDraw.Draw(im)
 | 
					    draw = ImageDraw.Draw(im)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1244,7 +1246,7 @@ def test_line_joint(xy):
 | 
				
			||||||
    assert_image_similar_tofile(im, "Tests/images/imagedraw_line_joint_curve.png", 3)
 | 
					    assert_image_similar_tofile(im, "Tests/images/imagedraw_line_joint_curve.png", 3)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_textsize_empty_string():
 | 
					def test_textsize_empty_string() -> None:
 | 
				
			||||||
    # https://github.com/python-pillow/Pillow/issues/2783
 | 
					    # https://github.com/python-pillow/Pillow/issues/2783
 | 
				
			||||||
    # Arrange
 | 
					    # Arrange
 | 
				
			||||||
    im = Image.new("RGB", (W, H))
 | 
					    im = Image.new("RGB", (W, H))
 | 
				
			||||||
| 
						 | 
					@ -1260,7 +1262,7 @@ def test_textsize_empty_string():
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@skip_unless_feature("freetype2")
 | 
					@skip_unless_feature("freetype2")
 | 
				
			||||||
def test_textbbox_stroke():
 | 
					def test_textbbox_stroke() -> None:
 | 
				
			||||||
    # Arrange
 | 
					    # Arrange
 | 
				
			||||||
    im = Image.new("RGB", (W, H))
 | 
					    im = Image.new("RGB", (W, H))
 | 
				
			||||||
    draw = ImageDraw.Draw(im)
 | 
					    draw = ImageDraw.Draw(im)
 | 
				
			||||||
| 
						 | 
					@ -1274,7 +1276,7 @@ def test_textbbox_stroke():
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@skip_unless_feature("freetype2")
 | 
					@skip_unless_feature("freetype2")
 | 
				
			||||||
def test_stroke():
 | 
					def test_stroke() -> None:
 | 
				
			||||||
    for suffix, stroke_fill in {"same": None, "different": "#0f0"}.items():
 | 
					    for suffix, stroke_fill in {"same": None, "different": "#0f0"}.items():
 | 
				
			||||||
        # Arrange
 | 
					        # Arrange
 | 
				
			||||||
        im = Image.new("RGB", (120, 130))
 | 
					        im = Image.new("RGB", (120, 130))
 | 
				
			||||||
| 
						 | 
					@ -1291,7 +1293,7 @@ def test_stroke():
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@skip_unless_feature("freetype2")
 | 
					@skip_unless_feature("freetype2")
 | 
				
			||||||
def test_stroke_descender():
 | 
					def test_stroke_descender() -> None:
 | 
				
			||||||
    # Arrange
 | 
					    # Arrange
 | 
				
			||||||
    im = Image.new("RGB", (120, 130))
 | 
					    im = Image.new("RGB", (120, 130))
 | 
				
			||||||
    draw = ImageDraw.Draw(im)
 | 
					    draw = ImageDraw.Draw(im)
 | 
				
			||||||
| 
						 | 
					@ -1305,7 +1307,7 @@ def test_stroke_descender():
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@skip_unless_feature("freetype2")
 | 
					@skip_unless_feature("freetype2")
 | 
				
			||||||
def test_split_word():
 | 
					def test_split_word() -> None:
 | 
				
			||||||
    # Arrange
 | 
					    # Arrange
 | 
				
			||||||
    im = Image.new("RGB", (230, 55))
 | 
					    im = Image.new("RGB", (230, 55))
 | 
				
			||||||
    expected = im.copy()
 | 
					    expected = im.copy()
 | 
				
			||||||
| 
						 | 
					@ -1326,7 +1328,7 @@ def test_split_word():
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@skip_unless_feature("freetype2")
 | 
					@skip_unless_feature("freetype2")
 | 
				
			||||||
def test_stroke_multiline():
 | 
					def test_stroke_multiline() -> None:
 | 
				
			||||||
    # Arrange
 | 
					    # Arrange
 | 
				
			||||||
    im = Image.new("RGB", (100, 250))
 | 
					    im = Image.new("RGB", (100, 250))
 | 
				
			||||||
    draw = ImageDraw.Draw(im)
 | 
					    draw = ImageDraw.Draw(im)
 | 
				
			||||||
| 
						 | 
					@ -1342,7 +1344,7 @@ def test_stroke_multiline():
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@skip_unless_feature("freetype2")
 | 
					@skip_unless_feature("freetype2")
 | 
				
			||||||
def test_setting_default_font():
 | 
					def test_setting_default_font() -> None:
 | 
				
			||||||
    # Arrange
 | 
					    # Arrange
 | 
				
			||||||
    im = Image.new("RGB", (100, 250))
 | 
					    im = Image.new("RGB", (100, 250))
 | 
				
			||||||
    draw = ImageDraw.Draw(im)
 | 
					    draw = ImageDraw.Draw(im)
 | 
				
			||||||
| 
						 | 
					@ -1359,7 +1361,7 @@ def test_setting_default_font():
 | 
				
			||||||
        assert isinstance(draw.getfont(), ImageFont.load_default().__class__)
 | 
					        assert isinstance(draw.getfont(), ImageFont.load_default().__class__)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_default_font_size():
 | 
					def test_default_font_size() -> None:
 | 
				
			||||||
    freetype_support = features.check_module("freetype2")
 | 
					    freetype_support = features.check_module("freetype2")
 | 
				
			||||||
    text = "Default font at a specific size."
 | 
					    text = "Default font at a specific size."
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1386,7 +1388,7 @@ def test_default_font_size():
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@pytest.mark.parametrize("bbox", BBOX)
 | 
					@pytest.mark.parametrize("bbox", BBOX)
 | 
				
			||||||
def test_same_color_outline(bbox):
 | 
					def test_same_color_outline(bbox) -> None:
 | 
				
			||||||
    # Prepare shape
 | 
					    # Prepare shape
 | 
				
			||||||
    x0, y0 = 5, 5
 | 
					    x0, y0 = 5, 5
 | 
				
			||||||
    x1, y1 = 5, 50
 | 
					    x1, y1 = 5, 50
 | 
				
			||||||
| 
						 | 
					@ -1432,7 +1434,7 @@ def test_same_color_outline(bbox):
 | 
				
			||||||
        (3, "triangle_width", {"width": 5, "outline": "yellow"}),
 | 
					        (3, "triangle_width", {"width": 5, "outline": "yellow"}),
 | 
				
			||||||
    ],
 | 
					    ],
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
def test_draw_regular_polygon(n_sides, polygon_name, args):
 | 
					def test_draw_regular_polygon(n_sides, polygon_name, args) -> None:
 | 
				
			||||||
    im = Image.new("RGBA", size=(W, H), color=(255, 0, 0, 0))
 | 
					    im = Image.new("RGBA", size=(W, H), color=(255, 0, 0, 0))
 | 
				
			||||||
    filename = f"Tests/images/imagedraw_{polygon_name}.png"
 | 
					    filename = f"Tests/images/imagedraw_{polygon_name}.png"
 | 
				
			||||||
    draw = ImageDraw.Draw(im)
 | 
					    draw = ImageDraw.Draw(im)
 | 
				
			||||||
| 
						 | 
					@ -1469,7 +1471,7 @@ def test_draw_regular_polygon(n_sides, polygon_name, args):
 | 
				
			||||||
        ),
 | 
					        ),
 | 
				
			||||||
    ],
 | 
					    ],
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
def test_compute_regular_polygon_vertices(n_sides, expected_vertices):
 | 
					def test_compute_regular_polygon_vertices(n_sides, expected_vertices) -> None:
 | 
				
			||||||
    bounding_circle = (W // 2, H // 2, 25)
 | 
					    bounding_circle = (W // 2, H // 2, 25)
 | 
				
			||||||
    vertices = ImageDraw._compute_regular_polygon_vertices(bounding_circle, n_sides, 0)
 | 
					    vertices = ImageDraw._compute_regular_polygon_vertices(bounding_circle, n_sides, 0)
 | 
				
			||||||
    assert vertices == expected_vertices
 | 
					    assert vertices == expected_vertices
 | 
				
			||||||
| 
						 | 
					@ -1521,13 +1523,13 @@ def test_compute_regular_polygon_vertices(n_sides, expected_vertices):
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
def test_compute_regular_polygon_vertices_input_error_handling(
 | 
					def test_compute_regular_polygon_vertices_input_error_handling(
 | 
				
			||||||
    n_sides, bounding_circle, rotation, expected_error, error_message
 | 
					    n_sides, bounding_circle, rotation, expected_error, error_message
 | 
				
			||||||
):
 | 
					) -> None:
 | 
				
			||||||
    with pytest.raises(expected_error) as e:
 | 
					    with pytest.raises(expected_error) as e:
 | 
				
			||||||
        ImageDraw._compute_regular_polygon_vertices(bounding_circle, n_sides, rotation)
 | 
					        ImageDraw._compute_regular_polygon_vertices(bounding_circle, n_sides, rotation)
 | 
				
			||||||
    assert str(e.value) == error_message
 | 
					    assert str(e.value) == error_message
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_continuous_horizontal_edges_polygon():
 | 
					def test_continuous_horizontal_edges_polygon() -> None:
 | 
				
			||||||
    xy = [
 | 
					    xy = [
 | 
				
			||||||
        (2, 6),
 | 
					        (2, 6),
 | 
				
			||||||
        (6, 6),
 | 
					        (6, 6),
 | 
				
			||||||
| 
						 | 
					@ -1546,7 +1548,7 @@ def test_continuous_horizontal_edges_polygon():
 | 
				
			||||||
    )
 | 
					    )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_discontiguous_corners_polygon():
 | 
					def test_discontiguous_corners_polygon() -> None:
 | 
				
			||||||
    img, draw = create_base_image_draw((84, 68))
 | 
					    img, draw = create_base_image_draw((84, 68))
 | 
				
			||||||
    draw.polygon(((1, 21), (34, 4), (71, 1), (38, 18)), BLACK)
 | 
					    draw.polygon(((1, 21), (34, 4), (71, 1), (38, 18)), BLACK)
 | 
				
			||||||
    draw.polygon(((71, 44), (38, 27), (1, 24)), BLACK)
 | 
					    draw.polygon(((71, 44), (38, 27), (1, 24)), BLACK)
 | 
				
			||||||
| 
						 | 
					@ -1558,7 +1560,7 @@ def test_discontiguous_corners_polygon():
 | 
				
			||||||
    assert_image_similar_tofile(img, expected, 1)
 | 
					    assert_image_similar_tofile(img, expected, 1)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_polygon2():
 | 
					def test_polygon2() -> None:
 | 
				
			||||||
    im = Image.new("RGB", (W, H))
 | 
					    im = Image.new("RGB", (W, H))
 | 
				
			||||||
    draw = ImageDraw.Draw(im)
 | 
					    draw = ImageDraw.Draw(im)
 | 
				
			||||||
    draw.polygon([(18, 30), (19, 31), (18, 30), (85, 30), (60, 72)], "red")
 | 
					    draw.polygon([(18, 30), (19, 31), (18, 30), (85, 30), (60, 72)], "red")
 | 
				
			||||||
| 
						 | 
					@ -1567,7 +1569,7 @@ def test_polygon2():
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@pytest.mark.parametrize("xy", ((1, 1, 0, 1), (1, 1, 1, 0)))
 | 
					@pytest.mark.parametrize("xy", ((1, 1, 0, 1), (1, 1, 1, 0)))
 | 
				
			||||||
def test_incorrectly_ordered_coordinates(xy):
 | 
					def test_incorrectly_ordered_coordinates(xy) -> None:
 | 
				
			||||||
    im = Image.new("RGB", (W, H))
 | 
					    im = Image.new("RGB", (W, H))
 | 
				
			||||||
    draw = ImageDraw.Draw(im)
 | 
					    draw = ImageDraw.Draw(im)
 | 
				
			||||||
    with pytest.raises(ValueError):
 | 
					    with pytest.raises(ValueError):
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -43,7 +43,7 @@ POINTS = (
 | 
				
			||||||
FONT_PATH = "Tests/fonts/FreeMono.ttf"
 | 
					FONT_PATH = "Tests/fonts/FreeMono.ttf"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_sanity():
 | 
					def test_sanity() -> None:
 | 
				
			||||||
    im = hopper("RGB").copy()
 | 
					    im = hopper("RGB").copy()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    draw = ImageDraw2.Draw(im)
 | 
					    draw = ImageDraw2.Draw(im)
 | 
				
			||||||
| 
						 | 
					@ -56,7 +56,7 @@ def test_sanity():
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@pytest.mark.parametrize("bbox", BBOX)
 | 
					@pytest.mark.parametrize("bbox", BBOX)
 | 
				
			||||||
def test_ellipse(bbox):
 | 
					def test_ellipse(bbox) -> None:
 | 
				
			||||||
    # Arrange
 | 
					    # Arrange
 | 
				
			||||||
    im = Image.new("RGB", (W, H))
 | 
					    im = Image.new("RGB", (W, H))
 | 
				
			||||||
    draw = ImageDraw2.Draw(im)
 | 
					    draw = ImageDraw2.Draw(im)
 | 
				
			||||||
| 
						 | 
					@ -70,7 +70,7 @@ def test_ellipse(bbox):
 | 
				
			||||||
    assert_image_similar_tofile(im, "Tests/images/imagedraw_ellipse_RGB.png", 1)
 | 
					    assert_image_similar_tofile(im, "Tests/images/imagedraw_ellipse_RGB.png", 1)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_ellipse_edge():
 | 
					def test_ellipse_edge() -> None:
 | 
				
			||||||
    # Arrange
 | 
					    # Arrange
 | 
				
			||||||
    im = Image.new("RGB", (W, H))
 | 
					    im = Image.new("RGB", (W, H))
 | 
				
			||||||
    draw = ImageDraw2.Draw(im)
 | 
					    draw = ImageDraw2.Draw(im)
 | 
				
			||||||
| 
						 | 
					@ -84,7 +84,7 @@ def test_ellipse_edge():
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@pytest.mark.parametrize("points", POINTS)
 | 
					@pytest.mark.parametrize("points", POINTS)
 | 
				
			||||||
def test_line(points):
 | 
					def test_line(points) -> None:
 | 
				
			||||||
    # Arrange
 | 
					    # Arrange
 | 
				
			||||||
    im = Image.new("RGB", (W, H))
 | 
					    im = Image.new("RGB", (W, H))
 | 
				
			||||||
    draw = ImageDraw2.Draw(im)
 | 
					    draw = ImageDraw2.Draw(im)
 | 
				
			||||||
| 
						 | 
					@ -98,7 +98,7 @@ def test_line(points):
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@pytest.mark.parametrize("points", POINTS)
 | 
					@pytest.mark.parametrize("points", POINTS)
 | 
				
			||||||
def test_line_pen_as_brush(points):
 | 
					def test_line_pen_as_brush(points) -> None:
 | 
				
			||||||
    # Arrange
 | 
					    # Arrange
 | 
				
			||||||
    im = Image.new("RGB", (W, H))
 | 
					    im = Image.new("RGB", (W, H))
 | 
				
			||||||
    draw = ImageDraw2.Draw(im)
 | 
					    draw = ImageDraw2.Draw(im)
 | 
				
			||||||
| 
						 | 
					@ -114,7 +114,7 @@ def test_line_pen_as_brush(points):
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@pytest.mark.parametrize("points", POINTS)
 | 
					@pytest.mark.parametrize("points", POINTS)
 | 
				
			||||||
def test_polygon(points):
 | 
					def test_polygon(points) -> None:
 | 
				
			||||||
    # Arrange
 | 
					    # Arrange
 | 
				
			||||||
    im = Image.new("RGB", (W, H))
 | 
					    im = Image.new("RGB", (W, H))
 | 
				
			||||||
    draw = ImageDraw2.Draw(im)
 | 
					    draw = ImageDraw2.Draw(im)
 | 
				
			||||||
| 
						 | 
					@ -129,7 +129,7 @@ def test_polygon(points):
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@pytest.mark.parametrize("bbox", BBOX)
 | 
					@pytest.mark.parametrize("bbox", BBOX)
 | 
				
			||||||
def test_rectangle(bbox):
 | 
					def test_rectangle(bbox) -> None:
 | 
				
			||||||
    # Arrange
 | 
					    # Arrange
 | 
				
			||||||
    im = Image.new("RGB", (W, H))
 | 
					    im = Image.new("RGB", (W, H))
 | 
				
			||||||
    draw = ImageDraw2.Draw(im)
 | 
					    draw = ImageDraw2.Draw(im)
 | 
				
			||||||
| 
						 | 
					@ -143,7 +143,7 @@ def test_rectangle(bbox):
 | 
				
			||||||
    assert_image_equal_tofile(im, "Tests/images/imagedraw_rectangle.png")
 | 
					    assert_image_equal_tofile(im, "Tests/images/imagedraw_rectangle.png")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_big_rectangle():
 | 
					def test_big_rectangle() -> None:
 | 
				
			||||||
    # Test drawing a rectangle bigger than the image
 | 
					    # Test drawing a rectangle bigger than the image
 | 
				
			||||||
    # Arrange
 | 
					    # Arrange
 | 
				
			||||||
    im = Image.new("RGB", (W, H))
 | 
					    im = Image.new("RGB", (W, H))
 | 
				
			||||||
| 
						 | 
					@ -160,7 +160,7 @@ def test_big_rectangle():
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@skip_unless_feature("freetype2")
 | 
					@skip_unless_feature("freetype2")
 | 
				
			||||||
def test_text():
 | 
					def test_text() -> None:
 | 
				
			||||||
    # Arrange
 | 
					    # Arrange
 | 
				
			||||||
    im = Image.new("RGB", (W, H))
 | 
					    im = Image.new("RGB", (W, H))
 | 
				
			||||||
    draw = ImageDraw2.Draw(im)
 | 
					    draw = ImageDraw2.Draw(im)
 | 
				
			||||||
| 
						 | 
					@ -175,7 +175,7 @@ def test_text():
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@skip_unless_feature("freetype2")
 | 
					@skip_unless_feature("freetype2")
 | 
				
			||||||
def test_textbbox():
 | 
					def test_textbbox() -> None:
 | 
				
			||||||
    # Arrange
 | 
					    # Arrange
 | 
				
			||||||
    im = Image.new("RGB", (W, H))
 | 
					    im = Image.new("RGB", (W, H))
 | 
				
			||||||
    draw = ImageDraw2.Draw(im)
 | 
					    draw = ImageDraw2.Draw(im)
 | 
				
			||||||
| 
						 | 
					@ -190,7 +190,7 @@ def test_textbbox():
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@skip_unless_feature("freetype2")
 | 
					@skip_unless_feature("freetype2")
 | 
				
			||||||
def test_textsize_empty_string():
 | 
					def test_textsize_empty_string() -> None:
 | 
				
			||||||
    # Arrange
 | 
					    # Arrange
 | 
				
			||||||
    im = Image.new("RGB", (W, H))
 | 
					    im = Image.new("RGB", (W, H))
 | 
				
			||||||
    draw = ImageDraw2.Draw(im)
 | 
					    draw = ImageDraw2.Draw(im)
 | 
				
			||||||
| 
						 | 
					@ -206,7 +206,7 @@ def test_textsize_empty_string():
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@skip_unless_feature("freetype2")
 | 
					@skip_unless_feature("freetype2")
 | 
				
			||||||
def test_flush():
 | 
					def test_flush() -> None:
 | 
				
			||||||
    # Arrange
 | 
					    # Arrange
 | 
				
			||||||
    im = Image.new("RGB", (W, H))
 | 
					    im = Image.new("RGB", (W, H))
 | 
				
			||||||
    draw = ImageDraw2.Draw(im)
 | 
					    draw = ImageDraw2.Draw(im)
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -7,7 +7,7 @@ from PIL import Image, ImageEnhance
 | 
				
			||||||
from .helper import assert_image_equal, hopper
 | 
					from .helper import assert_image_equal, hopper
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_sanity():
 | 
					def test_sanity() -> None:
 | 
				
			||||||
    # FIXME: assert_image
 | 
					    # FIXME: assert_image
 | 
				
			||||||
    # Implicit asserts no exception:
 | 
					    # Implicit asserts no exception:
 | 
				
			||||||
    ImageEnhance.Color(hopper()).enhance(0.5)
 | 
					    ImageEnhance.Color(hopper()).enhance(0.5)
 | 
				
			||||||
| 
						 | 
					@ -16,7 +16,7 @@ def test_sanity():
 | 
				
			||||||
    ImageEnhance.Sharpness(hopper()).enhance(0.5)
 | 
					    ImageEnhance.Sharpness(hopper()).enhance(0.5)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_crash():
 | 
					def test_crash() -> None:
 | 
				
			||||||
    # crashes on small images
 | 
					    # crashes on small images
 | 
				
			||||||
    im = Image.new("RGB", (1, 1))
 | 
					    im = Image.new("RGB", (1, 1))
 | 
				
			||||||
    ImageEnhance.Sharpness(im).enhance(0.5)
 | 
					    ImageEnhance.Sharpness(im).enhance(0.5)
 | 
				
			||||||
| 
						 | 
					@ -34,7 +34,7 @@ def _half_transparent_image():
 | 
				
			||||||
    return im
 | 
					    return im
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def _check_alpha(im, original, op, amount):
 | 
					def _check_alpha(im, original, op, amount) -> None:
 | 
				
			||||||
    assert im.getbands() == original.getbands()
 | 
					    assert im.getbands() == original.getbands()
 | 
				
			||||||
    assert_image_equal(
 | 
					    assert_image_equal(
 | 
				
			||||||
        im.getchannel("A"),
 | 
					        im.getchannel("A"),
 | 
				
			||||||
| 
						 | 
					@ -44,7 +44,7 @@ def _check_alpha(im, original, op, amount):
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@pytest.mark.parametrize("op", ("Color", "Brightness", "Contrast", "Sharpness"))
 | 
					@pytest.mark.parametrize("op", ("Color", "Brightness", "Contrast", "Sharpness"))
 | 
				
			||||||
def test_alpha(op):
 | 
					def test_alpha(op) -> None:
 | 
				
			||||||
    # Issue https://github.com/python-pillow/Pillow/issues/899
 | 
					    # Issue https://github.com/python-pillow/Pillow/issues/899
 | 
				
			||||||
    # Is alpha preserved through image enhancement?
 | 
					    # Is alpha preserved through image enhancement?
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -30,7 +30,7 @@ SAFEBLOCK = ImageFile.SAFEBLOCK
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class TestImageFile:
 | 
					class TestImageFile:
 | 
				
			||||||
    def test_parser(self):
 | 
					    def test_parser(self) -> None:
 | 
				
			||||||
        def roundtrip(format):
 | 
					        def roundtrip(format):
 | 
				
			||||||
            im = hopper("L").resize((1000, 1000), Image.Resampling.NEAREST)
 | 
					            im = hopper("L").resize((1000, 1000), Image.Resampling.NEAREST)
 | 
				
			||||||
            if format in ("MSP", "XBM"):
 | 
					            if format in ("MSP", "XBM"):
 | 
				
			||||||
| 
						 | 
					@ -84,7 +84,7 @@ class TestImageFile:
 | 
				
			||||||
        with pytest.raises(OSError):
 | 
					        with pytest.raises(OSError):
 | 
				
			||||||
            roundtrip("PDF")
 | 
					            roundtrip("PDF")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_ico(self):
 | 
					    def test_ico(self) -> None:
 | 
				
			||||||
        with open("Tests/images/python.ico", "rb") as f:
 | 
					        with open("Tests/images/python.ico", "rb") as f:
 | 
				
			||||||
            data = f.read()
 | 
					            data = f.read()
 | 
				
			||||||
        with ImageFile.Parser() as p:
 | 
					        with ImageFile.Parser() as p:
 | 
				
			||||||
| 
						 | 
					@ -93,7 +93,7 @@ class TestImageFile:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    @skip_unless_feature("webp")
 | 
					    @skip_unless_feature("webp")
 | 
				
			||||||
    @skip_unless_feature("webp_anim")
 | 
					    @skip_unless_feature("webp_anim")
 | 
				
			||||||
    def test_incremental_webp(self):
 | 
					    def test_incremental_webp(self) -> None:
 | 
				
			||||||
        with ImageFile.Parser() as p:
 | 
					        with ImageFile.Parser() as p:
 | 
				
			||||||
            with open("Tests/images/hopper.webp", "rb") as f:
 | 
					            with open("Tests/images/hopper.webp", "rb") as f:
 | 
				
			||||||
                p.feed(f.read(1024))
 | 
					                p.feed(f.read(1024))
 | 
				
			||||||
| 
						 | 
					@ -105,7 +105,7 @@ class TestImageFile:
 | 
				
			||||||
            assert (128, 128) == p.image.size
 | 
					            assert (128, 128) == p.image.size
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    @skip_unless_feature("zlib")
 | 
					    @skip_unless_feature("zlib")
 | 
				
			||||||
    def test_safeblock(self):
 | 
					    def test_safeblock(self) -> None:
 | 
				
			||||||
        im1 = hopper()
 | 
					        im1 = hopper()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        try:
 | 
					        try:
 | 
				
			||||||
| 
						 | 
					@ -116,17 +116,17 @@ class TestImageFile:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        assert_image_equal(im1, im2)
 | 
					        assert_image_equal(im1, im2)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_raise_oserror(self):
 | 
					    def test_raise_oserror(self) -> None:
 | 
				
			||||||
        with pytest.warns(DeprecationWarning):
 | 
					        with pytest.warns(DeprecationWarning):
 | 
				
			||||||
            with pytest.raises(OSError):
 | 
					            with pytest.raises(OSError):
 | 
				
			||||||
                ImageFile.raise_oserror(1)
 | 
					                ImageFile.raise_oserror(1)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_raise_typeerror(self):
 | 
					    def test_raise_typeerror(self) -> None:
 | 
				
			||||||
        with pytest.raises(TypeError):
 | 
					        with pytest.raises(TypeError):
 | 
				
			||||||
            parser = ImageFile.Parser()
 | 
					            parser = ImageFile.Parser()
 | 
				
			||||||
            parser.feed(1)
 | 
					            parser.feed(1)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_negative_stride(self):
 | 
					    def test_negative_stride(self) -> None:
 | 
				
			||||||
        with open("Tests/images/raw_negative_stride.bin", "rb") as f:
 | 
					        with open("Tests/images/raw_negative_stride.bin", "rb") as f:
 | 
				
			||||||
            input = f.read()
 | 
					            input = f.read()
 | 
				
			||||||
        p = ImageFile.Parser()
 | 
					        p = ImageFile.Parser()
 | 
				
			||||||
| 
						 | 
					@ -134,11 +134,11 @@ class TestImageFile:
 | 
				
			||||||
        with pytest.raises(OSError):
 | 
					        with pytest.raises(OSError):
 | 
				
			||||||
            p.close()
 | 
					            p.close()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_no_format(self):
 | 
					    def test_no_format(self) -> None:
 | 
				
			||||||
        buf = BytesIO(b"\x00" * 255)
 | 
					        buf = BytesIO(b"\x00" * 255)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        class DummyImageFile(ImageFile.ImageFile):
 | 
					        class DummyImageFile(ImageFile.ImageFile):
 | 
				
			||||||
            def _open(self):
 | 
					            def _open(self) -> None:
 | 
				
			||||||
                self._mode = "RGB"
 | 
					                self._mode = "RGB"
 | 
				
			||||||
                self._size = (1, 1)
 | 
					                self._size = (1, 1)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -146,12 +146,12 @@ class TestImageFile:
 | 
				
			||||||
        assert im.format is None
 | 
					        assert im.format is None
 | 
				
			||||||
        assert im.get_format_mimetype() is None
 | 
					        assert im.get_format_mimetype() is None
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_oserror(self):
 | 
					    def test_oserror(self) -> None:
 | 
				
			||||||
        im = Image.new("RGB", (1, 1))
 | 
					        im = Image.new("RGB", (1, 1))
 | 
				
			||||||
        with pytest.raises(OSError):
 | 
					        with pytest.raises(OSError):
 | 
				
			||||||
            im.save(BytesIO(), "JPEG2000", num_resolutions=2)
 | 
					            im.save(BytesIO(), "JPEG2000", num_resolutions=2)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_truncated(self):
 | 
					    def test_truncated(self) -> None:
 | 
				
			||||||
        b = BytesIO(
 | 
					        b = BytesIO(
 | 
				
			||||||
            b"BM000000000000"  # head_data
 | 
					            b"BM000000000000"  # head_data
 | 
				
			||||||
            + _binary.o32le(
 | 
					            + _binary.o32le(
 | 
				
			||||||
| 
						 | 
					@ -166,7 +166,7 @@ class TestImageFile:
 | 
				
			||||||
        assert str(e.value) == "Truncated File Read"
 | 
					        assert str(e.value) == "Truncated File Read"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    @skip_unless_feature("zlib")
 | 
					    @skip_unless_feature("zlib")
 | 
				
			||||||
    def test_truncated_with_errors(self):
 | 
					    def test_truncated_with_errors(self) -> None:
 | 
				
			||||||
        with Image.open("Tests/images/truncated_image.png") as im:
 | 
					        with Image.open("Tests/images/truncated_image.png") as im:
 | 
				
			||||||
            with pytest.raises(OSError):
 | 
					            with pytest.raises(OSError):
 | 
				
			||||||
                im.load()
 | 
					                im.load()
 | 
				
			||||||
| 
						 | 
					@ -176,7 +176,7 @@ class TestImageFile:
 | 
				
			||||||
                im.load()
 | 
					                im.load()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    @skip_unless_feature("zlib")
 | 
					    @skip_unless_feature("zlib")
 | 
				
			||||||
    def test_truncated_without_errors(self):
 | 
					    def test_truncated_without_errors(self) -> None:
 | 
				
			||||||
        with Image.open("Tests/images/truncated_image.png") as im:
 | 
					        with Image.open("Tests/images/truncated_image.png") as im:
 | 
				
			||||||
            ImageFile.LOAD_TRUNCATED_IMAGES = True
 | 
					            ImageFile.LOAD_TRUNCATED_IMAGES = True
 | 
				
			||||||
            try:
 | 
					            try:
 | 
				
			||||||
| 
						 | 
					@ -185,13 +185,13 @@ class TestImageFile:
 | 
				
			||||||
                ImageFile.LOAD_TRUNCATED_IMAGES = False
 | 
					                ImageFile.LOAD_TRUNCATED_IMAGES = False
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    @skip_unless_feature("zlib")
 | 
					    @skip_unless_feature("zlib")
 | 
				
			||||||
    def test_broken_datastream_with_errors(self):
 | 
					    def test_broken_datastream_with_errors(self) -> None:
 | 
				
			||||||
        with Image.open("Tests/images/broken_data_stream.png") as im:
 | 
					        with Image.open("Tests/images/broken_data_stream.png") as im:
 | 
				
			||||||
            with pytest.raises(OSError):
 | 
					            with pytest.raises(OSError):
 | 
				
			||||||
                im.load()
 | 
					                im.load()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    @skip_unless_feature("zlib")
 | 
					    @skip_unless_feature("zlib")
 | 
				
			||||||
    def test_broken_datastream_without_errors(self):
 | 
					    def test_broken_datastream_without_errors(self) -> None:
 | 
				
			||||||
        with Image.open("Tests/images/broken_data_stream.png") as im:
 | 
					        with Image.open("Tests/images/broken_data_stream.png") as im:
 | 
				
			||||||
            ImageFile.LOAD_TRUNCATED_IMAGES = True
 | 
					            ImageFile.LOAD_TRUNCATED_IMAGES = True
 | 
				
			||||||
            try:
 | 
					            try:
 | 
				
			||||||
| 
						 | 
					@ -210,7 +210,7 @@ class MockPyEncoder(ImageFile.PyEncoder):
 | 
				
			||||||
    def encode(self, buffer):
 | 
					    def encode(self, buffer):
 | 
				
			||||||
        return 1, 1, b""
 | 
					        return 1, 1, b""
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def cleanup(self):
 | 
					    def cleanup(self) -> None:
 | 
				
			||||||
        self.cleanup_called = True
 | 
					        self.cleanup_called = True
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -218,7 +218,7 @@ xoff, yoff, xsize, ysize = 10, 20, 100, 100
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class MockImageFile(ImageFile.ImageFile):
 | 
					class MockImageFile(ImageFile.ImageFile):
 | 
				
			||||||
    def _open(self):
 | 
					    def _open(self) -> None:
 | 
				
			||||||
        self.rawmode = "RGBA"
 | 
					        self.rawmode = "RGBA"
 | 
				
			||||||
        self._mode = "RGBA"
 | 
					        self._mode = "RGBA"
 | 
				
			||||||
        self._size = (200, 200)
 | 
					        self._size = (200, 200)
 | 
				
			||||||
| 
						 | 
					@ -227,7 +227,7 @@ class MockImageFile(ImageFile.ImageFile):
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class CodecsTest:
 | 
					class CodecsTest:
 | 
				
			||||||
    @classmethod
 | 
					    @classmethod
 | 
				
			||||||
    def setup_class(cls):
 | 
					    def setup_class(cls) -> None:
 | 
				
			||||||
        cls.decoder = MockPyDecoder(None)
 | 
					        cls.decoder = MockPyDecoder(None)
 | 
				
			||||||
        cls.encoder = MockPyEncoder(None)
 | 
					        cls.encoder = MockPyEncoder(None)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -244,7 +244,7 @@ class CodecsTest:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class TestPyDecoder(CodecsTest):
 | 
					class TestPyDecoder(CodecsTest):
 | 
				
			||||||
    def test_setimage(self):
 | 
					    def test_setimage(self) -> None:
 | 
				
			||||||
        buf = BytesIO(b"\x00" * 255)
 | 
					        buf = BytesIO(b"\x00" * 255)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        im = MockImageFile(buf)
 | 
					        im = MockImageFile(buf)
 | 
				
			||||||
| 
						 | 
					@ -259,7 +259,7 @@ class TestPyDecoder(CodecsTest):
 | 
				
			||||||
        with pytest.raises(ValueError):
 | 
					        with pytest.raises(ValueError):
 | 
				
			||||||
            self.decoder.set_as_raw(b"\x00")
 | 
					            self.decoder.set_as_raw(b"\x00")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_extents_none(self):
 | 
					    def test_extents_none(self) -> None:
 | 
				
			||||||
        buf = BytesIO(b"\x00" * 255)
 | 
					        buf = BytesIO(b"\x00" * 255)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        im = MockImageFile(buf)
 | 
					        im = MockImageFile(buf)
 | 
				
			||||||
| 
						 | 
					@ -272,7 +272,7 @@ class TestPyDecoder(CodecsTest):
 | 
				
			||||||
        assert self.decoder.state.xsize == 200
 | 
					        assert self.decoder.state.xsize == 200
 | 
				
			||||||
        assert self.decoder.state.ysize == 200
 | 
					        assert self.decoder.state.ysize == 200
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_negsize(self):
 | 
					    def test_negsize(self) -> None:
 | 
				
			||||||
        buf = BytesIO(b"\x00" * 255)
 | 
					        buf = BytesIO(b"\x00" * 255)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        im = MockImageFile(buf)
 | 
					        im = MockImageFile(buf)
 | 
				
			||||||
| 
						 | 
					@ -285,7 +285,7 @@ class TestPyDecoder(CodecsTest):
 | 
				
			||||||
        with pytest.raises(ValueError):
 | 
					        with pytest.raises(ValueError):
 | 
				
			||||||
            im.load()
 | 
					            im.load()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_oversize(self):
 | 
					    def test_oversize(self) -> None:
 | 
				
			||||||
        buf = BytesIO(b"\x00" * 255)
 | 
					        buf = BytesIO(b"\x00" * 255)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        im = MockImageFile(buf)
 | 
					        im = MockImageFile(buf)
 | 
				
			||||||
| 
						 | 
					@ -298,14 +298,14 @@ class TestPyDecoder(CodecsTest):
 | 
				
			||||||
        with pytest.raises(ValueError):
 | 
					        with pytest.raises(ValueError):
 | 
				
			||||||
            im.load()
 | 
					            im.load()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_decode(self):
 | 
					    def test_decode(self) -> None:
 | 
				
			||||||
        decoder = ImageFile.PyDecoder(None)
 | 
					        decoder = ImageFile.PyDecoder(None)
 | 
				
			||||||
        with pytest.raises(NotImplementedError):
 | 
					        with pytest.raises(NotImplementedError):
 | 
				
			||||||
            decoder.decode(None)
 | 
					            decoder.decode(None)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class TestPyEncoder(CodecsTest):
 | 
					class TestPyEncoder(CodecsTest):
 | 
				
			||||||
    def test_setimage(self):
 | 
					    def test_setimage(self) -> None:
 | 
				
			||||||
        buf = BytesIO(b"\x00" * 255)
 | 
					        buf = BytesIO(b"\x00" * 255)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        im = MockImageFile(buf)
 | 
					        im = MockImageFile(buf)
 | 
				
			||||||
| 
						 | 
					@ -320,7 +320,7 @@ class TestPyEncoder(CodecsTest):
 | 
				
			||||||
        assert self.encoder.state.xsize == xsize
 | 
					        assert self.encoder.state.xsize == xsize
 | 
				
			||||||
        assert self.encoder.state.ysize == ysize
 | 
					        assert self.encoder.state.ysize == ysize
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_extents_none(self):
 | 
					    def test_extents_none(self) -> None:
 | 
				
			||||||
        buf = BytesIO(b"\x00" * 255)
 | 
					        buf = BytesIO(b"\x00" * 255)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        im = MockImageFile(buf)
 | 
					        im = MockImageFile(buf)
 | 
				
			||||||
| 
						 | 
					@ -334,7 +334,7 @@ class TestPyEncoder(CodecsTest):
 | 
				
			||||||
        assert self.encoder.state.xsize == 200
 | 
					        assert self.encoder.state.xsize == 200
 | 
				
			||||||
        assert self.encoder.state.ysize == 200
 | 
					        assert self.encoder.state.ysize == 200
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_negsize(self):
 | 
					    def test_negsize(self) -> None:
 | 
				
			||||||
        buf = BytesIO(b"\x00" * 255)
 | 
					        buf = BytesIO(b"\x00" * 255)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        im = MockImageFile(buf)
 | 
					        im = MockImageFile(buf)
 | 
				
			||||||
| 
						 | 
					@ -352,7 +352,7 @@ class TestPyEncoder(CodecsTest):
 | 
				
			||||||
                im, fp, [("MOCK", (xoff, yoff, xoff + xsize, -10), 0, "RGB")]
 | 
					                im, fp, [("MOCK", (xoff, yoff, xoff + xsize, -10), 0, "RGB")]
 | 
				
			||||||
            )
 | 
					            )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_oversize(self):
 | 
					    def test_oversize(self) -> None:
 | 
				
			||||||
        buf = BytesIO(b"\x00" * 255)
 | 
					        buf = BytesIO(b"\x00" * 255)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        im = MockImageFile(buf)
 | 
					        im = MockImageFile(buf)
 | 
				
			||||||
| 
						 | 
					@ -372,7 +372,7 @@ class TestPyEncoder(CodecsTest):
 | 
				
			||||||
                [("MOCK", (xoff, yoff, xoff + xsize, yoff + ysize + 100), 0, "RGB")],
 | 
					                [("MOCK", (xoff, yoff, xoff + xsize, yoff + ysize + 100), 0, "RGB")],
 | 
				
			||||||
            )
 | 
					            )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_encode(self):
 | 
					    def test_encode(self) -> None:
 | 
				
			||||||
        encoder = ImageFile.PyEncoder(None)
 | 
					        encoder = ImageFile.PyEncoder(None)
 | 
				
			||||||
        with pytest.raises(NotImplementedError):
 | 
					        with pytest.raises(NotImplementedError):
 | 
				
			||||||
            encoder.encode(None)
 | 
					            encoder.encode(None)
 | 
				
			||||||
| 
						 | 
					@ -388,6 +388,6 @@ class TestPyEncoder(CodecsTest):
 | 
				
			||||||
        with pytest.raises(NotImplementedError):
 | 
					        with pytest.raises(NotImplementedError):
 | 
				
			||||||
            encoder.encode_to_file(None, None)
 | 
					            encoder.encode_to_file(None, None)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_zero_height(self):
 | 
					    def test_zero_height(self) -> None:
 | 
				
			||||||
        with pytest.raises(UnidentifiedImageError):
 | 
					        with pytest.raises(UnidentifiedImageError):
 | 
				
			||||||
            Image.open("Tests/images/zero_height.j2k")
 | 
					            Image.open("Tests/images/zero_height.j2k")
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -31,7 +31,7 @@ TEST_TEXT = "hey you\nyou are awesome\nthis looks awkward"
 | 
				
			||||||
pytestmark = skip_unless_feature("freetype2")
 | 
					pytestmark = skip_unless_feature("freetype2")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_sanity():
 | 
					def test_sanity() -> None:
 | 
				
			||||||
    assert re.search(r"\d+\.\d+\.\d+$", features.version_module("freetype2"))
 | 
					    assert re.search(r"\d+\.\d+\.\d+$", features.version_module("freetype2"))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -51,7 +51,7 @@ def font(layout_engine):
 | 
				
			||||||
    return ImageFont.truetype(FONT_PATH, FONT_SIZE, layout_engine=layout_engine)
 | 
					    return ImageFont.truetype(FONT_PATH, FONT_SIZE, layout_engine=layout_engine)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_font_properties(font):
 | 
					def test_font_properties(font) -> None:
 | 
				
			||||||
    assert font.path == FONT_PATH
 | 
					    assert font.path == FONT_PATH
 | 
				
			||||||
    assert font.size == FONT_SIZE
 | 
					    assert font.size == FONT_SIZE
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -80,11 +80,11 @@ def _render(font, layout_engine):
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@pytest.mark.parametrize("font", (FONT_PATH, Path(FONT_PATH)))
 | 
					@pytest.mark.parametrize("font", (FONT_PATH, Path(FONT_PATH)))
 | 
				
			||||||
def test_font_with_name(layout_engine, font):
 | 
					def test_font_with_name(layout_engine, font) -> None:
 | 
				
			||||||
    _render(font, layout_engine)
 | 
					    _render(font, layout_engine)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_font_with_filelike(layout_engine):
 | 
					def test_font_with_filelike(layout_engine) -> None:
 | 
				
			||||||
    def _font_as_bytes():
 | 
					    def _font_as_bytes():
 | 
				
			||||||
        with open(FONT_PATH, "rb") as f:
 | 
					        with open(FONT_PATH, "rb") as f:
 | 
				
			||||||
            font_bytes = BytesIO(f.read())
 | 
					            font_bytes = BytesIO(f.read())
 | 
				
			||||||
| 
						 | 
					@ -102,12 +102,12 @@ def test_font_with_filelike(layout_engine):
 | 
				
			||||||
    #   _render(shared_bytes)
 | 
					    #   _render(shared_bytes)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_font_with_open_file(layout_engine):
 | 
					def test_font_with_open_file(layout_engine) -> None:
 | 
				
			||||||
    with open(FONT_PATH, "rb") as f:
 | 
					    with open(FONT_PATH, "rb") as f:
 | 
				
			||||||
        _render(f, layout_engine)
 | 
					        _render(f, layout_engine)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_render_equal(layout_engine):
 | 
					def test_render_equal(layout_engine) -> None:
 | 
				
			||||||
    img_path = _render(FONT_PATH, layout_engine)
 | 
					    img_path = _render(FONT_PATH, layout_engine)
 | 
				
			||||||
    with open(FONT_PATH, "rb") as f:
 | 
					    with open(FONT_PATH, "rb") as f:
 | 
				
			||||||
        font_filelike = BytesIO(f.read())
 | 
					        font_filelike = BytesIO(f.read())
 | 
				
			||||||
| 
						 | 
					@ -116,7 +116,7 @@ def test_render_equal(layout_engine):
 | 
				
			||||||
    assert_image_equal(img_path, img_filelike)
 | 
					    assert_image_equal(img_path, img_filelike)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_non_ascii_path(tmp_path, layout_engine):
 | 
					def test_non_ascii_path(tmp_path: Path, layout_engine) -> None:
 | 
				
			||||||
    tempfile = str(tmp_path / ("temp_" + chr(128) + ".ttf"))
 | 
					    tempfile = str(tmp_path / ("temp_" + chr(128) + ".ttf"))
 | 
				
			||||||
    try:
 | 
					    try:
 | 
				
			||||||
        shutil.copy(FONT_PATH, tempfile)
 | 
					        shutil.copy(FONT_PATH, tempfile)
 | 
				
			||||||
| 
						 | 
					@ -126,7 +126,7 @@ def test_non_ascii_path(tmp_path, layout_engine):
 | 
				
			||||||
    ImageFont.truetype(tempfile, FONT_SIZE, layout_engine=layout_engine)
 | 
					    ImageFont.truetype(tempfile, FONT_SIZE, layout_engine=layout_engine)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_transparent_background(font):
 | 
					def test_transparent_background(font) -> None:
 | 
				
			||||||
    im = Image.new(mode="RGBA", size=(300, 100))
 | 
					    im = Image.new(mode="RGBA", size=(300, 100))
 | 
				
			||||||
    draw = ImageDraw.Draw(im)
 | 
					    draw = ImageDraw.Draw(im)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -140,7 +140,7 @@ def test_transparent_background(font):
 | 
				
			||||||
    assert_image_similar_tofile(im.convert("L"), target, 0.01)
 | 
					    assert_image_similar_tofile(im.convert("L"), target, 0.01)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_I16(font):
 | 
					def test_I16(font) -> None:
 | 
				
			||||||
    im = Image.new(mode="I;16", size=(300, 100))
 | 
					    im = Image.new(mode="I;16", size=(300, 100))
 | 
				
			||||||
    draw = ImageDraw.Draw(im)
 | 
					    draw = ImageDraw.Draw(im)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -153,7 +153,7 @@ def test_I16(font):
 | 
				
			||||||
    assert_image_similar_tofile(im.convert("L"), target, 0.01)
 | 
					    assert_image_similar_tofile(im.convert("L"), target, 0.01)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_textbbox_equal(font):
 | 
					def test_textbbox_equal(font) -> None:
 | 
				
			||||||
    im = Image.new(mode="RGB", size=(300, 100))
 | 
					    im = Image.new(mode="RGB", size=(300, 100))
 | 
				
			||||||
    draw = ImageDraw.Draw(im)
 | 
					    draw = ImageDraw.Draw(im)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -182,7 +182,7 @@ def test_textbbox_equal(font):
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
def test_getlength(
 | 
					def test_getlength(
 | 
				
			||||||
    text, mode, fontname, size, layout_engine, length_basic, length_raqm
 | 
					    text, mode, fontname, size, layout_engine, length_basic, length_raqm
 | 
				
			||||||
):
 | 
					) -> None:
 | 
				
			||||||
    f = ImageFont.truetype("Tests/fonts/" + fontname, size, layout_engine=layout_engine)
 | 
					    f = ImageFont.truetype("Tests/fonts/" + fontname, size, layout_engine=layout_engine)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    im = Image.new(mode, (1, 1), 0)
 | 
					    im = Image.new(mode, (1, 1), 0)
 | 
				
			||||||
| 
						 | 
					@ -197,7 +197,7 @@ def test_getlength(
 | 
				
			||||||
        assert length == length_raqm
 | 
					        assert length == length_raqm
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_float_size():
 | 
					def test_float_size() -> None:
 | 
				
			||||||
    lengths = []
 | 
					    lengths = []
 | 
				
			||||||
    for size in (48, 48.5, 49):
 | 
					    for size in (48, 48.5, 49):
 | 
				
			||||||
        f = ImageFont.truetype(
 | 
					        f = ImageFont.truetype(
 | 
				
			||||||
| 
						 | 
					@ -207,7 +207,7 @@ def test_float_size():
 | 
				
			||||||
    assert lengths[0] != lengths[1] != lengths[2]
 | 
					    assert lengths[0] != lengths[1] != lengths[2]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_render_multiline(font):
 | 
					def test_render_multiline(font) -> None:
 | 
				
			||||||
    im = Image.new(mode="RGB", size=(300, 100))
 | 
					    im = Image.new(mode="RGB", size=(300, 100))
 | 
				
			||||||
    draw = ImageDraw.Draw(im)
 | 
					    draw = ImageDraw.Draw(im)
 | 
				
			||||||
    line_spacing = font.getbbox("A")[3] + 4
 | 
					    line_spacing = font.getbbox("A")[3] + 4
 | 
				
			||||||
| 
						 | 
					@ -223,7 +223,7 @@ def test_render_multiline(font):
 | 
				
			||||||
    assert_image_similar_tofile(im, "Tests/images/multiline_text.png", 6.2)
 | 
					    assert_image_similar_tofile(im, "Tests/images/multiline_text.png", 6.2)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_render_multiline_text(font):
 | 
					def test_render_multiline_text(font) -> None:
 | 
				
			||||||
    # Test that text() correctly connects to multiline_text()
 | 
					    # Test that text() correctly connects to multiline_text()
 | 
				
			||||||
    # and that align defaults to left
 | 
					    # and that align defaults to left
 | 
				
			||||||
    im = Image.new(mode="RGB", size=(300, 100))
 | 
					    im = Image.new(mode="RGB", size=(300, 100))
 | 
				
			||||||
| 
						 | 
					@ -243,7 +243,7 @@ def test_render_multiline_text(font):
 | 
				
			||||||
@pytest.mark.parametrize(
 | 
					@pytest.mark.parametrize(
 | 
				
			||||||
    "align, ext", (("left", ""), ("center", "_center"), ("right", "_right"))
 | 
					    "align, ext", (("left", ""), ("center", "_center"), ("right", "_right"))
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
def test_render_multiline_text_align(font, align, ext):
 | 
					def test_render_multiline_text_align(font, align, ext) -> None:
 | 
				
			||||||
    im = Image.new(mode="RGB", size=(300, 100))
 | 
					    im = Image.new(mode="RGB", size=(300, 100))
 | 
				
			||||||
    draw = ImageDraw.Draw(im)
 | 
					    draw = ImageDraw.Draw(im)
 | 
				
			||||||
    draw.multiline_text((0, 0), TEST_TEXT, font=font, align=align)
 | 
					    draw.multiline_text((0, 0), TEST_TEXT, font=font, align=align)
 | 
				
			||||||
| 
						 | 
					@ -251,7 +251,7 @@ def test_render_multiline_text_align(font, align, ext):
 | 
				
			||||||
    assert_image_similar_tofile(im, f"Tests/images/multiline_text{ext}.png", 0.01)
 | 
					    assert_image_similar_tofile(im, f"Tests/images/multiline_text{ext}.png", 0.01)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_unknown_align(font):
 | 
					def test_unknown_align(font) -> None:
 | 
				
			||||||
    im = Image.new(mode="RGB", size=(300, 100))
 | 
					    im = Image.new(mode="RGB", size=(300, 100))
 | 
				
			||||||
    draw = ImageDraw.Draw(im)
 | 
					    draw = ImageDraw.Draw(im)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -260,14 +260,14 @@ def test_unknown_align(font):
 | 
				
			||||||
        draw.multiline_text((0, 0), TEST_TEXT, font=font, align="unknown")
 | 
					        draw.multiline_text((0, 0), TEST_TEXT, font=font, align="unknown")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_draw_align(font):
 | 
					def test_draw_align(font) -> None:
 | 
				
			||||||
    im = Image.new("RGB", (300, 100), "white")
 | 
					    im = Image.new("RGB", (300, 100), "white")
 | 
				
			||||||
    draw = ImageDraw.Draw(im)
 | 
					    draw = ImageDraw.Draw(im)
 | 
				
			||||||
    line = "some text"
 | 
					    line = "some text"
 | 
				
			||||||
    draw.text((100, 40), line, (0, 0, 0), font=font, align="left")
 | 
					    draw.text((100, 40), line, (0, 0, 0), font=font, align="left")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_multiline_bbox(font):
 | 
					def test_multiline_bbox(font) -> None:
 | 
				
			||||||
    im = Image.new(mode="RGB", size=(300, 100))
 | 
					    im = Image.new(mode="RGB", size=(300, 100))
 | 
				
			||||||
    draw = ImageDraw.Draw(im)
 | 
					    draw = ImageDraw.Draw(im)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -285,7 +285,7 @@ def test_multiline_bbox(font):
 | 
				
			||||||
    draw.textbbox((0, 0), TEST_TEXT, font=font, spacing=4)
 | 
					    draw.textbbox((0, 0), TEST_TEXT, font=font, spacing=4)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_multiline_width(font):
 | 
					def test_multiline_width(font) -> None:
 | 
				
			||||||
    im = Image.new(mode="RGB", size=(300, 100))
 | 
					    im = Image.new(mode="RGB", size=(300, 100))
 | 
				
			||||||
    draw = ImageDraw.Draw(im)
 | 
					    draw = ImageDraw.Draw(im)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -295,7 +295,7 @@ def test_multiline_width(font):
 | 
				
			||||||
    )
 | 
					    )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_multiline_spacing(font):
 | 
					def test_multiline_spacing(font) -> None:
 | 
				
			||||||
    im = Image.new(mode="RGB", size=(300, 100))
 | 
					    im = Image.new(mode="RGB", size=(300, 100))
 | 
				
			||||||
    draw = ImageDraw.Draw(im)
 | 
					    draw = ImageDraw.Draw(im)
 | 
				
			||||||
    draw.multiline_text((0, 0), TEST_TEXT, font=font, spacing=10)
 | 
					    draw.multiline_text((0, 0), TEST_TEXT, font=font, spacing=10)
 | 
				
			||||||
| 
						 | 
					@ -306,7 +306,7 @@ def test_multiline_spacing(font):
 | 
				
			||||||
@pytest.mark.parametrize(
 | 
					@pytest.mark.parametrize(
 | 
				
			||||||
    "orientation", (Image.Transpose.ROTATE_90, Image.Transpose.ROTATE_270)
 | 
					    "orientation", (Image.Transpose.ROTATE_90, Image.Transpose.ROTATE_270)
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
def test_rotated_transposed_font(font, orientation):
 | 
					def test_rotated_transposed_font(font, orientation) -> None:
 | 
				
			||||||
    img_gray = Image.new("L", (100, 100))
 | 
					    img_gray = Image.new("L", (100, 100))
 | 
				
			||||||
    draw = ImageDraw.Draw(img_gray)
 | 
					    draw = ImageDraw.Draw(img_gray)
 | 
				
			||||||
    word = "testing"
 | 
					    word = "testing"
 | 
				
			||||||
| 
						 | 
					@ -347,7 +347,7 @@ def test_rotated_transposed_font(font, orientation):
 | 
				
			||||||
        Image.Transpose.FLIP_TOP_BOTTOM,
 | 
					        Image.Transpose.FLIP_TOP_BOTTOM,
 | 
				
			||||||
    ),
 | 
					    ),
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
def test_unrotated_transposed_font(font, orientation):
 | 
					def test_unrotated_transposed_font(font, orientation) -> None:
 | 
				
			||||||
    img_gray = Image.new("L", (100, 100))
 | 
					    img_gray = Image.new("L", (100, 100))
 | 
				
			||||||
    draw = ImageDraw.Draw(img_gray)
 | 
					    draw = ImageDraw.Draw(img_gray)
 | 
				
			||||||
    word = "testing"
 | 
					    word = "testing"
 | 
				
			||||||
| 
						 | 
					@ -382,7 +382,7 @@ def test_unrotated_transposed_font(font, orientation):
 | 
				
			||||||
@pytest.mark.parametrize(
 | 
					@pytest.mark.parametrize(
 | 
				
			||||||
    "orientation", (Image.Transpose.ROTATE_90, Image.Transpose.ROTATE_270)
 | 
					    "orientation", (Image.Transpose.ROTATE_90, Image.Transpose.ROTATE_270)
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
def test_rotated_transposed_font_get_mask(font, orientation):
 | 
					def test_rotated_transposed_font_get_mask(font, orientation) -> None:
 | 
				
			||||||
    # Arrange
 | 
					    # Arrange
 | 
				
			||||||
    text = "mask this"
 | 
					    text = "mask this"
 | 
				
			||||||
    transposed_font = ImageFont.TransposedFont(font, orientation=orientation)
 | 
					    transposed_font = ImageFont.TransposedFont(font, orientation=orientation)
 | 
				
			||||||
| 
						 | 
					@ -403,7 +403,7 @@ def test_rotated_transposed_font_get_mask(font, orientation):
 | 
				
			||||||
        Image.Transpose.FLIP_TOP_BOTTOM,
 | 
					        Image.Transpose.FLIP_TOP_BOTTOM,
 | 
				
			||||||
    ),
 | 
					    ),
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
def test_unrotated_transposed_font_get_mask(font, orientation):
 | 
					def test_unrotated_transposed_font_get_mask(font, orientation) -> None:
 | 
				
			||||||
    # Arrange
 | 
					    # Arrange
 | 
				
			||||||
    text = "mask this"
 | 
					    text = "mask this"
 | 
				
			||||||
    transposed_font = ImageFont.TransposedFont(font, orientation=orientation)
 | 
					    transposed_font = ImageFont.TransposedFont(font, orientation=orientation)
 | 
				
			||||||
| 
						 | 
					@ -415,11 +415,11 @@ def test_unrotated_transposed_font_get_mask(font, orientation):
 | 
				
			||||||
    assert mask.size == (108, 13)
 | 
					    assert mask.size == (108, 13)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_free_type_font_get_name(font):
 | 
					def test_free_type_font_get_name(font) -> None:
 | 
				
			||||||
    assert ("FreeMono", "Regular") == font.getname()
 | 
					    assert ("FreeMono", "Regular") == font.getname()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_free_type_font_get_metrics(font):
 | 
					def test_free_type_font_get_metrics(font) -> None:
 | 
				
			||||||
    ascent, descent = font.getmetrics()
 | 
					    ascent, descent = font.getmetrics()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    assert isinstance(ascent, int)
 | 
					    assert isinstance(ascent, int)
 | 
				
			||||||
| 
						 | 
					@ -427,7 +427,7 @@ def test_free_type_font_get_metrics(font):
 | 
				
			||||||
    assert (ascent, descent) == (16, 4)
 | 
					    assert (ascent, descent) == (16, 4)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_free_type_font_get_mask(font):
 | 
					def test_free_type_font_get_mask(font) -> None:
 | 
				
			||||||
    # Arrange
 | 
					    # Arrange
 | 
				
			||||||
    text = "mask this"
 | 
					    text = "mask this"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -438,7 +438,7 @@ def test_free_type_font_get_mask(font):
 | 
				
			||||||
    assert mask.size == (108, 13)
 | 
					    assert mask.size == (108, 13)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_load_path_not_found():
 | 
					def test_load_path_not_found() -> None:
 | 
				
			||||||
    # Arrange
 | 
					    # Arrange
 | 
				
			||||||
    filename = "somefilenamethatdoesntexist.ttf"
 | 
					    filename = "somefilenamethatdoesntexist.ttf"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -449,13 +449,13 @@ def test_load_path_not_found():
 | 
				
			||||||
        ImageFont.truetype(filename)
 | 
					        ImageFont.truetype(filename)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_load_non_font_bytes():
 | 
					def test_load_non_font_bytes() -> None:
 | 
				
			||||||
    with open("Tests/images/hopper.jpg", "rb") as f:
 | 
					    with open("Tests/images/hopper.jpg", "rb") as f:
 | 
				
			||||||
        with pytest.raises(OSError):
 | 
					        with pytest.raises(OSError):
 | 
				
			||||||
            ImageFont.truetype(f)
 | 
					            ImageFont.truetype(f)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_default_font():
 | 
					def test_default_font() -> None:
 | 
				
			||||||
    # Arrange
 | 
					    # Arrange
 | 
				
			||||||
    txt = "This is a default font using FreeType support."
 | 
					    txt = "This is a default font using FreeType support."
 | 
				
			||||||
    im = Image.new(mode="RGB", size=(300, 100))
 | 
					    im = Image.new(mode="RGB", size=(300, 100))
 | 
				
			||||||
| 
						 | 
					@ -473,16 +473,16 @@ def test_default_font():
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@pytest.mark.parametrize("mode", (None, "1", "RGBA"))
 | 
					@pytest.mark.parametrize("mode", (None, "1", "RGBA"))
 | 
				
			||||||
def test_getbbox(font, mode):
 | 
					def test_getbbox(font, mode) -> None:
 | 
				
			||||||
    assert (0, 4, 12, 16) == font.getbbox("A", mode)
 | 
					    assert (0, 4, 12, 16) == font.getbbox("A", mode)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_getbbox_empty(font):
 | 
					def test_getbbox_empty(font) -> None:
 | 
				
			||||||
    # issue #2614, should not crash.
 | 
					    # issue #2614, should not crash.
 | 
				
			||||||
    assert (0, 0, 0, 0) == font.getbbox("")
 | 
					    assert (0, 0, 0, 0) == font.getbbox("")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_render_empty(font):
 | 
					def test_render_empty(font) -> None:
 | 
				
			||||||
    # issue 2666
 | 
					    # issue 2666
 | 
				
			||||||
    im = Image.new(mode="RGB", size=(300, 100))
 | 
					    im = Image.new(mode="RGB", size=(300, 100))
 | 
				
			||||||
    target = im.copy()
 | 
					    target = im.copy()
 | 
				
			||||||
| 
						 | 
					@ -492,7 +492,7 @@ def test_render_empty(font):
 | 
				
			||||||
    assert_image_equal(im, target)
 | 
					    assert_image_equal(im, target)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_unicode_extended(layout_engine):
 | 
					def test_unicode_extended(layout_engine) -> None:
 | 
				
			||||||
    # issue #3777
 | 
					    # issue #3777
 | 
				
			||||||
    text = "A\u278A\U0001F12B"
 | 
					    text = "A\u278A\U0001F12B"
 | 
				
			||||||
    target = "Tests/images/unicode_extended.png"
 | 
					    target = "Tests/images/unicode_extended.png"
 | 
				
			||||||
| 
						 | 
					@ -515,8 +515,8 @@ def test_unicode_extended(layout_engine):
 | 
				
			||||||
    (("linux", "/usr/local/share/fonts"), ("darwin", "/System/Library/Fonts")),
 | 
					    (("linux", "/usr/local/share/fonts"), ("darwin", "/System/Library/Fonts")),
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
@pytest.mark.skipif(is_win32(), reason="requires Unix or macOS")
 | 
					@pytest.mark.skipif(is_win32(), reason="requires Unix or macOS")
 | 
				
			||||||
def test_find_font(monkeypatch, platform, font_directory):
 | 
					def test_find_font(monkeypatch, platform, font_directory) -> None:
 | 
				
			||||||
    def _test_fake_loading_font(path_to_fake, fontname):
 | 
					    def _test_fake_loading_font(path_to_fake, fontname) -> None:
 | 
				
			||||||
        # Make a copy of FreeTypeFont so we can patch the original
 | 
					        # Make a copy of FreeTypeFont so we can patch the original
 | 
				
			||||||
        free_type_font = copy.deepcopy(ImageFont.FreeTypeFont)
 | 
					        free_type_font = copy.deepcopy(ImageFont.FreeTypeFont)
 | 
				
			||||||
        with monkeypatch.context() as m:
 | 
					        with monkeypatch.context() as m:
 | 
				
			||||||
| 
						 | 
					@ -567,7 +567,7 @@ def test_find_font(monkeypatch, platform, font_directory):
 | 
				
			||||||
    _test_fake_loading_font(font_directory + "/Duplicate.ttf", "Duplicate")
 | 
					    _test_fake_loading_font(font_directory + "/Duplicate.ttf", "Duplicate")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_imagefont_getters(font):
 | 
					def test_imagefont_getters(font) -> None:
 | 
				
			||||||
    assert font.getmetrics() == (16, 4)
 | 
					    assert font.getmetrics() == (16, 4)
 | 
				
			||||||
    assert font.font.ascent == 16
 | 
					    assert font.font.ascent == 16
 | 
				
			||||||
    assert font.font.descent == 4
 | 
					    assert font.font.descent == 4
 | 
				
			||||||
| 
						 | 
					@ -588,7 +588,7 @@ def test_imagefont_getters(font):
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@pytest.mark.parametrize("stroke_width", (0, 2))
 | 
					@pytest.mark.parametrize("stroke_width", (0, 2))
 | 
				
			||||||
def test_getsize_stroke(font, stroke_width):
 | 
					def test_getsize_stroke(font, stroke_width) -> None:
 | 
				
			||||||
    assert font.getbbox("A", stroke_width=stroke_width) == (
 | 
					    assert font.getbbox("A", stroke_width=stroke_width) == (
 | 
				
			||||||
        0 - stroke_width,
 | 
					        0 - stroke_width,
 | 
				
			||||||
        4 - stroke_width,
 | 
					        4 - stroke_width,
 | 
				
			||||||
| 
						 | 
					@ -597,7 +597,7 @@ def test_getsize_stroke(font, stroke_width):
 | 
				
			||||||
    )
 | 
					    )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_complex_font_settings():
 | 
					def test_complex_font_settings() -> None:
 | 
				
			||||||
    t = ImageFont.truetype(FONT_PATH, FONT_SIZE, layout_engine=ImageFont.Layout.BASIC)
 | 
					    t = ImageFont.truetype(FONT_PATH, FONT_SIZE, layout_engine=ImageFont.Layout.BASIC)
 | 
				
			||||||
    with pytest.raises(KeyError):
 | 
					    with pytest.raises(KeyError):
 | 
				
			||||||
        t.getmask("абвг", direction="rtl")
 | 
					        t.getmask("абвг", direction="rtl")
 | 
				
			||||||
| 
						 | 
					@ -607,7 +607,7 @@ def test_complex_font_settings():
 | 
				
			||||||
        t.getmask("абвг", language="sr")
 | 
					        t.getmask("абвг", language="sr")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_variation_get(font):
 | 
					def test_variation_get(font) -> None:
 | 
				
			||||||
    freetype = parse_version(features.version_module("freetype2"))
 | 
					    freetype = parse_version(features.version_module("freetype2"))
 | 
				
			||||||
    if freetype < parse_version("2.9.1"):
 | 
					    if freetype < parse_version("2.9.1"):
 | 
				
			||||||
        with pytest.raises(NotImplementedError):
 | 
					        with pytest.raises(NotImplementedError):
 | 
				
			||||||
| 
						 | 
					@ -677,7 +677,7 @@ def _check_text(font, path, epsilon):
 | 
				
			||||||
            raise
 | 
					            raise
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_variation_set_by_name(font):
 | 
					def test_variation_set_by_name(font) -> None:
 | 
				
			||||||
    freetype = parse_version(features.version_module("freetype2"))
 | 
					    freetype = parse_version(features.version_module("freetype2"))
 | 
				
			||||||
    if freetype < parse_version("2.9.1"):
 | 
					    if freetype < parse_version("2.9.1"):
 | 
				
			||||||
        with pytest.raises(NotImplementedError):
 | 
					        with pytest.raises(NotImplementedError):
 | 
				
			||||||
| 
						 | 
					@ -702,7 +702,7 @@ def test_variation_set_by_name(font):
 | 
				
			||||||
    _check_text(font, "Tests/images/variation_tiny_name.png", 40)
 | 
					    _check_text(font, "Tests/images/variation_tiny_name.png", 40)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_variation_set_by_axes(font):
 | 
					def test_variation_set_by_axes(font) -> None:
 | 
				
			||||||
    freetype = parse_version(features.version_module("freetype2"))
 | 
					    freetype = parse_version(features.version_module("freetype2"))
 | 
				
			||||||
    if freetype < parse_version("2.9.1"):
 | 
					    if freetype < parse_version("2.9.1"):
 | 
				
			||||||
        with pytest.raises(NotImplementedError):
 | 
					        with pytest.raises(NotImplementedError):
 | 
				
			||||||
| 
						 | 
					@ -737,7 +737,7 @@ def test_variation_set_by_axes(font):
 | 
				
			||||||
    ),
 | 
					    ),
 | 
				
			||||||
    ids=("ls", "ms", "rs", "ma", "mt", "mm", "mb", "md"),
 | 
					    ids=("ls", "ms", "rs", "ma", "mt", "mm", "mb", "md"),
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
def test_anchor(layout_engine, anchor, left, top):
 | 
					def test_anchor(layout_engine, anchor, left, top) -> None:
 | 
				
			||||||
    name, text = "quick", "Quick"
 | 
					    name, text = "quick", "Quick"
 | 
				
			||||||
    path = f"Tests/images/test_anchor_{name}_{anchor}.png"
 | 
					    path = f"Tests/images/test_anchor_{name}_{anchor}.png"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -782,7 +782,7 @@ def test_anchor(layout_engine, anchor, left, top):
 | 
				
			||||||
        ("md", "center"),
 | 
					        ("md", "center"),
 | 
				
			||||||
    ),
 | 
					    ),
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
def test_anchor_multiline(layout_engine, anchor, align):
 | 
					def test_anchor_multiline(layout_engine, anchor, align) -> None:
 | 
				
			||||||
    target = f"Tests/images/test_anchor_multiline_{anchor}_{align}.png"
 | 
					    target = f"Tests/images/test_anchor_multiline_{anchor}_{align}.png"
 | 
				
			||||||
    text = "a\nlong\ntext sample"
 | 
					    text = "a\nlong\ntext sample"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -800,7 +800,7 @@ def test_anchor_multiline(layout_engine, anchor, align):
 | 
				
			||||||
    assert_image_similar_tofile(im, target, 4)
 | 
					    assert_image_similar_tofile(im, target, 4)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_anchor_invalid(font):
 | 
					def test_anchor_invalid(font) -> None:
 | 
				
			||||||
    im = Image.new("RGB", (100, 100), "white")
 | 
					    im = Image.new("RGB", (100, 100), "white")
 | 
				
			||||||
    d = ImageDraw.Draw(im)
 | 
					    d = ImageDraw.Draw(im)
 | 
				
			||||||
    d.font = font
 | 
					    d.font = font
 | 
				
			||||||
| 
						 | 
					@ -826,7 +826,7 @@ def test_anchor_invalid(font):
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@pytest.mark.parametrize("bpp", (1, 2, 4, 8))
 | 
					@pytest.mark.parametrize("bpp", (1, 2, 4, 8))
 | 
				
			||||||
def test_bitmap_font(layout_engine, bpp):
 | 
					def test_bitmap_font(layout_engine, bpp) -> None:
 | 
				
			||||||
    text = "Bitmap Font"
 | 
					    text = "Bitmap Font"
 | 
				
			||||||
    layout_name = ["basic", "raqm"][layout_engine]
 | 
					    layout_name = ["basic", "raqm"][layout_engine]
 | 
				
			||||||
    target = f"Tests/images/bitmap_font_{bpp}_{layout_name}.png"
 | 
					    target = f"Tests/images/bitmap_font_{bpp}_{layout_name}.png"
 | 
				
			||||||
| 
						 | 
					@ -843,7 +843,7 @@ def test_bitmap_font(layout_engine, bpp):
 | 
				
			||||||
    assert_image_equal_tofile(im, target)
 | 
					    assert_image_equal_tofile(im, target)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_bitmap_font_stroke(layout_engine):
 | 
					def test_bitmap_font_stroke(layout_engine) -> None:
 | 
				
			||||||
    text = "Bitmap Font"
 | 
					    text = "Bitmap Font"
 | 
				
			||||||
    layout_name = ["basic", "raqm"][layout_engine]
 | 
					    layout_name = ["basic", "raqm"][layout_engine]
 | 
				
			||||||
    target = f"Tests/images/bitmap_font_stroke_{layout_name}.png"
 | 
					    target = f"Tests/images/bitmap_font_stroke_{layout_name}.png"
 | 
				
			||||||
| 
						 | 
					@ -861,7 +861,7 @@ def test_bitmap_font_stroke(layout_engine):
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@pytest.mark.parametrize("embedded_color", (False, True))
 | 
					@pytest.mark.parametrize("embedded_color", (False, True))
 | 
				
			||||||
def test_bitmap_blend(layout_engine, embedded_color):
 | 
					def test_bitmap_blend(layout_engine, embedded_color) -> None:
 | 
				
			||||||
    font = ImageFont.truetype(
 | 
					    font = ImageFont.truetype(
 | 
				
			||||||
        "Tests/fonts/EBDTTestFont.ttf", size=64, layout_engine=layout_engine
 | 
					        "Tests/fonts/EBDTTestFont.ttf", size=64, layout_engine=layout_engine
 | 
				
			||||||
    )
 | 
					    )
 | 
				
			||||||
| 
						 | 
					@ -873,7 +873,7 @@ def test_bitmap_blend(layout_engine, embedded_color):
 | 
				
			||||||
    assert_image_equal_tofile(im, "Tests/images/bitmap_font_blend.png")
 | 
					    assert_image_equal_tofile(im, "Tests/images/bitmap_font_blend.png")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_standard_embedded_color(layout_engine):
 | 
					def test_standard_embedded_color(layout_engine) -> None:
 | 
				
			||||||
    txt = "Hello World!"
 | 
					    txt = "Hello World!"
 | 
				
			||||||
    ttf = ImageFont.truetype(FONT_PATH, 40, layout_engine=layout_engine)
 | 
					    ttf = ImageFont.truetype(FONT_PATH, 40, layout_engine=layout_engine)
 | 
				
			||||||
    ttf.getbbox(txt)
 | 
					    ttf.getbbox(txt)
 | 
				
			||||||
| 
						 | 
					@ -908,7 +908,7 @@ def test_float_coord(layout_engine, fontmode):
 | 
				
			||||||
            raise
 | 
					            raise
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_cbdt(layout_engine):
 | 
					def test_cbdt(layout_engine) -> None:
 | 
				
			||||||
    try:
 | 
					    try:
 | 
				
			||||||
        font = ImageFont.truetype(
 | 
					        font = ImageFont.truetype(
 | 
				
			||||||
            "Tests/fonts/CBDTTestFont.ttf", size=64, layout_engine=layout_engine
 | 
					            "Tests/fonts/CBDTTestFont.ttf", size=64, layout_engine=layout_engine
 | 
				
			||||||
| 
						 | 
					@ -925,7 +925,7 @@ def test_cbdt(layout_engine):
 | 
				
			||||||
        pytest.skip("freetype compiled without libpng or CBDT support")
 | 
					        pytest.skip("freetype compiled without libpng or CBDT support")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_cbdt_mask(layout_engine):
 | 
					def test_cbdt_mask(layout_engine) -> None:
 | 
				
			||||||
    try:
 | 
					    try:
 | 
				
			||||||
        font = ImageFont.truetype(
 | 
					        font = ImageFont.truetype(
 | 
				
			||||||
            "Tests/fonts/CBDTTestFont.ttf", size=64, layout_engine=layout_engine
 | 
					            "Tests/fonts/CBDTTestFont.ttf", size=64, layout_engine=layout_engine
 | 
				
			||||||
| 
						 | 
					@ -942,7 +942,7 @@ def test_cbdt_mask(layout_engine):
 | 
				
			||||||
        pytest.skip("freetype compiled without libpng or CBDT support")
 | 
					        pytest.skip("freetype compiled without libpng or CBDT support")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_sbix(layout_engine):
 | 
					def test_sbix(layout_engine) -> None:
 | 
				
			||||||
    try:
 | 
					    try:
 | 
				
			||||||
        font = ImageFont.truetype(
 | 
					        font = ImageFont.truetype(
 | 
				
			||||||
            "Tests/fonts/chromacheck-sbix.woff", size=300, layout_engine=layout_engine
 | 
					            "Tests/fonts/chromacheck-sbix.woff", size=300, layout_engine=layout_engine
 | 
				
			||||||
| 
						 | 
					@ -959,7 +959,7 @@ def test_sbix(layout_engine):
 | 
				
			||||||
        pytest.skip("freetype compiled without libpng or SBIX support")
 | 
					        pytest.skip("freetype compiled without libpng or SBIX support")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_sbix_mask(layout_engine):
 | 
					def test_sbix_mask(layout_engine) -> None:
 | 
				
			||||||
    try:
 | 
					    try:
 | 
				
			||||||
        font = ImageFont.truetype(
 | 
					        font = ImageFont.truetype(
 | 
				
			||||||
            "Tests/fonts/chromacheck-sbix.woff", size=300, layout_engine=layout_engine
 | 
					            "Tests/fonts/chromacheck-sbix.woff", size=300, layout_engine=layout_engine
 | 
				
			||||||
| 
						 | 
					@ -977,7 +977,7 @@ def test_sbix_mask(layout_engine):
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@skip_unless_feature_version("freetype2", "2.10.0")
 | 
					@skip_unless_feature_version("freetype2", "2.10.0")
 | 
				
			||||||
def test_colr(layout_engine):
 | 
					def test_colr(layout_engine) -> None:
 | 
				
			||||||
    font = ImageFont.truetype(
 | 
					    font = ImageFont.truetype(
 | 
				
			||||||
        "Tests/fonts/BungeeColor-Regular_colr_Windows.ttf",
 | 
					        "Tests/fonts/BungeeColor-Regular_colr_Windows.ttf",
 | 
				
			||||||
        size=64,
 | 
					        size=64,
 | 
				
			||||||
| 
						 | 
					@ -993,7 +993,7 @@ def test_colr(layout_engine):
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@skip_unless_feature_version("freetype2", "2.10.0")
 | 
					@skip_unless_feature_version("freetype2", "2.10.0")
 | 
				
			||||||
def test_colr_mask(layout_engine):
 | 
					def test_colr_mask(layout_engine) -> None:
 | 
				
			||||||
    font = ImageFont.truetype(
 | 
					    font = ImageFont.truetype(
 | 
				
			||||||
        "Tests/fonts/BungeeColor-Regular_colr_Windows.ttf",
 | 
					        "Tests/fonts/BungeeColor-Regular_colr_Windows.ttf",
 | 
				
			||||||
        size=64,
 | 
					        size=64,
 | 
				
			||||||
| 
						 | 
					@ -1008,7 +1008,7 @@ def test_colr_mask(layout_engine):
 | 
				
			||||||
    assert_image_similar_tofile(im, "Tests/images/colr_bungee_mask.png", 22)
 | 
					    assert_image_similar_tofile(im, "Tests/images/colr_bungee_mask.png", 22)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_woff2(layout_engine):
 | 
					def test_woff2(layout_engine) -> None:
 | 
				
			||||||
    try:
 | 
					    try:
 | 
				
			||||||
        font = ImageFont.truetype(
 | 
					        font = ImageFont.truetype(
 | 
				
			||||||
            "Tests/fonts/OpenSans.woff2",
 | 
					            "Tests/fonts/OpenSans.woff2",
 | 
				
			||||||
| 
						 | 
					@ -1027,7 +1027,7 @@ def test_woff2(layout_engine):
 | 
				
			||||||
    assert_image_similar_tofile(im, "Tests/images/test_woff2.png", 5)
 | 
					    assert_image_similar_tofile(im, "Tests/images/test_woff2.png", 5)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_render_mono_size():
 | 
					def test_render_mono_size() -> None:
 | 
				
			||||||
    # issue 4177
 | 
					    # issue 4177
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    im = Image.new("P", (100, 30), "white")
 | 
					    im = Image.new("P", (100, 30), "white")
 | 
				
			||||||
| 
						 | 
					@ -1042,7 +1042,7 @@ def test_render_mono_size():
 | 
				
			||||||
    assert_image_equal_tofile(im, "Tests/images/text_mono.gif")
 | 
					    assert_image_equal_tofile(im, "Tests/images/text_mono.gif")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_too_many_characters(font):
 | 
					def test_too_many_characters(font) -> None:
 | 
				
			||||||
    with pytest.raises(ValueError):
 | 
					    with pytest.raises(ValueError):
 | 
				
			||||||
        font.getlength("A" * 1_000_001)
 | 
					        font.getlength("A" * 1_000_001)
 | 
				
			||||||
    with pytest.raises(ValueError):
 | 
					    with pytest.raises(ValueError):
 | 
				
			||||||
| 
						 | 
					@ -1070,14 +1070,14 @@ def test_too_many_characters(font):
 | 
				
			||||||
        "Tests/fonts/oom-4da0210eb7081b0bf15bf16cc4c52ce02c1e1bbc.ttf",
 | 
					        "Tests/fonts/oom-4da0210eb7081b0bf15bf16cc4c52ce02c1e1bbc.ttf",
 | 
				
			||||||
    ],
 | 
					    ],
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
def test_oom(test_file):
 | 
					def test_oom(test_file) -> None:
 | 
				
			||||||
    with open(test_file, "rb") as f:
 | 
					    with open(test_file, "rb") as f:
 | 
				
			||||||
        font = ImageFont.truetype(BytesIO(f.read()))
 | 
					        font = ImageFont.truetype(BytesIO(f.read()))
 | 
				
			||||||
        with pytest.raises(Image.DecompressionBombError):
 | 
					        with pytest.raises(Image.DecompressionBombError):
 | 
				
			||||||
            font.getmask("Test Text")
 | 
					            font.getmask("Test Text")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_raqm_missing_warning(monkeypatch):
 | 
					def test_raqm_missing_warning(monkeypatch) -> None:
 | 
				
			||||||
    monkeypatch.setattr(ImageFont.core, "HAVE_RAQM", False)
 | 
					    monkeypatch.setattr(ImageFont.core, "HAVE_RAQM", False)
 | 
				
			||||||
    with pytest.warns(UserWarning) as record:
 | 
					    with pytest.warns(UserWarning) as record:
 | 
				
			||||||
        font = ImageFont.truetype(
 | 
					        font = ImageFont.truetype(
 | 
				
			||||||
| 
						 | 
					@ -1091,6 +1091,6 @@ def test_raqm_missing_warning(monkeypatch):
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@pytest.mark.parametrize("size", [-1, 0])
 | 
					@pytest.mark.parametrize("size", [-1, 0])
 | 
				
			||||||
def test_invalid_truetype_sizes_raise_valueerror(layout_engine, size):
 | 
					def test_invalid_truetype_sizes_raise_valueerror(layout_engine, size) -> None:
 | 
				
			||||||
    with pytest.raises(ValueError):
 | 
					    with pytest.raises(ValueError):
 | 
				
			||||||
        ImageFont.truetype(FONT_PATH, size, layout_engine=layout_engine)
 | 
					        ImageFont.truetype(FONT_PATH, size, layout_engine=layout_engine)
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -12,7 +12,7 @@ FONT_PATH = "Tests/fonts/DejaVuSans/DejaVuSans.ttf"
 | 
				
			||||||
pytestmark = skip_unless_feature("raqm")
 | 
					pytestmark = skip_unless_feature("raqm")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_english():
 | 
					def test_english() -> None:
 | 
				
			||||||
    # smoke test, this should not fail
 | 
					    # smoke test, this should not fail
 | 
				
			||||||
    ttf = ImageFont.truetype(FONT_PATH, FONT_SIZE)
 | 
					    ttf = ImageFont.truetype(FONT_PATH, FONT_SIZE)
 | 
				
			||||||
    im = Image.new(mode="RGB", size=(300, 100))
 | 
					    im = Image.new(mode="RGB", size=(300, 100))
 | 
				
			||||||
| 
						 | 
					@ -20,7 +20,7 @@ def test_english():
 | 
				
			||||||
    draw.text((0, 0), "TEST", font=ttf, fill=500, direction="ltr")
 | 
					    draw.text((0, 0), "TEST", font=ttf, fill=500, direction="ltr")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_complex_text():
 | 
					def test_complex_text() -> None:
 | 
				
			||||||
    ttf = ImageFont.truetype(FONT_PATH, FONT_SIZE)
 | 
					    ttf = ImageFont.truetype(FONT_PATH, FONT_SIZE)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    im = Image.new(mode="RGB", size=(300, 100))
 | 
					    im = Image.new(mode="RGB", size=(300, 100))
 | 
				
			||||||
| 
						 | 
					@ -31,7 +31,7 @@ def test_complex_text():
 | 
				
			||||||
    assert_image_similar_tofile(im, target, 0.5)
 | 
					    assert_image_similar_tofile(im, target, 0.5)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_y_offset():
 | 
					def test_y_offset() -> None:
 | 
				
			||||||
    ttf = ImageFont.truetype("Tests/fonts/NotoNastaliqUrdu-Regular.ttf", FONT_SIZE)
 | 
					    ttf = ImageFont.truetype("Tests/fonts/NotoNastaliqUrdu-Regular.ttf", FONT_SIZE)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    im = Image.new(mode="RGB", size=(300, 100))
 | 
					    im = Image.new(mode="RGB", size=(300, 100))
 | 
				
			||||||
| 
						 | 
					@ -42,7 +42,7 @@ def test_y_offset():
 | 
				
			||||||
    assert_image_similar_tofile(im, target, 1.7)
 | 
					    assert_image_similar_tofile(im, target, 1.7)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_complex_unicode_text():
 | 
					def test_complex_unicode_text() -> None:
 | 
				
			||||||
    ttf = ImageFont.truetype(FONT_PATH, FONT_SIZE)
 | 
					    ttf = ImageFont.truetype(FONT_PATH, FONT_SIZE)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    im = Image.new(mode="RGB", size=(300, 100))
 | 
					    im = Image.new(mode="RGB", size=(300, 100))
 | 
				
			||||||
| 
						 | 
					@ -62,7 +62,7 @@ def test_complex_unicode_text():
 | 
				
			||||||
    assert_image_similar_tofile(im, target, 2.33)
 | 
					    assert_image_similar_tofile(im, target, 2.33)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_text_direction_rtl():
 | 
					def test_text_direction_rtl() -> None:
 | 
				
			||||||
    ttf = ImageFont.truetype(FONT_PATH, FONT_SIZE)
 | 
					    ttf = ImageFont.truetype(FONT_PATH, FONT_SIZE)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    im = Image.new(mode="RGB", size=(300, 100))
 | 
					    im = Image.new(mode="RGB", size=(300, 100))
 | 
				
			||||||
| 
						 | 
					@ -73,7 +73,7 @@ def test_text_direction_rtl():
 | 
				
			||||||
    assert_image_similar_tofile(im, target, 0.5)
 | 
					    assert_image_similar_tofile(im, target, 0.5)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_text_direction_ltr():
 | 
					def test_text_direction_ltr() -> None:
 | 
				
			||||||
    ttf = ImageFont.truetype(FONT_PATH, FONT_SIZE)
 | 
					    ttf = ImageFont.truetype(FONT_PATH, FONT_SIZE)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    im = Image.new(mode="RGB", size=(300, 100))
 | 
					    im = Image.new(mode="RGB", size=(300, 100))
 | 
				
			||||||
| 
						 | 
					@ -84,7 +84,7 @@ def test_text_direction_ltr():
 | 
				
			||||||
    assert_image_similar_tofile(im, target, 0.5)
 | 
					    assert_image_similar_tofile(im, target, 0.5)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_text_direction_rtl2():
 | 
					def test_text_direction_rtl2() -> None:
 | 
				
			||||||
    ttf = ImageFont.truetype(FONT_PATH, FONT_SIZE)
 | 
					    ttf = ImageFont.truetype(FONT_PATH, FONT_SIZE)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    im = Image.new(mode="RGB", size=(300, 100))
 | 
					    im = Image.new(mode="RGB", size=(300, 100))
 | 
				
			||||||
| 
						 | 
					@ -95,7 +95,7 @@ def test_text_direction_rtl2():
 | 
				
			||||||
    assert_image_similar_tofile(im, target, 0.5)
 | 
					    assert_image_similar_tofile(im, target, 0.5)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_text_direction_ttb():
 | 
					def test_text_direction_ttb() -> None:
 | 
				
			||||||
    ttf = ImageFont.truetype("Tests/fonts/NotoSansJP-Regular.otf", FONT_SIZE)
 | 
					    ttf = ImageFont.truetype("Tests/fonts/NotoSansJP-Regular.otf", FONT_SIZE)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    im = Image.new(mode="RGB", size=(100, 300))
 | 
					    im = Image.new(mode="RGB", size=(100, 300))
 | 
				
			||||||
| 
						 | 
					@ -110,7 +110,7 @@ def test_text_direction_ttb():
 | 
				
			||||||
    assert_image_similar_tofile(im, target, 2.8)
 | 
					    assert_image_similar_tofile(im, target, 2.8)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_text_direction_ttb_stroke():
 | 
					def test_text_direction_ttb_stroke() -> None:
 | 
				
			||||||
    ttf = ImageFont.truetype("Tests/fonts/NotoSansJP-Regular.otf", 50)
 | 
					    ttf = ImageFont.truetype("Tests/fonts/NotoSansJP-Regular.otf", 50)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    im = Image.new(mode="RGB", size=(100, 300))
 | 
					    im = Image.new(mode="RGB", size=(100, 300))
 | 
				
			||||||
| 
						 | 
					@ -133,7 +133,7 @@ def test_text_direction_ttb_stroke():
 | 
				
			||||||
    assert_image_similar_tofile(im, target, 19.4)
 | 
					    assert_image_similar_tofile(im, target, 19.4)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_ligature_features():
 | 
					def test_ligature_features() -> None:
 | 
				
			||||||
    ttf = ImageFont.truetype(FONT_PATH, FONT_SIZE)
 | 
					    ttf = ImageFont.truetype(FONT_PATH, FONT_SIZE)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    im = Image.new(mode="RGB", size=(300, 100))
 | 
					    im = Image.new(mode="RGB", size=(300, 100))
 | 
				
			||||||
| 
						 | 
					@ -146,7 +146,7 @@ def test_ligature_features():
 | 
				
			||||||
    assert liga_bbox == (0, 4, 13, 19)
 | 
					    assert liga_bbox == (0, 4, 13, 19)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_kerning_features():
 | 
					def test_kerning_features() -> None:
 | 
				
			||||||
    ttf = ImageFont.truetype(FONT_PATH, FONT_SIZE)
 | 
					    ttf = ImageFont.truetype(FONT_PATH, FONT_SIZE)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    im = Image.new(mode="RGB", size=(300, 100))
 | 
					    im = Image.new(mode="RGB", size=(300, 100))
 | 
				
			||||||
| 
						 | 
					@ -157,7 +157,7 @@ def test_kerning_features():
 | 
				
			||||||
    assert_image_similar_tofile(im, target, 0.5)
 | 
					    assert_image_similar_tofile(im, target, 0.5)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_arabictext_features():
 | 
					def test_arabictext_features() -> None:
 | 
				
			||||||
    ttf = ImageFont.truetype(FONT_PATH, FONT_SIZE)
 | 
					    ttf = ImageFont.truetype(FONT_PATH, FONT_SIZE)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    im = Image.new(mode="RGB", size=(300, 100))
 | 
					    im = Image.new(mode="RGB", size=(300, 100))
 | 
				
			||||||
| 
						 | 
					@ -174,7 +174,7 @@ def test_arabictext_features():
 | 
				
			||||||
    assert_image_similar_tofile(im, target, 0.5)
 | 
					    assert_image_similar_tofile(im, target, 0.5)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_x_max_and_y_offset():
 | 
					def test_x_max_and_y_offset() -> None:
 | 
				
			||||||
    ttf = ImageFont.truetype("Tests/fonts/ArefRuqaa-Regular.ttf", 40)
 | 
					    ttf = ImageFont.truetype("Tests/fonts/ArefRuqaa-Regular.ttf", 40)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    im = Image.new(mode="RGB", size=(50, 100))
 | 
					    im = Image.new(mode="RGB", size=(50, 100))
 | 
				
			||||||
| 
						 | 
					@ -185,7 +185,7 @@ def test_x_max_and_y_offset():
 | 
				
			||||||
    assert_image_similar_tofile(im, target, 0.5)
 | 
					    assert_image_similar_tofile(im, target, 0.5)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_language():
 | 
					def test_language() -> None:
 | 
				
			||||||
    ttf = ImageFont.truetype(FONT_PATH, FONT_SIZE)
 | 
					    ttf = ImageFont.truetype(FONT_PATH, FONT_SIZE)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    im = Image.new(mode="RGB", size=(300, 100))
 | 
					    im = Image.new(mode="RGB", size=(300, 100))
 | 
				
			||||||
| 
						 | 
					@ -208,7 +208,7 @@ def test_language():
 | 
				
			||||||
    ),
 | 
					    ),
 | 
				
			||||||
    ids=("None", "ltr", "rtl2", "rtl", "ttb"),
 | 
					    ids=("None", "ltr", "rtl2", "rtl", "ttb"),
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
def test_getlength(mode, text, direction, expected):
 | 
					def test_getlength(mode, text, direction, expected) -> None:
 | 
				
			||||||
    ttf = ImageFont.truetype(FONT_PATH, FONT_SIZE)
 | 
					    ttf = ImageFont.truetype(FONT_PATH, FONT_SIZE)
 | 
				
			||||||
    im = Image.new(mode, (1, 1), 0)
 | 
					    im = Image.new(mode, (1, 1), 0)
 | 
				
			||||||
    d = ImageDraw.Draw(im)
 | 
					    d = ImageDraw.Draw(im)
 | 
				
			||||||
| 
						 | 
					@ -230,7 +230,7 @@ def test_getlength(mode, text, direction, expected):
 | 
				
			||||||
    ("i" + ("\u030C" * 15) + "i", "i" + "\u032C" * 15 + "i", "\u035Cii", "i\u0305i"),
 | 
					    ("i" + ("\u030C" * 15) + "i", "i" + "\u032C" * 15 + "i", "\u035Cii", "i\u0305i"),
 | 
				
			||||||
    ids=("caron-above", "caron-below", "double-breve", "overline"),
 | 
					    ids=("caron-above", "caron-below", "double-breve", "overline"),
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
def test_getlength_combine(mode, direction, text):
 | 
					def test_getlength_combine(mode, direction, text) -> None:
 | 
				
			||||||
    if text == "i\u0305i" and direction == "ttb":
 | 
					    if text == "i\u0305i" and direction == "ttb":
 | 
				
			||||||
        pytest.skip("fails with this font")
 | 
					        pytest.skip("fails with this font")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -250,7 +250,7 @@ def test_getlength_combine(mode, direction, text):
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@pytest.mark.parametrize("anchor", ("lt", "mm", "rb", "sm"))
 | 
					@pytest.mark.parametrize("anchor", ("lt", "mm", "rb", "sm"))
 | 
				
			||||||
def test_anchor_ttb(anchor):
 | 
					def test_anchor_ttb(anchor) -> None:
 | 
				
			||||||
    text = "f"
 | 
					    text = "f"
 | 
				
			||||||
    path = f"Tests/images/test_anchor_ttb_{text}_{anchor}.png"
 | 
					    path = f"Tests/images/test_anchor_ttb_{text}_{anchor}.png"
 | 
				
			||||||
    f = ImageFont.truetype("Tests/fonts/NotoSans-Regular.ttf", 120)
 | 
					    f = ImageFont.truetype("Tests/fonts/NotoSans-Regular.ttf", 120)
 | 
				
			||||||
| 
						 | 
					@ -306,7 +306,7 @@ combine_tests = (
 | 
				
			||||||
@pytest.mark.parametrize(
 | 
					@pytest.mark.parametrize(
 | 
				
			||||||
    "name, text, anchor, dir, epsilon", combine_tests, ids=[r[0] for r in combine_tests]
 | 
					    "name, text, anchor, dir, epsilon", combine_tests, ids=[r[0] for r in combine_tests]
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
def test_combine(name, text, dir, anchor, epsilon):
 | 
					def test_combine(name, text, dir, anchor, epsilon) -> None:
 | 
				
			||||||
    path = f"Tests/images/test_combine_{name}.png"
 | 
					    path = f"Tests/images/test_combine_{name}.png"
 | 
				
			||||||
    f = ImageFont.truetype("Tests/fonts/NotoSans-Regular.ttf", 48)
 | 
					    f = ImageFont.truetype("Tests/fonts/NotoSans-Regular.ttf", 48)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -337,7 +337,7 @@ def test_combine(name, text, dir, anchor, epsilon):
 | 
				
			||||||
        ("rm", "right"),  # pass with getsize
 | 
					        ("rm", "right"),  # pass with getsize
 | 
				
			||||||
    ),
 | 
					    ),
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
def test_combine_multiline(anchor, align):
 | 
					def test_combine_multiline(anchor, align) -> None:
 | 
				
			||||||
    # test that multiline text uses getlength, not getsize or getbbox
 | 
					    # test that multiline text uses getlength, not getsize or getbbox
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    path = f"Tests/images/test_combine_multiline_{anchor}_{align}.png"
 | 
					    path = f"Tests/images/test_combine_multiline_{anchor}_{align}.png"
 | 
				
			||||||
| 
						 | 
					@ -355,7 +355,7 @@ def test_combine_multiline(anchor, align):
 | 
				
			||||||
    assert_image_similar_tofile(im, path, 0.015)
 | 
					    assert_image_similar_tofile(im, path, 0.015)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_anchor_invalid_ttb():
 | 
					def test_anchor_invalid_ttb() -> None:
 | 
				
			||||||
    font = ImageFont.truetype(FONT_PATH, FONT_SIZE)
 | 
					    font = ImageFont.truetype(FONT_PATH, FONT_SIZE)
 | 
				
			||||||
    im = Image.new("RGB", (100, 100), "white")
 | 
					    im = Image.new("RGB", (100, 100), "white")
 | 
				
			||||||
    d = ImageDraw.Draw(im)
 | 
					    d = ImageDraw.Draw(im)
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -12,16 +12,16 @@ from .helper import assert_image_equal_tofile
 | 
				
			||||||
original_core = ImageFont.core
 | 
					original_core = ImageFont.core
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def setup_module():
 | 
					def setup_module() -> None:
 | 
				
			||||||
    if features.check_module("freetype2"):
 | 
					    if features.check_module("freetype2"):
 | 
				
			||||||
        ImageFont.core = _util.DeferredError(ImportError)
 | 
					        ImageFont.core = _util.DeferredError(ImportError)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def teardown_module():
 | 
					def teardown_module() -> None:
 | 
				
			||||||
    ImageFont.core = original_core
 | 
					    ImageFont.core = original_core
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_default_font():
 | 
					def test_default_font() -> None:
 | 
				
			||||||
    # Arrange
 | 
					    # Arrange
 | 
				
			||||||
    txt = 'This is a "better than nothing" default font.'
 | 
					    txt = 'This is a "better than nothing" default font.'
 | 
				
			||||||
    im = Image.new(mode="RGB", size=(300, 100))
 | 
					    im = Image.new(mode="RGB", size=(300, 100))
 | 
				
			||||||
| 
						 | 
					@ -35,12 +35,12 @@ def test_default_font():
 | 
				
			||||||
    assert_image_equal_tofile(im, "Tests/images/default_font.png")
 | 
					    assert_image_equal_tofile(im, "Tests/images/default_font.png")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_size_without_freetype():
 | 
					def test_size_without_freetype() -> None:
 | 
				
			||||||
    with pytest.raises(ImportError):
 | 
					    with pytest.raises(ImportError):
 | 
				
			||||||
        ImageFont.load_default(size=14)
 | 
					        ImageFont.load_default(size=14)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_unicode():
 | 
					def test_unicode() -> None:
 | 
				
			||||||
    # should not segfault, should return UnicodeDecodeError
 | 
					    # should not segfault, should return UnicodeDecodeError
 | 
				
			||||||
    # issue #2826
 | 
					    # issue #2826
 | 
				
			||||||
    font = ImageFont.load_default()
 | 
					    font = ImageFont.load_default()
 | 
				
			||||||
| 
						 | 
					@ -48,7 +48,7 @@ def test_unicode():
 | 
				
			||||||
        font.getbbox("’")
 | 
					        font.getbbox("’")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_textbbox():
 | 
					def test_textbbox() -> None:
 | 
				
			||||||
    im = Image.new("RGB", (200, 200))
 | 
					    im = Image.new("RGB", (200, 200))
 | 
				
			||||||
    d = ImageDraw.Draw(im)
 | 
					    d = ImageDraw.Draw(im)
 | 
				
			||||||
    default_font = ImageFont.load_default()
 | 
					    default_font = ImageFont.load_default()
 | 
				
			||||||
| 
						 | 
					@ -56,7 +56,7 @@ def test_textbbox():
 | 
				
			||||||
    assert d.textbbox((0, 0), "test", font=default_font) == (0, 0, 24, 11)
 | 
					    assert d.textbbox((0, 0), "test", font=default_font) == (0, 0, 24, 11)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_decompression_bomb():
 | 
					def test_decompression_bomb() -> None:
 | 
				
			||||||
    glyph = struct.pack(">hhhhhhhhhh", 1, 0, 0, 0, 256, 256, 0, 0, 256, 256)
 | 
					    glyph = struct.pack(">hhhhhhhhhh", 1, 0, 0, 0, 256, 256, 0, 0, 256, 256)
 | 
				
			||||||
    fp = BytesIO(b"PILfont\n\nDATA\n" + glyph * 256)
 | 
					    fp = BytesIO(b"PILfont\n\nDATA\n" + glyph * 256)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -67,7 +67,7 @@ def test_decompression_bomb():
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@pytest.mark.timeout(4)
 | 
					@pytest.mark.timeout(4)
 | 
				
			||||||
def test_oom():
 | 
					def test_oom() -> None:
 | 
				
			||||||
    glyph = struct.pack(
 | 
					    glyph = struct.pack(
 | 
				
			||||||
        ">hhhhhhhhhh", 1, 0, -32767, -32767, 32767, 32767, -32767, -32767, 32767, 32767
 | 
					        ">hhhhhhhhhh", 1, 0, -32767, -32767, 32767, 32767, -32767, -32767, 32767, 32767
 | 
				
			||||||
    )
 | 
					    )
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -20,7 +20,7 @@ class TestImageGrab:
 | 
				
			||||||
    @pytest.mark.skipif(
 | 
					    @pytest.mark.skipif(
 | 
				
			||||||
        sys.platform not in ("win32", "darwin"), reason="requires Windows or macOS"
 | 
					        sys.platform not in ("win32", "darwin"), reason="requires Windows or macOS"
 | 
				
			||||||
    )
 | 
					    )
 | 
				
			||||||
    def test_grab(self):
 | 
					    def test_grab(self) -> None:
 | 
				
			||||||
        ImageGrab.grab()
 | 
					        ImageGrab.grab()
 | 
				
			||||||
        ImageGrab.grab(include_layered_windows=True)
 | 
					        ImageGrab.grab(include_layered_windows=True)
 | 
				
			||||||
        ImageGrab.grab(all_screens=True)
 | 
					        ImageGrab.grab(all_screens=True)
 | 
				
			||||||
| 
						 | 
					@ -29,7 +29,7 @@ class TestImageGrab:
 | 
				
			||||||
        assert im.size == (40, 60)
 | 
					        assert im.size == (40, 60)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    @skip_unless_feature("xcb")
 | 
					    @skip_unless_feature("xcb")
 | 
				
			||||||
    def test_grab_x11(self):
 | 
					    def test_grab_x11(self) -> None:
 | 
				
			||||||
        try:
 | 
					        try:
 | 
				
			||||||
            if sys.platform not in ("win32", "darwin"):
 | 
					            if sys.platform not in ("win32", "darwin"):
 | 
				
			||||||
                ImageGrab.grab()
 | 
					                ImageGrab.grab()
 | 
				
			||||||
| 
						 | 
					@ -39,7 +39,7 @@ class TestImageGrab:
 | 
				
			||||||
            pytest.skip(str(e))
 | 
					            pytest.skip(str(e))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    @pytest.mark.skipif(Image.core.HAVE_XCB, reason="tests missing XCB")
 | 
					    @pytest.mark.skipif(Image.core.HAVE_XCB, reason="tests missing XCB")
 | 
				
			||||||
    def test_grab_no_xcb(self):
 | 
					    def test_grab_no_xcb(self) -> None:
 | 
				
			||||||
        if sys.platform not in ("win32", "darwin") and not shutil.which(
 | 
					        if sys.platform not in ("win32", "darwin") and not shutil.which(
 | 
				
			||||||
            "gnome-screenshot"
 | 
					            "gnome-screenshot"
 | 
				
			||||||
        ):
 | 
					        ):
 | 
				
			||||||
| 
						 | 
					@ -52,12 +52,12 @@ class TestImageGrab:
 | 
				
			||||||
        assert str(e.value).startswith("Pillow was built without XCB support")
 | 
					        assert str(e.value).startswith("Pillow was built without XCB support")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    @skip_unless_feature("xcb")
 | 
					    @skip_unless_feature("xcb")
 | 
				
			||||||
    def test_grab_invalid_xdisplay(self):
 | 
					    def test_grab_invalid_xdisplay(self) -> None:
 | 
				
			||||||
        with pytest.raises(OSError) as e:
 | 
					        with pytest.raises(OSError) as e:
 | 
				
			||||||
            ImageGrab.grab(xdisplay="error.test:0.0")
 | 
					            ImageGrab.grab(xdisplay="error.test:0.0")
 | 
				
			||||||
        assert str(e.value).startswith("X connection failed")
 | 
					        assert str(e.value).startswith("X connection failed")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_grabclipboard(self):
 | 
					    def test_grabclipboard(self) -> None:
 | 
				
			||||||
        if sys.platform == "darwin":
 | 
					        if sys.platform == "darwin":
 | 
				
			||||||
            subprocess.call(["screencapture", "-cx"])
 | 
					            subprocess.call(["screencapture", "-cx"])
 | 
				
			||||||
        elif sys.platform == "win32":
 | 
					        elif sys.platform == "win32":
 | 
				
			||||||
| 
						 | 
					@ -82,7 +82,7 @@ $bmp = New-Object Drawing.Bitmap 200, 200
 | 
				
			||||||
        ImageGrab.grabclipboard()
 | 
					        ImageGrab.grabclipboard()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    @pytest.mark.skipif(sys.platform != "win32", reason="Windows only")
 | 
					    @pytest.mark.skipif(sys.platform != "win32", reason="Windows only")
 | 
				
			||||||
    def test_grabclipboard_file(self):
 | 
					    def test_grabclipboard_file(self) -> None:
 | 
				
			||||||
        p = subprocess.Popen(["powershell", "-command", "-"], stdin=subprocess.PIPE)
 | 
					        p = subprocess.Popen(["powershell", "-command", "-"], stdin=subprocess.PIPE)
 | 
				
			||||||
        p.stdin.write(rb'Set-Clipboard -Path "Tests\images\hopper.gif"')
 | 
					        p.stdin.write(rb'Set-Clipboard -Path "Tests\images\hopper.gif"')
 | 
				
			||||||
        p.communicate()
 | 
					        p.communicate()
 | 
				
			||||||
| 
						 | 
					@ -92,7 +92,7 @@ $bmp = New-Object Drawing.Bitmap 200, 200
 | 
				
			||||||
        assert os.path.samefile(im[0], "Tests/images/hopper.gif")
 | 
					        assert os.path.samefile(im[0], "Tests/images/hopper.gif")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    @pytest.mark.skipif(sys.platform != "win32", reason="Windows only")
 | 
					    @pytest.mark.skipif(sys.platform != "win32", reason="Windows only")
 | 
				
			||||||
    def test_grabclipboard_png(self):
 | 
					    def test_grabclipboard_png(self) -> None:
 | 
				
			||||||
        p = subprocess.Popen(["powershell", "-command", "-"], stdin=subprocess.PIPE)
 | 
					        p = subprocess.Popen(["powershell", "-command", "-"], stdin=subprocess.PIPE)
 | 
				
			||||||
        p.stdin.write(
 | 
					        p.stdin.write(
 | 
				
			||||||
            rb"""$bytes = [System.IO.File]::ReadAllBytes("Tests\images\hopper.png")
 | 
					            rb"""$bytes = [System.IO.File]::ReadAllBytes("Tests\images\hopper.png")
 | 
				
			||||||
| 
						 | 
					@ -113,7 +113,7 @@ $ms = new-object System.IO.MemoryStream(, $bytes)
 | 
				
			||||||
        reason="Linux with wl-clipboard only",
 | 
					        reason="Linux with wl-clipboard only",
 | 
				
			||||||
    )
 | 
					    )
 | 
				
			||||||
    @pytest.mark.parametrize("ext", ("gif", "png", "ico"))
 | 
					    @pytest.mark.parametrize("ext", ("gif", "png", "ico"))
 | 
				
			||||||
    def test_grabclipboard_wl_clipboard(self, ext):
 | 
					    def test_grabclipboard_wl_clipboard(self, ext) -> None:
 | 
				
			||||||
        image_path = "Tests/images/hopper." + ext
 | 
					        image_path = "Tests/images/hopper." + ext
 | 
				
			||||||
        with open(image_path, "rb") as fp:
 | 
					        with open(image_path, "rb") as fp:
 | 
				
			||||||
            subprocess.call(["wl-copy"], stdin=fp)
 | 
					            subprocess.call(["wl-copy"], stdin=fp)
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -24,7 +24,7 @@ B2 = B.resize((2, 2))
 | 
				
			||||||
images = {"A": A, "B": B, "F": F, "I": I}
 | 
					images = {"A": A, "B": B, "F": F, "I": I}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_sanity():
 | 
					def test_sanity() -> None:
 | 
				
			||||||
    assert ImageMath.eval("1") == 1
 | 
					    assert ImageMath.eval("1") == 1
 | 
				
			||||||
    assert ImageMath.eval("1+A", A=2) == 3
 | 
					    assert ImageMath.eval("1+A", A=2) == 3
 | 
				
			||||||
    assert pixel(ImageMath.eval("A+B", A=A, B=B)) == "I 3"
 | 
					    assert pixel(ImageMath.eval("A+B", A=A, B=B)) == "I 3"
 | 
				
			||||||
| 
						 | 
					@ -33,7 +33,7 @@ def test_sanity():
 | 
				
			||||||
    assert pixel(ImageMath.eval("int(float(A)+B)", images)) == "I 3"
 | 
					    assert pixel(ImageMath.eval("int(float(A)+B)", images)) == "I 3"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_ops():
 | 
					def test_ops() -> None:
 | 
				
			||||||
    assert pixel(ImageMath.eval("-A", images)) == "I -1"
 | 
					    assert pixel(ImageMath.eval("-A", images)) == "I -1"
 | 
				
			||||||
    assert pixel(ImageMath.eval("+B", images)) == "L 2"
 | 
					    assert pixel(ImageMath.eval("+B", images)) == "L 2"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -60,51 +60,51 @@ def test_ops():
 | 
				
			||||||
        "(lambda: (lambda: exec('pass'))())()",
 | 
					        "(lambda: (lambda: exec('pass'))())()",
 | 
				
			||||||
    ),
 | 
					    ),
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
def test_prevent_exec(expression):
 | 
					def test_prevent_exec(expression) -> None:
 | 
				
			||||||
    with pytest.raises(ValueError):
 | 
					    with pytest.raises(ValueError):
 | 
				
			||||||
        ImageMath.eval(expression)
 | 
					        ImageMath.eval(expression)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_prevent_double_underscores():
 | 
					def test_prevent_double_underscores() -> None:
 | 
				
			||||||
    with pytest.raises(ValueError):
 | 
					    with pytest.raises(ValueError):
 | 
				
			||||||
        ImageMath.eval("1", {"__": None})
 | 
					        ImageMath.eval("1", {"__": None})
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_prevent_builtins():
 | 
					def test_prevent_builtins() -> None:
 | 
				
			||||||
    with pytest.raises(ValueError):
 | 
					    with pytest.raises(ValueError):
 | 
				
			||||||
        ImageMath.eval("(lambda: exec('exit()'))()", {"exec": None})
 | 
					        ImageMath.eval("(lambda: exec('exit()'))()", {"exec": None})
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_logical():
 | 
					def test_logical() -> None:
 | 
				
			||||||
    assert pixel(ImageMath.eval("not A", images)) == 0
 | 
					    assert pixel(ImageMath.eval("not A", images)) == 0
 | 
				
			||||||
    assert pixel(ImageMath.eval("A and B", images)) == "L 2"
 | 
					    assert pixel(ImageMath.eval("A and B", images)) == "L 2"
 | 
				
			||||||
    assert pixel(ImageMath.eval("A or B", images)) == "L 1"
 | 
					    assert pixel(ImageMath.eval("A or B", images)) == "L 1"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_convert():
 | 
					def test_convert() -> None:
 | 
				
			||||||
    assert pixel(ImageMath.eval("convert(A+B, 'L')", images)) == "L 3"
 | 
					    assert pixel(ImageMath.eval("convert(A+B, 'L')", images)) == "L 3"
 | 
				
			||||||
    assert pixel(ImageMath.eval("convert(A+B, '1')", images)) == "1 0"
 | 
					    assert pixel(ImageMath.eval("convert(A+B, '1')", images)) == "1 0"
 | 
				
			||||||
    assert pixel(ImageMath.eval("convert(A+B, 'RGB')", images)) == "RGB (3, 3, 3)"
 | 
					    assert pixel(ImageMath.eval("convert(A+B, 'RGB')", images)) == "RGB (3, 3, 3)"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_compare():
 | 
					def test_compare() -> None:
 | 
				
			||||||
    assert pixel(ImageMath.eval("min(A, B)", images)) == "I 1"
 | 
					    assert pixel(ImageMath.eval("min(A, B)", images)) == "I 1"
 | 
				
			||||||
    assert pixel(ImageMath.eval("max(A, B)", images)) == "I 2"
 | 
					    assert pixel(ImageMath.eval("max(A, B)", images)) == "I 2"
 | 
				
			||||||
    assert pixel(ImageMath.eval("A == 1", images)) == "I 1"
 | 
					    assert pixel(ImageMath.eval("A == 1", images)) == "I 1"
 | 
				
			||||||
    assert pixel(ImageMath.eval("A == 2", images)) == "I 0"
 | 
					    assert pixel(ImageMath.eval("A == 2", images)) == "I 0"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_one_image_larger():
 | 
					def test_one_image_larger() -> None:
 | 
				
			||||||
    assert pixel(ImageMath.eval("A+B", A=A2, B=B)) == "I 3"
 | 
					    assert pixel(ImageMath.eval("A+B", A=A2, B=B)) == "I 3"
 | 
				
			||||||
    assert pixel(ImageMath.eval("A+B", A=A, B=B2)) == "I 3"
 | 
					    assert pixel(ImageMath.eval("A+B", A=A, B=B2)) == "I 3"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_abs():
 | 
					def test_abs() -> None:
 | 
				
			||||||
    assert pixel(ImageMath.eval("abs(A)", A=A)) == "I 1"
 | 
					    assert pixel(ImageMath.eval("abs(A)", A=A)) == "I 1"
 | 
				
			||||||
    assert pixel(ImageMath.eval("abs(B)", B=B)) == "I 2"
 | 
					    assert pixel(ImageMath.eval("abs(B)", B=B)) == "I 2"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_binary_mod():
 | 
					def test_binary_mod() -> None:
 | 
				
			||||||
    assert pixel(ImageMath.eval("A%A", A=A)) == "I 0"
 | 
					    assert pixel(ImageMath.eval("A%A", A=A)) == "I 0"
 | 
				
			||||||
    assert pixel(ImageMath.eval("B%B", B=B)) == "I 0"
 | 
					    assert pixel(ImageMath.eval("B%B", B=B)) == "I 0"
 | 
				
			||||||
    assert pixel(ImageMath.eval("A%B", A=A, B=B)) == "I 1"
 | 
					    assert pixel(ImageMath.eval("A%B", A=A, B=B)) == "I 1"
 | 
				
			||||||
| 
						 | 
					@ -113,90 +113,90 @@ def test_binary_mod():
 | 
				
			||||||
    assert pixel(ImageMath.eval("Z%B", B=B, Z=Z)) == "I 0"
 | 
					    assert pixel(ImageMath.eval("Z%B", B=B, Z=Z)) == "I 0"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_bitwise_invert():
 | 
					def test_bitwise_invert() -> None:
 | 
				
			||||||
    assert pixel(ImageMath.eval("~Z", Z=Z)) == "I -1"
 | 
					    assert pixel(ImageMath.eval("~Z", Z=Z)) == "I -1"
 | 
				
			||||||
    assert pixel(ImageMath.eval("~A", A=A)) == "I -2"
 | 
					    assert pixel(ImageMath.eval("~A", A=A)) == "I -2"
 | 
				
			||||||
    assert pixel(ImageMath.eval("~B", B=B)) == "I -3"
 | 
					    assert pixel(ImageMath.eval("~B", B=B)) == "I -3"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_bitwise_and():
 | 
					def test_bitwise_and() -> None:
 | 
				
			||||||
    assert pixel(ImageMath.eval("Z&Z", A=A, Z=Z)) == "I 0"
 | 
					    assert pixel(ImageMath.eval("Z&Z", A=A, Z=Z)) == "I 0"
 | 
				
			||||||
    assert pixel(ImageMath.eval("Z&A", A=A, Z=Z)) == "I 0"
 | 
					    assert pixel(ImageMath.eval("Z&A", A=A, Z=Z)) == "I 0"
 | 
				
			||||||
    assert pixel(ImageMath.eval("A&Z", A=A, Z=Z)) == "I 0"
 | 
					    assert pixel(ImageMath.eval("A&Z", A=A, Z=Z)) == "I 0"
 | 
				
			||||||
    assert pixel(ImageMath.eval("A&A", A=A, Z=Z)) == "I 1"
 | 
					    assert pixel(ImageMath.eval("A&A", A=A, Z=Z)) == "I 1"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_bitwise_or():
 | 
					def test_bitwise_or() -> None:
 | 
				
			||||||
    assert pixel(ImageMath.eval("Z|Z", A=A, Z=Z)) == "I 0"
 | 
					    assert pixel(ImageMath.eval("Z|Z", A=A, Z=Z)) == "I 0"
 | 
				
			||||||
    assert pixel(ImageMath.eval("Z|A", A=A, Z=Z)) == "I 1"
 | 
					    assert pixel(ImageMath.eval("Z|A", A=A, Z=Z)) == "I 1"
 | 
				
			||||||
    assert pixel(ImageMath.eval("A|Z", A=A, Z=Z)) == "I 1"
 | 
					    assert pixel(ImageMath.eval("A|Z", A=A, Z=Z)) == "I 1"
 | 
				
			||||||
    assert pixel(ImageMath.eval("A|A", A=A, Z=Z)) == "I 1"
 | 
					    assert pixel(ImageMath.eval("A|A", A=A, Z=Z)) == "I 1"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_bitwise_xor():
 | 
					def test_bitwise_xor() -> None:
 | 
				
			||||||
    assert pixel(ImageMath.eval("Z^Z", A=A, Z=Z)) == "I 0"
 | 
					    assert pixel(ImageMath.eval("Z^Z", A=A, Z=Z)) == "I 0"
 | 
				
			||||||
    assert pixel(ImageMath.eval("Z^A", A=A, Z=Z)) == "I 1"
 | 
					    assert pixel(ImageMath.eval("Z^A", A=A, Z=Z)) == "I 1"
 | 
				
			||||||
    assert pixel(ImageMath.eval("A^Z", A=A, Z=Z)) == "I 1"
 | 
					    assert pixel(ImageMath.eval("A^Z", A=A, Z=Z)) == "I 1"
 | 
				
			||||||
    assert pixel(ImageMath.eval("A^A", A=A, Z=Z)) == "I 0"
 | 
					    assert pixel(ImageMath.eval("A^A", A=A, Z=Z)) == "I 0"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_bitwise_leftshift():
 | 
					def test_bitwise_leftshift() -> None:
 | 
				
			||||||
    assert pixel(ImageMath.eval("Z<<0", Z=Z)) == "I 0"
 | 
					    assert pixel(ImageMath.eval("Z<<0", Z=Z)) == "I 0"
 | 
				
			||||||
    assert pixel(ImageMath.eval("Z<<1", Z=Z)) == "I 0"
 | 
					    assert pixel(ImageMath.eval("Z<<1", Z=Z)) == "I 0"
 | 
				
			||||||
    assert pixel(ImageMath.eval("A<<0", A=A)) == "I 1"
 | 
					    assert pixel(ImageMath.eval("A<<0", A=A)) == "I 1"
 | 
				
			||||||
    assert pixel(ImageMath.eval("A<<1", A=A)) == "I 2"
 | 
					    assert pixel(ImageMath.eval("A<<1", A=A)) == "I 2"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_bitwise_rightshift():
 | 
					def test_bitwise_rightshift() -> None:
 | 
				
			||||||
    assert pixel(ImageMath.eval("Z>>0", Z=Z)) == "I 0"
 | 
					    assert pixel(ImageMath.eval("Z>>0", Z=Z)) == "I 0"
 | 
				
			||||||
    assert pixel(ImageMath.eval("Z>>1", Z=Z)) == "I 0"
 | 
					    assert pixel(ImageMath.eval("Z>>1", Z=Z)) == "I 0"
 | 
				
			||||||
    assert pixel(ImageMath.eval("A>>0", A=A)) == "I 1"
 | 
					    assert pixel(ImageMath.eval("A>>0", A=A)) == "I 1"
 | 
				
			||||||
    assert pixel(ImageMath.eval("A>>1", A=A)) == "I 0"
 | 
					    assert pixel(ImageMath.eval("A>>1", A=A)) == "I 0"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_logical_eq():
 | 
					def test_logical_eq() -> None:
 | 
				
			||||||
    assert pixel(ImageMath.eval("A==A", A=A)) == "I 1"
 | 
					    assert pixel(ImageMath.eval("A==A", A=A)) == "I 1"
 | 
				
			||||||
    assert pixel(ImageMath.eval("B==B", B=B)) == "I 1"
 | 
					    assert pixel(ImageMath.eval("B==B", B=B)) == "I 1"
 | 
				
			||||||
    assert pixel(ImageMath.eval("A==B", A=A, B=B)) == "I 0"
 | 
					    assert pixel(ImageMath.eval("A==B", A=A, B=B)) == "I 0"
 | 
				
			||||||
    assert pixel(ImageMath.eval("B==A", A=A, B=B)) == "I 0"
 | 
					    assert pixel(ImageMath.eval("B==A", A=A, B=B)) == "I 0"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_logical_ne():
 | 
					def test_logical_ne() -> None:
 | 
				
			||||||
    assert pixel(ImageMath.eval("A!=A", A=A)) == "I 0"
 | 
					    assert pixel(ImageMath.eval("A!=A", A=A)) == "I 0"
 | 
				
			||||||
    assert pixel(ImageMath.eval("B!=B", B=B)) == "I 0"
 | 
					    assert pixel(ImageMath.eval("B!=B", B=B)) == "I 0"
 | 
				
			||||||
    assert pixel(ImageMath.eval("A!=B", A=A, B=B)) == "I 1"
 | 
					    assert pixel(ImageMath.eval("A!=B", A=A, B=B)) == "I 1"
 | 
				
			||||||
    assert pixel(ImageMath.eval("B!=A", A=A, B=B)) == "I 1"
 | 
					    assert pixel(ImageMath.eval("B!=A", A=A, B=B)) == "I 1"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_logical_lt():
 | 
					def test_logical_lt() -> None:
 | 
				
			||||||
    assert pixel(ImageMath.eval("A<A", A=A)) == "I 0"
 | 
					    assert pixel(ImageMath.eval("A<A", A=A)) == "I 0"
 | 
				
			||||||
    assert pixel(ImageMath.eval("B<B", B=B)) == "I 0"
 | 
					    assert pixel(ImageMath.eval("B<B", B=B)) == "I 0"
 | 
				
			||||||
    assert pixel(ImageMath.eval("A<B", A=A, B=B)) == "I 1"
 | 
					    assert pixel(ImageMath.eval("A<B", A=A, B=B)) == "I 1"
 | 
				
			||||||
    assert pixel(ImageMath.eval("B<A", A=A, B=B)) == "I 0"
 | 
					    assert pixel(ImageMath.eval("B<A", A=A, B=B)) == "I 0"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_logical_le():
 | 
					def test_logical_le() -> None:
 | 
				
			||||||
    assert pixel(ImageMath.eval("A<=A", A=A)) == "I 1"
 | 
					    assert pixel(ImageMath.eval("A<=A", A=A)) == "I 1"
 | 
				
			||||||
    assert pixel(ImageMath.eval("B<=B", B=B)) == "I 1"
 | 
					    assert pixel(ImageMath.eval("B<=B", B=B)) == "I 1"
 | 
				
			||||||
    assert pixel(ImageMath.eval("A<=B", A=A, B=B)) == "I 1"
 | 
					    assert pixel(ImageMath.eval("A<=B", A=A, B=B)) == "I 1"
 | 
				
			||||||
    assert pixel(ImageMath.eval("B<=A", A=A, B=B)) == "I 0"
 | 
					    assert pixel(ImageMath.eval("B<=A", A=A, B=B)) == "I 0"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_logical_gt():
 | 
					def test_logical_gt() -> None:
 | 
				
			||||||
    assert pixel(ImageMath.eval("A>A", A=A)) == "I 0"
 | 
					    assert pixel(ImageMath.eval("A>A", A=A)) == "I 0"
 | 
				
			||||||
    assert pixel(ImageMath.eval("B>B", B=B)) == "I 0"
 | 
					    assert pixel(ImageMath.eval("B>B", B=B)) == "I 0"
 | 
				
			||||||
    assert pixel(ImageMath.eval("A>B", A=A, B=B)) == "I 0"
 | 
					    assert pixel(ImageMath.eval("A>B", A=A, B=B)) == "I 0"
 | 
				
			||||||
    assert pixel(ImageMath.eval("B>A", A=A, B=B)) == "I 1"
 | 
					    assert pixel(ImageMath.eval("B>A", A=A, B=B)) == "I 1"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_logical_ge():
 | 
					def test_logical_ge() -> None:
 | 
				
			||||||
    assert pixel(ImageMath.eval("A>=A", A=A)) == "I 1"
 | 
					    assert pixel(ImageMath.eval("A>=A", A=A)) == "I 1"
 | 
				
			||||||
    assert pixel(ImageMath.eval("B>=B", B=B)) == "I 1"
 | 
					    assert pixel(ImageMath.eval("B>=B", B=B)) == "I 1"
 | 
				
			||||||
    assert pixel(ImageMath.eval("A>=B", A=A, B=B)) == "I 0"
 | 
					    assert pixel(ImageMath.eval("A>=B", A=A, B=B)) == "I 0"
 | 
				
			||||||
    assert pixel(ImageMath.eval("B>=A", A=A, B=B)) == "I 1"
 | 
					    assert pixel(ImageMath.eval("B>=A", A=A, B=B)) == "I 1"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_logical_equal():
 | 
					def test_logical_equal() -> None:
 | 
				
			||||||
    assert pixel(ImageMath.eval("equal(A, A)", A=A)) == "I 1"
 | 
					    assert pixel(ImageMath.eval("equal(A, A)", A=A)) == "I 1"
 | 
				
			||||||
    assert pixel(ImageMath.eval("equal(B, B)", B=B)) == "I 1"
 | 
					    assert pixel(ImageMath.eval("equal(B, B)", B=B)) == "I 1"
 | 
				
			||||||
    assert pixel(ImageMath.eval("equal(Z, Z)", Z=Z)) == "I 1"
 | 
					    assert pixel(ImageMath.eval("equal(Z, Z)", Z=Z)) == "I 1"
 | 
				
			||||||
| 
						 | 
					@ -205,7 +205,7 @@ def test_logical_equal():
 | 
				
			||||||
    assert pixel(ImageMath.eval("equal(A, Z)", A=A, Z=Z)) == "I 0"
 | 
					    assert pixel(ImageMath.eval("equal(A, Z)", A=A, Z=Z)) == "I 0"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_logical_not_equal():
 | 
					def test_logical_not_equal() -> None:
 | 
				
			||||||
    assert pixel(ImageMath.eval("notequal(A, A)", A=A)) == "I 0"
 | 
					    assert pixel(ImageMath.eval("notequal(A, A)", A=A)) == "I 0"
 | 
				
			||||||
    assert pixel(ImageMath.eval("notequal(B, B)", B=B)) == "I 0"
 | 
					    assert pixel(ImageMath.eval("notequal(B, B)", B=B)) == "I 0"
 | 
				
			||||||
    assert pixel(ImageMath.eval("notequal(Z, Z)", Z=Z)) == "I 0"
 | 
					    assert pixel(ImageMath.eval("notequal(Z, Z)", Z=Z)) == "I 0"
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,6 +1,8 @@
 | 
				
			||||||
# Test the ImageMorphology functionality
 | 
					# Test the ImageMorphology functionality
 | 
				
			||||||
from __future__ import annotations
 | 
					from __future__ import annotations
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					from pathlib import Path
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import pytest
 | 
					import pytest
 | 
				
			||||||
 | 
					
 | 
				
			||||||
from PIL import Image, ImageMorph, _imagingmorph
 | 
					from PIL import Image, ImageMorph, _imagingmorph
 | 
				
			||||||
| 
						 | 
					@ -50,18 +52,18 @@ def img_string_normalize(im):
 | 
				
			||||||
    return img_to_string(string_to_img(im))
 | 
					    return img_to_string(string_to_img(im))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def assert_img_equal_img_string(a, b_string):
 | 
					def assert_img_equal_img_string(a, b_string) -> None:
 | 
				
			||||||
    assert img_to_string(a) == img_string_normalize(b_string)
 | 
					    assert img_to_string(a) == img_string_normalize(b_string)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_str_to_img():
 | 
					def test_str_to_img() -> None:
 | 
				
			||||||
    assert_image_equal_tofile(A, "Tests/images/morph_a.png")
 | 
					    assert_image_equal_tofile(A, "Tests/images/morph_a.png")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@pytest.mark.parametrize(
 | 
					@pytest.mark.parametrize(
 | 
				
			||||||
    "op", ("corner", "dilation4", "dilation8", "erosion4", "erosion8", "edge")
 | 
					    "op", ("corner", "dilation4", "dilation8", "erosion4", "erosion8", "edge")
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
def test_lut(op):
 | 
					def test_lut(op) -> None:
 | 
				
			||||||
    lb = ImageMorph.LutBuilder(op_name=op)
 | 
					    lb = ImageMorph.LutBuilder(op_name=op)
 | 
				
			||||||
    assert lb.get_lut() is None
 | 
					    assert lb.get_lut() is None
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -70,7 +72,7 @@ def test_lut(op):
 | 
				
			||||||
        assert lut == bytearray(f.read())
 | 
					        assert lut == bytearray(f.read())
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_no_operator_loaded():
 | 
					def test_no_operator_loaded() -> None:
 | 
				
			||||||
    mop = ImageMorph.MorphOp()
 | 
					    mop = ImageMorph.MorphOp()
 | 
				
			||||||
    with pytest.raises(Exception) as e:
 | 
					    with pytest.raises(Exception) as e:
 | 
				
			||||||
        mop.apply(None)
 | 
					        mop.apply(None)
 | 
				
			||||||
| 
						 | 
					@ -84,7 +86,7 @@ def test_no_operator_loaded():
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# Test the named patterns
 | 
					# Test the named patterns
 | 
				
			||||||
def test_erosion8():
 | 
					def test_erosion8() -> None:
 | 
				
			||||||
    # erosion8
 | 
					    # erosion8
 | 
				
			||||||
    mop = ImageMorph.MorphOp(op_name="erosion8")
 | 
					    mop = ImageMorph.MorphOp(op_name="erosion8")
 | 
				
			||||||
    count, Aout = mop.apply(A)
 | 
					    count, Aout = mop.apply(A)
 | 
				
			||||||
| 
						 | 
					@ -103,7 +105,7 @@ def test_erosion8():
 | 
				
			||||||
    )
 | 
					    )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_dialation8():
 | 
					def test_dialation8() -> None:
 | 
				
			||||||
    # dialation8
 | 
					    # dialation8
 | 
				
			||||||
    mop = ImageMorph.MorphOp(op_name="dilation8")
 | 
					    mop = ImageMorph.MorphOp(op_name="dilation8")
 | 
				
			||||||
    count, Aout = mop.apply(A)
 | 
					    count, Aout = mop.apply(A)
 | 
				
			||||||
| 
						 | 
					@ -122,7 +124,7 @@ def test_dialation8():
 | 
				
			||||||
    )
 | 
					    )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_erosion4():
 | 
					def test_erosion4() -> None:
 | 
				
			||||||
    # erosion4
 | 
					    # erosion4
 | 
				
			||||||
    mop = ImageMorph.MorphOp(op_name="dilation4")
 | 
					    mop = ImageMorph.MorphOp(op_name="dilation4")
 | 
				
			||||||
    count, Aout = mop.apply(A)
 | 
					    count, Aout = mop.apply(A)
 | 
				
			||||||
| 
						 | 
					@ -141,7 +143,7 @@ def test_erosion4():
 | 
				
			||||||
    )
 | 
					    )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_edge():
 | 
					def test_edge() -> None:
 | 
				
			||||||
    # edge
 | 
					    # edge
 | 
				
			||||||
    mop = ImageMorph.MorphOp(op_name="edge")
 | 
					    mop = ImageMorph.MorphOp(op_name="edge")
 | 
				
			||||||
    count, Aout = mop.apply(A)
 | 
					    count, Aout = mop.apply(A)
 | 
				
			||||||
| 
						 | 
					@ -160,7 +162,7 @@ def test_edge():
 | 
				
			||||||
    )
 | 
					    )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_corner():
 | 
					def test_corner() -> None:
 | 
				
			||||||
    # Create a corner detector pattern
 | 
					    # Create a corner detector pattern
 | 
				
			||||||
    mop = ImageMorph.MorphOp(patterns=["1:(... ... ...)->0", "4:(00. 01. ...)->1"])
 | 
					    mop = ImageMorph.MorphOp(patterns=["1:(... ... ...)->0", "4:(00. 01. ...)->1"])
 | 
				
			||||||
    count, Aout = mop.apply(A)
 | 
					    count, Aout = mop.apply(A)
 | 
				
			||||||
| 
						 | 
					@ -188,7 +190,7 @@ def test_corner():
 | 
				
			||||||
    assert tuple(coords) == ((2, 2), (4, 2), (2, 4), (4, 4))
 | 
					    assert tuple(coords) == ((2, 2), (4, 2), (2, 4), (4, 4))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_mirroring():
 | 
					def test_mirroring() -> None:
 | 
				
			||||||
    # Test 'M' for mirroring
 | 
					    # Test 'M' for mirroring
 | 
				
			||||||
    mop = ImageMorph.MorphOp(patterns=["1:(... ... ...)->0", "M:(00. 01. ...)->1"])
 | 
					    mop = ImageMorph.MorphOp(patterns=["1:(... ... ...)->0", "M:(00. 01. ...)->1"])
 | 
				
			||||||
    count, Aout = mop.apply(A)
 | 
					    count, Aout = mop.apply(A)
 | 
				
			||||||
| 
						 | 
					@ -207,7 +209,7 @@ def test_mirroring():
 | 
				
			||||||
    )
 | 
					    )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_negate():
 | 
					def test_negate() -> None:
 | 
				
			||||||
    # Test 'N' for negate
 | 
					    # Test 'N' for negate
 | 
				
			||||||
    mop = ImageMorph.MorphOp(patterns=["1:(... ... ...)->0", "N:(00. 01. ...)->1"])
 | 
					    mop = ImageMorph.MorphOp(patterns=["1:(... ... ...)->0", "N:(00. 01. ...)->1"])
 | 
				
			||||||
    count, Aout = mop.apply(A)
 | 
					    count, Aout = mop.apply(A)
 | 
				
			||||||
| 
						 | 
					@ -226,7 +228,7 @@ def test_negate():
 | 
				
			||||||
    )
 | 
					    )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_incorrect_mode():
 | 
					def test_incorrect_mode() -> None:
 | 
				
			||||||
    im = hopper("RGB")
 | 
					    im = hopper("RGB")
 | 
				
			||||||
    mop = ImageMorph.MorphOp(op_name="erosion8")
 | 
					    mop = ImageMorph.MorphOp(op_name="erosion8")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -241,7 +243,7 @@ def test_incorrect_mode():
 | 
				
			||||||
    assert str(e.value) == "Image mode must be L"
 | 
					    assert str(e.value) == "Image mode must be L"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_add_patterns():
 | 
					def test_add_patterns() -> None:
 | 
				
			||||||
    # Arrange
 | 
					    # Arrange
 | 
				
			||||||
    lb = ImageMorph.LutBuilder(op_name="corner")
 | 
					    lb = ImageMorph.LutBuilder(op_name="corner")
 | 
				
			||||||
    assert lb.patterns == ["1:(... ... ...)->0", "4:(00. 01. ...)->1"]
 | 
					    assert lb.patterns == ["1:(... ... ...)->0", "4:(00. 01. ...)->1"]
 | 
				
			||||||
| 
						 | 
					@ -259,12 +261,12 @@ def test_add_patterns():
 | 
				
			||||||
    ]
 | 
					    ]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_unknown_pattern():
 | 
					def test_unknown_pattern() -> None:
 | 
				
			||||||
    with pytest.raises(Exception):
 | 
					    with pytest.raises(Exception):
 | 
				
			||||||
        ImageMorph.LutBuilder(op_name="unknown")
 | 
					        ImageMorph.LutBuilder(op_name="unknown")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_pattern_syntax_error():
 | 
					def test_pattern_syntax_error() -> None:
 | 
				
			||||||
    # Arrange
 | 
					    # Arrange
 | 
				
			||||||
    lb = ImageMorph.LutBuilder(op_name="corner")
 | 
					    lb = ImageMorph.LutBuilder(op_name="corner")
 | 
				
			||||||
    new_patterns = ["a pattern with a syntax error"]
 | 
					    new_patterns = ["a pattern with a syntax error"]
 | 
				
			||||||
| 
						 | 
					@ -276,7 +278,7 @@ def test_pattern_syntax_error():
 | 
				
			||||||
    assert str(e.value) == 'Syntax error in pattern "a pattern with a syntax error"'
 | 
					    assert str(e.value) == 'Syntax error in pattern "a pattern with a syntax error"'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_load_invalid_mrl():
 | 
					def test_load_invalid_mrl() -> None:
 | 
				
			||||||
    # Arrange
 | 
					    # Arrange
 | 
				
			||||||
    invalid_mrl = "Tests/images/hopper.png"
 | 
					    invalid_mrl = "Tests/images/hopper.png"
 | 
				
			||||||
    mop = ImageMorph.MorphOp()
 | 
					    mop = ImageMorph.MorphOp()
 | 
				
			||||||
| 
						 | 
					@ -287,7 +289,7 @@ def test_load_invalid_mrl():
 | 
				
			||||||
    assert str(e.value) == "Wrong size operator file!"
 | 
					    assert str(e.value) == "Wrong size operator file!"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_roundtrip_mrl(tmp_path):
 | 
					def test_roundtrip_mrl(tmp_path: Path) -> None:
 | 
				
			||||||
    # Arrange
 | 
					    # Arrange
 | 
				
			||||||
    tempfile = str(tmp_path / "temp.mrl")
 | 
					    tempfile = str(tmp_path / "temp.mrl")
 | 
				
			||||||
    mop = ImageMorph.MorphOp(op_name="corner")
 | 
					    mop = ImageMorph.MorphOp(op_name="corner")
 | 
				
			||||||
| 
						 | 
					@ -301,7 +303,7 @@ def test_roundtrip_mrl(tmp_path):
 | 
				
			||||||
    assert mop.lut == initial_lut
 | 
					    assert mop.lut == initial_lut
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_set_lut():
 | 
					def test_set_lut() -> None:
 | 
				
			||||||
    # Arrange
 | 
					    # Arrange
 | 
				
			||||||
    lb = ImageMorph.LutBuilder(op_name="corner")
 | 
					    lb = ImageMorph.LutBuilder(op_name="corner")
 | 
				
			||||||
    lut = lb.build_lut()
 | 
					    lut = lb.build_lut()
 | 
				
			||||||
| 
						 | 
					@ -314,7 +316,7 @@ def test_set_lut():
 | 
				
			||||||
    assert mop.lut == lut
 | 
					    assert mop.lut == lut
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_wrong_mode():
 | 
					def test_wrong_mode() -> None:
 | 
				
			||||||
    lut = ImageMorph.LutBuilder(op_name="corner").build_lut()
 | 
					    lut = ImageMorph.LutBuilder(op_name="corner").build_lut()
 | 
				
			||||||
    imrgb = Image.new("RGB", (10, 10))
 | 
					    imrgb = Image.new("RGB", (10, 10))
 | 
				
			||||||
    iml = Image.new("L", (10, 10))
 | 
					    iml = Image.new("L", (10, 10))
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -22,7 +22,7 @@ class Deformer:
 | 
				
			||||||
deformer = Deformer()
 | 
					deformer = Deformer()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_sanity():
 | 
					def test_sanity() -> None:
 | 
				
			||||||
    ImageOps.autocontrast(hopper("L"))
 | 
					    ImageOps.autocontrast(hopper("L"))
 | 
				
			||||||
    ImageOps.autocontrast(hopper("RGB"))
 | 
					    ImageOps.autocontrast(hopper("RGB"))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -84,7 +84,7 @@ def test_sanity():
 | 
				
			||||||
    ImageOps.exif_transpose(hopper("RGB"))
 | 
					    ImageOps.exif_transpose(hopper("RGB"))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_1pxfit():
 | 
					def test_1pxfit() -> None:
 | 
				
			||||||
    # Division by zero in equalize if image is 1 pixel high
 | 
					    # Division by zero in equalize if image is 1 pixel high
 | 
				
			||||||
    newimg = ImageOps.fit(hopper("RGB").resize((1, 1)), (35, 35))
 | 
					    newimg = ImageOps.fit(hopper("RGB").resize((1, 1)), (35, 35))
 | 
				
			||||||
    assert newimg.size == (35, 35)
 | 
					    assert newimg.size == (35, 35)
 | 
				
			||||||
| 
						 | 
					@ -96,7 +96,7 @@ def test_1pxfit():
 | 
				
			||||||
    assert newimg.size == (35, 35)
 | 
					    assert newimg.size == (35, 35)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_fit_same_ratio():
 | 
					def test_fit_same_ratio() -> None:
 | 
				
			||||||
    # The ratio for this image is 1000.0 / 755 = 1.3245033112582782
 | 
					    # The ratio for this image is 1000.0 / 755 = 1.3245033112582782
 | 
				
			||||||
    # If the ratios are not acknowledged to be the same,
 | 
					    # If the ratios are not acknowledged to be the same,
 | 
				
			||||||
    # and Pillow attempts to adjust the width to
 | 
					    # and Pillow attempts to adjust the width to
 | 
				
			||||||
| 
						 | 
					@ -108,13 +108,13 @@ def test_fit_same_ratio():
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@pytest.mark.parametrize("new_size", ((256, 256), (512, 256), (256, 512)))
 | 
					@pytest.mark.parametrize("new_size", ((256, 256), (512, 256), (256, 512)))
 | 
				
			||||||
def test_contain(new_size):
 | 
					def test_contain(new_size) -> None:
 | 
				
			||||||
    im = hopper()
 | 
					    im = hopper()
 | 
				
			||||||
    new_im = ImageOps.contain(im, new_size)
 | 
					    new_im = ImageOps.contain(im, new_size)
 | 
				
			||||||
    assert new_im.size == (256, 256)
 | 
					    assert new_im.size == (256, 256)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_contain_round():
 | 
					def test_contain_round() -> None:
 | 
				
			||||||
    im = Image.new("1", (43, 63), 1)
 | 
					    im = Image.new("1", (43, 63), 1)
 | 
				
			||||||
    new_im = ImageOps.contain(im, (5, 7))
 | 
					    new_im = ImageOps.contain(im, (5, 7))
 | 
				
			||||||
    assert new_im.width == 5
 | 
					    assert new_im.width == 5
 | 
				
			||||||
| 
						 | 
					@ -132,13 +132,13 @@ def test_contain_round():
 | 
				
			||||||
        ("hopper.png", (256, 256)),  # square
 | 
					        ("hopper.png", (256, 256)),  # square
 | 
				
			||||||
    ),
 | 
					    ),
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
def test_cover(image_name, expected_size):
 | 
					def test_cover(image_name, expected_size) -> None:
 | 
				
			||||||
    with Image.open("Tests/images/" + image_name) as im:
 | 
					    with Image.open("Tests/images/" + image_name) as im:
 | 
				
			||||||
        new_im = ImageOps.cover(im, (256, 256))
 | 
					        new_im = ImageOps.cover(im, (256, 256))
 | 
				
			||||||
        assert new_im.size == expected_size
 | 
					        assert new_im.size == expected_size
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_pad():
 | 
					def test_pad() -> None:
 | 
				
			||||||
    # Same ratio
 | 
					    # Same ratio
 | 
				
			||||||
    im = hopper()
 | 
					    im = hopper()
 | 
				
			||||||
    new_size = (im.width * 2, im.height * 2)
 | 
					    new_size = (im.width * 2, im.height * 2)
 | 
				
			||||||
| 
						 | 
					@ -158,7 +158,7 @@ def test_pad():
 | 
				
			||||||
            )
 | 
					            )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_pad_round():
 | 
					def test_pad_round() -> None:
 | 
				
			||||||
    im = Image.new("1", (1, 1), 1)
 | 
					    im = Image.new("1", (1, 1), 1)
 | 
				
			||||||
    new_im = ImageOps.pad(im, (4, 1))
 | 
					    new_im = ImageOps.pad(im, (4, 1))
 | 
				
			||||||
    assert new_im.load()[2, 0] == 1
 | 
					    assert new_im.load()[2, 0] == 1
 | 
				
			||||||
| 
						 | 
					@ -168,7 +168,7 @@ def test_pad_round():
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@pytest.mark.parametrize("mode", ("P", "PA"))
 | 
					@pytest.mark.parametrize("mode", ("P", "PA"))
 | 
				
			||||||
def test_palette(mode):
 | 
					def test_palette(mode) -> None:
 | 
				
			||||||
    im = hopper(mode)
 | 
					    im = hopper(mode)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    # Expand
 | 
					    # Expand
 | 
				
			||||||
| 
						 | 
					@ -182,7 +182,7 @@ def test_palette(mode):
 | 
				
			||||||
    )
 | 
					    )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_pil163():
 | 
					def test_pil163() -> None:
 | 
				
			||||||
    # Division by zero in equalize if < 255 pixels in image (@PIL163)
 | 
					    # Division by zero in equalize if < 255 pixels in image (@PIL163)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    i = hopper("RGB").resize((15, 16))
 | 
					    i = hopper("RGB").resize((15, 16))
 | 
				
			||||||
| 
						 | 
					@ -192,7 +192,7 @@ def test_pil163():
 | 
				
			||||||
    ImageOps.equalize(i.convert("RGB"))
 | 
					    ImageOps.equalize(i.convert("RGB"))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_scale():
 | 
					def test_scale() -> None:
 | 
				
			||||||
    # Test the scaling function
 | 
					    # Test the scaling function
 | 
				
			||||||
    i = hopper("L").resize((50, 50))
 | 
					    i = hopper("L").resize((50, 50))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -210,7 +210,7 @@ def test_scale():
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@pytest.mark.parametrize("border", (10, (1, 2, 3, 4)))
 | 
					@pytest.mark.parametrize("border", (10, (1, 2, 3, 4)))
 | 
				
			||||||
def test_expand_palette(border):
 | 
					def test_expand_palette(border) -> None:
 | 
				
			||||||
    with Image.open("Tests/images/p_16.tga") as im:
 | 
					    with Image.open("Tests/images/p_16.tga") as im:
 | 
				
			||||||
        im_expanded = ImageOps.expand(im, border, (255, 0, 0))
 | 
					        im_expanded = ImageOps.expand(im, border, (255, 0, 0))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -236,7 +236,7 @@ def test_expand_palette(border):
 | 
				
			||||||
        assert_image_equal(im_cropped, im)
 | 
					        assert_image_equal(im_cropped, im)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_colorize_2color():
 | 
					def test_colorize_2color() -> None:
 | 
				
			||||||
    # Test the colorizing function with 2-color functionality
 | 
					    # Test the colorizing function with 2-color functionality
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    # Open test image (256px by 10px, black to white)
 | 
					    # Open test image (256px by 10px, black to white)
 | 
				
			||||||
| 
						 | 
					@ -270,7 +270,7 @@ def test_colorize_2color():
 | 
				
			||||||
    )
 | 
					    )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_colorize_2color_offset():
 | 
					def test_colorize_2color_offset() -> None:
 | 
				
			||||||
    # Test the colorizing function with 2-color functionality and offset
 | 
					    # Test the colorizing function with 2-color functionality and offset
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    # Open test image (256px by 10px, black to white)
 | 
					    # Open test image (256px by 10px, black to white)
 | 
				
			||||||
| 
						 | 
					@ -306,7 +306,7 @@ def test_colorize_2color_offset():
 | 
				
			||||||
    )
 | 
					    )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_colorize_3color_offset():
 | 
					def test_colorize_3color_offset() -> None:
 | 
				
			||||||
    # Test the colorizing function with 3-color functionality and offset
 | 
					    # Test the colorizing function with 3-color functionality and offset
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    # Open test image (256px by 10px, black to white)
 | 
					    # Open test image (256px by 10px, black to white)
 | 
				
			||||||
| 
						 | 
					@ -359,14 +359,14 @@ def test_colorize_3color_offset():
 | 
				
			||||||
    )
 | 
					    )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_exif_transpose():
 | 
					def test_exif_transpose() -> None:
 | 
				
			||||||
    exts = [".jpg"]
 | 
					    exts = [".jpg"]
 | 
				
			||||||
    if features.check("webp") and features.check("webp_anim"):
 | 
					    if features.check("webp") and features.check("webp_anim"):
 | 
				
			||||||
        exts.append(".webp")
 | 
					        exts.append(".webp")
 | 
				
			||||||
    for ext in exts:
 | 
					    for ext in exts:
 | 
				
			||||||
        with Image.open("Tests/images/hopper" + ext) as base_im:
 | 
					        with Image.open("Tests/images/hopper" + ext) as base_im:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            def check(orientation_im):
 | 
					            def check(orientation_im) -> None:
 | 
				
			||||||
                for im in [
 | 
					                for im in [
 | 
				
			||||||
                    orientation_im,
 | 
					                    orientation_im,
 | 
				
			||||||
                    orientation_im.copy(),
 | 
					                    orientation_im.copy(),
 | 
				
			||||||
| 
						 | 
					@ -423,7 +423,7 @@ def test_exif_transpose():
 | 
				
			||||||
    assert 0x0112 not in transposed_im.getexif()
 | 
					    assert 0x0112 not in transposed_im.getexif()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_exif_transpose_in_place():
 | 
					def test_exif_transpose_in_place() -> None:
 | 
				
			||||||
    with Image.open("Tests/images/orientation_rectangle.jpg") as im:
 | 
					    with Image.open("Tests/images/orientation_rectangle.jpg") as im:
 | 
				
			||||||
        assert im.size == (2, 1)
 | 
					        assert im.size == (2, 1)
 | 
				
			||||||
        assert im.getexif()[0x0112] == 8
 | 
					        assert im.getexif()[0x0112] == 8
 | 
				
			||||||
| 
						 | 
					@ -435,13 +435,13 @@ def test_exif_transpose_in_place():
 | 
				
			||||||
        assert_image_equal(im, expected)
 | 
					        assert_image_equal(im, expected)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_autocontrast_unsupported_mode():
 | 
					def test_autocontrast_unsupported_mode() -> None:
 | 
				
			||||||
    im = Image.new("RGBA", (1, 1))
 | 
					    im = Image.new("RGBA", (1, 1))
 | 
				
			||||||
    with pytest.raises(OSError):
 | 
					    with pytest.raises(OSError):
 | 
				
			||||||
        ImageOps.autocontrast(im)
 | 
					        ImageOps.autocontrast(im)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_autocontrast_cutoff():
 | 
					def test_autocontrast_cutoff() -> None:
 | 
				
			||||||
    # Test the cutoff argument of autocontrast
 | 
					    # Test the cutoff argument of autocontrast
 | 
				
			||||||
    with Image.open("Tests/images/bw_gradient.png") as img:
 | 
					    with Image.open("Tests/images/bw_gradient.png") as img:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -452,7 +452,7 @@ def test_autocontrast_cutoff():
 | 
				
			||||||
        assert autocontrast(10) != autocontrast((1, 10))
 | 
					        assert autocontrast(10) != autocontrast((1, 10))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_autocontrast_mask_toy_input():
 | 
					def test_autocontrast_mask_toy_input() -> None:
 | 
				
			||||||
    # Test the mask argument of autocontrast
 | 
					    # Test the mask argument of autocontrast
 | 
				
			||||||
    with Image.open("Tests/images/bw_gradient.png") as img:
 | 
					    with Image.open("Tests/images/bw_gradient.png") as img:
 | 
				
			||||||
        rect_mask = Image.new("L", img.size, 0)
 | 
					        rect_mask = Image.new("L", img.size, 0)
 | 
				
			||||||
| 
						 | 
					@ -471,7 +471,7 @@ def test_autocontrast_mask_toy_input():
 | 
				
			||||||
        assert ImageStat.Stat(result_nomask).median == [128]
 | 
					        assert ImageStat.Stat(result_nomask).median == [128]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_autocontrast_mask_real_input():
 | 
					def test_autocontrast_mask_real_input() -> None:
 | 
				
			||||||
    # Test the autocontrast with a rectangular mask
 | 
					    # Test the autocontrast with a rectangular mask
 | 
				
			||||||
    with Image.open("Tests/images/iptc.jpg") as img:
 | 
					    with Image.open("Tests/images/iptc.jpg") as img:
 | 
				
			||||||
        rect_mask = Image.new("L", img.size, 0)
 | 
					        rect_mask = Image.new("L", img.size, 0)
 | 
				
			||||||
| 
						 | 
					@ -498,7 +498,7 @@ def test_autocontrast_mask_real_input():
 | 
				
			||||||
        )
 | 
					        )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_autocontrast_preserve_tone():
 | 
					def test_autocontrast_preserve_tone() -> None:
 | 
				
			||||||
    def autocontrast(mode, preserve_tone):
 | 
					    def autocontrast(mode, preserve_tone):
 | 
				
			||||||
        im = hopper(mode)
 | 
					        im = hopper(mode)
 | 
				
			||||||
        return ImageOps.autocontrast(im, preserve_tone=preserve_tone).histogram()
 | 
					        return ImageOps.autocontrast(im, preserve_tone=preserve_tone).histogram()
 | 
				
			||||||
| 
						 | 
					@ -507,7 +507,7 @@ def test_autocontrast_preserve_tone():
 | 
				
			||||||
    assert autocontrast("L", True) == autocontrast("L", False)
 | 
					    assert autocontrast("L", True) == autocontrast("L", False)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_autocontrast_preserve_gradient():
 | 
					def test_autocontrast_preserve_gradient() -> None:
 | 
				
			||||||
    gradient = Image.linear_gradient("L")
 | 
					    gradient = Image.linear_gradient("L")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    # test with a grayscale gradient that extends to 0,255.
 | 
					    # test with a grayscale gradient that extends to 0,255.
 | 
				
			||||||
| 
						 | 
					@ -533,7 +533,7 @@ def test_autocontrast_preserve_gradient():
 | 
				
			||||||
@pytest.mark.parametrize(
 | 
					@pytest.mark.parametrize(
 | 
				
			||||||
    "color", ((255, 255, 255), (127, 255, 0), (127, 127, 127), (0, 0, 0))
 | 
					    "color", ((255, 255, 255), (127, 255, 0), (127, 127, 127), (0, 0, 0))
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
def test_autocontrast_preserve_one_color(color):
 | 
					def test_autocontrast_preserve_one_color(color) -> None:
 | 
				
			||||||
    img = Image.new("RGB", (10, 10), color)
 | 
					    img = Image.new("RGB", (10, 10), color)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    # single color images shouldn't change
 | 
					    # single color images shouldn't change
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -18,7 +18,7 @@ def test_images():
 | 
				
			||||||
            im.close()
 | 
					            im.close()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_filter_api(test_images):
 | 
					def test_filter_api(test_images) -> None:
 | 
				
			||||||
    im = test_images["im"]
 | 
					    im = test_images["im"]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    test_filter = ImageFilter.GaussianBlur(2.0)
 | 
					    test_filter = ImageFilter.GaussianBlur(2.0)
 | 
				
			||||||
| 
						 | 
					@ -32,7 +32,7 @@ def test_filter_api(test_images):
 | 
				
			||||||
    assert i.size == (128, 128)
 | 
					    assert i.size == (128, 128)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_usm_formats(test_images):
 | 
					def test_usm_formats(test_images) -> None:
 | 
				
			||||||
    im = test_images["im"]
 | 
					    im = test_images["im"]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    usm = ImageFilter.UnsharpMask
 | 
					    usm = ImageFilter.UnsharpMask
 | 
				
			||||||
| 
						 | 
					@ -50,7 +50,7 @@ def test_usm_formats(test_images):
 | 
				
			||||||
        im.convert("YCbCr").filter(usm)
 | 
					        im.convert("YCbCr").filter(usm)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_blur_formats(test_images):
 | 
					def test_blur_formats(test_images) -> None:
 | 
				
			||||||
    im = test_images["im"]
 | 
					    im = test_images["im"]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    blur = ImageFilter.GaussianBlur
 | 
					    blur = ImageFilter.GaussianBlur
 | 
				
			||||||
| 
						 | 
					@ -68,7 +68,7 @@ def test_blur_formats(test_images):
 | 
				
			||||||
        im.convert("YCbCr").filter(blur)
 | 
					        im.convert("YCbCr").filter(blur)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_usm_accuracy(test_images):
 | 
					def test_usm_accuracy(test_images) -> None:
 | 
				
			||||||
    snakes = test_images["snakes"]
 | 
					    snakes = test_images["snakes"]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    src = snakes.convert("RGB")
 | 
					    src = snakes.convert("RGB")
 | 
				
			||||||
| 
						 | 
					@ -77,7 +77,7 @@ def test_usm_accuracy(test_images):
 | 
				
			||||||
    assert i.tobytes() == src.tobytes()
 | 
					    assert i.tobytes() == src.tobytes()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_blur_accuracy(test_images):
 | 
					def test_blur_accuracy(test_images) -> None:
 | 
				
			||||||
    snakes = test_images["snakes"]
 | 
					    snakes = test_images["snakes"]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    i = snakes.filter(ImageFilter.GaussianBlur(0.4))
 | 
					    i = snakes.filter(ImageFilter.GaussianBlur(0.4))
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,5 +1,7 @@
 | 
				
			||||||
from __future__ import annotations
 | 
					from __future__ import annotations
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					from pathlib import Path
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import pytest
 | 
					import pytest
 | 
				
			||||||
 | 
					
 | 
				
			||||||
from PIL import Image, ImagePalette
 | 
					from PIL import Image, ImagePalette
 | 
				
			||||||
| 
						 | 
					@ -7,19 +9,19 @@ from PIL import Image, ImagePalette
 | 
				
			||||||
from .helper import assert_image_equal, assert_image_equal_tofile
 | 
					from .helper import assert_image_equal, assert_image_equal_tofile
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_sanity():
 | 
					def test_sanity() -> None:
 | 
				
			||||||
    palette = ImagePalette.ImagePalette("RGB", list(range(256)) * 3)
 | 
					    palette = ImagePalette.ImagePalette("RGB", list(range(256)) * 3)
 | 
				
			||||||
    assert len(palette.colors) == 256
 | 
					    assert len(palette.colors) == 256
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_reload():
 | 
					def test_reload() -> None:
 | 
				
			||||||
    with Image.open("Tests/images/hopper.gif") as im:
 | 
					    with Image.open("Tests/images/hopper.gif") as im:
 | 
				
			||||||
        original = im.copy()
 | 
					        original = im.copy()
 | 
				
			||||||
        im.palette.dirty = 1
 | 
					        im.palette.dirty = 1
 | 
				
			||||||
        assert_image_equal(im.convert("RGB"), original.convert("RGB"))
 | 
					        assert_image_equal(im.convert("RGB"), original.convert("RGB"))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_getcolor():
 | 
					def test_getcolor() -> None:
 | 
				
			||||||
    palette = ImagePalette.ImagePalette()
 | 
					    palette = ImagePalette.ImagePalette()
 | 
				
			||||||
    assert len(palette.palette) == 0
 | 
					    assert len(palette.palette) == 0
 | 
				
			||||||
    assert len(palette.colors) == 0
 | 
					    assert len(palette.colors) == 0
 | 
				
			||||||
| 
						 | 
					@ -46,7 +48,7 @@ def test_getcolor():
 | 
				
			||||||
        palette.getcolor("unknown")
 | 
					        palette.getcolor("unknown")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_getcolor_rgba_color_rgb_palette():
 | 
					def test_getcolor_rgba_color_rgb_palette() -> None:
 | 
				
			||||||
    palette = ImagePalette.ImagePalette("RGB")
 | 
					    palette = ImagePalette.ImagePalette("RGB")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    # Opaque RGBA colors are converted
 | 
					    # Opaque RGBA colors are converted
 | 
				
			||||||
| 
						 | 
					@ -65,7 +67,7 @@ def test_getcolor_rgba_color_rgb_palette():
 | 
				
			||||||
        (255, ImagePalette.ImagePalette("RGB", list(range(256)) * 3)),
 | 
					        (255, ImagePalette.ImagePalette("RGB", list(range(256)) * 3)),
 | 
				
			||||||
    ],
 | 
					    ],
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
def test_getcolor_not_special(index, palette):
 | 
					def test_getcolor_not_special(index, palette) -> None:
 | 
				
			||||||
    im = Image.new("P", (1, 1))
 | 
					    im = Image.new("P", (1, 1))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    # Do not use transparency index as a new color
 | 
					    # Do not use transparency index as a new color
 | 
				
			||||||
| 
						 | 
					@ -79,7 +81,7 @@ def test_getcolor_not_special(index, palette):
 | 
				
			||||||
    assert index2 not in (index, index1)
 | 
					    assert index2 not in (index, index1)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_file(tmp_path):
 | 
					def test_file(tmp_path: Path) -> None:
 | 
				
			||||||
    palette = ImagePalette.ImagePalette("RGB", list(range(256)) * 3)
 | 
					    palette = ImagePalette.ImagePalette("RGB", list(range(256)) * 3)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    f = str(tmp_path / "temp.lut")
 | 
					    f = str(tmp_path / "temp.lut")
 | 
				
			||||||
| 
						 | 
					@ -97,7 +99,7 @@ def test_file(tmp_path):
 | 
				
			||||||
    assert p.palette == palette.tobytes()
 | 
					    assert p.palette == palette.tobytes()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_make_linear_lut():
 | 
					def test_make_linear_lut() -> None:
 | 
				
			||||||
    # Arrange
 | 
					    # Arrange
 | 
				
			||||||
    black = 0
 | 
					    black = 0
 | 
				
			||||||
    white = 255
 | 
					    white = 255
 | 
				
			||||||
| 
						 | 
					@ -113,7 +115,7 @@ def test_make_linear_lut():
 | 
				
			||||||
        assert lut[i] == i
 | 
					        assert lut[i] == i
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_make_linear_lut_not_yet_implemented():
 | 
					def test_make_linear_lut_not_yet_implemented() -> None:
 | 
				
			||||||
    # Update after FIXME
 | 
					    # Update after FIXME
 | 
				
			||||||
    # Arrange
 | 
					    # Arrange
 | 
				
			||||||
    black = 1
 | 
					    black = 1
 | 
				
			||||||
| 
						 | 
					@ -124,7 +126,7 @@ def test_make_linear_lut_not_yet_implemented():
 | 
				
			||||||
        ImagePalette.make_linear_lut(black, white)
 | 
					        ImagePalette.make_linear_lut(black, white)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_make_gamma_lut():
 | 
					def test_make_gamma_lut() -> None:
 | 
				
			||||||
    # Arrange
 | 
					    # Arrange
 | 
				
			||||||
    exp = 5
 | 
					    exp = 5
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -142,7 +144,7 @@ def test_make_gamma_lut():
 | 
				
			||||||
    assert lut[255] == 255
 | 
					    assert lut[255] == 255
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_rawmode_valueerrors(tmp_path):
 | 
					def test_rawmode_valueerrors(tmp_path: Path) -> None:
 | 
				
			||||||
    # Arrange
 | 
					    # Arrange
 | 
				
			||||||
    palette = ImagePalette.raw("RGB", list(range(256)) * 3)
 | 
					    palette = ImagePalette.raw("RGB", list(range(256)) * 3)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -156,7 +158,7 @@ def test_rawmode_valueerrors(tmp_path):
 | 
				
			||||||
        palette.save(f)
 | 
					        palette.save(f)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_getdata():
 | 
					def test_getdata() -> None:
 | 
				
			||||||
    # Arrange
 | 
					    # Arrange
 | 
				
			||||||
    data_in = list(range(256)) * 3
 | 
					    data_in = list(range(256)) * 3
 | 
				
			||||||
    palette = ImagePalette.ImagePalette("RGB", data_in)
 | 
					    palette = ImagePalette.ImagePalette("RGB", data_in)
 | 
				
			||||||
| 
						 | 
					@ -168,7 +170,7 @@ def test_getdata():
 | 
				
			||||||
    assert mode == "RGB"
 | 
					    assert mode == "RGB"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_rawmode_getdata():
 | 
					def test_rawmode_getdata() -> None:
 | 
				
			||||||
    # Arrange
 | 
					    # Arrange
 | 
				
			||||||
    data_in = list(range(256)) * 3
 | 
					    data_in = list(range(256)) * 3
 | 
				
			||||||
    palette = ImagePalette.raw("RGB", data_in)
 | 
					    palette = ImagePalette.raw("RGB", data_in)
 | 
				
			||||||
| 
						 | 
					@ -181,7 +183,7 @@ def test_rawmode_getdata():
 | 
				
			||||||
    assert data_in == data_out
 | 
					    assert data_in == data_out
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_2bit_palette(tmp_path):
 | 
					def test_2bit_palette(tmp_path: Path) -> None:
 | 
				
			||||||
    # issue #2258, 2 bit palettes are corrupted.
 | 
					    # issue #2258, 2 bit palettes are corrupted.
 | 
				
			||||||
    outfile = str(tmp_path / "temp.png")
 | 
					    outfile = str(tmp_path / "temp.png")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -193,6 +195,6 @@ def test_2bit_palette(tmp_path):
 | 
				
			||||||
    assert_image_equal_tofile(img, outfile)
 | 
					    assert_image_equal_tofile(img, outfile)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_invalid_palette():
 | 
					def test_invalid_palette() -> None:
 | 
				
			||||||
    with pytest.raises(OSError):
 | 
					    with pytest.raises(OSError):
 | 
				
			||||||
        ImagePalette.load("Tests/images/hopper.jpg")
 | 
					        ImagePalette.load("Tests/images/hopper.jpg")
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -9,7 +9,7 @@ import pytest
 | 
				
			||||||
from PIL import Image, ImagePath
 | 
					from PIL import Image, ImagePath
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_path():
 | 
					def test_path() -> None:
 | 
				
			||||||
    p = ImagePath.Path(list(range(10)))
 | 
					    p = ImagePath.Path(list(range(10)))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    # sequence interface
 | 
					    # sequence interface
 | 
				
			||||||
| 
						 | 
					@ -57,7 +57,7 @@ def test_path():
 | 
				
			||||||
        ImagePath.Path((0, 1)),
 | 
					        ImagePath.Path((0, 1)),
 | 
				
			||||||
    ),
 | 
					    ),
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
def test_path_constructors(coords):
 | 
					def test_path_constructors(coords) -> None:
 | 
				
			||||||
    # Arrange / Act
 | 
					    # Arrange / Act
 | 
				
			||||||
    p = ImagePath.Path(coords)
 | 
					    p = ImagePath.Path(coords)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -75,7 +75,7 @@ def test_path_constructors(coords):
 | 
				
			||||||
        [[0.0, 1.0]],
 | 
					        [[0.0, 1.0]],
 | 
				
			||||||
    ),
 | 
					    ),
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
def test_invalid_path_constructors(coords):
 | 
					def test_invalid_path_constructors(coords) -> None:
 | 
				
			||||||
    # Act
 | 
					    # Act
 | 
				
			||||||
    with pytest.raises(ValueError) as e:
 | 
					    with pytest.raises(ValueError) as e:
 | 
				
			||||||
        ImagePath.Path(coords)
 | 
					        ImagePath.Path(coords)
 | 
				
			||||||
| 
						 | 
					@ -93,7 +93,7 @@ def test_invalid_path_constructors(coords):
 | 
				
			||||||
        [0, 1, 2],
 | 
					        [0, 1, 2],
 | 
				
			||||||
    ),
 | 
					    ),
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
def test_path_odd_number_of_coordinates(coords):
 | 
					def test_path_odd_number_of_coordinates(coords) -> None:
 | 
				
			||||||
    # Act
 | 
					    # Act
 | 
				
			||||||
    with pytest.raises(ValueError) as e:
 | 
					    with pytest.raises(ValueError) as e:
 | 
				
			||||||
        ImagePath.Path(coords)
 | 
					        ImagePath.Path(coords)
 | 
				
			||||||
| 
						 | 
					@ -111,7 +111,7 @@ def test_path_odd_number_of_coordinates(coords):
 | 
				
			||||||
        (1, (0.0, 0.0, 0.0, 0.0)),
 | 
					        (1, (0.0, 0.0, 0.0, 0.0)),
 | 
				
			||||||
    ],
 | 
					    ],
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
def test_getbbox(coords, expected):
 | 
					def test_getbbox(coords, expected) -> None:
 | 
				
			||||||
    # Arrange
 | 
					    # Arrange
 | 
				
			||||||
    p = ImagePath.Path(coords)
 | 
					    p = ImagePath.Path(coords)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -119,7 +119,7 @@ def test_getbbox(coords, expected):
 | 
				
			||||||
    assert p.getbbox() == expected
 | 
					    assert p.getbbox() == expected
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_getbbox_no_args():
 | 
					def test_getbbox_no_args() -> None:
 | 
				
			||||||
    # Arrange
 | 
					    # Arrange
 | 
				
			||||||
    p = ImagePath.Path([0, 1, 2, 3])
 | 
					    p = ImagePath.Path([0, 1, 2, 3])
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -135,7 +135,7 @@ def test_getbbox_no_args():
 | 
				
			||||||
        (list(range(6)), [(0.0, 3.0), (4.0, 9.0), (8.0, 15.0)]),
 | 
					        (list(range(6)), [(0.0, 3.0), (4.0, 9.0), (8.0, 15.0)]),
 | 
				
			||||||
    ],
 | 
					    ],
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
def test_map(coords, expected):
 | 
					def test_map(coords, expected) -> None:
 | 
				
			||||||
    # Arrange
 | 
					    # Arrange
 | 
				
			||||||
    p = ImagePath.Path(coords)
 | 
					    p = ImagePath.Path(coords)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -147,7 +147,7 @@ def test_map(coords, expected):
 | 
				
			||||||
    assert list(p) == expected
 | 
					    assert list(p) == expected
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_transform():
 | 
					def test_transform() -> None:
 | 
				
			||||||
    # Arrange
 | 
					    # Arrange
 | 
				
			||||||
    p = ImagePath.Path([0, 1, 2, 3])
 | 
					    p = ImagePath.Path([0, 1, 2, 3])
 | 
				
			||||||
    theta = math.pi / 15
 | 
					    theta = math.pi / 15
 | 
				
			||||||
| 
						 | 
					@ -165,7 +165,7 @@ def test_transform():
 | 
				
			||||||
    ]
 | 
					    ]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_transform_with_wrap():
 | 
					def test_transform_with_wrap() -> None:
 | 
				
			||||||
    # Arrange
 | 
					    # Arrange
 | 
				
			||||||
    p = ImagePath.Path([0, 1, 2, 3])
 | 
					    p = ImagePath.Path([0, 1, 2, 3])
 | 
				
			||||||
    theta = math.pi / 15
 | 
					    theta = math.pi / 15
 | 
				
			||||||
| 
						 | 
					@ -184,7 +184,7 @@ def test_transform_with_wrap():
 | 
				
			||||||
    ]
 | 
					    ]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_overflow_segfault():
 | 
					def test_overflow_segfault() -> None:
 | 
				
			||||||
    # Some Pythons fail getting the argument as an integer, and it falls
 | 
					    # Some Pythons fail getting the argument as an integer, and it falls
 | 
				
			||||||
    # through to the sequence. Seeing this on 32-bit Windows.
 | 
					    # through to the sequence. Seeing this on 32-bit Windows.
 | 
				
			||||||
    with pytest.raises((TypeError, MemoryError)):
 | 
					    with pytest.raises((TypeError, MemoryError)):
 | 
				
			||||||
| 
						 | 
					@ -198,12 +198,12 @@ def test_overflow_segfault():
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class Evil:
 | 
					class Evil:
 | 
				
			||||||
    def __init__(self):
 | 
					    def __init__(self) -> None:
 | 
				
			||||||
        self.corrupt = Image.core.path(0x4000000000000000)
 | 
					        self.corrupt = Image.core.path(0x4000000000000000)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def __getitem__(self, i):
 | 
					    def __getitem__(self, i):
 | 
				
			||||||
        x = self.corrupt[i]
 | 
					        x = self.corrupt[i]
 | 
				
			||||||
        return struct.pack("dd", x[0], x[1])
 | 
					        return struct.pack("dd", x[0], x[1])
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def __setitem__(self, i, x):
 | 
					    def __setitem__(self, i, x) -> None:
 | 
				
			||||||
        self.corrupt[i] = struct.unpack("dd", x)
 | 
					        self.corrupt[i] = struct.unpack("dd", x)
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -16,7 +16,7 @@ if ImageQt.qt_is_installed:
 | 
				
			||||||
    from PIL.ImageQt import qRgba
 | 
					    from PIL.ImageQt import qRgba
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_rgb():
 | 
					def test_rgb() -> None:
 | 
				
			||||||
    # from https://doc.qt.io/archives/qt-4.8/qcolor.html
 | 
					    # from https://doc.qt.io/archives/qt-4.8/qcolor.html
 | 
				
			||||||
    # typedef QRgb
 | 
					    # typedef QRgb
 | 
				
			||||||
    # An ARGB quadruplet on the format #AARRGGBB,
 | 
					    # An ARGB quadruplet on the format #AARRGGBB,
 | 
				
			||||||
| 
						 | 
					@ -28,7 +28,7 @@ def test_rgb():
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    assert qRgb(0, 0, 0) == qRgba(0, 0, 0, 255)
 | 
					    assert qRgb(0, 0, 0) == qRgba(0, 0, 0, 255)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def checkrgb(r, g, b):
 | 
					    def checkrgb(r, g, b) -> None:
 | 
				
			||||||
        val = ImageQt.rgb(r, g, b)
 | 
					        val = ImageQt.rgb(r, g, b)
 | 
				
			||||||
        val = val % 2**24  # drop the alpha
 | 
					        val = val % 2**24  # drop the alpha
 | 
				
			||||||
        assert val >> 16 == r
 | 
					        assert val >> 16 == r
 | 
				
			||||||
| 
						 | 
					@ -41,7 +41,7 @@ def test_rgb():
 | 
				
			||||||
    checkrgb(0, 0, 255)
 | 
					    checkrgb(0, 0, 255)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_image():
 | 
					def test_image() -> None:
 | 
				
			||||||
    modes = ["1", "RGB", "RGBA", "L", "P"]
 | 
					    modes = ["1", "RGB", "RGBA", "L", "P"]
 | 
				
			||||||
    qt_format = ImageQt.QImage.Format if ImageQt.qt_version == "6" else ImageQt.QImage
 | 
					    qt_format = ImageQt.QImage.Format if ImageQt.qt_version == "6" else ImageQt.QImage
 | 
				
			||||||
    if hasattr(qt_format, "Format_Grayscale16"):  # Qt 5.13+
 | 
					    if hasattr(qt_format, "Format_Grayscale16"):  # Qt 5.13+
 | 
				
			||||||
| 
						 | 
					@ -55,6 +55,6 @@ def test_image():
 | 
				
			||||||
        assert_image_similar(roundtripped_im, im, 1)
 | 
					        assert_image_similar(roundtripped_im, im, 1)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_closed_file():
 | 
					def test_closed_file() -> None:
 | 
				
			||||||
    with warnings.catch_warnings():
 | 
					    with warnings.catch_warnings():
 | 
				
			||||||
        ImageQt.ImageQt("Tests/images/hopper.gif")
 | 
					        ImageQt.ImageQt("Tests/images/hopper.gif")
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,5 +1,7 @@
 | 
				
			||||||
from __future__ import annotations
 | 
					from __future__ import annotations
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					from pathlib import Path
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import pytest
 | 
					import pytest
 | 
				
			||||||
 | 
					
 | 
				
			||||||
from PIL import Image, ImageSequence, TiffImagePlugin
 | 
					from PIL import Image, ImageSequence, TiffImagePlugin
 | 
				
			||||||
| 
						 | 
					@ -7,7 +9,7 @@ from PIL import Image, ImageSequence, TiffImagePlugin
 | 
				
			||||||
from .helper import assert_image_equal, hopper, skip_unless_feature
 | 
					from .helper import assert_image_equal, hopper, skip_unless_feature
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_sanity(tmp_path):
 | 
					def test_sanity(tmp_path: Path) -> None:
 | 
				
			||||||
    test_file = str(tmp_path / "temp.im")
 | 
					    test_file = str(tmp_path / "temp.im")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    im = hopper("RGB")
 | 
					    im = hopper("RGB")
 | 
				
			||||||
| 
						 | 
					@ -27,7 +29,7 @@ def test_sanity(tmp_path):
 | 
				
			||||||
        ImageSequence.Iterator(0)
 | 
					        ImageSequence.Iterator(0)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_iterator():
 | 
					def test_iterator() -> None:
 | 
				
			||||||
    with Image.open("Tests/images/multipage.tiff") as im:
 | 
					    with Image.open("Tests/images/multipage.tiff") as im:
 | 
				
			||||||
        i = ImageSequence.Iterator(im)
 | 
					        i = ImageSequence.Iterator(im)
 | 
				
			||||||
        for index in range(0, im.n_frames):
 | 
					        for index in range(0, im.n_frames):
 | 
				
			||||||
| 
						 | 
					@ -38,14 +40,14 @@ def test_iterator():
 | 
				
			||||||
            next(i)
 | 
					            next(i)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_iterator_min_frame():
 | 
					def test_iterator_min_frame() -> None:
 | 
				
			||||||
    with Image.open("Tests/images/hopper.psd") as im:
 | 
					    with Image.open("Tests/images/hopper.psd") as im:
 | 
				
			||||||
        i = ImageSequence.Iterator(im)
 | 
					        i = ImageSequence.Iterator(im)
 | 
				
			||||||
        for index in range(1, im.n_frames):
 | 
					        for index in range(1, im.n_frames):
 | 
				
			||||||
            assert i[index] == next(i)
 | 
					            assert i[index] == next(i)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def _test_multipage_tiff():
 | 
					def _test_multipage_tiff() -> None:
 | 
				
			||||||
    with Image.open("Tests/images/multipage.tiff") as im:
 | 
					    with Image.open("Tests/images/multipage.tiff") as im:
 | 
				
			||||||
        for index, frame in enumerate(ImageSequence.Iterator(im)):
 | 
					        for index, frame in enumerate(ImageSequence.Iterator(im)):
 | 
				
			||||||
            frame.load()
 | 
					            frame.load()
 | 
				
			||||||
| 
						 | 
					@ -53,18 +55,18 @@ def _test_multipage_tiff():
 | 
				
			||||||
            frame.convert("RGB")
 | 
					            frame.convert("RGB")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_tiff():
 | 
					def test_tiff() -> None:
 | 
				
			||||||
    _test_multipage_tiff()
 | 
					    _test_multipage_tiff()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@skip_unless_feature("libtiff")
 | 
					@skip_unless_feature("libtiff")
 | 
				
			||||||
def test_libtiff():
 | 
					def test_libtiff() -> None:
 | 
				
			||||||
    TiffImagePlugin.READ_LIBTIFF = True
 | 
					    TiffImagePlugin.READ_LIBTIFF = True
 | 
				
			||||||
    _test_multipage_tiff()
 | 
					    _test_multipage_tiff()
 | 
				
			||||||
    TiffImagePlugin.READ_LIBTIFF = False
 | 
					    TiffImagePlugin.READ_LIBTIFF = False
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_consecutive():
 | 
					def test_consecutive() -> None:
 | 
				
			||||||
    with Image.open("Tests/images/multipage.tiff") as im:
 | 
					    with Image.open("Tests/images/multipage.tiff") as im:
 | 
				
			||||||
        first_frame = None
 | 
					        first_frame = None
 | 
				
			||||||
        for frame in ImageSequence.Iterator(im):
 | 
					        for frame in ImageSequence.Iterator(im):
 | 
				
			||||||
| 
						 | 
					@ -75,7 +77,7 @@ def test_consecutive():
 | 
				
			||||||
            break
 | 
					            break
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_palette_mmap():
 | 
					def test_palette_mmap() -> None:
 | 
				
			||||||
    # Using mmap in ImageFile can require to reload the palette.
 | 
					    # Using mmap in ImageFile can require to reload the palette.
 | 
				
			||||||
    with Image.open("Tests/images/multipage-mmap.tiff") as im:
 | 
					    with Image.open("Tests/images/multipage-mmap.tiff") as im:
 | 
				
			||||||
        color1 = im.getpalette()[:3]
 | 
					        color1 = im.getpalette()[:3]
 | 
				
			||||||
| 
						 | 
					@ -84,7 +86,7 @@ def test_palette_mmap():
 | 
				
			||||||
        assert color1 == color2
 | 
					        assert color1 == color2
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_all_frames():
 | 
					def test_all_frames() -> None:
 | 
				
			||||||
    # Test a single image
 | 
					    # Test a single image
 | 
				
			||||||
    with Image.open("Tests/images/iss634.gif") as im:
 | 
					    with Image.open("Tests/images/iss634.gif") as im:
 | 
				
			||||||
        ims = ImageSequence.all_frames(im)
 | 
					        ims = ImageSequence.all_frames(im)
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -7,12 +7,12 @@ from PIL import Image, ImageShow
 | 
				
			||||||
from .helper import hopper, is_win32, on_ci
 | 
					from .helper import hopper, is_win32, on_ci
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_sanity():
 | 
					def test_sanity() -> None:
 | 
				
			||||||
    dir(Image)
 | 
					    dir(Image)
 | 
				
			||||||
    dir(ImageShow)
 | 
					    dir(ImageShow)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_register():
 | 
					def test_register() -> None:
 | 
				
			||||||
    # Test registering a viewer that is not a class
 | 
					    # Test registering a viewer that is not a class
 | 
				
			||||||
    ImageShow.register("not a class")
 | 
					    ImageShow.register("not a class")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -24,9 +24,9 @@ def test_register():
 | 
				
			||||||
    "order",
 | 
					    "order",
 | 
				
			||||||
    [-1, 0],
 | 
					    [-1, 0],
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
def test_viewer_show(order):
 | 
					def test_viewer_show(order) -> None:
 | 
				
			||||||
    class TestViewer(ImageShow.Viewer):
 | 
					    class TestViewer(ImageShow.Viewer):
 | 
				
			||||||
        def show_image(self, image, **options):
 | 
					        def show_image(self, image, **options) -> bool:
 | 
				
			||||||
            self.methodCalled = True
 | 
					            self.methodCalled = True
 | 
				
			||||||
            return True
 | 
					            return True
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -48,12 +48,12 @@ def test_viewer_show(order):
 | 
				
			||||||
    reason="Only run on CIs; hangs on Windows CIs",
 | 
					    reason="Only run on CIs; hangs on Windows CIs",
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
@pytest.mark.parametrize("mode", ("1", "I;16", "LA", "RGB", "RGBA"))
 | 
					@pytest.mark.parametrize("mode", ("1", "I;16", "LA", "RGB", "RGBA"))
 | 
				
			||||||
def test_show(mode):
 | 
					def test_show(mode) -> None:
 | 
				
			||||||
    im = hopper(mode)
 | 
					    im = hopper(mode)
 | 
				
			||||||
    assert ImageShow.show(im)
 | 
					    assert ImageShow.show(im)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_show_without_viewers():
 | 
					def test_show_without_viewers() -> None:
 | 
				
			||||||
    viewers = ImageShow._viewers
 | 
					    viewers = ImageShow._viewers
 | 
				
			||||||
    ImageShow._viewers = []
 | 
					    ImageShow._viewers = []
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -63,7 +63,7 @@ def test_show_without_viewers():
 | 
				
			||||||
    ImageShow._viewers = viewers
 | 
					    ImageShow._viewers = viewers
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_viewer():
 | 
					def test_viewer() -> None:
 | 
				
			||||||
    viewer = ImageShow.Viewer()
 | 
					    viewer = ImageShow.Viewer()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    assert viewer.get_format(None) is None
 | 
					    assert viewer.get_format(None) is None
 | 
				
			||||||
| 
						 | 
					@ -73,14 +73,14 @@ def test_viewer():
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@pytest.mark.parametrize("viewer", ImageShow._viewers)
 | 
					@pytest.mark.parametrize("viewer", ImageShow._viewers)
 | 
				
			||||||
def test_viewers(viewer):
 | 
					def test_viewers(viewer) -> None:
 | 
				
			||||||
    try:
 | 
					    try:
 | 
				
			||||||
        viewer.get_command("test.jpg")
 | 
					        viewer.get_command("test.jpg")
 | 
				
			||||||
    except NotImplementedError:
 | 
					    except NotImplementedError:
 | 
				
			||||||
        pass
 | 
					        pass
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_ipythonviewer():
 | 
					def test_ipythonviewer() -> None:
 | 
				
			||||||
    pytest.importorskip("IPython", reason="IPython not installed")
 | 
					    pytest.importorskip("IPython", reason="IPython not installed")
 | 
				
			||||||
    for viewer in ImageShow._viewers:
 | 
					    for viewer in ImageShow._viewers:
 | 
				
			||||||
        if isinstance(viewer, ImageShow.IPythonViewer):
 | 
					        if isinstance(viewer, ImageShow.IPythonViewer):
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -7,7 +7,7 @@ from PIL import Image, ImageStat
 | 
				
			||||||
from .helper import hopper
 | 
					from .helper import hopper
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_sanity():
 | 
					def test_sanity() -> None:
 | 
				
			||||||
    im = hopper()
 | 
					    im = hopper()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    st = ImageStat.Stat(im)
 | 
					    st = ImageStat.Stat(im)
 | 
				
			||||||
| 
						 | 
					@ -31,7 +31,7 @@ def test_sanity():
 | 
				
			||||||
        ImageStat.Stat(1)
 | 
					        ImageStat.Stat(1)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_hopper():
 | 
					def test_hopper() -> None:
 | 
				
			||||||
    im = hopper()
 | 
					    im = hopper()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    st = ImageStat.Stat(im)
 | 
					    st = ImageStat.Stat(im)
 | 
				
			||||||
| 
						 | 
					@ -44,7 +44,7 @@ def test_hopper():
 | 
				
			||||||
    assert st.sum[2] == 1563008
 | 
					    assert st.sum[2] == 1563008
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_constant():
 | 
					def test_constant() -> None:
 | 
				
			||||||
    im = Image.new("L", (128, 128), 128)
 | 
					    im = Image.new("L", (128, 128), 128)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    st = ImageStat.Stat(im)
 | 
					    st = ImageStat.Stat(im)
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -23,7 +23,7 @@ TK_MODES = ("1", "L", "P", "RGB", "RGBA")
 | 
				
			||||||
pytestmark = pytest.mark.skipif(not HAS_TK, reason="Tk not installed")
 | 
					pytestmark = pytest.mark.skipif(not HAS_TK, reason="Tk not installed")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def setup_module():
 | 
					def setup_module() -> None:
 | 
				
			||||||
    try:
 | 
					    try:
 | 
				
			||||||
        # setup tk
 | 
					        # setup tk
 | 
				
			||||||
        tk.Frame()
 | 
					        tk.Frame()
 | 
				
			||||||
| 
						 | 
					@ -34,7 +34,7 @@ def setup_module():
 | 
				
			||||||
        pytest.skip(f"TCL Error: {v}")
 | 
					        pytest.skip(f"TCL Error: {v}")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_kw():
 | 
					def test_kw() -> None:
 | 
				
			||||||
    TEST_JPG = "Tests/images/hopper.jpg"
 | 
					    TEST_JPG = "Tests/images/hopper.jpg"
 | 
				
			||||||
    TEST_PNG = "Tests/images/hopper.png"
 | 
					    TEST_PNG = "Tests/images/hopper.png"
 | 
				
			||||||
    with Image.open(TEST_JPG) as im1:
 | 
					    with Image.open(TEST_JPG) as im1:
 | 
				
			||||||
| 
						 | 
					@ -57,7 +57,7 @@ def test_kw():
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@pytest.mark.parametrize("mode", TK_MODES)
 | 
					@pytest.mark.parametrize("mode", TK_MODES)
 | 
				
			||||||
def test_photoimage(mode):
 | 
					def test_photoimage(mode) -> None:
 | 
				
			||||||
    # test as image:
 | 
					    # test as image:
 | 
				
			||||||
    im = hopper(mode)
 | 
					    im = hopper(mode)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -71,7 +71,7 @@ def test_photoimage(mode):
 | 
				
			||||||
    assert_image_equal(reloaded, im.convert("RGBA"))
 | 
					    assert_image_equal(reloaded, im.convert("RGBA"))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_photoimage_apply_transparency():
 | 
					def test_photoimage_apply_transparency() -> None:
 | 
				
			||||||
    with Image.open("Tests/images/pil123p.png") as im:
 | 
					    with Image.open("Tests/images/pil123p.png") as im:
 | 
				
			||||||
        im_tk = ImageTk.PhotoImage(im)
 | 
					        im_tk = ImageTk.PhotoImage(im)
 | 
				
			||||||
        reloaded = ImageTk.getimage(im_tk)
 | 
					        reloaded = ImageTk.getimage(im_tk)
 | 
				
			||||||
| 
						 | 
					@ -79,7 +79,7 @@ def test_photoimage_apply_transparency():
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@pytest.mark.parametrize("mode", TK_MODES)
 | 
					@pytest.mark.parametrize("mode", TK_MODES)
 | 
				
			||||||
def test_photoimage_blank(mode):
 | 
					def test_photoimage_blank(mode) -> None:
 | 
				
			||||||
    # test a image using mode/size:
 | 
					    # test a image using mode/size:
 | 
				
			||||||
    im_tk = ImageTk.PhotoImage(mode, (100, 100))
 | 
					    im_tk = ImageTk.PhotoImage(mode, (100, 100))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -91,7 +91,7 @@ def test_photoimage_blank(mode):
 | 
				
			||||||
    assert_image_equal(reloaded.convert(mode), im)
 | 
					    assert_image_equal(reloaded.convert(mode), im)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_bitmapimage():
 | 
					def test_bitmapimage() -> None:
 | 
				
			||||||
    im = hopper("1")
 | 
					    im = hopper("1")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    # this should not crash
 | 
					    # this should not crash
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -8,10 +8,10 @@ from .helper import hopper, is_win32
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class TestImageWin:
 | 
					class TestImageWin:
 | 
				
			||||||
    def test_sanity(self):
 | 
					    def test_sanity(self) -> None:
 | 
				
			||||||
        dir(ImageWin)
 | 
					        dir(ImageWin)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_hdc(self):
 | 
					    def test_hdc(self) -> None:
 | 
				
			||||||
        # Arrange
 | 
					        # Arrange
 | 
				
			||||||
        dc = 50
 | 
					        dc = 50
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -22,7 +22,7 @@ class TestImageWin:
 | 
				
			||||||
        # Assert
 | 
					        # Assert
 | 
				
			||||||
        assert dc2 == 50
 | 
					        assert dc2 == 50
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_hwnd(self):
 | 
					    def test_hwnd(self) -> None:
 | 
				
			||||||
        # Arrange
 | 
					        # Arrange
 | 
				
			||||||
        wnd = 50
 | 
					        wnd = 50
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -36,7 +36,7 @@ class TestImageWin:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@pytest.mark.skipif(not is_win32(), reason="Windows only")
 | 
					@pytest.mark.skipif(not is_win32(), reason="Windows only")
 | 
				
			||||||
class TestImageWinDib:
 | 
					class TestImageWinDib:
 | 
				
			||||||
    def test_dib_image(self):
 | 
					    def test_dib_image(self) -> None:
 | 
				
			||||||
        # Arrange
 | 
					        # Arrange
 | 
				
			||||||
        im = hopper()
 | 
					        im = hopper()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -46,7 +46,7 @@ class TestImageWinDib:
 | 
				
			||||||
        # Assert
 | 
					        # Assert
 | 
				
			||||||
        assert dib.size == im.size
 | 
					        assert dib.size == im.size
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_dib_mode_string(self):
 | 
					    def test_dib_mode_string(self) -> None:
 | 
				
			||||||
        # Arrange
 | 
					        # Arrange
 | 
				
			||||||
        mode = "RGBA"
 | 
					        mode = "RGBA"
 | 
				
			||||||
        size = (128, 128)
 | 
					        size = (128, 128)
 | 
				
			||||||
| 
						 | 
					@ -57,7 +57,7 @@ class TestImageWinDib:
 | 
				
			||||||
        # Assert
 | 
					        # Assert
 | 
				
			||||||
        assert dib.size == (128, 128)
 | 
					        assert dib.size == (128, 128)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_dib_paste(self):
 | 
					    def test_dib_paste(self) -> None:
 | 
				
			||||||
        # Arrange
 | 
					        # Arrange
 | 
				
			||||||
        im = hopper()
 | 
					        im = hopper()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -71,7 +71,7 @@ class TestImageWinDib:
 | 
				
			||||||
        # Assert
 | 
					        # Assert
 | 
				
			||||||
        assert dib.size == (128, 128)
 | 
					        assert dib.size == (128, 128)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_dib_paste_bbox(self):
 | 
					    def test_dib_paste_bbox(self) -> None:
 | 
				
			||||||
        # Arrange
 | 
					        # Arrange
 | 
				
			||||||
        im = hopper()
 | 
					        im = hopper()
 | 
				
			||||||
        bbox = (0, 0, 10, 10)
 | 
					        bbox = (0, 0, 10, 10)
 | 
				
			||||||
| 
						 | 
					@ -86,7 +86,7 @@ class TestImageWinDib:
 | 
				
			||||||
        # Assert
 | 
					        # Assert
 | 
				
			||||||
        assert dib.size == (128, 128)
 | 
					        assert dib.size == (128, 128)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_dib_frombytes_tobytes_roundtrip(self):
 | 
					    def test_dib_frombytes_tobytes_roundtrip(self) -> None:
 | 
				
			||||||
        # Arrange
 | 
					        # Arrange
 | 
				
			||||||
        # Make two different DIB images
 | 
					        # Make two different DIB images
 | 
				
			||||||
        im = hopper()
 | 
					        im = hopper()
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,6 +1,7 @@
 | 
				
			||||||
from __future__ import annotations
 | 
					from __future__ import annotations
 | 
				
			||||||
 | 
					
 | 
				
			||||||
from io import BytesIO
 | 
					from io import BytesIO
 | 
				
			||||||
 | 
					from pathlib import Path
 | 
				
			||||||
 | 
					
 | 
				
			||||||
from PIL import Image, ImageWin
 | 
					from PIL import Image, ImageWin
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -83,7 +84,7 @@ if is_win32():
 | 
				
			||||||
        memcpy(bp + bf.bfOffBits, pixels, bi.biSizeImage)
 | 
					        memcpy(bp + bf.bfOffBits, pixels, bi.biSizeImage)
 | 
				
			||||||
        return bytearray(buf)
 | 
					        return bytearray(buf)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_pointer(tmp_path):
 | 
					    def test_pointer(tmp_path: Path) -> None:
 | 
				
			||||||
        im = hopper()
 | 
					        im = hopper()
 | 
				
			||||||
        (width, height) = im.size
 | 
					        (width, height) = im.size
 | 
				
			||||||
        opath = str(tmp_path / "temp.png")
 | 
					        opath = str(tmp_path / "temp.png")
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -10,7 +10,7 @@ X = 255
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class TestLibPack:
 | 
					class TestLibPack:
 | 
				
			||||||
    def assert_pack(self, mode, rawmode, data, *pixels):
 | 
					    def assert_pack(self, mode, rawmode, data, *pixels) -> None:
 | 
				
			||||||
        """
 | 
					        """
 | 
				
			||||||
        data - either raw bytes with data or just number of bytes in rawmode.
 | 
					        data - either raw bytes with data or just number of bytes in rawmode.
 | 
				
			||||||
        """
 | 
					        """
 | 
				
			||||||
| 
						 | 
					@ -24,7 +24,7 @@ class TestLibPack:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        assert data == im.tobytes("raw", rawmode)
 | 
					        assert data == im.tobytes("raw", rawmode)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_1(self):
 | 
					    def test_1(self) -> None:
 | 
				
			||||||
        self.assert_pack("1", "1", b"\x01", 0, 0, 0, 0, 0, 0, 0, X)
 | 
					        self.assert_pack("1", "1", b"\x01", 0, 0, 0, 0, 0, 0, 0, X)
 | 
				
			||||||
        self.assert_pack("1", "1;I", b"\x01", X, X, X, X, X, X, X, 0)
 | 
					        self.assert_pack("1", "1;I", b"\x01", X, X, X, X, X, X, X, 0)
 | 
				
			||||||
        self.assert_pack("1", "1;R", b"\x01", X, 0, 0, 0, 0, 0, 0, 0)
 | 
					        self.assert_pack("1", "1;R", b"\x01", X, 0, 0, 0, 0, 0, 0, 0)
 | 
				
			||||||
| 
						 | 
					@ -37,29 +37,29 @@ class TestLibPack:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        self.assert_pack("1", "L", b"\xff\x00\x00\xff\x00\x00", X, 0, 0, X, 0, 0)
 | 
					        self.assert_pack("1", "L", b"\xff\x00\x00\xff\x00\x00", X, 0, 0, X, 0, 0)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_L(self):
 | 
					    def test_L(self) -> None:
 | 
				
			||||||
        self.assert_pack("L", "L", 1, 1, 2, 3, 4)
 | 
					        self.assert_pack("L", "L", 1, 1, 2, 3, 4)
 | 
				
			||||||
        self.assert_pack("L", "L;16", b"\x00\xc6\x00\xaf", 198, 175)
 | 
					        self.assert_pack("L", "L;16", b"\x00\xc6\x00\xaf", 198, 175)
 | 
				
			||||||
        self.assert_pack("L", "L;16B", b"\xc6\x00\xaf\x00", 198, 175)
 | 
					        self.assert_pack("L", "L;16B", b"\xc6\x00\xaf\x00", 198, 175)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_LA(self):
 | 
					    def test_LA(self) -> None:
 | 
				
			||||||
        self.assert_pack("LA", "LA", 2, (1, 2), (3, 4), (5, 6))
 | 
					        self.assert_pack("LA", "LA", 2, (1, 2), (3, 4), (5, 6))
 | 
				
			||||||
        self.assert_pack("LA", "LA;L", 2, (1, 4), (2, 5), (3, 6))
 | 
					        self.assert_pack("LA", "LA;L", 2, (1, 4), (2, 5), (3, 6))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_La(self):
 | 
					    def test_La(self) -> None:
 | 
				
			||||||
        self.assert_pack("La", "La", 2, (1, 2), (3, 4), (5, 6))
 | 
					        self.assert_pack("La", "La", 2, (1, 2), (3, 4), (5, 6))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_P(self):
 | 
					    def test_P(self) -> None:
 | 
				
			||||||
        self.assert_pack("P", "P;1", b"\xe4", 1, 1, 1, 0, 0, 255, 0, 0)
 | 
					        self.assert_pack("P", "P;1", b"\xe4", 1, 1, 1, 0, 0, 255, 0, 0)
 | 
				
			||||||
        self.assert_pack("P", "P;2", b"\xe4", 3, 2, 1, 0)
 | 
					        self.assert_pack("P", "P;2", b"\xe4", 3, 2, 1, 0)
 | 
				
			||||||
        self.assert_pack("P", "P;4", b"\x02\xef", 0, 2, 14, 15)
 | 
					        self.assert_pack("P", "P;4", b"\x02\xef", 0, 2, 14, 15)
 | 
				
			||||||
        self.assert_pack("P", "P", 1, 1, 2, 3, 4)
 | 
					        self.assert_pack("P", "P", 1, 1, 2, 3, 4)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_PA(self):
 | 
					    def test_PA(self) -> None:
 | 
				
			||||||
        self.assert_pack("PA", "PA", 2, (1, 2), (3, 4), (5, 6))
 | 
					        self.assert_pack("PA", "PA", 2, (1, 2), (3, 4), (5, 6))
 | 
				
			||||||
        self.assert_pack("PA", "PA;L", 2, (1, 4), (2, 5), (3, 6))
 | 
					        self.assert_pack("PA", "PA;L", 2, (1, 4), (2, 5), (3, 6))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_RGB(self):
 | 
					    def test_RGB(self) -> None:
 | 
				
			||||||
        self.assert_pack("RGB", "RGB", 3, (1, 2, 3), (4, 5, 6), (7, 8, 9))
 | 
					        self.assert_pack("RGB", "RGB", 3, (1, 2, 3), (4, 5, 6), (7, 8, 9))
 | 
				
			||||||
        self.assert_pack(
 | 
					        self.assert_pack(
 | 
				
			||||||
            "RGB", "RGBX", b"\x01\x02\x03\xff\x05\x06\x07\xff", (1, 2, 3), (5, 6, 7)
 | 
					            "RGB", "RGBX", b"\x01\x02\x03\xff\x05\x06\x07\xff", (1, 2, 3), (5, 6, 7)
 | 
				
			||||||
| 
						 | 
					@ -79,7 +79,7 @@ class TestLibPack:
 | 
				
			||||||
        self.assert_pack("RGB", "G", 1, (9, 1, 9), (9, 2, 9), (9, 3, 9))
 | 
					        self.assert_pack("RGB", "G", 1, (9, 1, 9), (9, 2, 9), (9, 3, 9))
 | 
				
			||||||
        self.assert_pack("RGB", "B", 1, (9, 9, 1), (9, 9, 2), (9, 9, 3))
 | 
					        self.assert_pack("RGB", "B", 1, (9, 9, 1), (9, 9, 2), (9, 9, 3))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_RGBA(self):
 | 
					    def test_RGBA(self) -> None:
 | 
				
			||||||
        self.assert_pack("RGBA", "RGBA", 4, (1, 2, 3, 4), (5, 6, 7, 8), (9, 10, 11, 12))
 | 
					        self.assert_pack("RGBA", "RGBA", 4, (1, 2, 3, 4), (5, 6, 7, 8), (9, 10, 11, 12))
 | 
				
			||||||
        self.assert_pack(
 | 
					        self.assert_pack(
 | 
				
			||||||
            "RGBA", "RGBA;L", 4, (1, 4, 7, 10), (2, 5, 8, 11), (3, 6, 9, 12)
 | 
					            "RGBA", "RGBA;L", 4, (1, 4, 7, 10), (2, 5, 8, 11), (3, 6, 9, 12)
 | 
				
			||||||
| 
						 | 
					@ -101,12 +101,12 @@ class TestLibPack:
 | 
				
			||||||
        self.assert_pack("RGBA", "B", 1, (6, 7, 1, 9), (6, 7, 2, 0), (6, 7, 3, 9))
 | 
					        self.assert_pack("RGBA", "B", 1, (6, 7, 1, 9), (6, 7, 2, 0), (6, 7, 3, 9))
 | 
				
			||||||
        self.assert_pack("RGBA", "A", 1, (6, 7, 0, 1), (6, 7, 0, 2), (0, 7, 0, 3))
 | 
					        self.assert_pack("RGBA", "A", 1, (6, 7, 0, 1), (6, 7, 0, 2), (0, 7, 0, 3))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_RGBa(self):
 | 
					    def test_RGBa(self) -> None:
 | 
				
			||||||
        self.assert_pack("RGBa", "RGBa", 4, (1, 2, 3, 4), (5, 6, 7, 8), (9, 10, 11, 12))
 | 
					        self.assert_pack("RGBa", "RGBa", 4, (1, 2, 3, 4), (5, 6, 7, 8), (9, 10, 11, 12))
 | 
				
			||||||
        self.assert_pack("RGBa", "BGRa", 4, (3, 2, 1, 4), (7, 6, 5, 8), (11, 10, 9, 12))
 | 
					        self.assert_pack("RGBa", "BGRa", 4, (3, 2, 1, 4), (7, 6, 5, 8), (11, 10, 9, 12))
 | 
				
			||||||
        self.assert_pack("RGBa", "aBGR", 4, (4, 3, 2, 1), (8, 7, 6, 5), (12, 11, 10, 9))
 | 
					        self.assert_pack("RGBa", "aBGR", 4, (4, 3, 2, 1), (8, 7, 6, 5), (12, 11, 10, 9))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_RGBX(self):
 | 
					    def test_RGBX(self) -> None:
 | 
				
			||||||
        self.assert_pack("RGBX", "RGBX", 4, (1, 2, 3, 4), (5, 6, 7, 8), (9, 10, 11, 12))
 | 
					        self.assert_pack("RGBX", "RGBX", 4, (1, 2, 3, 4), (5, 6, 7, 8), (9, 10, 11, 12))
 | 
				
			||||||
        self.assert_pack(
 | 
					        self.assert_pack(
 | 
				
			||||||
            "RGBX", "RGBX;L", 4, (1, 4, 7, 10), (2, 5, 8, 11), (3, 6, 9, 12)
 | 
					            "RGBX", "RGBX;L", 4, (1, 4, 7, 10), (2, 5, 8, 11), (3, 6, 9, 12)
 | 
				
			||||||
| 
						 | 
					@ -134,7 +134,7 @@ class TestLibPack:
 | 
				
			||||||
        self.assert_pack("RGBX", "B", 1, (6, 7, 1, 9), (6, 7, 2, 0), (6, 7, 3, 9))
 | 
					        self.assert_pack("RGBX", "B", 1, (6, 7, 1, 9), (6, 7, 2, 0), (6, 7, 3, 9))
 | 
				
			||||||
        self.assert_pack("RGBX", "X", 1, (6, 7, 0, 1), (6, 7, 0, 2), (0, 7, 0, 3))
 | 
					        self.assert_pack("RGBX", "X", 1, (6, 7, 0, 1), (6, 7, 0, 2), (0, 7, 0, 3))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_CMYK(self):
 | 
					    def test_CMYK(self) -> None:
 | 
				
			||||||
        self.assert_pack("CMYK", "CMYK", 4, (1, 2, 3, 4), (5, 6, 7, 8), (9, 10, 11, 12))
 | 
					        self.assert_pack("CMYK", "CMYK", 4, (1, 2, 3, 4), (5, 6, 7, 8), (9, 10, 11, 12))
 | 
				
			||||||
        self.assert_pack(
 | 
					        self.assert_pack(
 | 
				
			||||||
            "CMYK",
 | 
					            "CMYK",
 | 
				
			||||||
| 
						 | 
					@ -149,7 +149,7 @@ class TestLibPack:
 | 
				
			||||||
        )
 | 
					        )
 | 
				
			||||||
        self.assert_pack("CMYK", "K", 1, (6, 7, 0, 1), (6, 7, 0, 2), (0, 7, 0, 3))
 | 
					        self.assert_pack("CMYK", "K", 1, (6, 7, 0, 1), (6, 7, 0, 2), (0, 7, 0, 3))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_YCbCr(self):
 | 
					    def test_YCbCr(self) -> None:
 | 
				
			||||||
        self.assert_pack("YCbCr", "YCbCr", 3, (1, 2, 3), (4, 5, 6), (7, 8, 9))
 | 
					        self.assert_pack("YCbCr", "YCbCr", 3, (1, 2, 3), (4, 5, 6), (7, 8, 9))
 | 
				
			||||||
        self.assert_pack("YCbCr", "YCbCr;L", 3, (1, 4, 7), (2, 5, 8), (3, 6, 9))
 | 
					        self.assert_pack("YCbCr", "YCbCr;L", 3, (1, 4, 7), (2, 5, 8), (3, 6, 9))
 | 
				
			||||||
        self.assert_pack(
 | 
					        self.assert_pack(
 | 
				
			||||||
| 
						 | 
					@ -172,19 +172,19 @@ class TestLibPack:
 | 
				
			||||||
        self.assert_pack("YCbCr", "Cb", 1, (6, 1, 8, 9), (6, 2, 8, 9), (6, 3, 8, 9))
 | 
					        self.assert_pack("YCbCr", "Cb", 1, (6, 1, 8, 9), (6, 2, 8, 9), (6, 3, 8, 9))
 | 
				
			||||||
        self.assert_pack("YCbCr", "Cr", 1, (6, 7, 1, 9), (6, 7, 2, 0), (6, 7, 3, 9))
 | 
					        self.assert_pack("YCbCr", "Cr", 1, (6, 7, 1, 9), (6, 7, 2, 0), (6, 7, 3, 9))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_LAB(self):
 | 
					    def test_LAB(self) -> None:
 | 
				
			||||||
        self.assert_pack("LAB", "LAB", 3, (1, 130, 131), (4, 133, 134), (7, 136, 137))
 | 
					        self.assert_pack("LAB", "LAB", 3, (1, 130, 131), (4, 133, 134), (7, 136, 137))
 | 
				
			||||||
        self.assert_pack("LAB", "L", 1, (1, 9, 9), (2, 9, 9), (3, 9, 9))
 | 
					        self.assert_pack("LAB", "L", 1, (1, 9, 9), (2, 9, 9), (3, 9, 9))
 | 
				
			||||||
        self.assert_pack("LAB", "A", 1, (9, 1, 9), (9, 2, 9), (9, 3, 9))
 | 
					        self.assert_pack("LAB", "A", 1, (9, 1, 9), (9, 2, 9), (9, 3, 9))
 | 
				
			||||||
        self.assert_pack("LAB", "B", 1, (9, 9, 1), (9, 9, 2), (9, 9, 3))
 | 
					        self.assert_pack("LAB", "B", 1, (9, 9, 1), (9, 9, 2), (9, 9, 3))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_HSV(self):
 | 
					    def test_HSV(self) -> None:
 | 
				
			||||||
        self.assert_pack("HSV", "HSV", 3, (1, 2, 3), (4, 5, 6), (7, 8, 9))
 | 
					        self.assert_pack("HSV", "HSV", 3, (1, 2, 3), (4, 5, 6), (7, 8, 9))
 | 
				
			||||||
        self.assert_pack("HSV", "H", 1, (1, 9, 9), (2, 9, 9), (3, 9, 9))
 | 
					        self.assert_pack("HSV", "H", 1, (1, 9, 9), (2, 9, 9), (3, 9, 9))
 | 
				
			||||||
        self.assert_pack("HSV", "S", 1, (9, 1, 9), (9, 2, 9), (9, 3, 9))
 | 
					        self.assert_pack("HSV", "S", 1, (9, 1, 9), (9, 2, 9), (9, 3, 9))
 | 
				
			||||||
        self.assert_pack("HSV", "V", 1, (9, 9, 1), (9, 9, 2), (9, 9, 3))
 | 
					        self.assert_pack("HSV", "V", 1, (9, 9, 1), (9, 9, 2), (9, 9, 3))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_I(self):
 | 
					    def test_I(self) -> None:
 | 
				
			||||||
        self.assert_pack("I", "I;16B", 2, 0x0102, 0x0304)
 | 
					        self.assert_pack("I", "I;16B", 2, 0x0102, 0x0304)
 | 
				
			||||||
        self.assert_pack(
 | 
					        self.assert_pack(
 | 
				
			||||||
            "I", "I;32S", b"\x83\x00\x00\x01\x01\x00\x00\x83", 0x01000083, -2097151999
 | 
					            "I", "I;32S", b"\x83\x00\x00\x01\x01\x00\x00\x83", 0x01000083, -2097151999
 | 
				
			||||||
| 
						 | 
					@ -209,10 +209,10 @@ class TestLibPack:
 | 
				
			||||||
                0x01000083,
 | 
					                0x01000083,
 | 
				
			||||||
            )
 | 
					            )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_I16(self):
 | 
					    def test_I16(self) -> None:
 | 
				
			||||||
        self.assert_pack("I;16N", "I;16N", 2, 0x0201, 0x0403, 0x0605)
 | 
					        self.assert_pack("I;16N", "I;16N", 2, 0x0201, 0x0403, 0x0605)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_F_float(self):
 | 
					    def test_F_float(self) -> None:
 | 
				
			||||||
        self.assert_pack("F", "F;32F", 4, 1.539989614439558e-36, 4.063216068939723e-34)
 | 
					        self.assert_pack("F", "F;32F", 4, 1.539989614439558e-36, 4.063216068939723e-34)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if sys.byteorder == "little":
 | 
					        if sys.byteorder == "little":
 | 
				
			||||||
| 
						 | 
					@ -228,7 +228,7 @@ class TestLibPack:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class TestLibUnpack:
 | 
					class TestLibUnpack:
 | 
				
			||||||
    def assert_unpack(self, mode, rawmode, data, *pixels):
 | 
					    def assert_unpack(self, mode, rawmode, data, *pixels) -> None:
 | 
				
			||||||
        """
 | 
					        """
 | 
				
			||||||
        data - either raw bytes with data or just number of bytes in rawmode.
 | 
					        data - either raw bytes with data or just number of bytes in rawmode.
 | 
				
			||||||
        """
 | 
					        """
 | 
				
			||||||
| 
						 | 
					@ -241,7 +241,7 @@ class TestLibUnpack:
 | 
				
			||||||
        for x, pixel in enumerate(pixels):
 | 
					        for x, pixel in enumerate(pixels):
 | 
				
			||||||
            assert pixel == im.getpixel((x, 0))
 | 
					            assert pixel == im.getpixel((x, 0))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_1(self):
 | 
					    def test_1(self) -> None:
 | 
				
			||||||
        self.assert_unpack("1", "1", b"\x01", 0, 0, 0, 0, 0, 0, 0, X)
 | 
					        self.assert_unpack("1", "1", b"\x01", 0, 0, 0, 0, 0, 0, 0, X)
 | 
				
			||||||
        self.assert_unpack("1", "1;I", b"\x01", X, X, X, X, X, X, X, 0)
 | 
					        self.assert_unpack("1", "1;I", b"\x01", X, X, X, X, X, X, X, 0)
 | 
				
			||||||
        self.assert_unpack("1", "1;R", b"\x01", X, 0, 0, 0, 0, 0, 0, 0)
 | 
					        self.assert_unpack("1", "1;R", b"\x01", X, 0, 0, 0, 0, 0, 0, 0)
 | 
				
			||||||
| 
						 | 
					@ -254,7 +254,7 @@ class TestLibUnpack:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        self.assert_unpack("1", "1;8", b"\x00\x01\x02\xff", 0, X, X, X)
 | 
					        self.assert_unpack("1", "1;8", b"\x00\x01\x02\xff", 0, X, X, X)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_L(self):
 | 
					    def test_L(self) -> None:
 | 
				
			||||||
        self.assert_unpack("L", "L;2", b"\xe4", 255, 170, 85, 0)
 | 
					        self.assert_unpack("L", "L;2", b"\xe4", 255, 170, 85, 0)
 | 
				
			||||||
        self.assert_unpack("L", "L;2I", b"\xe4", 0, 85, 170, 255)
 | 
					        self.assert_unpack("L", "L;2I", b"\xe4", 0, 85, 170, 255)
 | 
				
			||||||
        self.assert_unpack("L", "L;2R", b"\xe4", 0, 170, 85, 255)
 | 
					        self.assert_unpack("L", "L;2R", b"\xe4", 0, 170, 85, 255)
 | 
				
			||||||
| 
						 | 
					@ -273,14 +273,14 @@ class TestLibUnpack:
 | 
				
			||||||
        self.assert_unpack("L", "L;16", b"\x00\xc6\x00\xaf", 198, 175)
 | 
					        self.assert_unpack("L", "L;16", b"\x00\xc6\x00\xaf", 198, 175)
 | 
				
			||||||
        self.assert_unpack("L", "L;16B", b"\xc6\x00\xaf\x00", 198, 175)
 | 
					        self.assert_unpack("L", "L;16B", b"\xc6\x00\xaf\x00", 198, 175)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_LA(self):
 | 
					    def test_LA(self) -> None:
 | 
				
			||||||
        self.assert_unpack("LA", "LA", 2, (1, 2), (3, 4), (5, 6))
 | 
					        self.assert_unpack("LA", "LA", 2, (1, 2), (3, 4), (5, 6))
 | 
				
			||||||
        self.assert_unpack("LA", "LA;L", 2, (1, 4), (2, 5), (3, 6))
 | 
					        self.assert_unpack("LA", "LA;L", 2, (1, 4), (2, 5), (3, 6))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_La(self):
 | 
					    def test_La(self) -> None:
 | 
				
			||||||
        self.assert_unpack("La", "La", 2, (1, 2), (3, 4), (5, 6))
 | 
					        self.assert_unpack("La", "La", 2, (1, 2), (3, 4), (5, 6))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_P(self):
 | 
					    def test_P(self) -> None:
 | 
				
			||||||
        self.assert_unpack("P", "P;1", b"\xe4", 1, 1, 1, 0, 0, 1, 0, 0)
 | 
					        self.assert_unpack("P", "P;1", b"\xe4", 1, 1, 1, 0, 0, 1, 0, 0)
 | 
				
			||||||
        self.assert_unpack("P", "P;2", b"\xe4", 3, 2, 1, 0)
 | 
					        self.assert_unpack("P", "P;2", b"\xe4", 3, 2, 1, 0)
 | 
				
			||||||
        # erroneous?
 | 
					        # erroneous?
 | 
				
			||||||
| 
						 | 
					@ -291,11 +291,11 @@ class TestLibUnpack:
 | 
				
			||||||
        self.assert_unpack("P", "P", 1, 1, 2, 3, 4)
 | 
					        self.assert_unpack("P", "P", 1, 1, 2, 3, 4)
 | 
				
			||||||
        self.assert_unpack("P", "P;R", 1, 128, 64, 192, 32)
 | 
					        self.assert_unpack("P", "P;R", 1, 128, 64, 192, 32)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_PA(self):
 | 
					    def test_PA(self) -> None:
 | 
				
			||||||
        self.assert_unpack("PA", "PA", 2, (1, 2), (3, 4), (5, 6))
 | 
					        self.assert_unpack("PA", "PA", 2, (1, 2), (3, 4), (5, 6))
 | 
				
			||||||
        self.assert_unpack("PA", "PA;L", 2, (1, 4), (2, 5), (3, 6))
 | 
					        self.assert_unpack("PA", "PA;L", 2, (1, 4), (2, 5), (3, 6))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_RGB(self):
 | 
					    def test_RGB(self) -> None:
 | 
				
			||||||
        self.assert_unpack("RGB", "RGB", 3, (1, 2, 3), (4, 5, 6), (7, 8, 9))
 | 
					        self.assert_unpack("RGB", "RGB", 3, (1, 2, 3), (4, 5, 6), (7, 8, 9))
 | 
				
			||||||
        self.assert_unpack("RGB", "RGB;L", 3, (1, 4, 7), (2, 5, 8), (3, 6, 9))
 | 
					        self.assert_unpack("RGB", "RGB;L", 3, (1, 4, 7), (2, 5, 8), (3, 6, 9))
 | 
				
			||||||
        self.assert_unpack("RGB", "RGB;R", 3, (128, 64, 192), (32, 160, 96))
 | 
					        self.assert_unpack("RGB", "RGB;R", 3, (128, 64, 192), (32, 160, 96))
 | 
				
			||||||
| 
						 | 
					@ -346,14 +346,14 @@ class TestLibUnpack:
 | 
				
			||||||
            "RGB", "CMYK", 4, (250, 249, 248), (242, 241, 240), (234, 233, 233)
 | 
					            "RGB", "CMYK", 4, (250, 249, 248), (242, 241, 240), (234, 233, 233)
 | 
				
			||||||
        )
 | 
					        )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_BGR(self):
 | 
					    def test_BGR(self) -> None:
 | 
				
			||||||
        self.assert_unpack("BGR;15", "BGR;15", 3, (8, 131, 0), (24, 0, 8), (41, 131, 8))
 | 
					        self.assert_unpack("BGR;15", "BGR;15", 3, (8, 131, 0), (24, 0, 8), (41, 131, 8))
 | 
				
			||||||
        self.assert_unpack(
 | 
					        self.assert_unpack(
 | 
				
			||||||
            "BGR;16", "BGR;16", 3, (8, 64, 0), (24, 129, 0), (41, 194, 0)
 | 
					            "BGR;16", "BGR;16", 3, (8, 64, 0), (24, 129, 0), (41, 194, 0)
 | 
				
			||||||
        )
 | 
					        )
 | 
				
			||||||
        self.assert_unpack("BGR;24", "BGR;24", 3, (1, 2, 3), (4, 5, 6), (7, 8, 9))
 | 
					        self.assert_unpack("BGR;24", "BGR;24", 3, (1, 2, 3), (4, 5, 6), (7, 8, 9))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_RGBA(self):
 | 
					    def test_RGBA(self) -> None:
 | 
				
			||||||
        self.assert_unpack("RGBA", "LA", 2, (1, 1, 1, 2), (3, 3, 3, 4), (5, 5, 5, 6))
 | 
					        self.assert_unpack("RGBA", "LA", 2, (1, 1, 1, 2), (3, 3, 3, 4), (5, 5, 5, 6))
 | 
				
			||||||
        self.assert_unpack(
 | 
					        self.assert_unpack(
 | 
				
			||||||
            "RGBA", "LA;16B", 4, (1, 1, 1, 3), (5, 5, 5, 7), (9, 9, 9, 11)
 | 
					            "RGBA", "LA;16B", 4, (1, 1, 1, 3), (5, 5, 5, 7), (9, 9, 9, 11)
 | 
				
			||||||
| 
						 | 
					@ -522,7 +522,7 @@ class TestLibUnpack:
 | 
				
			||||||
                "RGBA", "A;16N", 2, (0, 0, 0, 1), (0, 0, 0, 3), (0, 0, 0, 5)
 | 
					                "RGBA", "A;16N", 2, (0, 0, 0, 1), (0, 0, 0, 3), (0, 0, 0, 5)
 | 
				
			||||||
            )
 | 
					            )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_RGBa(self):
 | 
					    def test_RGBa(self) -> None:
 | 
				
			||||||
        self.assert_unpack(
 | 
					        self.assert_unpack(
 | 
				
			||||||
            "RGBa", "RGBa", 4, (1, 2, 3, 4), (5, 6, 7, 8), (9, 10, 11, 12)
 | 
					            "RGBa", "RGBa", 4, (1, 2, 3, 4), (5, 6, 7, 8), (9, 10, 11, 12)
 | 
				
			||||||
        )
 | 
					        )
 | 
				
			||||||
| 
						 | 
					@ -536,7 +536,7 @@ class TestLibUnpack:
 | 
				
			||||||
            "RGBa", "aBGR", 4, (4, 3, 2, 1), (8, 7, 6, 5), (12, 11, 10, 9)
 | 
					            "RGBa", "aBGR", 4, (4, 3, 2, 1), (8, 7, 6, 5), (12, 11, 10, 9)
 | 
				
			||||||
        )
 | 
					        )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_RGBX(self):
 | 
					    def test_RGBX(self) -> None:
 | 
				
			||||||
        self.assert_unpack("RGBX", "RGB", 3, (1, 2, 3, X), (4, 5, 6, X), (7, 8, 9, X))
 | 
					        self.assert_unpack("RGBX", "RGB", 3, (1, 2, 3, X), (4, 5, 6, X), (7, 8, 9, X))
 | 
				
			||||||
        self.assert_unpack("RGBX", "RGB;L", 3, (1, 4, 7, X), (2, 5, 8, X), (3, 6, 9, X))
 | 
					        self.assert_unpack("RGBX", "RGB;L", 3, (1, 4, 7, X), (2, 5, 8, X), (3, 6, 9, X))
 | 
				
			||||||
        self.assert_unpack("RGBX", "RGB;16B", 6, (1, 3, 5, X), (7, 9, 11, X))
 | 
					        self.assert_unpack("RGBX", "RGB;16B", 6, (1, 3, 5, X), (7, 9, 11, X))
 | 
				
			||||||
| 
						 | 
					@ -581,7 +581,7 @@ class TestLibUnpack:
 | 
				
			||||||
        self.assert_unpack("RGBX", "B", 1, (0, 0, 1, 0), (0, 0, 2, 0), (0, 0, 3, 0))
 | 
					        self.assert_unpack("RGBX", "B", 1, (0, 0, 1, 0), (0, 0, 2, 0), (0, 0, 3, 0))
 | 
				
			||||||
        self.assert_unpack("RGBX", "X", 1, (0, 0, 0, 1), (0, 0, 0, 2), (0, 0, 0, 3))
 | 
					        self.assert_unpack("RGBX", "X", 1, (0, 0, 0, 1), (0, 0, 0, 2), (0, 0, 0, 3))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_CMYK(self):
 | 
					    def test_CMYK(self) -> None:
 | 
				
			||||||
        self.assert_unpack(
 | 
					        self.assert_unpack(
 | 
				
			||||||
            "CMYK", "CMYK", 4, (1, 2, 3, 4), (5, 6, 7, 8), (9, 10, 11, 12)
 | 
					            "CMYK", "CMYK", 4, (1, 2, 3, 4), (5, 6, 7, 8), (9, 10, 11, 12)
 | 
				
			||||||
        )
 | 
					        )
 | 
				
			||||||
| 
						 | 
					@ -619,25 +619,25 @@ class TestLibUnpack:
 | 
				
			||||||
            "CMYK", "K;I", 1, (0, 0, 0, 254), (0, 0, 0, 253), (0, 0, 0, 252)
 | 
					            "CMYK", "K;I", 1, (0, 0, 0, 254), (0, 0, 0, 253), (0, 0, 0, 252)
 | 
				
			||||||
        )
 | 
					        )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_YCbCr(self):
 | 
					    def test_YCbCr(self) -> None:
 | 
				
			||||||
        self.assert_unpack("YCbCr", "YCbCr", 3, (1, 2, 3), (4, 5, 6), (7, 8, 9))
 | 
					        self.assert_unpack("YCbCr", "YCbCr", 3, (1, 2, 3), (4, 5, 6), (7, 8, 9))
 | 
				
			||||||
        self.assert_unpack("YCbCr", "YCbCr;L", 3, (1, 4, 7), (2, 5, 8), (3, 6, 9))
 | 
					        self.assert_unpack("YCbCr", "YCbCr;L", 3, (1, 4, 7), (2, 5, 8), (3, 6, 9))
 | 
				
			||||||
        self.assert_unpack("YCbCr", "YCbCrK", 4, (1, 2, 3), (5, 6, 7), (9, 10, 11))
 | 
					        self.assert_unpack("YCbCr", "YCbCrK", 4, (1, 2, 3), (5, 6, 7), (9, 10, 11))
 | 
				
			||||||
        self.assert_unpack("YCbCr", "YCbCrX", 4, (1, 2, 3), (5, 6, 7), (9, 10, 11))
 | 
					        self.assert_unpack("YCbCr", "YCbCrX", 4, (1, 2, 3), (5, 6, 7), (9, 10, 11))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_LAB(self):
 | 
					    def test_LAB(self) -> None:
 | 
				
			||||||
        self.assert_unpack("LAB", "LAB", 3, (1, 130, 131), (4, 133, 134), (7, 136, 137))
 | 
					        self.assert_unpack("LAB", "LAB", 3, (1, 130, 131), (4, 133, 134), (7, 136, 137))
 | 
				
			||||||
        self.assert_unpack("LAB", "L", 1, (1, 0, 0), (2, 0, 0), (3, 0, 0))
 | 
					        self.assert_unpack("LAB", "L", 1, (1, 0, 0), (2, 0, 0), (3, 0, 0))
 | 
				
			||||||
        self.assert_unpack("LAB", "A", 1, (0, 1, 0), (0, 2, 0), (0, 3, 0))
 | 
					        self.assert_unpack("LAB", "A", 1, (0, 1, 0), (0, 2, 0), (0, 3, 0))
 | 
				
			||||||
        self.assert_unpack("LAB", "B", 1, (0, 0, 1), (0, 0, 2), (0, 0, 3))
 | 
					        self.assert_unpack("LAB", "B", 1, (0, 0, 1), (0, 0, 2), (0, 0, 3))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_HSV(self):
 | 
					    def test_HSV(self) -> None:
 | 
				
			||||||
        self.assert_unpack("HSV", "HSV", 3, (1, 2, 3), (4, 5, 6), (7, 8, 9))
 | 
					        self.assert_unpack("HSV", "HSV", 3, (1, 2, 3), (4, 5, 6), (7, 8, 9))
 | 
				
			||||||
        self.assert_unpack("HSV", "H", 1, (1, 0, 0), (2, 0, 0), (3, 0, 0))
 | 
					        self.assert_unpack("HSV", "H", 1, (1, 0, 0), (2, 0, 0), (3, 0, 0))
 | 
				
			||||||
        self.assert_unpack("HSV", "S", 1, (0, 1, 0), (0, 2, 0), (0, 3, 0))
 | 
					        self.assert_unpack("HSV", "S", 1, (0, 1, 0), (0, 2, 0), (0, 3, 0))
 | 
				
			||||||
        self.assert_unpack("HSV", "V", 1, (0, 0, 1), (0, 0, 2), (0, 0, 3))
 | 
					        self.assert_unpack("HSV", "V", 1, (0, 0, 1), (0, 0, 2), (0, 0, 3))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_I(self):
 | 
					    def test_I(self) -> None:
 | 
				
			||||||
        self.assert_unpack("I", "I;8", 1, 0x01, 0x02, 0x03, 0x04)
 | 
					        self.assert_unpack("I", "I;8", 1, 0x01, 0x02, 0x03, 0x04)
 | 
				
			||||||
        self.assert_unpack("I", "I;8S", b"\x01\x83", 1, -125)
 | 
					        self.assert_unpack("I", "I;8S", b"\x01\x83", 1, -125)
 | 
				
			||||||
        self.assert_unpack("I", "I;16", 2, 0x0201, 0x0403)
 | 
					        self.assert_unpack("I", "I;16", 2, 0x0201, 0x0403)
 | 
				
			||||||
| 
						 | 
					@ -678,7 +678,7 @@ class TestLibUnpack:
 | 
				
			||||||
                0x01000083,
 | 
					                0x01000083,
 | 
				
			||||||
            )
 | 
					            )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_F_int(self):
 | 
					    def test_F_int(self) -> None:
 | 
				
			||||||
        self.assert_unpack("F", "F;8", 1, 0x01, 0x02, 0x03, 0x04)
 | 
					        self.assert_unpack("F", "F;8", 1, 0x01, 0x02, 0x03, 0x04)
 | 
				
			||||||
        self.assert_unpack("F", "F;8S", b"\x01\x83", 1, -125)
 | 
					        self.assert_unpack("F", "F;8S", b"\x01\x83", 1, -125)
 | 
				
			||||||
        self.assert_unpack("F", "F;16", 2, 0x0201, 0x0403)
 | 
					        self.assert_unpack("F", "F;16", 2, 0x0201, 0x0403)
 | 
				
			||||||
| 
						 | 
					@ -717,7 +717,7 @@ class TestLibUnpack:
 | 
				
			||||||
                16777348,
 | 
					                16777348,
 | 
				
			||||||
            )
 | 
					            )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_F_float(self):
 | 
					    def test_F_float(self) -> None:
 | 
				
			||||||
        self.assert_unpack(
 | 
					        self.assert_unpack(
 | 
				
			||||||
            "F", "F;32F", 4, 1.539989614439558e-36, 4.063216068939723e-34
 | 
					            "F", "F;32F", 4, 1.539989614439558e-36, 4.063216068939723e-34
 | 
				
			||||||
        )
 | 
					        )
 | 
				
			||||||
| 
						 | 
					@ -768,7 +768,7 @@ class TestLibUnpack:
 | 
				
			||||||
                -1234.5,
 | 
					                -1234.5,
 | 
				
			||||||
            )
 | 
					            )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_I16(self):
 | 
					    def test_I16(self) -> None:
 | 
				
			||||||
        self.assert_unpack("I;16", "I;16", 2, 0x0201, 0x0403, 0x0605)
 | 
					        self.assert_unpack("I;16", "I;16", 2, 0x0201, 0x0403, 0x0605)
 | 
				
			||||||
        self.assert_unpack("I;16", "I;16B", 2, 0x0102, 0x0304, 0x0506)
 | 
					        self.assert_unpack("I;16", "I;16B", 2, 0x0102, 0x0304, 0x0506)
 | 
				
			||||||
        self.assert_unpack("I;16B", "I;16B", 2, 0x0102, 0x0304, 0x0506)
 | 
					        self.assert_unpack("I;16B", "I;16B", 2, 0x0102, 0x0304, 0x0506)
 | 
				
			||||||
| 
						 | 
					@ -785,7 +785,7 @@ class TestLibUnpack:
 | 
				
			||||||
            self.assert_unpack("I;16L", "I;16N", 2, 0x0102, 0x0304, 0x0506)
 | 
					            self.assert_unpack("I;16L", "I;16N", 2, 0x0102, 0x0304, 0x0506)
 | 
				
			||||||
            self.assert_unpack("I;16N", "I;16N", 2, 0x0102, 0x0304, 0x0506)
 | 
					            self.assert_unpack("I;16N", "I;16N", 2, 0x0102, 0x0304, 0x0506)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_CMYK16(self):
 | 
					    def test_CMYK16(self) -> None:
 | 
				
			||||||
        self.assert_unpack("CMYK", "CMYK;16L", 8, (2, 4, 6, 8), (10, 12, 14, 16))
 | 
					        self.assert_unpack("CMYK", "CMYK;16L", 8, (2, 4, 6, 8), (10, 12, 14, 16))
 | 
				
			||||||
        self.assert_unpack("CMYK", "CMYK;16B", 8, (1, 3, 5, 7), (9, 11, 13, 15))
 | 
					        self.assert_unpack("CMYK", "CMYK;16B", 8, (1, 3, 5, 7), (9, 11, 13, 15))
 | 
				
			||||||
        if sys.byteorder == "little":
 | 
					        if sys.byteorder == "little":
 | 
				
			||||||
| 
						 | 
					@ -793,7 +793,7 @@ class TestLibUnpack:
 | 
				
			||||||
        else:
 | 
					        else:
 | 
				
			||||||
            self.assert_unpack("CMYK", "CMYK;16N", 8, (1, 3, 5, 7), (9, 11, 13, 15))
 | 
					            self.assert_unpack("CMYK", "CMYK;16N", 8, (1, 3, 5, 7), (9, 11, 13, 15))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_value_error(self):
 | 
					    def test_value_error(self) -> None:
 | 
				
			||||||
        with pytest.raises(ValueError):
 | 
					        with pytest.raises(ValueError):
 | 
				
			||||||
            self.assert_unpack("L", "L", 0, 0)
 | 
					            self.assert_unpack("L", "L", 0, 0)
 | 
				
			||||||
        with pytest.raises(ValueError):
 | 
					        with pytest.raises(ValueError):
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -7,7 +7,7 @@ import pytest
 | 
				
			||||||
from PIL import Image
 | 
					from PIL import Image
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_overflow():
 | 
					def test_overflow() -> None:
 | 
				
			||||||
    # There is the potential to overflow comparisons in map.c
 | 
					    # There is the potential to overflow comparisons in map.c
 | 
				
			||||||
    # if there are > SIZE_MAX bytes in the image or if
 | 
					    # if there are > SIZE_MAX bytes in the image or if
 | 
				
			||||||
    # the file encodes an offset that makes
 | 
					    # the file encodes an offset that makes
 | 
				
			||||||
| 
						 | 
					@ -25,7 +25,7 @@ def test_overflow():
 | 
				
			||||||
    Image.MAX_IMAGE_PIXELS = max_pixels
 | 
					    Image.MAX_IMAGE_PIXELS = max_pixels
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_tobytes():
 | 
					def test_tobytes() -> None:
 | 
				
			||||||
    # Note that this image triggers the decompression bomb warning:
 | 
					    # Note that this image triggers the decompression bomb warning:
 | 
				
			||||||
    max_pixels = Image.MAX_IMAGE_PIXELS
 | 
					    max_pixels = Image.MAX_IMAGE_PIXELS
 | 
				
			||||||
    Image.MAX_IMAGE_PIXELS = None
 | 
					    Image.MAX_IMAGE_PIXELS = None
 | 
				
			||||||
| 
						 | 
					@ -39,7 +39,7 @@ def test_tobytes():
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@pytest.mark.skipif(sys.maxsize <= 2**32, reason="Requires 64-bit system")
 | 
					@pytest.mark.skipif(sys.maxsize <= 2**32, reason="Requires 64-bit system")
 | 
				
			||||||
def test_ysize():
 | 
					def test_ysize() -> None:
 | 
				
			||||||
    numpy = pytest.importorskip("numpy", reason="NumPy not installed")
 | 
					    numpy = pytest.importorskip("numpy", reason="NumPy not installed")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    # Should not raise 'Integer overflow in ysize'
 | 
					    # Should not raise 'Integer overflow in ysize'
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,5 +1,7 @@
 | 
				
			||||||
from __future__ import annotations
 | 
					from __future__ import annotations
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					from pathlib import Path
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import pytest
 | 
					import pytest
 | 
				
			||||||
 | 
					
 | 
				
			||||||
from PIL import Image
 | 
					from PIL import Image
 | 
				
			||||||
| 
						 | 
					@ -9,7 +11,7 @@ from .helper import hopper
 | 
				
			||||||
original = hopper().resize((32, 32)).convert("I")
 | 
					original = hopper().resize((32, 32)).convert("I")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def verify(im1):
 | 
					def verify(im1) -> None:
 | 
				
			||||||
    im2 = original.copy()
 | 
					    im2 = original.copy()
 | 
				
			||||||
    assert im1.size == im2.size
 | 
					    assert im1.size == im2.size
 | 
				
			||||||
    pix1 = im1.load()
 | 
					    pix1 = im1.load()
 | 
				
			||||||
| 
						 | 
					@ -25,7 +27,7 @@ def verify(im1):
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@pytest.mark.parametrize("mode", ("L", "I;16", "I;16B", "I;16L", "I"))
 | 
					@pytest.mark.parametrize("mode", ("L", "I;16", "I;16B", "I;16L", "I"))
 | 
				
			||||||
def test_basic(tmp_path, mode):
 | 
					def test_basic(tmp_path: Path, mode) -> None:
 | 
				
			||||||
    # PIL 1.1 has limited support for 16-bit image data.  Check that
 | 
					    # PIL 1.1 has limited support for 16-bit image data.  Check that
 | 
				
			||||||
    # create/copy/transform and save works as expected.
 | 
					    # create/copy/transform and save works as expected.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -75,7 +77,7 @@ def test_basic(tmp_path, mode):
 | 
				
			||||||
    assert im_in.getpixel((0, 0)) == min(512, maximum)
 | 
					    assert im_in.getpixel((0, 0)) == min(512, maximum)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_tobytes():
 | 
					def test_tobytes() -> None:
 | 
				
			||||||
    def tobytes(mode):
 | 
					    def tobytes(mode):
 | 
				
			||||||
        return Image.new(mode, (1, 1), 1).tobytes()
 | 
					        return Image.new(mode, (1, 1), 1).tobytes()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -87,7 +89,7 @@ def test_tobytes():
 | 
				
			||||||
    assert tobytes("I") == b"\x01\x00\x00\x00"[::order]
 | 
					    assert tobytes("I") == b"\x01\x00\x00\x00"[::order]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_convert():
 | 
					def test_convert() -> None:
 | 
				
			||||||
    im = original.copy()
 | 
					    im = original.copy()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    for mode in ("I;16", "I;16B", "I;16N"):
 | 
					    for mode in ("I;16", "I;16B", "I;16N"):
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -13,8 +13,8 @@ numpy = pytest.importorskip("numpy", reason="NumPy not installed")
 | 
				
			||||||
TEST_IMAGE_SIZE = (10, 10)
 | 
					TEST_IMAGE_SIZE = (10, 10)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_numpy_to_image():
 | 
					def test_numpy_to_image() -> None:
 | 
				
			||||||
    def to_image(dtype, bands=1, boolean=0):
 | 
					    def to_image(dtype, bands: int = 1, boolean: int = 0):
 | 
				
			||||||
        if bands == 1:
 | 
					        if bands == 1:
 | 
				
			||||||
            if boolean:
 | 
					            if boolean:
 | 
				
			||||||
                data = [0, 255] * 50
 | 
					                data = [0, 255] * 50
 | 
				
			||||||
| 
						 | 
					@ -82,7 +82,7 @@ def test_numpy_to_image():
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# Based on an erring example at
 | 
					# Based on an erring example at
 | 
				
			||||||
# https://stackoverflow.com/questions/10854903/what-is-causing-dimension-dependent-attributeerror-in-pil-fromarray-function
 | 
					# https://stackoverflow.com/questions/10854903/what-is-causing-dimension-dependent-attributeerror-in-pil-fromarray-function
 | 
				
			||||||
def test_3d_array():
 | 
					def test_3d_array() -> None:
 | 
				
			||||||
    size = (5, TEST_IMAGE_SIZE[0], TEST_IMAGE_SIZE[1])
 | 
					    size = (5, TEST_IMAGE_SIZE[0], TEST_IMAGE_SIZE[1])
 | 
				
			||||||
    a = numpy.ones(size, dtype=numpy.uint8)
 | 
					    a = numpy.ones(size, dtype=numpy.uint8)
 | 
				
			||||||
    assert_image(Image.fromarray(a[1, :, :]), "L", TEST_IMAGE_SIZE)
 | 
					    assert_image(Image.fromarray(a[1, :, :]), "L", TEST_IMAGE_SIZE)
 | 
				
			||||||
| 
						 | 
					@ -94,12 +94,12 @@ def test_3d_array():
 | 
				
			||||||
    assert_image(Image.fromarray(a[:, :, 1]), "L", TEST_IMAGE_SIZE)
 | 
					    assert_image(Image.fromarray(a[:, :, 1]), "L", TEST_IMAGE_SIZE)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_1d_array():
 | 
					def test_1d_array() -> None:
 | 
				
			||||||
    a = numpy.ones(5, dtype=numpy.uint8)
 | 
					    a = numpy.ones(5, dtype=numpy.uint8)
 | 
				
			||||||
    assert_image(Image.fromarray(a), "L", (1, 5))
 | 
					    assert_image(Image.fromarray(a), "L", (1, 5))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def _test_img_equals_nparray(img, np):
 | 
					def _test_img_equals_nparray(img, np) -> None:
 | 
				
			||||||
    assert len(np.shape) >= 2
 | 
					    assert len(np.shape) >= 2
 | 
				
			||||||
    np_size = np.shape[1], np.shape[0]
 | 
					    np_size = np.shape[1], np.shape[0]
 | 
				
			||||||
    assert img.size == np_size
 | 
					    assert img.size == np_size
 | 
				
			||||||
| 
						 | 
					@ -109,14 +109,14 @@ def _test_img_equals_nparray(img, np):
 | 
				
			||||||
            assert_deep_equal(px[x, y], np[y, x])
 | 
					            assert_deep_equal(px[x, y], np[y, x])
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_16bit():
 | 
					def test_16bit() -> None:
 | 
				
			||||||
    with Image.open("Tests/images/16bit.cropped.tif") as img:
 | 
					    with Image.open("Tests/images/16bit.cropped.tif") as img:
 | 
				
			||||||
        np_img = numpy.array(img)
 | 
					        np_img = numpy.array(img)
 | 
				
			||||||
        _test_img_equals_nparray(img, np_img)
 | 
					        _test_img_equals_nparray(img, np_img)
 | 
				
			||||||
    assert np_img.dtype == numpy.dtype("<u2")
 | 
					    assert np_img.dtype == numpy.dtype("<u2")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_1bit():
 | 
					def test_1bit() -> None:
 | 
				
			||||||
    # Test that 1-bit arrays convert to numpy and back
 | 
					    # Test that 1-bit arrays convert to numpy and back
 | 
				
			||||||
    # See: https://github.com/python-pillow/Pillow/issues/350
 | 
					    # See: https://github.com/python-pillow/Pillow/issues/350
 | 
				
			||||||
    arr = numpy.array([[1, 0, 0, 1, 0], [0, 1, 0, 0, 0]], "u1")
 | 
					    arr = numpy.array([[1, 0, 0, 1, 0], [0, 1, 0, 0, 0]], "u1")
 | 
				
			||||||
| 
						 | 
					@ -126,7 +126,7 @@ def test_1bit():
 | 
				
			||||||
    numpy.testing.assert_array_equal(arr, arr_back)
 | 
					    numpy.testing.assert_array_equal(arr, arr_back)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_save_tiff_uint16():
 | 
					def test_save_tiff_uint16() -> None:
 | 
				
			||||||
    # Tests that we're getting the pixel value in the right byte order.
 | 
					    # Tests that we're getting the pixel value in the right byte order.
 | 
				
			||||||
    pixel_value = 0x1234
 | 
					    pixel_value = 0x1234
 | 
				
			||||||
    a = numpy.array(
 | 
					    a = numpy.array(
 | 
				
			||||||
| 
						 | 
					@ -157,7 +157,7 @@ def test_save_tiff_uint16():
 | 
				
			||||||
        ("HSV", numpy.uint8),
 | 
					        ("HSV", numpy.uint8),
 | 
				
			||||||
    ),
 | 
					    ),
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
def test_to_array(mode, dtype):
 | 
					def test_to_array(mode, dtype) -> None:
 | 
				
			||||||
    img = hopper(mode)
 | 
					    img = hopper(mode)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    # Resize to non-square
 | 
					    # Resize to non-square
 | 
				
			||||||
| 
						 | 
					@ -169,7 +169,7 @@ def test_to_array(mode, dtype):
 | 
				
			||||||
    assert np_img.dtype == dtype
 | 
					    assert np_img.dtype == dtype
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_point_lut():
 | 
					def test_point_lut() -> None:
 | 
				
			||||||
    # See https://github.com/python-pillow/Pillow/issues/439
 | 
					    # See https://github.com/python-pillow/Pillow/issues/439
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    data = list(range(256)) * 3
 | 
					    data = list(range(256)) * 3
 | 
				
			||||||
| 
						 | 
					@ -180,7 +180,7 @@ def test_point_lut():
 | 
				
			||||||
    im.point(lut)
 | 
					    im.point(lut)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_putdata():
 | 
					def test_putdata() -> None:
 | 
				
			||||||
    # Shouldn't segfault
 | 
					    # Shouldn't segfault
 | 
				
			||||||
    # See https://github.com/python-pillow/Pillow/issues/1008
 | 
					    # See https://github.com/python-pillow/Pillow/issues/1008
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -207,12 +207,12 @@ def test_putdata():
 | 
				
			||||||
        numpy.float64,
 | 
					        numpy.float64,
 | 
				
			||||||
    ),
 | 
					    ),
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
def test_roundtrip_eye(dtype):
 | 
					def test_roundtrip_eye(dtype) -> None:
 | 
				
			||||||
    arr = numpy.eye(10, dtype=dtype)
 | 
					    arr = numpy.eye(10, dtype=dtype)
 | 
				
			||||||
    numpy.testing.assert_array_equal(arr, numpy.array(Image.fromarray(arr)))
 | 
					    numpy.testing.assert_array_equal(arr, numpy.array(Image.fromarray(arr)))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_zero_size():
 | 
					def test_zero_size() -> None:
 | 
				
			||||||
    # Shouldn't cause floating point exception
 | 
					    # Shouldn't cause floating point exception
 | 
				
			||||||
    # See https://github.com/python-pillow/Pillow/issues/2259
 | 
					    # See https://github.com/python-pillow/Pillow/issues/2259
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -222,13 +222,13 @@ def test_zero_size():
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@skip_unless_feature("libtiff")
 | 
					@skip_unless_feature("libtiff")
 | 
				
			||||||
def test_load_first():
 | 
					def test_load_first() -> None:
 | 
				
			||||||
    with Image.open("Tests/images/g4_orientation_5.tif") as im:
 | 
					    with Image.open("Tests/images/g4_orientation_5.tif") as im:
 | 
				
			||||||
        a = numpy.array(im)
 | 
					        a = numpy.array(im)
 | 
				
			||||||
        assert a.shape == (88, 590)
 | 
					        assert a.shape == (88, 590)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_bool():
 | 
					def test_bool() -> None:
 | 
				
			||||||
    # https://github.com/python-pillow/Pillow/issues/2044
 | 
					    # https://github.com/python-pillow/Pillow/issues/2044
 | 
				
			||||||
    a = numpy.zeros((10, 2), dtype=bool)
 | 
					    a = numpy.zeros((10, 2), dtype=bool)
 | 
				
			||||||
    a[0][0] = True
 | 
					    a[0][0] = True
 | 
				
			||||||
| 
						 | 
					@ -237,7 +237,7 @@ def test_bool():
 | 
				
			||||||
    assert im2.getdata()[0] == 255
 | 
					    assert im2.getdata()[0] == 255
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_no_resource_warning_for_numpy_array():
 | 
					def test_no_resource_warning_for_numpy_array() -> None:
 | 
				
			||||||
    # https://github.com/python-pillow/Pillow/issues/835
 | 
					    # https://github.com/python-pillow/Pillow/issues/835
 | 
				
			||||||
    # Arrange
 | 
					    # Arrange
 | 
				
			||||||
    from numpy import array
 | 
					    from numpy import array
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
Some files were not shown because too many files have changed in this diff Show More
		Loading…
	
		Reference in New Issue
	
	Block a user