const fs = require('fs'); const path = require('path'); const { PNG } = require('pngjs'); const SIZE = 600; function hexToRgb(hex) { const clean = hex.replace('#', ''); return { r: parseInt(clean.substring(0, 2), 16), g: parseInt(clean.substring(2, 4), 16), b: parseInt(clean.substring(4, 6), 16), }; } function setPixel(png, x, y, color) { if (x < 0 || y < 0 || x >= png.width || y >= png.height) return; const idx = (png.width * y + x) << 2; png.data[idx] = color.r; png.data[idx + 1] = color.g; png.data[idx + 2] = color.b; png.data[idx + 3] = 255; } function fillRect(png, x0, y0, x1, y1, color) { const sx = Math.max(0, Math.floor(x0)); const sy = Math.max(0, Math.floor(y0)); const ex = Math.min(png.width - 1, Math.ceil(x1)); const ey = Math.min(png.height - 1, Math.ceil(y1)); for (let y = sy; y <= ey; y++) { for (let x = sx; x <= ex; x++) setPixel(png, x, y, color); } } function fillCircle(png, cx, cy, r, color) { const rr = r * r; const x0 = Math.floor(cx - r); const x1 = Math.ceil(cx + r); const y0 = Math.floor(cy - r); const y1 = Math.ceil(cy + r); for (let y = y0; y <= y1; y++) { for (let x = x0; x <= x1; x++) { const dx = x - cx; const dy = y - cy; if (dx * dx + dy * dy <= rr) setPixel(png, x, y, color); } } } function fillEllipse(png, cx, cy, rx, ry, color) { const rx2 = rx * rx; const ry2 = ry * ry; const x0 = Math.floor(cx - rx); const x1 = Math.ceil(cx + rx); const y0 = Math.floor(cy - ry); const y1 = Math.ceil(cy + ry); for (let y = y0; y <= y1; y++) { for (let x = x0; x <= x1; x++) { const dx = x - cx; const dy = y - cy; if ((dx * dx) / rx2 + (dy * dy) / ry2 <= 1) setPixel(png, x, y, color); } } } function drawThickLine(png, x0, y0, x1, y1, thickness, color) { const steps = Math.max(Math.abs(x1 - x0), Math.abs(y1 - y0)); for (let i = 0; i <= steps; i++) { const t = i / (steps || 1); const x = Math.round(x0 + (x1 - x0) * t); const y = Math.round(y0 + (y1 - y0) * t); fillCircle(png, x, y, thickness / 2, color); } } function drawLogo(filename, theme) { const png = new PNG({ width: SIZE, height: SIZE }); const bg = hexToRgb(theme.bg); const card = hexToRgb(theme.card); const bowl = hexToRgb(theme.bowl); const accent = hexToRgb(theme.accent); fillRect(png, 0, 0, SIZE - 1, SIZE - 1, bg); // Card background shape fillRect(png, 80, 80, 520, 520, card); fillCircle(png, 80, 80, 70, card); fillCircle(png, 520, 80, 70, card); fillCircle(png, 80, 520, 70, card); fillCircle(png, 520, 520, 70, card); // Bowl fillEllipse(png, 300, 350, 165, 90, bowl); fillRect(png, 135, 350, 465, 430, bowl); fillEllipse(png, 300, 430, 165, 45, bowl); // Bowl top cut fillEllipse(png, 300, 340, 175, 68, card); fillEllipse(png, 300, 346, 175, 4, accent); // Noodles fillEllipse(png, 250, 372, 50, 12, accent); fillEllipse(png, 300, 374, 55, 13, accent); fillEllipse(png, 350, 372, 50, 12, accent); // Steam fillEllipse(png, 245, 255, 14, 32, accent); fillEllipse(png, 300, 235, 16, 38, accent); fillEllipse(png, 355, 255, 14, 32, accent); // Chopsticks drawThickLine(png, 360, 205, 485, 330, 11, accent); drawThickLine(png, 390, 188, 515, 313, 11, accent); const outPath = path.join(__dirname, filename); fs.writeFileSync(outPath, PNG.sync.write(png)); return outPath; } const light = drawLogo('lunch-pick-logo-light-600.png', { bg: '#F8FAFC', card: '#E0F2FE', bowl: '#0EA5E9', accent: '#0C4A6E', }); const dark = drawLogo('lunch-pick-logo-dark-600.png', { bg: '#0B1220', card: '#13233C', bowl: '#38BDF8', accent: '#E2E8F0', }); console.log(light); console.log(dark);