Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Assert image type #8619

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
44 changes: 44 additions & 0 deletions Tests/test_file_apng.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
# (referenced from https://wiki.mozilla.org/APNG_Specification)
def test_apng_basic() -> None:
with Image.open("Tests/images/apng/single_frame.png") as im:
assert isinstance(im, PngImagePlugin.PngImageFile)
assert not im.is_animated
assert im.n_frames == 1
assert im.get_format_mimetype() == "image/apng"
Expand All @@ -20,6 +21,7 @@ def test_apng_basic() -> None:
assert im.getpixel((64, 32)) == (0, 255, 0, 255)

with Image.open("Tests/images/apng/single_frame_default.png") as im:
assert isinstance(im, PngImagePlugin.PngImageFile)
assert im.is_animated
assert im.n_frames == 2
assert im.get_format_mimetype() == "image/apng"
Expand Down Expand Up @@ -49,60 +51,71 @@ def test_apng_basic() -> None:
)
def test_apng_fdat(filename: str) -> None:
with Image.open(filename) as im:
assert isinstance(im, PngImagePlugin.PngImageFile)
im.seek(im.n_frames - 1)
assert im.getpixel((0, 0)) == (0, 255, 0, 255)
assert im.getpixel((64, 32)) == (0, 255, 0, 255)


def test_apng_dispose() -> None:
with Image.open("Tests/images/apng/dispose_op_none.png") as im:
assert isinstance(im, PngImagePlugin.PngImageFile)
im.seek(im.n_frames - 1)
assert im.getpixel((0, 0)) == (0, 255, 0, 255)
assert im.getpixel((64, 32)) == (0, 255, 0, 255)

with Image.open("Tests/images/apng/dispose_op_background.png") as im:
assert isinstance(im, PngImagePlugin.PngImageFile)
im.seek(im.n_frames - 1)
assert im.getpixel((0, 0)) == (0, 0, 0, 0)
assert im.getpixel((64, 32)) == (0, 0, 0, 0)

with Image.open("Tests/images/apng/dispose_op_background_final.png") as im:
assert isinstance(im, PngImagePlugin.PngImageFile)
im.seek(im.n_frames - 1)
assert im.getpixel((0, 0)) == (0, 255, 0, 255)
assert im.getpixel((64, 32)) == (0, 255, 0, 255)

with Image.open("Tests/images/apng/dispose_op_previous.png") as im:
assert isinstance(im, PngImagePlugin.PngImageFile)
im.seek(im.n_frames - 1)
assert im.getpixel((0, 0)) == (0, 255, 0, 255)
assert im.getpixel((64, 32)) == (0, 255, 0, 255)

with Image.open("Tests/images/apng/dispose_op_previous_final.png") as im:
assert isinstance(im, PngImagePlugin.PngImageFile)
im.seek(im.n_frames - 1)
assert im.getpixel((0, 0)) == (0, 255, 0, 255)
assert im.getpixel((64, 32)) == (0, 255, 0, 255)

with Image.open("Tests/images/apng/dispose_op_previous_first.png") as im:
assert isinstance(im, PngImagePlugin.PngImageFile)
im.seek(im.n_frames - 1)
assert im.getpixel((0, 0)) == (0, 0, 0, 0)
assert im.getpixel((64, 32)) == (0, 0, 0, 0)


def test_apng_dispose_region() -> None:
with Image.open("Tests/images/apng/dispose_op_none_region.png") as im:
assert isinstance(im, PngImagePlugin.PngImageFile)
im.seek(im.n_frames - 1)
assert im.getpixel((0, 0)) == (0, 255, 0, 255)
assert im.getpixel((64, 32)) == (0, 255, 0, 255)

with Image.open("Tests/images/apng/dispose_op_background_before_region.png") as im:
assert isinstance(im, PngImagePlugin.PngImageFile)
im.seek(im.n_frames - 1)
assert im.getpixel((0, 0)) == (0, 0, 0, 0)
assert im.getpixel((64, 32)) == (0, 0, 0, 0)

with Image.open("Tests/images/apng/dispose_op_background_region.png") as im:
assert isinstance(im, PngImagePlugin.PngImageFile)
im.seek(im.n_frames - 1)
assert im.getpixel((0, 0)) == (0, 0, 255, 255)
assert im.getpixel((64, 32)) == (0, 0, 0, 0)

