Merge pull request #6128 from radarhere/gif_rgba

This commit is contained in:
Hugo van Kemenade 2022-03-23 18:36:03 +02:00 committed by GitHub
commit e5ce1c8c57
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 26 additions and 23 deletions

View File

@ -842,6 +842,17 @@ def test_rgb_transparency(tmp_path):
assert "transparency" not in reloaded.info assert "transparency" not in reloaded.info
def test_rgba_transparency(tmp_path):
out = str(tmp_path / "temp.gif")
im = hopper("P")
im.save(out, save_all=True, append_images=[Image.new("RGBA", im.size)])
with Image.open(out) as reloaded:
reloaded.seek(1)
assert_image_equal(hopper("P").convert("RGB"), reloaded)
def test_bbox(tmp_path): def test_bbox(tmp_path):
out = str(tmp_path / "temp.gif") out = str(tmp_path / "temp.gif")

View File

@ -424,7 +424,7 @@ class GifImageFile(ImageFile.ImageFile):
RAWMODE = {"1": "L", "L": "L", "P": "P"} RAWMODE = {"1": "L", "L": "L", "P": "P"}
def _normalize_mode(im, initial_call=False): def _normalize_mode(im):
""" """
Takes an image (or frame), returns an image in a mode that is appropriate Takes an image (or frame), returns an image in a mode that is appropriate
for saving in a Gif. for saving in a Gif.
@ -432,31 +432,20 @@ def _normalize_mode(im, initial_call=False):
It may return the original image, or it may return an image converted to It may return the original image, or it may return an image converted to
palette or 'L' mode. palette or 'L' mode.
UNDONE: What is the point of mucking with the initial call palette, for
an image that shouldn't have a palette, or it would be a mode 'P' and
get returned in the RAWMODE clause.
:param im: Image object :param im: Image object
:param initial_call: Default false, set to true for a single frame.
:returns: Image object :returns: Image object
""" """
if im.mode in RAWMODE: if im.mode in RAWMODE:
im.load() im.load()
return im return im
if Image.getmodebase(im.mode) == "RGB": if Image.getmodebase(im.mode) == "RGB":
if initial_call: im = im.convert("P", palette=Image.Palette.ADAPTIVE)
palette_size = 256 if im.palette.mode == "RGBA":
if im.palette: for rgba in im.palette.colors.keys():
palette_size = len(im.palette.getdata()[1]) // 3 if rgba[3] == 0:
im = im.convert("P", palette=Image.Palette.ADAPTIVE, colors=palette_size) im.info["transparency"] = im.palette.colors[rgba]
if im.palette.mode == "RGBA": break
for rgba in im.palette.colors.keys(): return im
if rgba[3] == 0:
im.info["transparency"] = im.palette.colors[rgba]
break
return im
else:
return im.convert("P")
return im.convert("L") return im.convert("L")
@ -514,7 +503,7 @@ def _normalize_palette(im, palette, info):
def _write_single_frame(im, fp, palette): def _write_single_frame(im, fp, palette):
im_out = _normalize_mode(im, True) im_out = _normalize_mode(im)
for k, v in im_out.info.items(): for k, v in im_out.info.items():
im.encoderinfo.setdefault(k, v) im.encoderinfo.setdefault(k, v)
im_out = _normalize_palette(im_out, palette, im.encoderinfo) im_out = _normalize_palette(im_out, palette, im.encoderinfo)
@ -646,11 +635,14 @@ def get_interlace(im):
def _write_local_header(fp, im, offset, flags): def _write_local_header(fp, im, offset, flags):
transparent_color_exists = False transparent_color_exists = False
try: try:
transparency = im.encoderinfo["transparency"] if "transparency" in im.encoderinfo:
except KeyError: transparency = im.encoderinfo["transparency"]
else:
transparency = im.info["transparency"]
transparency = int(transparency)
except (KeyError, ValueError):
pass pass
else: else:
transparency = int(transparency)
# optimize the block away if transparent color is not used # optimize the block away if transparent color is not used
transparent_color_exists = True transparent_color_exists = True