I was working on a personal project the other day and I needed to create some images (frames) and save them as a playable GIF. Working in Python, I excepted to find an easy solution fast but oh boy did it take me too long to find it.
Here I am now, creating a blog post to help future people looking to create gifs in Python.
The code used in this post is available here.
What are GIFs
The **Graphics Interchange Format **is a bitmap image format that was developed in 1987.
A GIF is basically a series of images that have different settings such as:
- Looping
- Duration per frame (image)
- Others…
A GIF can also be a static image.
What is Pillow (PIL Fork)
Python Imaging Library (PIL) is a free library for the Python programming language that adds support for opening, manipulating, and saving many different image file formats.
On the other hand, Pillow is a fork of the PIL library introducing many changes and enhancements, whether to make the API easier to use or to handle more image formats and requirements.
N.B: PIL and Pillow cannot co-exist, you can only install/use one or the other.
Creating GIFs in Python
Installing Pillow
You can easily install Pillow using Pip:
pip install Pillow
Creating GIFs
As an example, I will be creating a GIF where a ball moves down.
At first, we’ll create a method that creates an image and draws a ball on it, this will help us keep things clean.
from PIL import Image, ImageDraw
def create_image_with_ball(width, height, ball_x, ball_y, ball_size):
img = Image.new('RGB', (width, height), (255, 255, 255))
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.ellipse((ball_x, ball_y, ball_x + ball_size, ball_y + ball_size), fill='red')
return img
In the code above, we create a new RGB image using Image.new
that has a certain size and a white background.
We then use ImageDraw
to draw a red ellipse (circle) into our image using the coordinates given in the arguments.
All we have to do now is create multiple images (frames) while moving the ball down:
# Create the frames
frames = []
x, y = 0, 0
for i in range(10):
new_frame = create_image_with_ball(400, 400, x, y, 40)
frames.append(new_frame)
x += 40
y += 40
# Save into a GIF file that loops forever
frames[0].save('moving_ball.gif', format='GIF', append_images=frames[1:], save_all=True, duration=100, loop=0)
Here’s the breakdown of the code above:
- Initialize an empty list
frames
and 0-coordinatesx
andy
. - In a for loop (10 runs), we create a 400×400 image with a ball in our coordiantes.
- Change the coordinates so that the ball moves down (in diagonal, since the Y position changes too).
- Save the first frame with the others using
format='GIF'
andappend_images=frames[1:]
.- Every frame will run for 100ms (
duration=100
). - The GIF image will loop forever (
loop=0
, if loop was set to 1 then it will loop 1 time, 2 = 2 times, etc…).
- Every frame will run for 100ms (
Our magnificent moving ball looks like this:
I hope this can help anyone looking for a way to handle images and create GIFs!