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

When saving GIF frame that restores to background color, do not fill identical pixels #7788

Merged
merged 2 commits into from Mar 11, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
22 changes: 22 additions & 0 deletions Tests/test_file_gif.py
Expand Up @@ -647,6 +647,9 @@ def test_dispose2_palette(tmp_path: Path) -> None:
# Center remains red every frame
assert rgb_img.getpixel((50, 50)) == circle

# Check that frame transparency wasn't added unnecessarily
assert img._frame_transparency is None


def test_dispose2_diff(tmp_path: Path) -> None:
out = str(tmp_path / "temp.gif")
Expand Down Expand Up @@ -734,6 +737,25 @@ def test_dispose2_background_frame(tmp_path: Path) -> None:
assert im.n_frames == 3


def test_dispose2_previous_frame(tmp_path: Path) -> None:
out = str(tmp_path / "temp.gif")

im = Image.new("P", (100, 100))
im.info["transparency"] = 0
d = ImageDraw.Draw(im)
d.rectangle([(0, 0), (100, 50)], 1)
im.putpalette((0, 0, 0, 255, 0, 0))

im2 = Image.new("P", (100, 100))
im2.putpalette((0, 0, 0))

im.save(out, save_all=True, append_images=[im2], disposal=[0, 2])

with Image.open(out) as im:
im.seek(1)
assert im.getpixel((0, 0)) == (0, 0, 0, 255)


def test_transparency_in_second_frame(tmp_path: Path) -> None:
out = str(tmp_path / "temp.gif")
with Image.open("Tests/images/different_transparency.gif") as im:
Expand Down
6 changes: 3 additions & 3 deletions src/PIL/GifImagePlugin.py
Expand Up @@ -629,16 +629,16 @@ def _write_multiple_frames(im, fp, palette):
"duration"
]
continue
if encoderinfo.get("disposal") == 2:
if im_frames[-1]["encoderinfo"].get("disposal") == 2:
if background_im is None:
color = im.encoderinfo.get(
"transparency", im.info.get("transparency", (0, 0, 0))
)
background = _get_background(im_frame, color)
background_im = Image.new("P", im_frame.size, background)
background_im.putpalette(im_frames[0]["im"].palette)
delta, bbox = _getbbox(background_im, im_frame)
if encoderinfo.get("optimize") and im_frame.mode != "1":
bbox = _getbbox(background_im, im_frame)[1]
elif encoderinfo.get("optimize") and im_frame.mode != "1":
if "transparency" not in encoderinfo:
try:
encoderinfo["transparency"] = (
Expand Down