with Image.open("Tests/images/apng/dispose_op_previous_region.png") as im:
assert isinstance(im, PngImagePlugin.PngImageFile)
im.seek(im.n_frames - 1)
assert im.getpixel((0, 0)) == (0, 255, 0, 255)
assert im.getpixel((64, 32)) == (0, 255, 0, 255)
Expand All @@ -129,6 +142,7 @@ def test_apng_dispose_op_previous_frame() -> None:
# ],
# )
with Image.open("Tests/images/apng/dispose_op_previous_frame.png") as im:
assert isinstance(im, PngImagePlugin.PngImageFile)
im.seek(im.n_frames - 1)
assert im.getpixel((0, 0)) == (255, 0, 0, 255)

Expand All @@ -142,26 +156,31 @@ def test_apng_dispose_op_background_p_mode() -> None:

def test_apng_blend() -> None:
with Image.open("Tests/images/apng/blend_op_source_solid.png") as im:
assert isinstance(im, PngImagePlugin.PngImageFile)
im.seek(im.n_frames - 1)
assert im.getpixel((0, 0)) == (0, 255, 0, 255)
assert im.getpixel((64, 32)) == (0, 255, 0, 255)

with Image.open("Tests/images/apng/blend_op_source_transparent.png") as im:
assert isinstance(im, PngImagePlugin.PngImageFile)
im.seek(im.n_frames - 1)
assert im.getpixel((0, 0)) == (0, 0, 0, 0)
assert im.getpixel((64, 32)) == (0, 0, 0, 0)

with Image.open("Tests/images/apng/blend_op_source_near_transparent.png") as im:
assert isinstance(im, PngImagePlugin.PngImageFile)
im.seek(im.n_frames - 1)
assert im.getpixel((0, 0)) == (0, 255, 0, 2)
assert im.getpixel((64, 32)) == (0, 255, 0, 2)

with Image.open("Tests/images/apng/blend_op_over.png") as im:
assert isinstance(im, PngImagePlugin.PngImageFile)
im.seek(im.n_frames - 1)
assert im.getpixel((0, 0)) == (0, 255, 0, 255)
assert im.getpixel((64, 32)) == (0, 255, 0, 255)

with Image.open("Tests/images/apng/blend_op_over_near_transparent.png") as im:
assert isinstance(im, PngImagePlugin.PngImageFile)
im.seek(im.n_frames - 1)
assert im.getpixel((0, 0)) == (0, 255, 0, 97)
assert im.getpixel((64, 32)) == (0, 255, 0, 255)
Expand All @@ -175,6 +194,7 @@ def test_apng_blend_transparency() -> None:

def test_apng_chunk_order() -> None:
with Image.open("Tests/images/apng/fctl_actl.png") as im:
assert isinstance(im, PngImagePlugin.PngImageFile)
im.seek(im.n_frames - 1)
assert im.getpixel((0, 0)) == (0, 255, 0, 255)
assert im.getpixel((64, 32)) == (0, 255, 0, 255)
Expand Down Expand Up @@ -230,38 +250,44 @@ def test_apng_num_plays() -> None:

def test_apng_mode() -> None:
with Image.open("Tests/images/apng/mode_16bit.png") as im:
assert isinstance(im, PngImagePlugin.PngImageFile)
assert im.mode == "RGBA"
im.seek(im.n_frames - 1)
assert im.getpixel((0, 0)) == (0, 0, 128, 191)
assert im.getpixel((64, 32)) == (0, 0, 128, 191)

with Image.open("Tests/images/apng/mode_grayscale.png") as im:
assert isinstance(im, PngImagePlugin.PngImageFile)
assert im.mode == "L"
im.seek(im.n_frames - 1)
assert im.getpixel((0, 0)) == 128
assert im.getpixel((64, 32)) == 255

with Image.open("Tests/images/apng/mode_grayscale_alpha.png") as im:
assert isinstance(im, PngImagePlugin.PngImageFile)
assert im.mode == "LA"
im.seek(im.n_frames - 1)
assert im.getpixel((0, 0)) == (128, 191)
assert im.getpixel((64, 32)) == (128, 191)

with Image.open("Tests/images/apng/mode_palette.png") as im:
assert isinstance(im, PngImagePlugin.PngImageFile)
assert im.mode == "P"
im.seek(im.n_frames - 1)
im = im.convert("RGB")
assert im.getpixel((0, 0)) == (0, 255, 0)
assert im.getpixel((64, 32)) == (0, 255, 0)

with Image.open("Tests/images/apng/mode_palette_alpha.png") as im:
assert isinstance(im, PngImagePlugin.PngImageFile)
assert im.mode == "P"
im.seek(im.n_frames - 1)
im = im.convert("RGBA")
assert im.getpixel((0, 0)) == (0, 255, 0, 255)
assert im.getpixel((64, 32)) == (0, 255, 0, 255)

