import { PNG } from "pngjs"; import fs from "node:fs"; function icon(size: number, out: string, pad = 0.12) { const png = new PNG({ width: size, height: size }); const r = size * 0.24; const x0 = size * pad, x1 = size * (1 - pad); for (let y = 0; y < size; y++) for (let x = 0; x < size; x++) { const i = (size * y + x) * 4; // rounded square dark background const inX = x >= x0 && x <= x1, inY = y >= x0 && y <= x1; let inside = inX && inY; if (inside) { const cx = Math.max(x0 + r, Math.min(x1 - r, x)), cy = Math.max(x0 + r, Math.min(x1 - r, y)); inside = (x - cx) ** 2 + (y - cy) ** 2 <= r * r; } if (!inside) { png.data[i + 3] = pad === 0 ? 255 : 0; png.data[i] = 10; png.data[i + 1] = 12; png.data[i + 2] = 16; continue; } const t = (x + y) / (2 * size); // gradient blue → amber png.data[i] = Math.round(0x6d + (0xf0 - 0x6d) * t * 0.35); png.data[i + 1] = Math.round(0x9c + (0xb3 - 0x9c) * t * 0.35); png.data[i + 2] = Math.round(0xff + (0x5b - 0xff) * t * 0.35); png.data[i + 3] = 255; // dark inner card const m = size * 0.2; if (x > m && x < size - m && y > m && y < size - m) { png.data[i] = 14; png.data[i + 1] = 17; png.data[i + 2] = 24; } // two dots for (const [dx, dy, cr, cg, cb] of [[0.34, 0.64, 0x6d, 0x9c, 0xff], [0.66, 0.36, 0xf0, 0xb3, 0x5b]] as const) if ((x - dx * size) ** 2 + (y - dy * size) ** 2 <= (size * 0.07) ** 2) { png.data[i] = cr; png.data[i + 1] = cg; png.data[i + 2] = cb; } // curve approx: thick line between dots const ax = 0.34 * size, ay = 0.64 * size, bx = 0.66 * size, by = 0.36 * size; const len2 = (bx - ax) ** 2 + (by - ay) ** 2; const tt = Math.max(0, Math.min(1, ((x - ax) * (bx - ax) + (y - ay) * (by - ay)) / len2)); const px = ax + tt * (bx - ax), py = ay + tt * (by - ay); if ((x - px) ** 2 + (y - py) ** 2 <= (size * 0.035) ** 2 && tt > 0.15 && tt < 0.85) { png.data[i] = 0x9f; png.data[i + 1] = 0xa8; png.data[i + 2] = 0xc8; } } fs.writeFileSync(out, PNG.sync.write(png)); } icon(192, "public/icons/icon-192.png"); icon(512, "public/icons/icon-512.png"); icon(512, "public/icons/maskable-512.png", 0); icon(180, "public/icons/apple-touch-icon.png", 0); console.log("icons ok");