0

I'm trying to display a gif on top of an image. The gif originally has a transparent background. The code below does that, except it created a black background around the original gif that flickers white when the gif resets. If I don't resize the gif then there would still be a white background around the original gif after its merged with the image.

Is there a way to keep the original gif's background transparent when merging?

from PIL import Image


background = Image.open('GrassyField.png').convert("RGBA")
gif = Image.open("1.gif")

foreground_w, foreground_w = gif.size
background_w, background_h = background.size
frames = []

for num in range(gif.n_frames):
    gif.seek(num)
    layer = Image.new('RGBA', (foreground_w, foreground_w), (0, 0, 0, 0)).resize((background_w, 
        background_h))
    layer.paste(background, (0, 0), mask=background)

    layer.paste(gif.resize((100, 100)).convert('RGBA'), (220, 25))

    frames.append(layer)
    frames[0].save('output.gif',
            save_all=True,
            append_images=frames[1:],
            duration=100,loop=0)

1 Answers1

1

Let's say that 1.gif is:

1.gif

and GrassyField.png is:

enter image description here

using this code:

import PIL.Image
import PIL.ImageSequence

with PIL.Image.open('1.gif') as foreground_animation, PIL.Image.open('GrassyField.png') as background_image:
    image_roles = {
        'foreground': foreground_animation, 
        'background': background_image.convert(mode='RGBA')
    }

    def create_frames(images_roles):
        for current_frame in PIL.ImageSequence.Iterator(image_roles['foreground']):
            current_background = image_roles['background'].copy()
            current_foreground = current_frame.convert(mode='RGBA').resize((100, 100))
            current_background.alpha_composite(current_foreground, dest=(220,25))
            yield current_background

    frames = tuple(create_frames(image_roles))
    frames[0].save(
        'output.gif',
        save_all=True,
        append_images=frames[1:],
        duration=100,loop=0
    )

You get output.gif:

enter image description here

Is that what you wanted?

EvensF
  • 1,479
  • 1
  • 10
  • 17
  • Yes! This is actually what I was trying to do, thanks a lot. – AdvancedFee Feb 17 '22 at 17:56
  • @AdvancedFee would you please give me an advice in modifying your code so that you can give a GIF with a white background and the output is just like yours? So basically remove the GIF's white background somehow and then overlap it on the background image. – Valentin Popescu Mar 27 '22 at 17:36
  • @ValentinPopescu: I think you should ask a separate question describing your situation. – EvensF Mar 28 '22 at 22:38
  • @AdvancedFee I managed to do the task with a little bit more processing: I wrote a script that extracted every frame from a GIF then write it on the disk; I would then apply this script https://stackoverflow.com/a/63003020/12339258 on each individual image to remove their white background; I would then apply this script https://stackoverflow.com/a/51219787/12339258 to generate a new GIF with transparent background; finally, I would give it as input to your script and that's basically it. Hope this helps somebody out! – Valentin Popescu Mar 29 '22 at 10:33