From b383a175be70da0df33babea3d480efd9768e937 Mon Sep 17 00:00:00 2001 From: Andrew Murray Date: Mon, 29 Nov 2021 17:49:06 +1100 Subject: [PATCH 1/4] Convert subsequent GIF frames to RGB or RGBA --- .../images/different_transparency_merged.gif | Bin 3046 -> 0 bytes .../images/different_transparency_merged.png | Bin 0 -> 333 bytes Tests/images/dispose_none_load_end_second.gif | Bin 17208 -> 0 bytes Tests/images/dispose_none_load_end_second.png | Bin 0 -> 27507 bytes .../dispose_prev_first_frame_seeked.gif | Bin 1028 -> 0 bytes .../dispose_prev_first_frame_seeked.png | Bin 0 -> 208 bytes .../images/missing_background_first_frame.gif | Bin 950 -> 0 bytes .../images/missing_background_first_frame.png | Bin 0 -> 382 bytes Tests/test_file_gif.py | 20 ++-- src/PIL/GifImagePlugin.py | 89 +++++++++++++++--- src/PIL/PdfImagePlugin.py | 2 +- 11 files changed, 87 insertions(+), 24 deletions(-) delete mode 100644 Tests/images/different_transparency_merged.gif create mode 100644 Tests/images/different_transparency_merged.png delete mode 100644 Tests/images/dispose_none_load_end_second.gif create mode 100644 Tests/images/dispose_none_load_end_second.png delete mode 100644 Tests/images/dispose_prev_first_frame_seeked.gif create mode 100644 Tests/images/dispose_prev_first_frame_seeked.png delete mode 100644 Tests/images/missing_background_first_frame.gif create mode 100644 Tests/images/missing_background_first_frame.png diff --git a/Tests/images/different_transparency_merged.gif b/Tests/images/different_transparency_merged.gif deleted file mode 100644 index 94d0f53e0dd6a4716c934cd321c625cb5ca210c2..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3046 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 diff --git a/Tests/images/different_transparency_merged.png b/Tests/images/different_transparency_merged.png new file mode 100644 index 0000000000000000000000000000000000000000..3438f62a6f47b24abdce3462d2a7e1e1a47888de GIT binary patch literal 333 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 AS^xk5 diff --git a/Tests/images/dispose_none_load_end_second.png b/Tests/images/dispose_none_load_end_second.png new file mode 100644 index 0000000000000000000000000000000000000000..dc01ccbdd0c67bce32fe5dd103bc0c7dab7f03a6 GIT binary patch literal 27507 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 Y4p{dnan(Fx!$P)CJU%&B3QP+%Ez+Tq zs7w_>6|HVV?i-n87wW{9^ONAJ@}0E04IcJt`2J*w*w8Tw;GA>%_6z#_f?#J07q@!_ znUF=eY(HxA#Epc#8lLVS9G`gHNTB~Z;-dWQx()zXU0*g?Eg;Ip`BZ@pZH{eOgpcG4 zr$?bIPh(eJx3KY(+e>2?$-vV}lnQiclZ)bPuwX4%R0hA(5t4zID=0&mlr2wV7l-X_ zIR}sv%L-O42Q;r>_h4Us`N!v*xV!1+%7F3X7ss=dYXv4H%9y2GDBc0nucVPWFjyumAu607*qoM6N<$f?k%Zp8x;= literal 0 HcmV?d00001 diff --git a/Tests/test_file_gif.py b/Tests/test_file_gif.py index fae7e912c8c..497cc5ed3d2 100644 --- a/Tests/test_file_gif.py +++ b/Tests/test_file_gif.py @@ -324,7 +324,7 @@ def test_dispose_none_load_end(): with Image.open("Tests/images/dispose_none_load_end.gif") as img: img.seek(1) - assert_image_equal_tofile(img, "Tests/images/dispose_none_load_end_second.gif") + assert_image_equal_tofile(img, "Tests/images/dispose_none_load_end_second.png") def test_dispose_background(): @@ -340,12 +340,16 @@ def test_dispose_background(): def test_dispose_background_transparency(): with Image.open("Tests/images/dispose_bgnd_transparency.gif") as img: img.seek(2) - px = img.convert("RGBA").load() + px = img.load() assert px[35, 30][3] == 0 def test_transparent_dispose(): - expected_colors = [(2, 1, 2), (0, 1, 0), (2, 1, 2)] + expected_colors = [ + (2, 1, 2), + ((0, 255, 24, 255), (0, 0, 255, 255), (0, 255, 24, 255)), + ((0, 0, 0, 0), (0, 0, 255, 255), (0, 0, 0, 0)), + ] with Image.open("Tests/images/transparent_dispose.gif") as img: for frame in range(3): img.seek(frame) @@ -368,7 +372,7 @@ def test_dispose_previous_first_frame(): with Image.open("Tests/images/dispose_prev_first_frame.gif") as im: im.seek(1) assert_image_equal_tofile( - im, "Tests/images/dispose_prev_first_frame_seeked.gif" + im, "Tests/images/dispose_prev_first_frame_seeked.png" ) @@ -508,7 +512,7 @@ def test_dispose2_background(tmp_path): with Image.open(out) as im: im.seek(1) - assert im.getpixel((0, 0)) == 0 + assert im.getpixel((0, 0)) == (255, 0, 0) def test_transparency_in_second_frame(): @@ -517,9 +521,9 @@ def test_transparency_in_second_frame(): # Seek to the second frame im.seek(im.tell() + 1) - assert im.info["transparency"] == 0 + assert "transparency" not in im.info - assert_image_equal_tofile(im, "Tests/images/different_transparency_merged.gif") + assert_image_equal_tofile(im, "Tests/images/different_transparency_merged.png") def test_no_transparency_in_second_frame(): @@ -926,4 +930,4 @@ def test_missing_background(): # but the disposal method is "Restore to background color" with Image.open("Tests/images/missing_background.gif") as im: im.seek(1) - assert_image_equal_tofile(im, "Tests/images/missing_background_first_frame.gif") + assert_image_equal_tofile(im, "Tests/images/missing_background_first_frame.png") diff --git a/src/PIL/GifImagePlugin.py b/src/PIL/GifImagePlugin.py index 5b466884470..44d15b5961e 100644 --- a/src/PIL/GifImagePlugin.py +++ b/src/PIL/GifImagePlugin.py @@ -124,8 +124,7 @@ def seek(self, frame): if not self._seek_check(frame): return if frame < self.__frame: - if frame != 0: - self.im = None + self.im = None self._seek(0) last_frame = self.__frame @@ -165,12 +164,21 @@ def _seek(self, frame): pass self.__offset = 0 + if self.__frame == 1: + self.pyaccess = None + if "transparency" in self.info: + self.mode = "RGBA" + self.im.putpalettealpha(self.info["transparency"], 0) + self.im = self.im.convert("RGBA", Image.FLOYDSTEINBERG) + + del self.info["transparency"] + else: + self.mode = "RGB" + self.im = self.im.convert("RGB", Image.FLOYDSTEINBERG) if self.dispose: self.im.paste(self.dispose, self.dispose_extent) - from copy import copy - - self.palette = copy(self.global_palette) + palette = None info = {} frame_transparency = None @@ -246,7 +254,7 @@ def _seek(self, frame): if flags & 128: bits = (flags & 7) + 1 - self.palette = ImagePalette.raw("RGB", self.fp.read(3 << bits)) + palette = ImagePalette.raw("RGB", self.fp.read(3 << bits)) # image data bits = self.fp.read(1)[0] @@ -257,6 +265,15 @@ def _seek(self, frame): pass # raise OSError, "illegal GIF tag `%x`" % s[0] + frame_palette = palette or self.global_palette + + def _rgb(color): + if frame_palette: + color = tuple(frame_palette.palette[color * 3 : color * 3 + 3]) + else: + color = (color, color, color) + return color + try: if self.disposal_method < 2: # do not dispose or none specified @@ -272,9 +289,13 @@ def _seek(self, frame): # by convention, attempt to use transparency first color = self.info.get("transparency", frame_transparency) - if color is None: - color = self.info.get("background", 0) - self.dispose = Image.core.fill("P", dispose_size, color) + if color is not None: + dispose_mode = "RGBA" + color = _rgb(color) + (0,) + else: + dispose_mode = "RGB" + color = _rgb(self.info.get("background", 0)) + self.dispose = Image.core.fill(dispose_mode, dispose_size, color) else: # replace with previous contents if self.im: @@ -286,7 +307,7 @@ def _seek(self, frame): Image._decompression_bomb_check(dispose_size) self.dispose = Image.core.fill( - "P", dispose_size, frame_transparency + "RGBA", dispose_size, _rgb(frame_transparency) + (0,) ) except AttributeError: pass @@ -316,16 +337,54 @@ def _seek(self, frame): elif k in self.info: del self.info[k] - self.mode = "L" - if self.palette: - self.mode = "P" + if frame == 0: + self.mode = "P" if frame_palette else "L" + + if self.mode == "P" and not palette: + from copy import copy + + palette = copy(self.global_palette) + self.palette = palette + else: + self._frame_palette = frame_palette + self._frame_transparency = frame_transparency 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"]) + if self.__frame == 0: + if "transparency" in self.info: + self.im = Image.core.fill( + self.mode, self.size, self.info["transparency"] + ) + else: + self._prev_im = self.im + if self._frame_palette: + self.mode = "P" + self.im = Image.core.fill("P", self.size, self._frame_transparency or 0) + self.im.putpalette(*self._frame_palette.getdata()) + self._frame_palette = None + else: + self.mode = "L" + self.im = None super().load_prepare() + def load_end(self): + if self.__frame == 0: + return + if self._frame_transparency is not None: + self.im.putpalettealpha(self._frame_transparency, 0) + frame_im = self.im.convert("RGBA") + else: + frame_im = self.im.convert("RGB") + frame_im = self._crop(frame_im, self.dispose_extent) + + self.im = self._prev_im + self.mode = self.im.mode + if frame_im.mode == "RGBA": + self.im.paste(frame_im, self.dispose_extent, frame_im) + else: + self.im.paste(frame_im, self.dispose_extent) + def tell(self): return self.__frame diff --git a/src/PIL/PdfImagePlugin.py b/src/PIL/PdfImagePlugin.py index 49ba077e667..1131c63256e 100644 --- a/src/PIL/PdfImagePlugin.py +++ b/src/PIL/PdfImagePlugin.py @@ -135,7 +135,7 @@ def _save(im, fp, filename, save_all=False): procset = "ImageB" # grayscale elif im.mode == "P": filter = "ASCIIHexDecode" - palette = im.im.getpalette("RGB") + palette = im.getpalette() colorspace = [ PdfParser.PdfName("Indexed"), PdfParser.PdfName("DeviceRGB"), From 6337428df1e11b1e02d1757bcc288520e8fd33a8 Mon Sep 17 00:00:00 2001 From: Andrew Murray Date: Mon, 29 Nov 2021 14:10:18 +1100 Subject: [PATCH 2/4] Loading transparent pixels in C from subsequent GIF frames is no longer a problem --- src/PIL/GifImagePlugin.py | 10 +++------- src/decode.c | 4 +--- src/libImaging/Gif.h | 3 --- src/libImaging/GifDecode.c | 36 +++++++++++++++--------------------- 4 files changed, 19 insertions(+), 34 deletions(-) diff --git a/src/PIL/GifImagePlugin.py b/src/PIL/GifImagePlugin.py index 44d15b5961e..55b09abec54 100644 --- a/src/PIL/GifImagePlugin.py +++ b/src/PIL/GifImagePlugin.py @@ -313,18 +313,14 @@ def _rgb(color): pass 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 + if frame == 0 and frame_transparency is not None: + self.info["transparency"] = frame_transparency self.tile = [ ( "gif", (x0, y0, x1, y1), self.__offset, - (bits, interlace, transparency), + (bits, interlace), ) ] else: diff --git a/src/decode.c b/src/decode.c index cb018a4e706..e236264cdb4 100644 --- a/src/decode.c +++ b/src/decode.c @@ -433,8 +433,7 @@ PyImaging_GifDecoderNew(PyObject *self, PyObject *args) { char *mode; int bits = 8; int interlace = 0; - int transparency = -1; - if (!PyArg_ParseTuple(args, "s|iii", &mode, &bits, &interlace, &transparency)) { + if (!PyArg_ParseTuple(args, "s|ii", &mode, &bits, &interlace)) { return NULL; } @@ -452,7 +451,6 @@ PyImaging_GifDecoderNew(PyObject *self, PyObject *args) { ((GIFDECODERSTATE *)decoder->state.context)->bits = bits; ((GIFDECODERSTATE *)decoder->state.context)->interlace = interlace; - ((GIFDECODERSTATE *)decoder->state.context)->transparency = transparency; return (PyObject *)decoder; } diff --git a/src/libImaging/Gif.h b/src/libImaging/Gif.h index 91132e2e627..4029bbfe5f1 100644 --- a/src/libImaging/Gif.h +++ b/src/libImaging/Gif.h @@ -30,9 +30,6 @@ typedef struct { */ int interlace; - /* The transparent palette index, or -1 for no transparency. */ - int transparency; - /* PRIVATE CONTEXT (set by decoder) */ /* Interlace parameters */ diff --git a/src/libImaging/GifDecode.c b/src/libImaging/GifDecode.c index 301f604b9b8..30478e24aac 100644 --- a/src/libImaging/GifDecode.c +++ b/src/libImaging/GifDecode.c @@ -248,33 +248,27 @@ ImagingGifDecode(Imaging im, ImagingCodecState state, UINT8 *buffer, Py_ssize_t /* To squeeze some extra pixels out of this loop, we test for some common cases and handle them separately. */ - /* If we have transparency, we need to use the regular loop. */ - if (context->transparency == -1) { - if (i == 1) { - if (state->x < state->xsize - 1) { - /* Single pixel, not at the end of the line. */ - *out++ = p[0]; - state->x++; - continue; - } - } else if (state->x + i <= state->xsize) { - /* This string fits into current line. */ - memcpy(out, p, i); - out += i; - state->x += i; - if (state->x == state->xsize) { - NEWLINE(state, context); - } + if (i == 1) { + if (state->x < state->xsize - 1) { + /* Single pixel, not at the end of the line. */ + *out++ = p[0]; + state->x++; continue; } + } else if (state->x + i <= state->xsize) { + /* This string fits into current line. */ + memcpy(out, p, i); + out += i; + state->x += i; + if (state->x == state->xsize) { + NEWLINE(state, context); + } + continue; } /* No shortcut, copy pixel by pixel */ for (c = 0; c < i; c++) { - if (p[c] != context->transparency) { - *out = p[c]; - } - out++; + *out++ = p[c]; if (++state->x >= state->xsize) { NEWLINE(state, context); } From 1fb1bec0e80084aa675d7a8fd3e1d0525fe1cc06 Mon Sep 17 00:00:00 2001 From: Andrew Murray Date: Mon, 29 Nov 2021 15:12:24 +1100 Subject: [PATCH 3/4] Added test --- Tests/images/dispose_bgnd_rgba.gif | Bin 0 -> 1450 bytes Tests/test_file_gif.py | 26 ++++++++++++++++++++++++++ 2 files changed, 26 insertions(+) create mode 100644 Tests/images/dispose_bgnd_rgba.gif diff --git a/Tests/images/dispose_bgnd_rgba.gif b/Tests/images/dispose_bgnd_rgba.gif new file mode 100644 index 0000000000000000000000000000000000000000..c18a0ba71f1abf98b1bbd212dc55577255c79bc6 GIT binary patch literal 1450 zcmYk*dpOg390%~62GBX5oue1U_A1tz!r@Ujn+no+zYwJuV)B_ znV}s`@cU;ti8XCXi#g1>=mUS5bxv5ueW_~PlHd-a6}i5XX~oO#{Y2t>s0Xqp_$OoI zUrl2Sp4Q0PGE?GNhyap6iO8e74*8TFNYDb5$x{a z=Wi3h%Et{HU;8CKaN&d>dF3_oL(Xxt9tNv>LduQ6^wwUCbTX_enL$lg7CB&ZOwUixc()pKms!LXjT;ss!Ml$w|sSzW#S{PEqr z3!tCnzPq>fYI_aeE$}*yXUBP9L>V#P;l}_PYBWSJosG{CW*2Zt6SWi82L^3n@sCNyYbIK&yK8-9us$r?T19uJX!JbXToDqi8^WWZx zCB>0#@RC?_GEsv9kZzwz?2FfhP?CEq%fFTp5bl$No}LemV*OTetgvWBM0!}awL zD+mDTWHus?tGaC^I@#B3c} zkK%+UwZM3P!oz%;o~EAHPQ1gYk}&uTsynD!VZqI5Y3IdWR;G9i%G#|iG&n3oqJsp& zkN6~QIagCBKY}Sm(G_hN7am}(XcG}fD{_R#66J#miOAUKE9S8V1>x505S$%c9+zZ@ zi&npSHZL*jUU^5mj-*mcVQH@uF0Xi?_ZK&-3&SJM-kF2a2@Ve@`YtG-#-`a;71Pod z#Koo8ovVT??xEEJ_XSAzQsA#}*#8b@0Omgj(f>u$`VB#?x%OLJ#CAjuW|vgxtvg3ml3tIHsek?H7Be zr%ahi?;NfhAl;|-)pm_&FdvTchxU(75~m3Lsk6w@<;U~BgZjL=T%WezSevdgjx#R{ z99ITeUZ`Y;6d&kjjt@=h#rimrd$qqUL!M*gN(X%x8cE>vSFGfJ;=J+=IbYR*!;5E9;%?d-y;vN=!cWOYPXYS#y(fUpXR7Vnet!Lr^(OCP4SWuxu* z6S(fAzr$ia9~*=Z`uzg5eM9pDLlYPD zOdG21V}vq(F;h($ literal 0 HcmV?d00001 diff --git a/Tests/test_file_gif.py b/Tests/test_file_gif.py index 497cc5ed3d2..13eb06897b9 100644 --- a/Tests/test_file_gif.py +++ b/Tests/test_file_gif.py @@ -163,6 +163,32 @@ def test_roundtrip_save_all(tmp_path): assert reread.n_frames == 5 +@pytest.mark.parametrize( + "path, mode", + ( + ("Tests/images/dispose_bgnd.gif", "RGB"), + # Hexeditted copy of dispose_bgnd to add transparency + ("Tests/images/dispose_bgnd_rgba.gif", "RGBA"), + ), +) +def test_loading_multiple_palettes(path, mode): + with Image.open(path) as im: + assert im.mode == "P" + first_frame_colors = im.palette.colors.keys() + original_color = im.convert("RGB").load()[0, 0] + + im.seek(1) + assert im.mode == mode + if mode == "RGBA": + im = im.convert("RGB") + + # Check a color only from the old palette + assert im.load()[0, 0] == original_color + + # Check a color from the new palette + assert im.load()[24, 24] not in first_frame_colors + + def test_headers_saving_for_animated_gifs(tmp_path): important_headers = ["background", "version", "duration", "loop"] # Multiframe image From eeb685b6c43ed2961d45583651d3b35cc2bdd4a8 Mon Sep 17 00:00:00 2001 From: Andrew Murray Date: Mon, 29 Nov 2021 18:50:22 +1100 Subject: [PATCH 4/4] GIFs change mode for later frames [ci skip] --- docs/handbook/image-file-formats.rst | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/docs/handbook/image-file-formats.rst b/docs/handbook/image-file-formats.rst index 1a5dee0b480..dc1b89075c7 100644 --- a/docs/handbook/image-file-formats.rst +++ b/docs/handbook/image-file-formats.rst @@ -91,8 +91,9 @@ Pillow reads GIF87a and GIF89a versions of the GIF file format. The library writes run-length encoded files in GIF87a by default, unless GIF89a features are used or GIF89a is already in use. -Note that GIF files are always read as grayscale (``L``) -or palette mode (``P``) images. +GIF files are initially read as grayscale (``L``) or palette mode (``P``) +images, but seeking to later frames in an image will change the mode to either +``RGB`` or ``RGBA``, depending on whether the first frame had transparency. The :py:meth:`~PIL.Image.open` method sets the following :py:attr:`~PIL.Image.Image.info` properties: