51 lines
1.5 KiB
JavaScript
51 lines
1.5 KiB
JavaScript
// 生成 icons/app.png(256x256 纯蓝方块图标)
|
||
const zlib = require("zlib");
|
||
const fs = require("fs");
|
||
const path = require("path");
|
||
|
||
const W = 256, H = 256;
|
||
const row = Buffer.alloc(1 + W * 4);
|
||
row[0] = 0;
|
||
for (let x = 0; x < W; x++) {
|
||
row[1 + x * 4] = 0;
|
||
row[2 + x * 4] = 110;
|
||
row[3 + x * 4] = 255;
|
||
row[4 + x * 4] = 255;
|
||
}
|
||
const raw = Buffer.concat(Array(H).fill(row));
|
||
|
||
const crcTable = [];
|
||
for (let n = 0; n < 256; n++) {
|
||
let c = n;
|
||
for (let k = 0; k < 8; k++) c = (c & 1) ? (0xedb88320 ^ (c >>> 1)) : (c >>> 1);
|
||
crcTable[n] = c >>> 0;
|
||
}
|
||
function crc32(buf) {
|
||
let c = 0xffffffff;
|
||
for (const b of buf) c = crcTable[(c ^ b) & 0xff] ^ (c >>> 8);
|
||
return (c ^ 0xffffffff) >>> 0;
|
||
}
|
||
function chunk(type, data) {
|
||
const len = Buffer.alloc(4);
|
||
len.writeUInt32BE(data.length);
|
||
const t = Buffer.from(type, "ascii");
|
||
const crc = Buffer.alloc(4);
|
||
crc.writeUInt32BE(crc32(Buffer.concat([t, data])));
|
||
return Buffer.concat([len, t, data, crc]);
|
||
}
|
||
|
||
const ihdr = Buffer.alloc(13);
|
||
ihdr.writeUInt32BE(W, 0);
|
||
ihdr.writeUInt32BE(H, 4);
|
||
ihdr[8] = 8; // bit depth
|
||
ihdr[9] = 6; // color type RGBA
|
||
const png = Buffer.concat([
|
||
Buffer.from([0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a]),
|
||
chunk("IHDR", ihdr),
|
||
chunk("IDAT", zlib.deflateSync(raw)),
|
||
chunk("IEND", Buffer.alloc(0)),
|
||
]);
|
||
fs.mkdirSync(path.join(__dirname, "icons"), { recursive: true });
|
||
fs.writeFileSync(path.join(__dirname, "icons", "app.png"), png);
|
||
console.log("icon generated:", png.length, "bytes");
|