diff --git a/Tests/images/different_transparency.gif b/Tests/images/different_transparency.gif new file mode 100644 index 000000000..2d36bef9e Binary files /dev/null and b/Tests/images/different_transparency.gif differ diff --git a/Tests/images/different_transparency_merged.gif b/Tests/images/different_transparency_merged.gif new file mode 100644 index 000000000..94d0f53e0 Binary files /dev/null and b/Tests/images/different_transparency_merged.gif differ diff --git a/Tests/test_file_gif.py b/Tests/test_file_gif.py index 1b2314d51..52d7f035d 100644 --- a/Tests/test_file_gif.py +++ b/Tests/test_file_gif.py @@ -468,12 +468,25 @@ def test_dispose2_background(tmp_path): assert im.getpixel((0, 0)) == 0 -def test_iss634(): +def test_transparency_in_second_frame(): + with Image.open("Tests/images/different_transparency.gif") as im: + assert im.info["transparency"] == 0 + + # Seek to the second frame + im.seek(im.tell() + 1) + assert im.info["transparency"] == 0 + + assert_image_equal_tofile(im, "Tests/images/different_transparency_merged.gif") + + +def test_no_transparency_in_second_frame(): with Image.open("Tests/images/iss634.gif") as img: # Seek to the second frame img.seek(img.tell() + 1) + assert "transparency" not in img.info + # All transparent pixels should be replaced with the color from the first frame - assert img.histogram()[img.info["transparency"]] == 0 + assert img.histogram()[255] == 0 def test_duration(tmp_path): diff --git a/Tests/test_file_webp_animated.py b/Tests/test_file_webp_animated.py index 26e903488..25ebffe02 100644 --- a/Tests/test_file_webp_animated.py +++ b/Tests/test_file_webp_animated.py @@ -45,12 +45,12 @@ def test_write_animation_L(tmp_path): # Compare first and last frames to the original animated GIF orig.load() im.load() - assert_image_similar(im, orig.convert("RGBA"), 25.0) + assert_image_similar(im, orig.convert("RGBA"), 32.9) orig.seek(orig.n_frames - 1) im.seek(im.n_frames - 1) orig.load() im.load() - assert_image_similar(im, orig.convert("RGBA"), 25.0) + assert_image_similar(im, orig.convert("RGBA"), 32.9) @pytest.mark.xfail(is_big_endian(), reason="Fails on big-endian") diff --git a/src/PIL/GifImagePlugin.py b/src/PIL/GifImagePlugin.py index bf2db4260..2f6d98204 100644 --- a/src/PIL/GifImagePlugin.py +++ b/src/PIL/GifImagePlugin.py @@ -173,6 +173,8 @@ class GifImageFile(ImageFile.ImageFile): self.palette = copy(self.global_palette) info = {} + frame_transparency = None + interlace = None while True: s = self.fp.read(1) @@ -191,7 +193,7 @@ class GifImageFile(ImageFile.ImageFile): # flags = block[0] if flags & 1: - info["transparency"] = block[3] + frame_transparency = block[3] info["duration"] = i16(block, 1) * 10 # disposal method - find the value of bits 4 - 6 @@ -249,10 +251,6 @@ class GifImageFile(ImageFile.ImageFile): # image data bits = self.fp.read(1)[0] self.__offset = self.fp.tell() - self.tile = [("gif", - (x0, y0, x1, y1), - self.__offset, - (bits, interlace, info.get("transparency", -1)))] break else: @@ -278,11 +276,26 @@ class GifImageFile(ImageFile.ImageFile): except (AttributeError, KeyError): pass - if not self.tile: + if interlace is not None: + transparency = -1 + if frame_transparency is not None: + if frame == 0: + self.info["transparency"] = frame_transparency + else: + transparency = frame_transparency + self.tile = [ + ( + "gif", + (x0, y0, x1, y1), + self.__offset, + (bits, interlace, transparency), + ) + ] + else: # self.__fp = None raise EOFError - for k in ["transparency", "duration", "comment", "extension", "loop"]: + for k in ["duration", "comment", "extension", "loop"]: if k in info: self.info[k] = info[k] elif k in self.info: