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/.

← Back to index

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 px
  • DURATION_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]:
No description has been provided for this image

✅ Project complete¶

Check your output folder: outputs/gif_animation_studio/

Next: Project 14: PDF Certificate Maker · Index