with Image.open("Tests/images/apng/mode_palette_1bit_alpha.png") as im:
assert isinstance(im, PngImagePlugin.PngImageFile)
assert im.mode == "P"
im.seek(im.n_frames - 1)
im = im.convert("RGBA")
Expand All @@ -271,52 +297,63 @@ def test_apng_mode() -> None:

def test_apng_chunk_errors() -> None:
with Image.open("Tests/images/apng/chunk_no_actl.png") as im:
assert isinstance(im, PngImagePlugin.PngImageFile)
assert not im.is_animated

with pytest.warns(UserWarning):
with Image.open("Tests/images/apng/chunk_multi_actl.png") as im:
im.load()
assert isinstance(im, PngImagePlugin.PngImageFile)
assert not im.is_animated

with Image.open("Tests/images/apng/chunk_actl_after_idat.png") as im:
assert isinstance(im, PngImagePlugin.PngImageFile)
assert not im.is_animated

with Image.open("Tests/images/apng/chunk_no_fctl.png") as im:
assert isinstance(im, PngImagePlugin.PngImageFile)
with pytest.raises(SyntaxError):
im.seek(im.n_frames - 1)

with Image.open("Tests/images/apng/chunk_repeat_fctl.png") as im:
assert isinstance(im, PngImagePlugin.PngImageFile)
with pytest.raises(SyntaxError):
im.seek(im.n_frames - 1)

with Image.open("Tests/images/apng/chunk_no_fdat.png") as im:
assert isinstance(im, PngImagePlugin.PngImageFile)
with pytest.raises(SyntaxError):
im.seek(im.n_frames - 1)


def test_apng_syntax_errors() -> None:
with pytest.warns(UserWarning):
with Image.open("Tests/images/apng/syntax_num_frames_zero.png") as im:
assert isinstance(im, PngImagePlugin.PngImageFile)
assert not im.is_animated
with pytest.raises(OSError):
im.load()

with pytest.warns(UserWarning):
with Image.open("Tests/images/apng/syntax_num_frames_zero_default.png") as im:
assert isinstance(im, PngImagePlugin.PngImageFile)
assert not im.is_animated
im.load()

# we can handle this case gracefully
with Image.open("Tests/images/apng/syntax_num_frames_low.png") as im:
assert isinstance(im, PngImagePlugin.PngImageFile)
im.seek(im.n_frames - 1)

with pytest.raises(OSError):
with Image.open("Tests/images/apng/syntax_num_frames_high.png") as im:
assert isinstance(im, PngImagePlugin.PngImageFile)
im.seek(im.n_frames - 1)
im.load()

with pytest.warns(UserWarning):
with Image.open("Tests/images/apng/syntax_num_frames_invalid.png") as im:
assert isinstance(im, PngImagePlugin.PngImageFile)
assert not im.is_animated
im.load()

Expand All @@ -336,6 +373,7 @@ def test_apng_syntax_errors() -> None:
def test_apng_sequence_errors(test_file: str) -> None:
with pytest.raises(SyntaxError):
with Image.open(f"Tests/images/apng/{test_file}") as im:
assert isinstance(im, PngImagePlugin.PngImageFile)
im.seek(im.n_frames - 1)
im.load()

Expand All @@ -346,6 +384,7 @@ def test_apng_save(tmp_path: Path) -> None:
im.save(test_file, save_all=True)

with Image.open(test_file) as im:
assert isinstance(im, PngImagePlugin.PngImageFile)
im.load()
assert not im.is_animated
assert im.n_frames == 1
Expand All @@ -361,6 +400,7 @@ def test_apng_save(tmp_path: Path) -> None:
)

with Image.open(test_file) as im:
assert isinstance(im, PngImagePlugin.PngImageFile)
im.load()
assert im.is_animated
assert im.n_frames == 2
Expand Down Expand Up @@ -400,6 +440,7 @@ def test_apng_save_split_fdat(tmp_path: Path) -> None:
append_images=frames,
)
with Image.open(test_file) as im:
assert isinstance(im, PngImagePlugin.PngImageFile)
im.seek(im.n_frames - 1)
im.load()

Expand Down Expand Up @@ -442,6 +483,7 @@ def test_apng_save_duration_loop(tmp_path: Path) -> None:
test_file, save_all=True, append_images=[frame, frame], duration=[500, 100, 150]
)
with Image.open(test_file) as im:
assert isinstance(im, PngImagePlugin.PngImageFile)
assert im.n_frames == 1
assert "duration" not in im.info

