learning_ai_clock/web/scripts/generate-icons.mjs

81 lines
2.2 KiB
JavaScript

#!/usr/bin/env node
import fs from 'fs';
import zlib from 'zlib';
import path from 'path';
import { fileURLToPath } from 'url';
const __dirname = path.dirname(fileURLToPath(import.meta.url));
const dir = path.join(__dirname, '..', 'public', 'icons');
fs.mkdirSync(dir, { recursive: true });
function crc32(data) {
let crc = 0xffffffff;
const table = new Int32Array(256);
for (let i = 0; i < 256; i++) {
let c = i;
for (let j = 0; j < 8; j++) c = (c & 1) ? (0xedb88320 ^ (c >>> 1)) : (c >>> 1);
table[i] = c;
}
for (let i = 0; i < data.length; i++) crc = table[(crc ^ data[i]) & 0xff] ^ (crc >>> 8);
return (crc ^ 0xffffffff) >>> 0;
}
function chunk(type, data) {
const len = Buffer.alloc(4);
len.writeUInt32BE(data.length);
const typeData = Buffer.concat([Buffer.from(type), data]);
const crcBuf = Buffer.alloc(4);
crcBuf.writeUInt32BE(crc32(typeData));
return Buffer.concat([len, typeData, crcBuf]);
}
function makePNG(w, h) {
const rowBytes = 1 + w * 3;
const buf = Buffer.alloc(rowBytes * h);
const cx = w / 2, cy = h / 2;
const outerR = Math.min(w, h) / 2 - 2;
const innerR = outerR * 0.65;
let offset = 0;
for (let y = 0; y < h; y++) {
buf[offset++] = 0; // filter none
for (let x = 0; x < w; x++) {
const dx = x - cx, dy = y - cy;
const dist = Math.sqrt(dx * dx + dy * dy);
if (dist <= outerR && dist >= innerR) {
buf[offset++] = 90; buf[offset++] = 140; buf[offset++] = 255;
} else {
buf[offset++] = 6; buf[offset++] = 7; buf[offset++] = 10;
}
}
}
const compressed = zlib.deflateSync(buf.slice(0, offset));
const ihdr = Buffer.alloc(13);
ihdr.writeUInt32BE(w, 0);
ihdr.writeUInt32BE(h, 4);
ihdr[8] = 8; ihdr[9] = 2;
return Buffer.concat([
Buffer.from([137, 80, 78, 71, 13, 10, 26, 10]),
chunk('IHDR', ihdr),
chunk('IDAT', compressed),
chunk('IEND', Buffer.alloc(0))
]);
}
const icons = [
[192, 'icon-192.png'],
[512, 'icon-512.png'],
[512, 'icon-512-maskable.png'],
[180, 'apple-touch-icon.png'],
];
for (const [size, name] of icons) {
const png = makePNG(size, size);
fs.writeFileSync(path.join(dir, name), png);
console.log(`Created ${name} (${png.length} bytes)`);
}
console.log('Done!');