Create an animated gif with PIL

With the following example, made modifying the code from this blog, we create the images with some text that is moving trough the image. We just used PIL to do this. Here is the code.

from PIL import Image, ImageDraw, ImageFont

fnt = ImageFont.truetype("arial", 36)
def create_image_with_text(wh, text):
    width, height = wh
    img = Image.new('RGB', (300, 200), "yellow")
    draw = ImageDraw.Draw(img)
    # draw.ellipse takes a 4-tuple (x0, y0, x1, y1) where (x0, y0) is the top-left bound of the box
    # and (x1, y1) is the lower-right bound of the box.
    draw.text((width, height), text, font = fnt, fill="black")
    return img
# Create the frames
frames = []
x, y = 0, 0
for i in range(100):
    new_frame = create_image_with_text((x-100,y), "HELLO")
    frames.append(new_frame)
    x += 4
    y += 1

# Save into a GIF file that loops forever
frames[0].save('moving_text.gif', format='GIF',
               append_images=frames[1:], save_all=True, duration=30, loop=0)


A different kind of animation

This time we tried to make something different, showing one letter at the time without moving around the text.

from PIL import Image, ImageDraw, ImageFont

fnt = ImageFont.truetype("arial", 36)
def create_image_with_text(wh, text):
    global img
    width, height = wh
    img = Image.new('RGB', (300, 100), "yellow")
    draw = ImageDraw.Draw(img)
    # draw.ellipse takes a 4-tuple (x0, y0, x1, y1) where (x0, y0) is the top-left bound of the box
    # and (x1, y1) is the lower-right bound of the box.
    draw.text((width, height), text, font = fnt, fill="black")
    return img

# Create the frames
frames = []
x, y = 0, 0
string = "HELLO FOLKS..."
string2 = "A BIG HUG  "

for i in range(len(string)):
    new_frame = create_image_with_text((x,y), string[:i])
    frames.append(new_frame)
for i in range(len(string)):
    new_frame = create_image_with_text((x,y+60), string2[:i])
    frames.append(new_frame)

# Save into a GIF file that loops forever
frames[0].save('progressive_text.gif', format='GIF',
               append_images=frames[1:], save_all=True, duration=100, loop=0)

This was the output

A further abstraction to make banner alike animated gif

This time we made a little more of abstraction to make more easy to add more text to the animation.

from PIL import Image, ImageDraw, ImageFont

def create_image_with_text(size, text):
    img = Image.new('RGB', (600, 50), "yellow")
    draw = ImageDraw.Draw(img)
    draw.text((size[0], size[1]), text, font = fnt, fill="black")
    return img

frames = []

def roll(text):
    for i in range(len(text)+1):
        new_frame = create_image_with_text((0,0), text[:i])
        frames.append(new_frame)
# <<< ========== Customize font and text below ============== >>>>
fnt = ImageFont.truetype("arial", 36)
all_text = """ Pythonprogramming
Brought you this code
This text was made
with PIL and Python""".splitlines()
[roll(text) for text in all_text]
# <<< ======================================================== >>>
frames[0].save('banner1.gif', format='GIF',
               append_images=frames[1:], save_all=True, duration=80, loop=0)

The resulting output is showed in the following animated gif below:

Experimenting with color changes

This time we want to make some changes in the colors. This is a bit experimental, so I guess you should try by yourself the effect that is more suitable for your changing the parameters accordingly. This are the changes in the function create_image_with_text that were made.

c = 0
inc = 10
def create_image_with_text(size, text):
    global c, inc
    img = Image.new('RGB', (350, 50), (255-(c-9),255-(c-9),255-(c-9)))
    draw = ImageDraw.Draw(img)
    draw.text((size[0], size[1]), text, font = fnt, fill=(c,c,c))
    c += inc
        
    return img

And this are the changes in the other function roll.

def roll(text):
    global c
    for i in range(len(text)+1):
        new_frame = create_image_with_text((0,0),
        text[:i]) frames.append(new_frame)
    c = 0

The resultig output of the code above generated this animated gif file that you can see below this text:

This is the whole code of the script to make the animated gif above.

from PIL import Image, ImageDraw, ImageFont

c = 0
inc = 10
def create_image_with_text(size, text):
    global c, inc
    img = Image.new('RGB', (350, 50), (255-(c-9),255-(c-9),255-(c-9)))
    draw = ImageDraw.Draw(img)
    draw.text((size[0], size[1]), text, font = fnt, fill=(c,c,c))
    c += inc
        
    return img

# Create the frames
frames = []

def roll(text):
    global c
    for i in range(len(text)+1):
        new_frame = create_image_with_text((0,0), text[:i])
        frames.append(new_frame)
    c = 0

fnt = ImageFont.truetype("arial", 36)
all_text = """ Pythonprogramming
Brought you this code
.................
Hi folks 
This text was made
with PIL and Python
Great Job """.splitlines()
[roll(text) for text in all_text]


# Save into a GIF file that loops forever
frames[0].save('banner_c.gif', format='GIF',
               append_images=frames[1:], save_all=True, duration=80, loop=0)
print("Done")

The next step could be a GUI to create the gif, with the chance to add the text and adjust the parameters like font size, colors etc.

Show the text over an existing Image

Now we want to take this to the next level, adding the animated text on top of an existing image, any image. This is what we change in the code above:

def create_image_with_text(size, text):
    global c, inc
    img = Image.open("blended.png")
    w,h = img.size
    draw = ImageDraw.Draw(img)
    draw.text((w // 5, h // 2), text, font = fnt, fill=(c,c,c))
    c += inc
    return img

This is the result

This is the entire code

from PIL import Image, ImageDraw, ImageFont

c = 0
inc = 10
def create_image_with_text(size, text):
    global c, inc
    img = Image.open("blended.png")
    w,h = img.size
    draw = ImageDraw.Draw(img)
    draw.text((w // 5, h // 2), text, font = fnt, fill=(c,c,c))
    c += inc
    return img

# Create the frames
frames = []

def roll(text):
    global c
    for i in range(len(text)+1):
        new_frame = create_image_with_text((0,0), text[:i])
        frames.append(new_frame)
    c = 0

fnt = ImageFont.truetype("arial", 36)
all_text = """ Pythonprogramming
Brought you this code
.................
Hi folks 
This text was made
with PIL and Python
Great Job """.splitlines()
for text in all_text:
    roll(text)


# Save into a GIF file that loops forever
frames[0].save('background2.gif', format='GIF',
               append_images=frames[1:], save_all=True, duration=80, loop=0)
print("Done")

Using some png files to create an animated gif

This time we do not create the different frames adding a text ‘in progress’ in the following frame, but we get existing png files, so that we can do animate anything that could be pictures, drawings. In the following example we have always text showed, but it could be any image.

from PIL import Image
import glob

# Create the frames
frames = []
imgs = glob.glob("*.png")
for i in imgs:
    new_frame = Image.open(i)
    frames.append(new_frame)

# Save into a GIF file that loops forever
frames[0].save('png_to_gif.gif', format='GIF',
               append_images=frames[1:],
               save_all=True,
               duration=300, loop=0)
from IPython.display import HTML
HTML("<img src='png_to_gif.gif'>")

In this case we cannot change the colors on the fly, but we can do other cool stuff. If you want to do this without creating the single images, use the code of the previous paragraph.

How to make the png files to create an animated gif: an example

Here is the gif made with the example of the code and the video above.

Published by pythonprogramming

Started with basic on the spectrum, loved javascript in the 90ies and python in the 2000, now I am back with python, still making some javascript stuff when needed.