Project 13: GIF Animation Studio 🎬¶
Difficulty: 🟡 Intermediate
Run cells top to bottom. Each step builds on the previous one and saves real files under outputs/gif_animation_studio/.
Description¶
Build a frame-by-frame animated GIF — understand timing, loops, and image sequences.
Libraries & Modules¶
PIL.Image,ImageDraw- Built-in:
math
Python Concepts You'll Practice¶
Loops, frame lists, image compositing, animation timing
🎛️ Parameter Variations¶
FRAMES— 20 vs 60 (smoothness)SIZE— 200 vs 500 pxDURATION_MS— milliseconds per frame (50 = fast, 200 = slow)ANIMATION—'pulse','orbit','rainbow'
In [1]:
# Install dependencies for this project (safe to re-run)
import sys
!{sys.executable} -m pip install pillow numpy matplotlib wordcloud qrcode[pil] python-barcode fpdf2 jinja2 folium plotly pandas scipy ipywidgets -q
Skipping pip install (already installed)
In [2]:
# Interactive Jupyter setup — run this cell first
%matplotlib inline
from pathlib import Path
from IPython.display import display, Image as IPImage, HTML, Markdown, Audio, IFrame
OUTPUT_DIR = Path("outputs") / "gif_animation_studio"
OUTPUT_DIR.mkdir(parents=True, exist_ok=True)
print(f"✅ Outputs folder: {OUTPUT_DIR.resolve()}")
✅ Outputs folder: C:\Users\Hansel Yan\Projects\CodeItAll\outputs\gif_animation_studio
Step 1 — Generate animation frames¶
In [3]:
from PIL import Image, ImageDraw
import math
# 🎛️ TWEAK THESE
FRAMES = 30
SIZE = 300
DURATION_MS = 80
ANIMATION = "orbit" # "orbit" | "pulse" | "rainbow"
LOOP = 0 # 0 = infinite loop
frames = []
for i in range(FRAMES):
img = Image.new("RGB", (SIZE, SIZE), (15, 15, 35))
draw = ImageDraw.Draw(img)
t = i / FRAMES * 2 * math.pi
if ANIMATION == "orbit":
cx = SIZE // 2 + int(80 * math.cos(t))
cy = SIZE // 2 + int(80 * math.sin(t))
r = 40
color = (int(128 + 127 * math.sin(t)), 100, int(128 + 127 * math.cos(t)))
elif ANIMATION == "pulse":
cx, cy = SIZE // 2, SIZE // 2
r = int(30 + 25 * math.sin(t * 2))
color = (255, int(100 + 100 * math.sin(t)), 80)
else: # rainbow
cx, cy = SIZE // 2, SIZE // 2
r = 50
hue = int(i / FRAMES * 255)
color = ((hue * 3) % 256, (hue * 5) % 256, (hue * 7) % 256)
draw.ellipse([cx - r, cy - r, cx + r, cy + r], fill=color)
frames.append(img)
print(f"Generated {len(frames)} frames for '{ANIMATION}' animation")
Generated 30 frames for 'orbit' animation
Step 2 — Save animated GIF¶
In [4]:
out = OUTPUT_DIR / f"animation_{ANIMATION}.gif"
frames[0].save(
out,
save_all=True,
append_images=frames[1:],
duration=DURATION_MS,
loop=LOOP,
)
print(f"Saved GIF: {out}")
frames[0] # first frame preview
Saved GIF: outputs\gif_animation_studio\animation_orbit.gif
Out[4]: