Keep subsequent L frames without transparency as L

This commit is contained in:
Andrew Murray 2022-03-20 15:09:01 +11:00
parent a6a843e548
commit 7928e944cb
4 changed files with 30 additions and 17 deletions

BIN
Tests/images/no_palette.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 48 B

View File

@ -59,7 +59,15 @@ def test_invalid_file():
GifImagePlugin.GifImageFile(invalid_file) GifImagePlugin.GifImageFile(invalid_file)
def test_l_mode_transparency(): def test_l_mode_subsequent_frames():
with Image.open("Tests/images/no_palette.gif") as im:
assert im.mode == "L"
assert im.load()[0, 0] == 0
im.seek(1)
assert im.mode == "L"
assert im.load()[0, 0] == 0
with Image.open("Tests/images/no_palette_with_transparency.gif") as im: with Image.open("Tests/images/no_palette_with_transparency.gif") as im:
assert im.mode == "L" assert im.mode == "L"
assert im.load()[0, 0] == 0 assert im.load()[0, 0] == 0

View File

@ -106,8 +106,9 @@ writes run-length encoded files in GIF87a by default, unless GIF89a features
are used or GIF89a is already in use. are used or GIF89a is already in use.
GIF files are initially read as grayscale (``L``) or palette mode (``P``) 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 images. Seeking to later frames in a ``P`` image will change the image to
``RGB`` or ``RGBA``, depending on whether the first frame had transparency. ``RGB`` (or ``RGBA`` if the first frame had transparency). ``L`` images will
stay in ``L`` mode (or change to ``LA`` if the first frame had transparency).
The :py:meth:`~PIL.Image.open` method sets the following The :py:meth:`~PIL.Image.open` method sets the following
:py:attr:`~PIL.Image.Image.info` properties: :py:attr:`~PIL.Image.Image.info` properties:

View File

@ -174,21 +174,22 @@ class GifImageFile(ImageFile.ImageFile):
if update_image: if update_image:
if self.__frame == 1: if self.__frame == 1:
self.pyaccess = None self.pyaccess = None
if "transparency" in self.info: if self.mode == "P":
if self.mode == "P": if "transparency" in self.info:
self.im.putpalettealpha(self.info["transparency"], 0) self.im.putpalettealpha(self.info["transparency"], 0)
self.im = self.im.convert("RGBA", Image.Dither.FLOYDSTEINBERG) self.im = self.im.convert("RGBA", Image.Dither.FLOYDSTEINBERG)
self.mode = "RGBA" self.mode = "RGBA"
del self.info["transparency"]
else: else:
self.im = self.im.convert_transparent( self.mode = "RGB"
"LA", self.info["transparency"] self.im = self.im.convert("RGB", Image.Dither.FLOYDSTEINBERG)
) elif "transparency" in self.info:
self.mode = "LA" self.im = self.im.convert_transparent(
"LA", self.info["transparency"]
)
self.mode = "LA"
del self.info["transparency"] del self.info["transparency"]
else:
self.mode = "RGB"
self.im = self.im.convert("RGB", Image.Dither.FLOYDSTEINBERG)
if self.dispose: if self.dispose:
self.im.paste(self.dispose, self.dispose_extent) self.im.paste(self.dispose, self.dispose_extent)
@ -387,14 +388,17 @@ class GifImageFile(ImageFile.ImageFile):
def load_end(self): def load_end(self):
if self.__frame == 0: if self.__frame == 0:
return return
if self._frame_transparency is not None: if self.mode == "P":
if self.mode == "P": if self._frame_transparency is not None:
self.im.putpalettealpha(self._frame_transparency, 0) self.im.putpalettealpha(self._frame_transparency, 0)
frame_im = self.im.convert("RGBA") frame_im = self.im.convert("RGBA")
else: else:
frame_im = self.im.convert_transparent("LA", self._frame_transparency) frame_im = self.im.convert("RGB")
else: else:
frame_im = self.im.convert("RGB") if self._frame_transparency is not None:
frame_im = self.im.convert_transparent("LA", self._frame_transparency)
else:
frame_im = self.im
frame_im = self._crop(frame_im, self.dispose_extent) frame_im = self._crop(frame_im, self.dispose_extent)
self.im = self._prev_im self.im = self._prev_im