Skip to content

Commit

Permalink
Merge pull request #8104 from radarhere/apng
Browse files Browse the repository at this point in the history
  • Loading branch information
hugovk committed Jun 25, 2024
2 parents 02e8bf9 + 272d235 commit a4188bb
Show file tree
Hide file tree
Showing 2 changed files with 19 additions and 9 deletions.
15 changes: 13 additions & 2 deletions Tests/test_file_apng.py
Original file line number Diff line number Diff line change
Expand Up @@ -706,10 +706,21 @@ def test_different_modes_in_later_frames(
assert reloaded.mode == mode


def test_apng_repeated_seeks_give_correct_info() -> None:
def test_different_durations(tmp_path: Path) -> None:
test_file = str(tmp_path / "temp.png")

with Image.open("Tests/images/apng/different_durations.png") as im:
for i in range(3):
for _ in range(3):
im.seek(0)
assert im.info["duration"] == 4000

im.seek(1)
assert im.info["duration"] == 1000

im.save(test_file, save_all=True)

with Image.open(test_file) as reloaded:
assert reloaded.info["duration"] == 4000

reloaded.seek(1)
assert reloaded.info["duration"] == 1000
13 changes: 6 additions & 7 deletions src/PIL/PngImagePlugin.py
Original file line number Diff line number Diff line change
Expand Up @@ -1115,7 +1115,7 @@ def write(self, data: bytes) -> None:


def _write_multiple_frames(im, fp, chunk, mode, rawmode, default_image, append_images):
duration = im.encoderinfo.get("duration", im.info.get("duration", 0))
duration = im.encoderinfo.get("duration")
loop = im.encoderinfo.get("loop", im.info.get("loop", 0))
disposal = im.encoderinfo.get("disposal", im.info.get("disposal", Disposal.OP_NONE))
blend = im.encoderinfo.get("blend", im.info.get("blend", Blend.OP_SOURCE))
Expand All @@ -1136,6 +1136,8 @@ def _write_multiple_frames(im, fp, chunk, mode, rawmode, default_image, append_i
encoderinfo = im.encoderinfo.copy()
if isinstance(duration, (list, tuple)):
encoderinfo["duration"] = duration[frame_count]
elif duration is None and "duration" in im_frame.info:
encoderinfo["duration"] = im_frame.info["duration"]
if isinstance(disposal, (list, tuple)):
encoderinfo["disposal"] = disposal[frame_count]
if isinstance(blend, (list, tuple)):
Expand Down Expand Up @@ -1170,15 +1172,12 @@ def _write_multiple_frames(im, fp, chunk, mode, rawmode, default_image, append_i
not bbox
and prev_disposal == encoderinfo.get("disposal")
and prev_blend == encoderinfo.get("blend")
and "duration" in encoderinfo
):
previous["encoderinfo"]["duration"] += encoderinfo.get(
"duration", duration
)
previous["encoderinfo"]["duration"] += encoderinfo["duration"]
continue
else:
bbox = None
if "duration" not in encoderinfo:
encoderinfo["duration"] = duration
im_frames.append({"im": im_frame, "bbox": bbox, "encoderinfo": encoderinfo})

if len(im_frames) == 1 and not default_image:
Expand Down Expand Up @@ -1208,7 +1207,7 @@ def _write_multiple_frames(im, fp, chunk, mode, rawmode, default_image, append_i
im_frame = im_frame.crop(bbox)
size = im_frame.size
encoderinfo = frame_data["encoderinfo"]
frame_duration = int(round(encoderinfo["duration"]))
frame_duration = int(round(encoderinfo.get("duration", 0)))
frame_disposal = encoderinfo.get("disposal", disposal)
frame_blend = encoderinfo.get("blend", blend)
# frame control
Expand Down

0 comments on commit a4188bb

Please sign in to comment.