From 5b4cb5052a29f63112863c534a3d7847afdc47a6 Mon Sep 17 00:00:00 2001 From: Andrew Murray Date: Fri, 25 Jun 2021 21:54:21 +1000 Subject: [PATCH 1/4] Draw first frame on top of transparency --- Tests/images/first_frame_transparency.gif | Bin 0 -> 972 bytes Tests/test_file_gif.py | 6 ++++++ src/PIL/GifImagePlugin.py | 6 ++++++ 3 files changed, 12 insertions(+) create mode 100644 Tests/images/first_frame_transparency.gif diff --git a/Tests/images/first_frame_transparency.gif b/Tests/images/first_frame_transparency.gif new file mode 100644 index 0000000000000000000000000000000000000000..86dc0de64a9d172b88396b7a6eb500bde328746f GIT binary patch literal 972 zcmZ?wbhEHb^ky((XlGzx_z#4mU^E0qXb33&WMO1rU}Vsd1O|W+5IS(IWMJfw@z}7y zv58SgE9S(8hliR4l$i=VHYPE2N(e^XSz)l)y-&e5jpbyZirXY{6|&rCZQ9YOsoH^S zV;AR%N{77&-4wrgc=hg05c Sj)bAt(OyaWG9M!a25SJ54@>s| literal 0 HcmV?d00001 diff --git a/Tests/test_file_gif.py b/Tests/test_file_gif.py index df029dceb..556ecec6b 100644 --- a/Tests/test_file_gif.py +++ b/Tests/test_file_gif.py @@ -298,6 +298,12 @@ def test_eoferror(): im.seek(n_frames - 1) +def test_first_frame_transparency(): + with Image.open("Tests/images/first_frame_transparency.gif") as im: + px = im.load() + assert px[0, 0] == im.info["transparency"] + + def test_dispose_none(): with Image.open("Tests/images/dispose_none.gif") as img: try: diff --git a/src/PIL/GifImagePlugin.py b/src/PIL/GifImagePlugin.py index 5c93de2c9..658bee214 100644 --- a/src/PIL/GifImagePlugin.py +++ b/src/PIL/GifImagePlugin.py @@ -317,6 +317,12 @@ class GifImageFile(ImageFile.ImageFile): if self.palette: self.mode = "P" + def load_prepare(self): + if not self.im and "transparency" in self.info: + self.im = Image.core.fill(self.mode, self.size, self.info["transparency"]) + + super(GifImageFile, self).load_prepare() + def tell(self): return self.__frame From 432677740d01996fe0e606a7616923699a4cb3bd Mon Sep 17 00:00:00 2001 From: Glenn Maynard Date: Tue, 23 Oct 2018 22:34:29 -0500 Subject: [PATCH 2/4] Add a test for an image that works with other GIF decoders. This test is fixed by the next commits. --- Tests/images/transparent_dispose.gif | Bin 0 -> 95 bytes Tests/test_file_gif.py | 11 +++++++++++ 2 files changed, 11 insertions(+) create mode 100644 Tests/images/transparent_dispose.gif diff --git a/Tests/images/transparent_dispose.gif b/Tests/images/transparent_dispose.gif new file mode 100644 index 0000000000000000000000000000000000000000..92b615543de7a4c82a3a3449e27b81d8efa7d4fe GIT binary patch literal 95 zcmZ?wbhEHbWM*Jwn8?7u@LvLmfiw^({$ye0Vqjv>0dYX`3`|TRAs}H+BQ)Wb0I+JX PFi;&(Em*Y=BZD;nY>Eoh literal 0 HcmV?d00001 diff --git a/Tests/test_file_gif.py b/Tests/test_file_gif.py index 556ecec6b..9267fb567 100644 --- a/Tests/test_file_gif.py +++ b/Tests/test_file_gif.py @@ -337,6 +337,17 @@ def test_dispose_background(): pass +def test_transparent_dispose(): + img = Image.open("Tests/images/transparent_dispose.gif") + + expected_colors = [(2, 1, 2), (0, 1, 0), (2, 1, 2)] + for frame in range(3): + img.seek(frame) + for x in range(3): + color = img.getpixel((x, 0)) + assert color == expected_colors[frame][x] + + def test_dispose_previous(): with Image.open("Tests/images/dispose_prev.gif") as img: try: From f6d504c8f6988feb993ecf7ac46d896784eaca32 Mon Sep 17 00:00:00 2001 From: Andrew Murray Date: Fri, 25 Jun 2021 23:16:46 +1000 Subject: [PATCH 3/4] Use context manager --- Tests/test_file_gif.py | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/Tests/test_file_gif.py b/Tests/test_file_gif.py index 9267fb567..2b577b36f 100644 --- a/Tests/test_file_gif.py +++ b/Tests/test_file_gif.py @@ -338,14 +338,13 @@ def test_dispose_background(): def test_transparent_dispose(): - img = Image.open("Tests/images/transparent_dispose.gif") - expected_colors = [(2, 1, 2), (0, 1, 0), (2, 1, 2)] - for frame in range(3): - img.seek(frame) - for x in range(3): - color = img.getpixel((x, 0)) - assert color == expected_colors[frame][x] + with Image.open("Tests/images/transparent_dispose.gif") as img: + for frame in range(3): + img.seek(frame) + for x in range(3): + color = img.getpixel((x, 0)) + assert color == expected_colors[frame][x] def test_dispose_previous(): From e29a7d8a94ab88eccae91a0b8903ff170ec03bb2 Mon Sep 17 00:00:00 2001 From: Andrew Murray Date: Sat, 26 Jun 2021 00:55:31 +1000 Subject: [PATCH 4/4] Replace with transparency if available for disposal method 2 --- src/PIL/GifImagePlugin.py | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/src/PIL/GifImagePlugin.py b/src/PIL/GifImagePlugin.py index 658bee214..2f988ff43 100644 --- a/src/PIL/GifImagePlugin.py +++ b/src/PIL/GifImagePlugin.py @@ -269,9 +269,14 @@ class GifImageFile(ImageFile.ImageFile): dispose_size = (x1 - x0, y1 - y0) Image._decompression_bomb_check(dispose_size) - self.dispose = Image.core.fill( - "P", dispose_size, self.info.get("background", 0) + + # by convention, attempt to use transparency first + color = ( + frame_transparency + if frame_transparency is not None + else self.info.get("background", 0) ) + self.dispose = Image.core.fill("P", dispose_size, color) else: # replace with previous contents if self.im: