Friday, July 4, 2025

Creating a Universal Flag Generator in Python — Animate Any Country's Flag

In this follow-up to our American and Indian flag animation tutorials, we introduce an exciting new project: a universal flag generator in Python that takes the name of any country as a command-line argument and renders a waving animated version of its flag using official proportions and layouts wherever available.

 Why a Universal Flag Generator?

Flags are powerful symbols of identity, unity, and history. Automating their rendering programmatically not only teaches us geometry and animation, but also reveals how each flag has a unique story encoded in its layout and proportions.

 Standards Followed

  • For official dimensions, we refer to each country's legal or constitutional definitions, where available.
  • Fallback standards include data from Flagspot.net and Wikipedia.
  • Aspect ratios (2:3, 1:2, 3:5, etc.) are respected for each flag.
  • Colors are defined using official hexadecimal codes where available.

 Structure of the Program

  1. Accept a country name via argparse
  2. Lookup predefined metadata: aspect ratio, colors, layout type
  3. Render flag using matplotlib and apply a sine wave for animation
  4. Fallback with a helpful message if the flag is not supported

烙 Supported Flags (Initial Version)

  • India
  • United States
  • France
  • Germany
  • Japan
  • Italy
  • United Kingdom
  • Brazil

 Plans for Expansion

  • UN member states
  • Dynamic SVG imports from Wikimedia
  • Saving to GIF/MP4 formats

 Full Code (Python 3)

import argparse
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.animation as animation

flags = {
    "india": {"colors": ["#FF9933", "white", "#138808"], "ratios": (3, 2), "type": "tricolor_h"},
    "france": {"colors": ["#0055A4", "white", "#EF4135"], "ratios": (3, 2), "type": "tricolor_v"},
    "germany": {"colors": ["#000000", "#DD0000", "#FFCE00"], "ratios": (5, 3), "type": "tricolor_h"},
    "italy": {"colors": ["#008C45", "white", "#CD212A"], "ratios": (2, 3), "type": "tricolor_v"},
    "japan": {"colors": ["white", "#BC002D"], "ratios": (2, 3), "type": "circle"},
    # Add more as needed
}

def draw_flag(country, ax, frame):
    info = flags[country]
    w, h = info["ratios"]
    ax.clear()
    ax.set_xlim(0, w)
    ax.set_ylim(0, h)
    ax.set_aspect('equal')
    ax.axis('off')

    x = np.linspace(0, w, 300)
    wave_offset = frame / 10.0

    if info["type"] == "tricolor_h":
        stripe_h = h / 3
        for i, color in enumerate(info["colors"]):
            y_base = h - (i + 1) * stripe_h
            y_wave = y_base + 0.05 * np.sin(2 * np.pi * x / w + wave_offset + i)
            ax.fill_between(x, y_wave, y_wave + stripe_h, color=color)
    elif info["type"] == "tricolor_v":
        stripe_w = w / 3
        for i, color in enumerate(info["colors"]):
            x_base = i * stripe_w
            x_wave = x_base + 0.02 * np.sin(2 * np.pi * frame / 20.0 + i)
            ax.fill_betweenx(np.linspace(0, h, 200), x_base, x_base + stripe_w, color=color)
    elif info["type"] == "circle":
        ax.fill_between(x, 0, h, color=info["colors"][0])
        cx, cy, r = w/2, h/2, h*3/10
        circle = plt.Circle((cx, cy), r, color=info["colors"][1])
        ax.add_patch(circle)

parser = argparse.ArgumentParser()
parser.add_argument("country", help="Name of country (e.g., india, france, germany)")
args = parser.parse_args()

country = args.country.lower()
if country not in flags:
    print(f"Sorry, '{args.country}' is not yet supported.")
    exit()

fig, ax = plt.subplots(figsize=(9, 6))
ani = animation.FuncAnimation(fig, lambda f: draw_flag(country, ax, f), frames=200, interval=50)
plt.show()

 Conclusion

This script lets you render the waving flag of any supported country simply by running:

python flag_wave.py india

As you expand this dictionary and logic, you can support flags with stars, suns, crescents, crosses, or even heraldic emblems. Flags are geometry with deep cultural meaning — a perfect canvas for code + culture.

Keep coding the world, one flag at a time! 

No comments: