emoji-upload: Fix transparency issues on GIF emoji upload.

This preserves the alpha layer on GIF images that need to be resized
before being uploaded.  Two important changes occur here:

1. The new frame is a *copy* of the original image, which preserves the
   GIF info.
2. The disposal method of the original GIF is preserved.  This
   essentially determines what state each frame of the GIF starts from
   when it is drawn; see PIL's docs:
   https://pillow.readthedocs.io/en/stable/handbook/image-file-formats.html#saving
   for more info.

This resolves some but not all of the test cases in #16370.
This commit is contained in:
Cody Piersall 2020-10-01 21:11:07 -05:00 committed by Tim Abbott
parent b7a94be152
commit 5dab6e9d31

View File

@ -153,19 +153,22 @@ def resize_logo(image_data: bytes) -> bytes:
def resize_gif(im: GifImageFile, size: int=DEFAULT_EMOJI_SIZE) -> bytes:
frames = []
duration_info = []
disposals = []
# If 'loop' info is not set then loop for infinite number of times.
loop = im.info.get("loop", 0)
for frame_num in range(0, im.n_frames):
im.seek(frame_num)
new_frame = Image.new("RGBA", im.size)
new_frame = im.copy()
new_frame.paste(im, (0, 0), im.convert("RGBA"))
new_frame = ImageOps.pad(new_frame, (size, size), Image.ANTIALIAS)
frames.append(new_frame)
duration_info.append(im.info['duration'])
disposals.append(im.disposal_method)
out = io.BytesIO()
frames[0].save(out, save_all=True, optimize=True,
frames[0].save(out, save_all=True, optimize=False,
format="GIF", append_images=frames[1:],
duration=duration_info,
disposal=disposals,
loop=loop)
return out.getvalue()