-
Notifications
You must be signed in to change notification settings - Fork 191
Expand file tree
/
Copy pathtest-texture-seams.html
More file actions
58 lines (56 loc) · 2.64 KB
/
Copy pathtest-texture-seams.html
File metadata and controls
58 lines (56 loc) · 2.64 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
<!DOCTYPE html>
<!-- Measure wrap-edge continuity of ALL preset textures (PNG + JPEG) using
the browser's own decoder — the same pixels displacement samples.
Serve repo root, open this page; results stream to the HTTP server log
via beacon requests and render in the page body. -->
<html>
<head><meta charset="utf-8"><title>texture-seams</title></head>
<body><pre id="out">running…</pre>
<script>
const FILES = [
'basket.png','brick.png','bubble.png','crystal.png','dots.png','grid.png',
'isogrid.png','knitting.png','leather2.png','stripes.png','stripes_02.png','weave.png',
'carbonFiber.jpg','gripSurface.jpg','hexagon.jpg','hexagons.jpg','knurling.jpg','noise.jpg',
'voronoi.jpg','weave_02.jpg','weave_03.jpg','wood.jpg','woodgrain_02.jpg','woodgrain_03.jpg',
];
const out = [];
const beacon = (s) => { try { fetch('/__test__/' + encodeURIComponent(s)).catch(() => {}); } catch {} };
function analyze(g, w, h) {
const colDiff = (x0, x1) => { let s = 0; for (let y = 0; y < h; y++) s += Math.abs(g[y*w+x0] - g[y*w+x1]); return s / h; };
const rowDiff = (y0, y1) => { let s = 0; for (let x = 0; x < w; x++) s += Math.abs(g[y0*w+x] - g[y1*w+x]); return s / w; };
let interior = 0, n = 0;
for (let x = 8; x < w - 8; x += Math.max(1, (w / 32) | 0)) { interior += colDiff(x, x + 1); n++; }
for (let y = 8; y < h - 8; y += Math.max(1, (h / 32) | 0)) { interior += rowDiff(y, y + 1); n++; }
interior /= n;
return { interior, wrapX: colDiff(w - 1, 0), wrapY: rowDiff(h - 1, 0) };
}
(async () => {
for (const f of FILES) {
try {
const img = new Image();
img.src = 'textures/' + f;
await img.decode();
const c = document.createElement('canvas');
c.width = img.naturalWidth; c.height = img.naturalHeight;
const ctx = c.getContext('2d');
ctx.drawImage(img, 0, 0);
const d = ctx.getImageData(0, 0, c.width, c.height).data;
const g = new Uint8ClampedArray(c.width * c.height);
for (let i = 0; i < g.length; i++) g[i] = d[i * 4];
const { interior, wrapX, wrapY } = analyze(g, c.width, c.height);
const worst = Math.max(wrapX, wrapY) / Math.max(interior, 0.01);
const verdict = worst < 1.5 ? 'seamless' : worst < 3 ? 'slight-seam' : 'SEAM';
const line = `${f} ${c.width}x${c.height} interior=${interior.toFixed(2)} wrapX=${wrapX.toFixed(2)} wrapY=${wrapY.toFixed(2)} ${verdict} ${worst.toFixed(1)}x`;
out.push(line); beacon(line);
} catch (e) {
const line = `${f} ERROR ${e.message}`;
out.push(line); beacon(line);
}
document.getElementById('out').textContent = out.join('\n');
}
beacon('DONE');
document.title = 'DONE';
})();
</script>
</body>
</html>