Files
LoveLiveMusicPlayer-Next/scripts/gen-tray-icon.mjs
2026-08-08 18:34:12 +08:00

95 lines
2.5 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import { deflateSync } from 'zlib'
import { writeFileSync, mkdirSync } from 'fs'
import { dirname, resolve } from 'path'
import { fileURLToPath } from 'url'
/** 生成一个简洁的托盘图标(粉色唱片盘),输出到 resources/tray.png */
const __dirname = dirname(fileURLToPath(import.meta.url))
const SIZE = 32
const cx = SIZE / 2 - 0.5
const cy = SIZE / 2 - 0.5
const rOuter = 15
const rHole = 4
function px(x, y) {
const dx = x - cx
const dy = y - cy
const d = Math.sqrt(dx * dx + dy * dy)
// 抗锯齿边缘
const edge = (r) => Math.max(0, Math.min(1, r - d + 0.5))
const inDisc = edge(rOuter)
const inHole = edge(rHole)
if (inDisc <= 0) return [0, 0, 0, 0]
// 唱片主体粉色,中心孔洞白色
const pink = [255, 55, 95]
const white = [255, 255, 255]
const a = Math.round(255 * inDisc)
if (inHole > 0) {
const t = inHole
return [
Math.round(pink[0] * (1 - t) + white[0] * t),
Math.round(pink[1] * (1 - t) + white[1] * t),
Math.round(pink[2] * (1 - t) + white[2] * t),
a
]
}
return [pink[0], pink[1], pink[2], a]
}
// 构造原始 RGBA 扫描行(每行前置 filter 0
const raw = Buffer.alloc((SIZE * 4 + 1) * SIZE)
let p = 0
for (let y = 0; y < SIZE; y++) {
raw[p++] = 0
for (let x = 0; x < SIZE; x++) {
const [r, g, b, a] = px(x, y)
raw[p++] = r
raw[p++] = g
raw[p++] = b
raw[p++] = a
}
}
const crcTable = (() => {
const t = []
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
t[n] = c >>> 0
}
return t
})()
function crc32(buf) {
let c = 0xffffffff
for (let i = 0; i < buf.length; i++) c = crcTable[(c ^ buf[i]) & 0xff] ^ (c >>> 8)
return (c ^ 0xffffffff) >>> 0
}
function chunk(type, data) {
const len = Buffer.alloc(4)
len.writeUInt32BE(data.length, 0)
const typeBuf = Buffer.from(type, 'ascii')
const body = Buffer.concat([typeBuf, data])
const crc = Buffer.alloc(4)
crc.writeUInt32BE(crc32(body), 0)
return Buffer.concat([len, body, crc])
}
const sig = Buffer.from([137, 80, 78, 71, 13, 10, 26, 10])
const ihdr = Buffer.alloc(13)
ihdr.writeUInt32BE(SIZE, 0)
ihdr.writeUInt32BE(SIZE, 4)
ihdr[8] = 8 // bit depth
ihdr[9] = 6 // color type RGBA
const png = Buffer.concat([
sig,
chunk('IHDR', ihdr),
chunk('IDAT', deflateSync(raw)),
chunk('IEND', Buffer.alloc(0))
])
const out = resolve(__dirname, '../resources/tray.png')
mkdirSync(dirname(out), { recursive: true })
writeFileSync(out, png)
console.log('wrote', out, png.length, 'bytes')