"""Alpha-masked textures for the cottage window box: a row of geraniums and lavender (flowers.png) and trailing ivy hanging over the front (ivy.png). Both 512x256 RGBA, meant for alpha_mode mask. local/hear-venv/Scripts/python.exe flowers_tex.py OUTDIR Claude Opus 5.5 (Tessel), 2026-10-10.""" import math import sys from pathlib import Path import numpy as np from PIL import Image, ImageDraw rng = np.random.default_rng(11) OUT = Path(sys.argv[1] if len(sys.argv) > 1 else ".") W, H = 512, 256 def leaf(d, x, y, ang, size, col): pts = [] for t in np.linspace(0, math.pi * 2, 14): r = size * (0.5 + 0.5 * abs(math.sin(t))) px, py = math.cos(t) * r, math.sin(t) * r * 0.55 ca, sa = math.cos(ang), math.sin(ang) pts.append((x + px * ca - py * sa, y + px * sa + py * ca)) d.polygon(pts, fill=col) def flowers(): img = Image.new("RGBA", (W, H), (0, 0, 0, 0)) d = ImageDraw.Draw(img) greens = [(46, 96, 44, 255), (60, 116, 52, 255), (38, 80, 40, 255)] x = 8 while x < W - 8: kind = rng.choice(["geranium", "geranium", "lavender", "white"]) top = int(rng.uniform(70, 120)) # foliage mound for _ in range(28): leaf(d, x + rng.uniform(-22, 22), rng.uniform(top + 15, H - 4), rng.uniform(0, math.pi), rng.uniform(12, 20), tuple(greens[int(rng.integers(3))])) if kind == "lavender": for _ in range(6): sx = x + rng.uniform(-18, 18) sy = rng.uniform(top, top + 30) d.line([(sx, H - 20), (sx + rng.uniform(-6, 6), sy)], fill=(70, 110, 60, 255), width=2) for k in range(9): yy = sy + k * 4 c = (int(rng.uniform(120, 150)), int(rng.uniform(100, 120)), int(rng.uniform(190, 220)), 255) d.ellipse([sx - 3, yy - 3, sx + 3, yy + 3], fill=c) else: base = (205, 44, 52) if kind == "geranium" else (240, 236, 228) if kind == "geranium" and rng.random() < 0.4: base = (232, 96, 130) for _ in range(3): cx, cy = x + rng.uniform(-14, 14), top + rng.uniform(0, 25) d.line([(cx, cy), (cx + rng.uniform(-4, 4), H - 30)], fill=(60, 100, 50, 255), width=2) for _ in range(22): # a ball of florets a, r = rng.uniform(0, 6.28), rng.uniform(0, 13) px, py = cx + math.cos(a) * r, cy + math.sin(a) * r * 0.8 shade = rng.uniform(0.8, 1.1) c = tuple(int(min(255, v * shade)) for v in base) + (255,) d.ellipse([px - 4, py - 4, px + 4, py + 4], fill=c) x += int(rng.uniform(26, 38)) return img def ivy(): img = Image.new("RGBA", (W, H), (0, 0, 0, 0)) d = ImageDraw.Draw(img) for _ in range(22): x = rng.uniform(0, W) length = rng.uniform(80, H - 10) y = 0.0 while y < length: nx = x + rng.uniform(-6, 6) ny = y + rng.uniform(8, 14) d.line([(x, y), (nx, ny)], fill=(70, 80, 40, 255), width=2) side = 1 if rng.random() < 0.5 else -1 c = (int(rng.uniform(40, 70)), int(rng.uniform(95, 130)), int(rng.uniform(40, 60)), 255) leaf(d, nx + side * 7, ny, rng.uniform(0, math.pi), rng.uniform(6, 10), c) x, y = nx, ny return img OUT.mkdir(parents=True, exist_ok=True) flowers().save(OUT / "flowers.png") ivy().save(OUT / "ivy.png") print(OUT / "flowers.png", OUT / "ivy.png")