jupyter-widgets / ipywidgets

Interactive Widgets for the Jupyter Notebook
https://ipywidgets.readthedocs.io
BSD 3-Clause "New" or "Revised" License
3.16k stars 950 forks source link

GIF with transparency loaded in `Output` are static #3632

Open jfthuong opened 1 year ago

jfthuong commented 1 year ago

Description

When displaying a gif with display(Image(gif_path)), a gif can be displayed properly and is animated.

However putting this code in a with out block (with out being an Output, the GIF becomes static).

Reproduce

from pathlib import Path

from ipywidgets import Output
from IPython.display import display, Image as IPythonImage
from PIL import Image

def make_gif(gif_path: Path, img_dir: Path):
    """Make a gif from the screenshots"""
    frames = [Image.open(image) for image in img_dir.glob("*.png")]
    frame_one = frames[0]
    frame_one.save(
        gif_path,
        format="GIF",
        append_images=frames[1:],
        # optimize = False,
        save_all=True,
        duration=500,
        loop=10,
    )

out = Output()
display(out)

gif_path = Path("my_image.gif")
make_gif(gif_path, Path("png_images")
gif = IPythonImage(filename=gif_path )

with out:
    display(gif)

display(gif)

The first GIF is static but the second one is animated.

I was using Jupyter in VS Code.

Expected behavior

Second Gif shall be animated.

Context

jfthuong commented 1 year ago

It's actually not working from this GIF generated by PIL gif_from_PIL

But works with a GIF downloaded from Internet cat

The code I use to generate with PIL is the following:

from pathlib import Path
from PIL import Image

def make_gif(gif_path: Path, img_dir: Path):
    """Make a gif from the screenshots"""
    frames = [Image.open(image) for image in img_dir.glob("*.png")]
    frame_one = frames[0]
    frame_one.save(
        gif_path,
        format="GIF",
        append_images=frames[1:],
        # optimize = False,
        save_all=True,
        duration=500,
        loop=10,
    )

... it will work though if we modify the function to convert images to RGB with:

    frames = [Image.open(image).convert("RGB") for image in img_dir.glob("*.png")]