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

"Noise" in the background of GIF animations #4263

Closed
jiannmeng opened this issue Dec 10, 2019 · 6 comments
Closed

"Noise" in the background of GIF animations #4263

jiannmeng opened this issue Dec 10, 2019 · 6 comments
Labels

Comments

@jiannmeng
Copy link

jiannmeng commented Dec 10, 2019

What did you do?

Saved an animated GIF with a plain background and an incrementing integer in the middle.

What did you expect to happen?

The output should look like this (the "good" gif):
good

What actually happened?

The output looks like this (the "bad" gif):
bad
Notice the background is full of noise, and the noise at the bottom right changes every frame.

What are your OS, Python and Pillow versions?

  • OS: Windows 10
  • Python: 3.7
  • Pillow: 6.2.1
from PIL import Image, ImageDraw, ImageFont
from io import BytesIO

save_kwargs = {
    "format": "GIF",
    "save_all": True,
    "duration": 100,
    "loop": False,
}

font = ImageFont.truetype(font="arial", size=36)
frames = []
for i in range(0, 20):
    frame = Image.new("RGB", (200, 200), color="#FFAD94")
    draw = ImageDraw.Draw(frame)
    draw.text((90, 90), str(i), font=font)
    frames.append(frame)

# Bad - Save the Image objects directly to an animated GIF.
frames[0].save("bad.gif", append_images=frames[1:], **save_kwargs)

# Good - Save each Image object as a static GIF, then stitch the GIFs together
# to form the animated GIF.
byteframes = []
for f in frames:
    byte = BytesIO()
    byteframes.append(byte)
    f.save(byte, format="GIF")
imgs = [Image.open(byteframe) for byteframe in byteframes]
imgs[0].save("good.gif", append_images=imgs[1:], **save_kwargs)
@jiannmeng jiannmeng reopened this Dec 10, 2019
@radarhere radarhere added the GIF label Dec 10, 2019
@radarhere
Copy link
Member

By changing the mode of the image to P, I find that the following code works -

from PIL import Image, ImageDraw, ImageFont
from io import BytesIO

save_kwargs = {
    "format": "GIF",
    "save_all": True,
    "duration": 100,
    "loop": False,
}

font = ImageFont.truetype(font="/System/Library/Fonts/Supplemental/Arial.ttf", size=36)
frames = []
for i in range(0, 20):
    frame = Image.new("P", (200, 200), color="#FFAD94")
    draw = ImageDraw.Draw(frame)
    draw.text((90, 90), str(i), "#fff", font=font)
    frames.append(frame)

frames[0].save("bad.gif", append_images=frames[1:], **save_kwargs)

@jiannmeng
Copy link
Author

Thanks @radarhere , changing "RGB" to "P" works perfectly - and was about 10x faster than "RGB" mode!

@radarhere
Copy link
Member

Does that resolve this issue for you then?

@jiannmeng
Copy link
Author

Yes, thank you!

@vikky1992
Copy link

If we are not creating the image by Image.new() method and we are reading an existing .png image, how can we set the mode parameter?

@radarhere
Copy link
Member

To change an image from one mode to another, use the convert method - https://pillow.readthedocs.io/en/latest/reference/Image.html#PIL.Image.Image.convert

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

No branches or pull requests

3 participants