# Generates the PWA icons in public/icons and the catalog icon in .kody/icon.png. # A calm mark: a softly lit arched frame on a dark background. Needs Pillow. from PIL import Image, ImageDraw, ImageFilter BG = (16, 17, 22) GOLD = (214, 182, 120) LIGHT = (255, 236, 196) def draw(size, maskable): s = size * 4 img = Image.new('RGBA', (s, s), BG + (255,)) pad = s * (0.24 if maskable else 0.16) w = s - 2 * pad arch_w = w * 0.62 arch_h = w * 0.86 left = (s - arch_w) / 2 top = (s - arch_h) / 2 r = arch_w / 2 glow = Image.new('RGBA', (s, s), (0, 0, 0, 0)) g = ImageDraw.Draw(glow) g.ellipse([s / 2 - r * 0.9, top + r * 0.2, s / 2 + r * 0.9, top + r * 2.0], fill=LIGHT + (150,)) glow = glow.filter(ImageFilter.GaussianBlur(s * 0.06)) img.alpha_composite(glow) d = ImageDraw.Draw(img) line = max(2, int(s * 0.022)) d.arc([left, top, left + arch_w, top + arch_w], 180, 360, fill=GOLD, width=line) d.line([left + line / 2, top + r, left + line / 2, top + arch_h], fill=GOLD, width=line) d.line([left + arch_w - line / 2, top + r, left + arch_w - line / 2, top + arch_h], fill=GOLD, width=line) d.line([left, top + arch_h - line / 2, left + arch_w, top + arch_h - line / 2], fill=GOLD, width=line) img = img.resize((size, size), Image.LANCZOS) if not maskable: mask = Image.new('L', (size, size), 0) ImageDraw.Draw(mask).rounded_rectangle([0, 0, size - 1, size - 1], radius=int(size * 0.2), fill=255) img.putalpha(mask) return img for size in (192, 512): draw(size, False).save(f'public/icons/icon-{size}.png', optimize=True) draw(size, True).save(f'public/icons/maskable-{size}.png', optimize=True) draw(512, False).save('.kody/icon.png', optimize=True)