mirror of
https://github.com/python-pillow/Pillow.git
synced 2025-02-11 17:10:58 +03:00
added animated cursor tests
This commit is contained in:
parent
551e2a6afc
commit
5eb3e53502
BIN
Tests/images/ani/aero_busy_0.png
Normal file
BIN
Tests/images/ani/aero_busy_0.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 1.5 KiB |
BIN
Tests/images/ani/aero_busy_8.png
Normal file
BIN
Tests/images/ani/aero_busy_8.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 1.5 KiB |
BIN
Tests/images/ani/posy_busy_0.png
Normal file
BIN
Tests/images/ani/posy_busy_0.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 3.1 KiB |
BIN
Tests/images/ani/posy_busy_24.png
Normal file
BIN
Tests/images/ani/posy_busy_24.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 3.1 KiB |
BIN
Tests/images/ani/stopwtch_0.png
Normal file
BIN
Tests/images/ani/stopwtch_0.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 344 B |
BIN
Tests/images/ani/stopwtch_5.png
Normal file
BIN
Tests/images/ani/stopwtch_5.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 331 B |
132
Tests/test_file_ani.py
Normal file
132
Tests/test_file_ani.py
Normal file
|
@ -0,0 +1,132 @@
|
||||||
|
from io import BytesIO
|
||||||
|
import pytest
|
||||||
|
from PIL import Image
|
||||||
|
|
||||||
|
|
||||||
|
def test_aero_busy():
|
||||||
|
with Image.open("Tests/images/ani/aero_busy.ani") as im:
|
||||||
|
assert im.size == (64, 64)
|
||||||
|
assert im.info["frames"] == 18
|
||||||
|
|
||||||
|
with Image.open("Tests/images/ani/aero_busy_0.png") as png:
|
||||||
|
assert png.tobytes() == im.tobytes()
|
||||||
|
|
||||||
|
im.seek(8)
|
||||||
|
with Image.open("Tests/images/ani/aero_busy_8.png") as png:
|
||||||
|
assert png.tobytes() == im.tobytes()
|
||||||
|
|
||||||
|
with pytest.raises(EOFError):
|
||||||
|
im.seek(-1)
|
||||||
|
|
||||||
|
with pytest.raises(EOFError):
|
||||||
|
im.seek(18)
|
||||||
|
|
||||||
|
|
||||||
|
def test_posy_busy():
|
||||||
|
with Image.open("Tests/images/ani/posy_busy.ani") as im:
|
||||||
|
assert im.size == (96, 96)
|
||||||
|
assert im.info["frames"] == 77
|
||||||
|
|
||||||
|
with Image.open("Tests/images/ani/posy_busy_0.png") as png:
|
||||||
|
assert png.tobytes() == im.tobytes()
|
||||||
|
|
||||||
|
im.seek(24)
|
||||||
|
with Image.open("Tests/images/ani/posy_busy_24.png") as png:
|
||||||
|
assert png.tobytes() == im.tobytes()
|
||||||
|
|
||||||
|
with pytest.raises(EOFError):
|
||||||
|
im.seek(77)
|
||||||
|
|
||||||
|
|
||||||
|
def test_stopwtch():
|
||||||
|
with Image.open("Tests/images/ani/stopwtch.ani") as im:
|
||||||
|
assert im.size == (32, 32)
|
||||||
|
assert im.info["frames"] == 8
|
||||||
|
|
||||||
|
assert im.info["seq"][0] == 0
|
||||||
|
assert im.info["seq"][2] == 0
|
||||||
|
|
||||||
|
for i, r in enumerate(im.info["rate"]):
|
||||||
|
if i == 1 or i == 2:
|
||||||
|
assert r == 16
|
||||||
|
else:
|
||||||
|
assert r == 8
|
||||||
|
|
||||||
|
with Image.open("Tests/images/ani/stopwtch_0.png") as png:
|
||||||
|
assert png.tobytes() == im.tobytes()
|
||||||
|
|
||||||
|
im.seek(5)
|
||||||
|
with Image.open("Tests/images/ani/stopwtch_5.png") as png:
|
||||||
|
assert png.tobytes() == im.tobytes()
|
||||||
|
|
||||||
|
with pytest.raises(EOFError):
|
||||||
|
im.seek(8)
|
||||||
|
|
||||||
|
|
||||||
|
def test_save():
|
||||||
|
directory_path = "Tests/images/ani/"
|
||||||
|
filenames = ["aero_busy_0.png", "aero_busy_8.png",
|
||||||
|
"posy_busy_0.png", "posy_busy_24.png",
|
||||||
|
"stopwtch_0.png", "stopwtch_5.png"]
|
||||||
|
|
||||||
|
images = [Image.open(directory_path + filename) for filename in filenames]
|
||||||
|
|
||||||
|
with BytesIO() as output:
|
||||||
|
images[0].save(output, append_images=[images[1]], seq=[
|
||||||
|
0, 1], rate=[5, 10], format="ANI")
|
||||||
|
|
||||||
|
with Image.open(output, formats=["ANI"]) as im:
|
||||||
|
assert im.tobytes() == images[0].tobytes()
|
||||||
|
im.seek(1)
|
||||||
|
assert im.tobytes() == images[1].tobytes()
|
||||||
|
assert im.info['seq'] == [0, 1]
|
||||||
|
assert im.info['rate'] == [5, 10]
|
||||||
|
|
||||||
|
with BytesIO() as output:
|
||||||
|
images[2].save(output, append_images=[images[3]], seq=[
|
||||||
|
1, 0], rate=[2, 2], format="ANI", sizes=[(96, 96)])
|
||||||
|
|
||||||
|
with Image.open(output, formats=["ANI"]) as im:
|
||||||
|
assert im.tobytes() == images[2].tobytes()
|
||||||
|
im.seek(1)
|
||||||
|
assert im.tobytes() == images[3].tobytes()
|
||||||
|
assert im.info['seq'] == [1, 0]
|
||||||
|
assert im.info['rate'] == [2, 2]
|
||||||
|
|
||||||
|
with BytesIO() as output:
|
||||||
|
images[4].save(output, append_images=[images[5]], seq=[
|
||||||
|
0, 1], rate=[3, 4], format="ANI")
|
||||||
|
|
||||||
|
with Image.open(output, formats=["ANI"]) as im:
|
||||||
|
assert im.tobytes() == images[4].tobytes()
|
||||||
|
im.seek(1)
|
||||||
|
assert im.tobytes() == images[5].tobytes()
|
||||||
|
assert im.info['seq'] == [0, 1]
|
||||||
|
assert im.info['rate'] == [3, 4]
|
||||||
|
|
||||||
|
with BytesIO() as output:
|
||||||
|
images[0].save(output, append_images=images[1:],
|
||||||
|
seq=[0, 2, 4, 1, 3, 5, 0, 1, 0, 1],
|
||||||
|
rate=[1, 2, 3, 1, 2, 3, 1, 2, 3, 4],
|
||||||
|
format="ANI", sizes=[(32, 32)])
|
||||||
|
|
||||||
|
with Image.open(output, formats=["ANI"]) as im:
|
||||||
|
assert im.info['frames'] == 6
|
||||||
|
assert im.info['seq'] == [0, 2, 4, 1, 3, 5, 0, 1, 0, 1]
|
||||||
|
assert im.info['rate'] == [1, 2, 3, 1, 2, 3, 1, 2, 3, 4]
|
||||||
|
assert im.size == (32, 32)
|
||||||
|
|
||||||
|
im.seek(4)
|
||||||
|
assert im.tobytes() == images[4].tobytes()
|
||||||
|
|
||||||
|
with BytesIO() as output:
|
||||||
|
with pytest.raises(ValueError):
|
||||||
|
images[0].save(output, append_images=images[1:], seq=[
|
||||||
|
0, 1, 8, 1, 2], rate=[1, 1, 1, 1, 1], format="ANI", sizes=[(32, 32)])
|
||||||
|
|
||||||
|
with pytest.raises(ValueError):
|
||||||
|
images[0].save(output, append_images=images[1:], seq=[
|
||||||
|
0, 1, 1, 1, 2], rate=[1, 1, 1, 1], format="ANI", sizes=[(32, 32)])
|
||||||
|
|
||||||
|
with pytest.raises(ValueError):
|
||||||
|
images[0].save(output, append_images=images[1:], rate=[1, 1, 1, 1], format="ANI", sizes=[(32, 32)])
|
|
@ -15,22 +15,21 @@ def _accept(s):
|
||||||
def _save_frame(im: Image.Image, fp: BytesIO, filename: str, info: dict):
|
def _save_frame(im: Image.Image, fp: BytesIO, filename: str, info: dict):
|
||||||
fp.write(b"\0\0\2\0")
|
fp.write(b"\0\0\2\0")
|
||||||
bmp = True
|
bmp = True
|
||||||
s = im.encoderinfo.get(
|
s = info.get(
|
||||||
"sizes",
|
"sizes",
|
||||||
[(16, 16), (24, 24), (32, 32), (48, 48), (64, 64), (128, 128), (256, 256)],
|
[(16, 16), (24, 24), (32, 32), (48, 48), (64, 64), (128, 128), (256, 256)],
|
||||||
)
|
)
|
||||||
h = im.encoderinfo.get("hotspots", [(0, 0) for i in range(len(s))])
|
h = info.get("hotspots", [(0, 0) for _ in range(len(s))])
|
||||||
|
|
||||||
if len(h) != len(s):
|
if len(h) != len(s):
|
||||||
raise ValueError("Number of hotspots must be equal to number of cursor sizes")
|
raise ValueError("Number of hotspots must be equal to number of cursor sizes")
|
||||||
|
|
||||||
# sort and remove duplicate sizes
|
# sort and remove duplicate sizes
|
||||||
sizes = []
|
sizes, hotspots = [], []
|
||||||
hotspots = []
|
for size, hotspot in sorted(zip(s, h), key=lambda x: x[0]):
|
||||||
for size, hotspot in zip(*sorted(zip(s, h), lambda x: x[0])):
|
|
||||||
if size not in sizes:
|
if size not in sizes:
|
||||||
sizes.append(size)
|
sizes.append(size)
|
||||||
hotspots.append(hotspots)
|
hotspots.append(hotspot)
|
||||||
|
|
||||||
frames = []
|
frames = []
|
||||||
width, height = im.size
|
width, height = im.size
|
||||||
|
@ -72,6 +71,7 @@ def _save_frame(im: Image.Image, fp: BytesIO, filename: str, info: dict):
|
||||||
image_bytes = image_io.read()
|
image_bytes = image_io.read()
|
||||||
if bmp:
|
if bmp:
|
||||||
image_bytes = image_bytes[:8] + o32(height * 2) + image_bytes[12:]
|
image_bytes = image_bytes[:8] + o32(height * 2) + image_bytes[12:]
|
||||||
|
|
||||||
bytes_len = len(image_bytes)
|
bytes_len = len(image_bytes)
|
||||||
fp.write(o32(bytes_len)) # dwBytesInRes(4)
|
fp.write(o32(bytes_len)) # dwBytesInRes(4)
|
||||||
fp.write(o32(offset)) # dwImageOffset(4)
|
fp.write(o32(offset)) # dwImageOffset(4)
|
||||||
|
@ -121,7 +121,8 @@ def _write_multiple_frames(im: Image.Image, fp: BytesIO, filename: str):
|
||||||
list_offset = fp.tell()
|
list_offset = fp.tell()
|
||||||
fp.write(b"fram")
|
fp.write(b"fram")
|
||||||
|
|
||||||
frames = [im] + im.encoderinfo.get("append_images", [])
|
frames = [im]
|
||||||
|
frames.extend(im.encoderinfo.get("append_images", []))
|
||||||
for frame in frames:
|
for frame in frames:
|
||||||
fp.write(b"icon" + o32(0))
|
fp.write(b"icon" + o32(0))
|
||||||
icon_offset = fp.tell()
|
icon_offset = fp.tell()
|
||||||
|
@ -342,7 +343,7 @@ class AniFile:
|
||||||
|
|
||||||
def frame(self, frame):
|
def frame(self, frame):
|
||||||
if frame > self.anih["nFrames"]:
|
if frame > self.anih["nFrames"]:
|
||||||
raise ValueError("Frame index out of animation bounds")
|
raise EOFError("Frame index out of animation bounds")
|
||||||
|
|
||||||
offset, size = self.image_data[frame].values()
|
offset, size = self.image_data[frame].values()
|
||||||
self.buf.seek(offset)
|
self.buf.seek(offset)
|
||||||
|
@ -392,6 +393,7 @@ class AniImageFile(ImageFile.ImageFile):
|
||||||
self.info["frames"] = self.ani.anih["nFrames"]
|
self.info["frames"] = self.ani.anih["nFrames"]
|
||||||
|
|
||||||
self.frame = 0
|
self.frame = 0
|
||||||
|
self._min_frame = 0
|
||||||
self.seek(0)
|
self.seek(0)
|
||||||
self.size = self.im.size
|
self.size = self.im.size
|
||||||
|
|
||||||
|
@ -413,8 +415,9 @@ class AniImageFile(ImageFile.ImageFile):
|
||||||
self.mode = im.mode
|
self.mode = im.mode
|
||||||
|
|
||||||
def seek(self, frame):
|
def seek(self, frame):
|
||||||
if frame > self.info["frames"]:
|
|
||||||
raise ValueError("Frame index out of animation bounds")
|
if frame > self.info["frames"] - 1 or frame < 0:
|
||||||
|
raise EOFError("Frame index out of animation bounds")
|
||||||
|
|
||||||
self.frame = frame
|
self.frame = frame
|
||||||
self.load()
|
self.load()
|
||||||
|
|
Loading…
Reference in New Issue
Block a user