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

Background is white instead of being transparent #6162

Closed
hriguich opened this issue Mar 29, 2022 · 3 comments · Fixed by #6176
Closed

Background is white instead of being transparent #6162

hriguich opened this issue Mar 29, 2022 · 3 comments · Fixed by #6176
Labels

Comments

@hriguich
Copy link

hriguich commented Mar 29, 2022

What did you do?

Overlay add png images on a gif file frames

What did you expect to happen?

Get a gif with the pngs added on each layer and a transparent background

What actually happened?

I'm getting the gif as I want it but with a white background

What are your OS, Python and Pillow versions?

  • OS: MacOs 11.6.5
  • Python: python3.7
  • Pillow: 9.1

All the png files have a transparent background and also the gif has a transparent background !

Here is an image from the end result gif (the file is too big i couldn't upload it here):
Screen Shot 2022-03-29 at 13 59 33

from PIL import Image, ImageSequence

background   = Image.open('images/1.png')#.convert('RGBA')
animated_gif = Image.open("images/2.gif")
layer1 = Image.open('images/3.png')
layer2 = Image.open('images/4.png')
all_frames = []


for gif_frame in ImageSequence.Iterator(animated_gif):


    new_frame = background.copy()
    layerr1 = layer1.copy()
    layerr2 = layer2.copy()

    gif_frame = gif_frame.convert('RGBA')
    
    new_frame.paste(layerr2, mask=layerr2)
    new_frame.paste(gif_frame, mask=gif_frame) 
    new_frame.paste(layerr1, mask=layerr1)
    all_frames.append(new_frame)


all_frames[0].save("image2.gif",transparency = 255, background = 255, save_all=True, append_images=all_frames[1:], duration=50, loop=0)

Please help me with this, this is the first time I'm using pillow !

@radarhere
Copy link
Member

Hi. It would be ideal to get a copy of your original files, so that we could exactly replicate your problem.

Otherwise, your problem looks similar to #6115. On April 1, Pillow 9.1.0 is due to be released with the fix for that issue. I suspect that if you wait until then, upgrade your copy of Pillow, and run your code without transparency = 255, your problem will be fixed.

@radarhere radarhere added the GIF label Mar 29, 2022
@hriguich
Copy link
Author

hriguich commented Apr 1, 2022

Hi,
Thank you so much for your reply. I did wait for the new update release to test again but it still doesn't work.
It shows a transparent background in some frames and the others have a background.
I've uploaded the script and the images I used to google drive here: https://drive.google.com/file/d/12zh9ouo5Pk3Tsh6tZ6QWo28QsXqRsoxw/view?usp=sharing

And here is the gif I get when i run the script: https://drive.google.com/file/d/1010FRU3sy3IBMv3E3h1nUHRqzssyy_QN/view?usp=sharing

The files are big, I couldn't upload them here.
You'd do me a big favor if you can help with this issue.
Thank you so much

@radarhere
Copy link
Member

Ok, the problem is that Pillow calculates a different transparency for each frame of your GIF, but then doesn't use those different transparencies when saving. I've created PR #6176 to resolve this.

However, I imagine you would like a fix sooner than the next release of Pillow. So I've put together the following code that saves your image as intended.

from PIL import Image, ImageSequence, GifImagePlugin

# Patch Pillow to set the transparency of all frames to 255 when saving a GIF
original_normalize_mode = GifImagePlugin._normalize_mode
def _normalize_mode(im):
	im = original_normalize_mode(im)
	if "transparency" in im.info:
		dest_map = list(range(256))
		dest_map[im.info["transparency"]] = 255
		dest_map[255] = im.info["transparency"]
		im.info["transparency"] = 255
		im = im.remap_palette(dest_map)
	return im
GifImagePlugin._normalize_mode = _normalize_mode

background   = Image.open('images/1.png').convert('RGBA')
animated_gif = Image.open("images/2.gif")
layer1 = Image.open('images/3.png').convert('RGBA')
layer2 = Image.open('images/4.png').convert('RGBA')
all_frames = []
durations = []

for gif_frame in ImageSequence.Iterator(animated_gif):

    # duplicate background image because we will change it (we will paste 
    new_frame = Image.new('RGBA',gif_frame.size,(0,0,0,0))
    back = background.copy()
    layerr1 = layer1.copy()
    layerr2 = layer2.copy()
    # convert to `RGBA` to use `Alpha` in `paste` as transparency mask
    gif_frame = gif_frame.convert('RGBA')
    new_frame.paste(back, mask=back)
    new_frame.paste(layerr2, mask=layerr2)
    new_frame.paste(gif_frame, mask=gif_frame) 
    new_frame.paste(layerr1, mask=layerr1)
    all_frames.append(new_frame)
    durations.append(gif_frame.info['duration'])

# save first frame and append other frames with duration 100ms 
all_frames[0].save("image2.gif",transparency=255,interlace=True, disposal=0, save_all=True, append_images=all_frames[1:], loop=0, duration=durations)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants