I’m using Ubuntu 16.04 to play.
Week 1: Making GIFs
It’s not my first attempt at creating moving images. Each time I met with a problem that stopped me in my tracks until I ran out of steam and lost interest. But now two changes brought me success!
First I found out that Pillow 3.4.0 can now save images sequences!
Second I discovered Gizeh, a very nice library written by Zulko. Gizeh is a wrapper for cairocffi, which is a Python binding for Cairo, which is a 2D graphics library written in C… Lots of things to learn!
I did get into some trouble while installing Gizeh. Pip installed a version that was different from what is available on github. I didn’t have access to some elements (ellipse, bezier_curve, more?). To fix this I just replaced the gizeh.py file on my computer with the one from github.
To help with the gif making process I made an image viewer using Pillow and Tkinter. Mixing those two also gave me trouble. For some reason ImageTk was missing and I had to install python-pil.imagetk (thanks to saulspatz). After I managed to get the viewer running it was trivial to make a GIF from my pictures. By the way, do you know about Lena Söderberg?
Once I learened to make GIFs the next step was to learn how to draw my own images. Being lazy I used Gizeh’s square example as a starting point. The idea was to have those squares revolve.
I learned a lot with this little project. Not only about code but also about animation. (Getting a gif to loop perfectly can be tricky)
ps. Don’t forget to read about beautiful Lena
Here’s the code:
import gizeh as gz
import numpy as np
from PIL import Image
SIZE = 400 # dimension of the final picture
fps = 30
frames = 30 # how many frames in the GIF
temp_name = 'frame_' # prefix for temporary png files
temp_files =  # our list of png files
# We generate n_squares random values of size, angle, color, position.
# 'rand' is a function that generates numbers between 0 and 1
n_squares = 100
sizes = 20 + 40 * np.random.rand(n_squares)
angles = 2*np.pi * np.random.rand(n_squares)
colors = np.random.rand(n_squares, 3)
positions = SIZE * np.random.rand(n_squares, 2)
# draw our frames and save temporary files as .png
for frame in range(0,frames):
surface = gz.Surface(SIZE, SIZE, bg_color=(0,0,0))
for angle, size, pos, color in zip(angles, sizes, positions, colors):
angle = (np.pi/frames) * frame / 2 + angle # rotate the square
square = gz.square(size, xy=pos, angle=angle, fill=color,
frame_name = temp_name + str(frame) + '.png'
# build the gif
sequence = 
for file in temp_files:
sequence.append(Image.open(file)) # load png files as Pillow images
sequence.save(name, save_all=True, append_images=sequence[1:],
# clean up our temporary png files
for file in temp_files:
if __name__ == '__main__':