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

If first GIF frame has transparency for RGB_ALWAYS loading strategy, use RGBA mode #6592

Merged
merged 1 commit into from Oct 12, 2022
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
17 changes: 12 additions & 5 deletions Tests/test_file_gif.py
Expand Up @@ -84,17 +84,24 @@ def test_l_mode_transparency():


def test_strategy():
with Image.open("Tests/images/iss634.gif") as im:
expected_rgb_always = im.convert("RGB")

with Image.open("Tests/images/chi.gif") as im:
expected_zero = im.convert("RGB")
expected_rgb_always_rgba = im.convert("RGBA")

im.seek(1)
expected_one = im.convert("RGB")
expected_different = im.convert("RGB")

try:
GifImagePlugin.LOADING_STRATEGY = GifImagePlugin.LoadingStrategy.RGB_ALWAYS
with Image.open("Tests/images/chi.gif") as im:
with Image.open("Tests/images/iss634.gif") as im:
assert im.mode == "RGB"
assert_image_equal(im, expected_zero)
assert_image_equal(im, expected_rgb_always)

with Image.open("Tests/images/chi.gif") as im:
assert im.mode == "RGBA"
assert_image_equal(im, expected_rgb_always_rgba)

GifImagePlugin.LOADING_STRATEGY = (
GifImagePlugin.LoadingStrategy.RGB_AFTER_DIFFERENT_PALETTE_ONLY
Expand All @@ -105,7 +112,7 @@ def test_strategy():

im.seek(1)
assert im.mode == "P"
assert_image_equal(im.convert("RGB"), expected_one)
assert_image_equal(im.convert("RGB"), expected_different)

# Change to RGB mode when a frame has an individual palette
with Image.open("Tests/images/iss634.gif") as im:
Expand Down
24 changes: 15 additions & 9 deletions src/PIL/GifImagePlugin.py
Expand Up @@ -299,11 +299,13 @@ def _seek(self, frame, update_image=True):
self.im.paste(self.dispose, self.dispose_extent)

self._frame_palette = palette or self.global_palette
self._frame_transparency = frame_transparency
if frame == 0:
if self._frame_palette:
self.mode = (
"RGB" if LOADING_STRATEGY == LoadingStrategy.RGB_ALWAYS else "P"
)
if LOADING_STRATEGY == LoadingStrategy.RGB_ALWAYS:
self.mode = "RGBA" if frame_transparency is not None else "RGB"
else:
self.mode = "P"
else:
self.mode = "L"

Expand All @@ -313,7 +315,6 @@ def _seek(self, frame, update_image=True):
palette = copy(self.global_palette)
self.palette = palette
else:
self._frame_transparency = frame_transparency
if self.mode == "P":
if (
LOADING_STRATEGY != LoadingStrategy.RGB_AFTER_DIFFERENT_PALETTE_ONLY
Expand Down Expand Up @@ -386,7 +387,8 @@ def _rgb(color):
transparency = -1
if frame_transparency is not None:
if frame == 0:
self.info["transparency"] = frame_transparency
if LOADING_STRATEGY != LoadingStrategy.RGB_ALWAYS:
self.info["transparency"] = frame_transparency
elif self.mode not in ("RGB", "RGBA"):
transparency = frame_transparency
self.tile = [
Expand All @@ -410,9 +412,9 @@ def load_prepare(self):
temp_mode = "P" if self._frame_palette else "L"
self._prev_im = None
if self.__frame == 0:
if "transparency" in self.info:
if self._frame_transparency is not None:
self.im = Image.core.fill(
temp_mode, self.size, self.info["transparency"]
temp_mode, self.size, self._frame_transparency
)
elif self.mode in ("RGB", "RGBA"):
self._prev_im = self.im
Expand All @@ -429,8 +431,12 @@ def load_prepare(self):
def load_end(self):
if self.__frame == 0:
if self.mode == "P" and LOADING_STRATEGY == LoadingStrategy.RGB_ALWAYS:
self.mode = "RGB"
self.im = self.im.convert("RGB", Image.Dither.FLOYDSTEINBERG)
if self._frame_transparency is not None:
self.im.putpalettealpha(self._frame_transparency, 0)
self.mode = "RGBA"
else:
self.mode = "RGB"
self.im = self.im.convert(self.mode, Image.Dither.FLOYDSTEINBERG)
return
if self.mode == "P" and self._prev_im:
if self._frame_transparency is not None:
Expand Down