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

GIF degrading after initial frame when import #5837

Closed
tomhaydn opened this issue Nov 16, 2021 · 4 comments · Fixed by #5857
Closed

GIF degrading after initial frame when import #5837

tomhaydn opened this issue Nov 16, 2021 · 4 comments · Fixed by #5857
Labels

Comments

@tomhaydn
Copy link

tomhaydn commented Nov 16, 2021

I'm trying to create a programatic assembler for a variety of animated gifs. I want to do this by grabbing each of the parts (each individually animated) and layering them to create the final GIF. All parts apart from the background have transparency.

from PIL import Image, ImageSequence, GifImagePlugin
import os


bg = Image.open('images/bg/Background Sky.gif')
body = Image.open('images/body/Body Blue.gif')
eyes = Image.open('images/eyes/Eyes Green.gif')
headwear = Image.open('images/headwear/Headwear Party Hat.gif')

frames = []
for idx, frame in enumerate(ImageSequence.Iterator(bg)):
    frame = Image.new('RGBA', (640, 640), color=(255,0,0,0))
    frame.paste(ImageSequence.Iterator(bg)[idx])
    frame.paste(ImageSequence.Iterator(body)[idx], mask=ImageSequence.Iterator(body)[idx].convert("RGBA"))
    frame.paste(ImageSequence.Iterator(eyes)[idx], mask=ImageSequence.Iterator(eyes)[idx].convert("RGBA"))
    frame.paste(ImageSequence.Iterator(headwear)[idx], mask=ImageSequence.Iterator(headwear)[idx].convert("RGBA"))
    
    frames.append(frame)

print(frames)

#frames[0].save('images/generated/output.gif', save_all=True, append_images=frames[0:])
frames[0].save('images/generated/output.gif', save_all=True, append_images=frames[1:], loop=0)

This is the final output:
output

This is the raw background:
Background Sky

I have tried to set the frame to a copy of the frame within the for loop:
frame = frame.copy()

But this fails also.

@radarhere radarhere added the GIF label Nov 16, 2021
@radarhere radarhere changed the title Gif degrading after initial frame when import GIF degrading after initial frame when import Nov 16, 2021
@tomhaydn
Copy link
Author

Upon further investigation, it seems that non-animated parts of the gif are 'removed' on subsequent frames.

@radarhere
Copy link
Member

You've provided "Background Sky.gif". Would you also be able to provide "Body Blue.gif", "Eyes Green.gif" and "Headwear Party Hat.gif"?
I realise they are probably not the core of the problem, but it would just be helpful to be able to easily run your sample code.

@tomhaydn
Copy link
Author

tomhaydn commented Nov 17, 2021

Let's simplify it...

from PIL import Image, ImageSequence, GifImagePlugin

bg = Image.open('images/bg/Background Sky.gif')

frames = []
for idx, frame in enumerate(ImageSequence.Iterator(bg)):
    frame = Image.new('RGBA', (640, 640), color=(255,0,0,0))
    frame.paste(ImageSequence.Iterator(bg)[idx])
    
    frames.append(frame)

print(frames)

frames[0].save('images/generated/output.gif', save_all=True, append_images=frames[1:], loop=0)

The issue occurs on its own. Have tried an array of different ways, including tweaking the disposal. See below saves each frame individually but gives the same result:

from PIL import Image, ImageSequence, GifImagePlugin
import os

bg = Image.open('images/bg/Background Starry Night.gif')

print(bg.info)
print(bg.palette)
print(bg.mode)
print(bg.format)
print(bg.load())

print(bg.n_frames)
bg.convert('RGBA')
bg.save('images/generated/outputmain.gif', format='GIF', save_all=True, disposal=2)
for idx in range(bg.n_frames):
    bg.seek(idx)
    bg.save('images/generated/output'+ str(idx) +'.png', disposal=2, optimize=False, interlace=False, include_color_table=True)

@radarhere
Copy link
Member

I've created PR #5857 to resolve this.

With it,

from PIL import Image, ImageSequence, GifImagePlugin

bg = Image.open('images/bg/Background Sky.gif')

frames = []
for idx, frame in enumerate(ImageSequence.Iterator(bg)):
    frame = Image.new('RGBA', (640, 640), color=(255,0,0,0))
    frame.paste(ImageSequence.Iterator(bg)[idx])
    
    frames.append(frame)

print(frames)

frames[0].save('images/generated/output.gif', save_all=True, append_images=frames[1:], loop=0)

now gives

output

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