Skip to content

Commit

Permalink
Assert image type
Browse files Browse the repository at this point in the history
  • Loading branch information
radarhere committed Dec 23, 2024
1 parent 0e3f51d commit 8aeecd8
Show file tree
Hide file tree
Showing 26 changed files with 253 additions and 9 deletions.
43 changes: 43 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,44 +297,53 @@ 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
exception = None
with Image.open("Tests/images/apng/syntax_num_frames_low.png") as im:
assert isinstance(im, PngImagePlugin.PngImageFile)
try:
im.seek(im.n_frames - 1)
except Exception as e:
Expand All @@ -317,11 +352,13 @@ def test_apng_syntax_errors() -> None:

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 @@ -341,6 +378,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 @@ -351,6 +389,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 @@ -366,6 +405,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 @@ -405,6 +445,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)
exception = None
try:
im.seek(im.n_frames - 1)
Expand Down Expand Up @@ -452,6 +493,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 @@ -473,6 +515,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
9 changes: 9 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 All @@ -39,6 +43,8 @@ def test_prefix_chunk() -> None:
ImageFile.LOAD_TRUNCATED_IMAGES = True
try:
with Image.open(animated_test_file_with_prefix_chunk) as im:
assert isinstance(im, FliImagePlugin.FliImageFile)

assert im.mode == "P"
assert im.size == (320, 200)
assert im.format == "FLI"
Expand Down Expand Up @@ -114,16 +120,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

0 comments on commit 8aeecd8

Please sign in to comment.