Skip to content

Commit

Permalink
Merge pull request #7146 from radarhere/apng_duration
Browse files Browse the repository at this point in the history
Fixed combining single duration across duplicate APNG frames
  • Loading branch information
mergify[bot] committed Jun 6, 2023
2 parents 9264c3d + 97df237 commit 6b3991b
Show file tree
Hide file tree
Showing 2 changed files with 17 additions and 3 deletions.
11 changes: 11 additions & 0 deletions Tests/test_file_apng.py
Original file line number Diff line number Diff line change
Expand Up @@ -447,6 +447,17 @@ def test_apng_save_duration_loop(tmp_path):
assert im.info.get("duration") == 750


def test_apng_save_duplicate_duration(tmp_path):
test_file = str(tmp_path / "temp.png")
frame = Image.new("RGB", (1, 1))

# Test a single duration is correctly combined across duplicate frames
frame.save(test_file, save_all=True, append_images=[frame, frame], duration=500)
with Image.open(test_file) as im:
assert im.n_frames == 1
assert im.info.get("duration") == 1500


def test_apng_save_disposal(tmp_path):
test_file = str(tmp_path / "temp.png")
size = (128, 64)
Expand Down
9 changes: 6 additions & 3 deletions src/PIL/PngImagePlugin.py
Original file line number Diff line number Diff line change
Expand Up @@ -1146,11 +1146,14 @@ def _write_multiple_frames(im, fp, chunk, rawmode, default_image, append_images)
and prev_disposal == encoderinfo.get("disposal")
and prev_blend == encoderinfo.get("blend")
):
if isinstance(duration, (list, tuple)):
previous["encoderinfo"]["duration"] += encoderinfo["duration"]
previous["encoderinfo"]["duration"] += encoderinfo.get(
"duration", duration
)
continue
else:
bbox = None
if "duration" not in encoderinfo:
encoderinfo["duration"] = duration
im_frames.append({"im": im_frame, "bbox": bbox, "encoderinfo": encoderinfo})

# animation control
Expand All @@ -1175,7 +1178,7 @@ def _write_multiple_frames(im, fp, chunk, rawmode, default_image, append_images)
im_frame = im_frame.crop(bbox)
size = im_frame.size
encoderinfo = frame_data["encoderinfo"]
frame_duration = int(round(encoderinfo.get("duration", duration)))
frame_duration = int(round(encoderinfo["duration"]))
frame_disposal = encoderinfo.get("disposal", disposal)
frame_blend = encoderinfo.get("blend", blend)
# frame control
Expand Down

0 comments on commit 6b3991b

Please sign in to comment.