+51
@@ -0,0 +1,51 @@
|
||||
import fs from "node:fs";
|
||||
|
||||
const meta = JSON.parse(fs.readFileSync("clip.rgba.json", "utf8"));
|
||||
const px = fs.readFileSync("clip.rgba");
|
||||
const { w, ch, h } = meta;
|
||||
const at = (x, y) => { const o = (y * w + x) * ch; return [px[o], px[o + 1], px[o + 2]]; };
|
||||
const D = (a, b) => Math.abs(a[0] - b[0]) + Math.abs(a[1] - b[1]) + Math.abs(a[2] - b[2]);
|
||||
const hex = (c) => c.map((v) => v.toString(16).padStart(2, "0")).join("");
|
||||
|
||||
const Y0 = Number(process.argv[2] || 372);
|
||||
const Y1 = Number(process.argv[3] || 500);
|
||||
|
||||
const isInk = (x, y) => {
|
||||
const c = at(x, y);
|
||||
if (D(c, [255, 255, 255]) <= 20) return false;
|
||||
if (D(c, [227, 234, 246]) <= 14) return false;
|
||||
if (D(c, [230, 235, 244]) <= 14) return false;
|
||||
if (D(c, [236, 237, 243]) <= 10) return false;
|
||||
return true;
|
||||
};
|
||||
|
||||
const seen = new Uint8Array(w * h);
|
||||
const comps = [];
|
||||
for (let y = Y0; y < Y1; y++) {
|
||||
for (let x = 0; x < w; x++) {
|
||||
if (seen[y * w + x] || !isInk(x, y)) continue;
|
||||
let minX = x, maxX = x, minY = y, maxY = y, n = 0, sr = 0, sg = 0, sb = 0;
|
||||
const st = [x, y];
|
||||
seen[y * w + x] = 1;
|
||||
while (st.length) {
|
||||
const cy = st.pop(), cx = st.pop();
|
||||
n++;
|
||||
const c = at(cx, cy);
|
||||
sr += c[0]; sg += c[1]; sb += c[2];
|
||||
if (cx < minX) minX = cx; if (cx > maxX) maxX = cx;
|
||||
if (cy < minY) minY = cy; if (cy > maxY) maxY = cy;
|
||||
for (const [dx, dy] of [[1, 0], [-1, 0], [0, 1], [0, -1]]) {
|
||||
const nx = cx + dx, ny = cy + dy;
|
||||
if (nx < 0 || nx >= w || ny < Y0 || ny >= Y1) continue;
|
||||
if (!seen[ny * w + nx] && isInk(nx, ny)) { seen[ny * w + nx] = 1; st.push(nx, ny); }
|
||||
}
|
||||
}
|
||||
if (n > 25) comps.push({ x: minX, y: minY, w: maxX - minX + 1, h: maxY - minY + 1, n, c: [Math.round(sr / n), Math.round(sg / n), Math.round(sb / n)] });
|
||||
}
|
||||
}
|
||||
|
||||
comps.sort((a, b) => a.x - b.x);
|
||||
console.log(`区域 y${Y0}-${Y1} 内「墨迹」连通域 ${comps.length} 个(按 x 排序,CSS 坐标):`);
|
||||
for (const b of comps) {
|
||||
console.log(` x${Math.round(b.x / 2)} y${Math.round(b.y / 2)} ${Math.round(b.w / 2)}x${Math.round(b.h / 2)} px${b.n} avg#${hex(b.c)}`);
|
||||
}
|
||||
Reference in New Issue
Block a user