# Generates the PWA PNG icons and src/icons.ts (base64). Run: python3 scripts/make-icons.py import base64, io from PIL import Image, ImageDraw BG = (20, 22, 28) WHITE = (247, 246, 242) LINE = (201, 198, 189) BLACK = (27, 28, 32) GOLD = (242, 181, 68) def draw(size, maskable): s = 4 # supersample W = size * s img = Image.new('RGB', (W, W), BG) d = ImageDraw.Draw(img) if not maskable: # transparent corners for the "any" icon img = Image.new('RGBA', (W, W), (0, 0, 0, 0)) d = ImageDraw.Draw(img) d.rounded_rectangle([0, 0, W - 1, W - 1], radius=int(W * 0.21), fill=BG) art = 0.58 if maskable else 0.72 # maskable keeps art inside the safe zone kw = W * art kh = kw * 0.76 x0 = (W - kw) / 2 y0 = (W - kh) / 2 d.rounded_rectangle([x0, y0, x0 + kw, y0 + kh], radius=int(kw * 0.09), fill=WHITE) step = kw / 4 for i in range(1, 4): x = x0 + step * i d.line([x, y0, x, y0 + kh], fill=LINE, width=max(2, int(W * 0.012))) bw = step * 0.7 bh = kh * 0.58 for i, color in ((1, BLACK), (2, GOLD), (3, BLACK)): cx = x0 + step * i d.rounded_rectangle([cx - bw / 2, y0, cx + bw / 2, y0 + bh], radius=int(bw * 0.18), fill=color) return img.resize((size, size), Image.LANCZOS) out = {} for name, size, maskable in ( ('icon-192.png', 192, False), ('icon-512.png', 512, False), ('maskable-192.png', 192, True), ('maskable-512.png', 512, True), ): buf = io.BytesIO() draw(size, maskable).save(buf, 'PNG', optimize=True) out[name] = base64.b64encode(buf.getvalue()).decode() open('/tmp/' + name, 'wb').write(buf.getvalue()) with open('src/icons.ts', 'w') as f: f.write('// Generated by scripts/make-icons.py. Do not edit by hand.\n') f.write('export const PNG_ICONS: Record = {\n') for name, b64 in out.items(): f.write("\t'%s': '%s',\n" % (name, b64)) f.write('}\n') print({k: len(v) for k, v in out.items()})