Expand All @@ -453,6 +495,7 @@ def test_apng_save_duration_loop(tmp_path: Path) -> None:
duration=[500, 100, 150],
)
with Image.open(test_file) as im:
assert isinstance(im, PngImagePlugin.PngImageFile)
assert im.n_frames == 2
assert im.info["duration"] == 600

Expand All @@ -463,6 +506,7 @@ def test_apng_save_duration_loop(tmp_path: Path) -> None:
frame.info["duration"] = 300
frame.save(test_file, save_all=True, append_images=[frame, different_frame])
with Image.open(test_file) as im:
assert isinstance(im, PngImagePlugin.PngImageFile)
assert im.n_frames == 2
assert im.info["duration"] == 600

Expand Down
2 changes: 2 additions & 0 deletions Tests/test_file_dcx.py
Original file line number Diff line number Diff line change
Expand Up @@ -69,12 +69,14 @@ def test_tell() -> None:

def test_n_frames() -> None:
with Image.open(TEST_FILE) as im:
assert isinstance(im, DcxImagePlugin.DcxImageFile)
assert im.n_frames == 1
assert not im.is_animated


def test_eoferror() -> None:
with Image.open(TEST_FILE) as im:
assert isinstance(im, DcxImagePlugin.DcxImageFile)
n_frames = im.n_frames

# Test seeking past the last frame
Expand Down
6 changes: 6 additions & 0 deletions Tests/test_file_eps.py
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,8 @@
def test_sanity(filename: str, size: tuple[int, int], scale: int) -> None:
expected_size = tuple(s * scale for s in size)
with Image.open(filename) as image:
assert isinstance(image, EpsImagePlugin.EpsImageFile)

image.load(scale=scale)
assert image.mode == "RGB"
assert image.size == expected_size
Expand Down Expand Up @@ -223,6 +225,8 @@ def test_showpage() -> None:
@pytest.mark.skipif(not HAS_GHOSTSCRIPT, reason="Ghostscript not available")
def test_transparency() -> None:
with Image.open("Tests/images/eps/reqd_showpage.eps") as plot_image:
assert isinstance(plot_image, EpsImagePlugin.EpsImageFile)

plot_image.load(transparency=True)
assert plot_image.mode == "RGBA"

Expand Down Expand Up @@ -304,6 +308,7 @@ def test_render_scale2() -> None:

# Zero bounding box
with Image.open(FILE1) as image1_scale2:
assert isinstance(image1_scale2, EpsImagePlugin.EpsImageFile)
image1_scale2.load(scale=2)
with Image.open(FILE1_COMPARE_SCALE2) as image1_scale2_compare:
image1_scale2_compare = image1_scale2_compare.convert("RGB")
Expand All @@ -312,6 +317,7 @@ def test_render_scale2() -> None:

# Non-zero bounding box
with Image.open(FILE2) as image2_scale2:
assert isinstance(image2_scale2, EpsImagePlugin.EpsImageFile)
image2_scale2.load(scale=2)
with Image.open(FILE2_COMPARE_SCALE2) as image2_scale2_compare:
image2_scale2_compare = image2_scale2_compare.convert("RGB")
Expand Down
7 changes: 7 additions & 0 deletions Tests/test_file_fli.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,13 +21,17 @@

def test_sanity() -> None:
with Image.open(static_test_file) as im:
assert isinstance(im, FliImagePlugin.FliImageFile)

im.load()
assert im.mode == "P"
assert im.size == (128, 128)
assert im.format == "FLI"
assert not im.is_animated

with Image.open(animated_test_file) as im:
assert isinstance(im, FliImagePlugin.FliImageFile)

assert im.mode == "P"
assert im.size == (320, 200)
assert im.format == "FLI"
Expand Down Expand Up @@ -111,16 +115,19 @@ def test_palette_chunk_second() -> None:

def test_n_frames() -> None:
with Image.open(static_test_file) as im:
assert isinstance(im, FliImagePlugin.FliImageFile)
assert im.n_frames == 1
assert not im.is_animated

with Image.open(animated_test_file) as im:
assert isinstance(im, FliImagePlugin.FliImageFile)
assert im.n_frames == 384
assert im.is_animated


def test_eoferror() -> None:
with Image.open(animated_test_file) as im:
assert isinstance(im, FliImagePlugin.FliImageFile)
n_frames = im.n_frames

# Test seeking past the last frame
Expand Down
Loading
Loading