I have the following code that creates 60 frames using pillow in python 3.11.10 and that I want to use to create a gif (repeating endless), with a duration per frame of 0.1 seconds. The first 4 frames should show a red square, and the rest of the time (almost 6 seconds) it should be basically black. However, the created GIF only seems to contain 2 frames, one frame with the red square and one without. How to create the gif properly?
from PIL import Image, ImageDraw
import imageio
import numpy as np
# Colors
red = (255, 0, 0)
black = (0, 0, 0)
grey = (30, 30, 30)
frames = []
framerate = 10
frame_count = 60
for i in range(frame_count):
# Create an image with black background
img = Image.new('RGB', (55, 50), black)
draw = ImageDraw.Draw(img)
# Draw rectangle
draw.rectangle((10, 20, 45, 30), fill=red if i<5 else grey)
# Append frame to the list
frames.append(np.array(img))
# Save frames as a GIF
imageio.mimsave("test.gif", frames, duration=1./framerate, loop=0, plugin='pillow')
Here is the created gif:
Expected behavior: 0.4 seconds showing that red square, then 5.6 seconds showing basically black.
With Grismar's suggestion:
The image gets optimised to have the flickering behaviour, you need to explicitly set the disposal method to completely replace the first frame (as well as applying the fix in the other answer since that's just a mistake):
from PIL import Image, ImageDraw
import imageio
import numpy as np
# Colors
red = (255, 0, 0)
black = (0, 0, 0)
grey = (30, 30, 30)
frames = []
framerate = 10
frame_count = 60
for i in range(frame_count):
# Create an image with black background
img = Image.new('RGB', (55, 50), black)
draw = ImageDraw.Draw(img)
# Draw rectangle
draw.rectangle((10, 20, 45, 30), fill=red if i<5 else grey)
# Append frame to the list
frames.append(img)
# Save frames as a GIF using PIL directly, with the correct disposal method
frames[0].save(
"test.gif",
save_all=True,
append_images=frames[1:],
duration=int(1000 / framerate), # duration in ms per frame
loop=0,
disposal=0 # use the appropriate disposal method here, no transparency
)
See also https://giflib.sourceforge.net/whatsinagif/animation_and_transparency.html