chore: establish YCode replication baseline and TODO

This commit is contained in:
xiaohan.yuan committed 2026-10-17 02:43:49 +08:00
commit 6dc59f89ba
1118 files changed
+196002

No files matched your search

+130
View File
@@ -0,0 +1,130 @@
/**
* 无依赖 PNG 像素差异对比(8 位、非隔行、RGB/RGBA)。
*
* 用途:验证 CSS 重构(如 token 化)是否改变了实际渲染。
*
* 用法:node scripts/pngdiff.mjs <before.png> <after.png> [channelThreshold]
*/
import { readFileSync } from 'node:fs'
import { inflateSync } from 'node:zlib'
function decodePng(buf) {
if (buf.readUInt32BE(0) !== 0x89504e47) throw new Error('不是 PNG')
let pos = 8
let width = 0
let height = 0
let bitDepth = 0
let colorType = 0
let interlace = 0
const idat = []
while (pos < buf.length) {
const len = buf.readUInt32BE(pos)
const type = buf.toString('ascii', pos + 4, pos + 8)
const data = buf.subarray(pos + 8, pos + 8 + len)
if (type === 'IHDR') {
width = data.readUInt32BE(0)
height = data.readUInt32BE(4)
bitDepth = data[8]
colorType = data[9]
interlace = data[12]
} else if (type === 'IDAT') {
idat.push(data)
} else if (type === 'IEND') {
break
}
pos += 12 + len
}
if (bitDepth !== 8) throw new Error(`仅支持 8 位深度,实际 ${bitDepth}`)
if (interlace !== 0) throw new Error('不支持隔行 PNG')
const channels = colorType === 6 ? 4 : colorType === 2 ? 3 : 0
if (!channels) throw new Error(`不支持的颜色类型 ${colorType}`)
const raw = inflateSync(Buffer.concat(idat))
const stride = width * channels
const pixels = Buffer.alloc(height * stride)
for (let y = 0; y < height; y++) {
const filter = raw[y * (stride + 1)]
const line = raw.subarray(y * (stride + 1) + 1, y * (stride + 1) + 1 + stride)
const prev = y > 0 ? pixels.subarray((y - 1) * stride, y * stride) : null
const out = pixels.subarray(y * stride, (y + 1) * stride)
for (let i = 0; i < stride; i++) {
const a = i >= channels ? out[i - channels] : 0
const b = prev ? prev[i] : 0
const c = prev && i >= channels ? prev[i - channels] : 0
let v = line[i]
switch (filter) {
case 0:
break
case 1:
v = (v + a) & 0xff
break
case 2:
v = (v + b) & 0xff
break
case 3:
v = (v + ((a + b) >> 1)) & 0xff
break
case 4: {
const p = a + b - c
const pa = Math.abs(p - a)
const pb = Math.abs(p - b)
const pc = Math.abs(p - c)
const pr = pa <= pb && pa <= pc ? a : pb <= pc ? b : c
v = (v + pr) & 0xff
break
}
default:
throw new Error(`未知过滤器 ${filter}`)
}
out[i] = v
}
}
return { width, height, channels, pixels }
}
const [, , beforePath, afterPath, thresholdArg] = process.argv
const threshold = Number(thresholdArg ?? 0)
const a = decodePng(readFileSync(beforePath))
const b = decodePng(readFileSync(afterPath))
if (a.width !== b.width || a.height !== b.height) {
console.log(`尺寸不同:${a.width}x${a.height} vs ${b.width}x${b.height}`)
const minW = Math.min(a.width, b.width)
const minH = Math.min(a.height, b.height)
console.log(`仅比较重叠区域 ${minW}x${minH}`)
}
const w = Math.min(a.width, b.width)
const h = Math.min(a.height, b.height)
let changed = 0
let maxDelta = 0
let sumDelta = 0
const perChannel = [0, 0, 0, 0]
for (let y = 0; y < h; y++) {
for (let x = 0; x < w; x++) {
let diff = false
for (let c = 0; c < 3; c++) {
const ia = y * a.width * a.channels + x * a.channels + c
const ib = y * b.width * b.channels + x * b.channels + c
const d = Math.abs(a.pixels[ia] - b.pixels[ib])
if (d > threshold) diff = true
if (d > 0) perChannel[c] += 1
if (d > maxDelta) maxDelta = d
sumDelta += d
}
if (diff) changed++
}
}
const total = w * h
console.log(`总像素 ${total}`)
console.log(`变化像素 ${changed} (${((changed / total) * 100).toFixed(3)}%)`)
console.log(`最大通道差 ${maxDelta}`)
console.log(`平均通道差 ${(sumDelta / (total * 3)).toFixed(4)}`)
console.log(`通道变化数 R=${perChannel[0]} G=${perChannel[1]} B=${perChannel[2]}`)