@testivai/witness 1.0.0 → 1.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +44 -13
- package/dist/baselines/index.d.ts +6 -0
- package/dist/baselines/index.d.ts.map +1 -0
- package/dist/baselines/index.js +9 -0
- package/dist/baselines/index.js.map +1 -0
- package/dist/baselines/store.d.ts +79 -0
- package/dist/baselines/store.d.ts.map +1 -0
- package/dist/baselines/store.js +234 -0
- package/dist/baselines/store.js.map +1 -0
- package/dist/bin/testivai.js +2 -0
- package/dist/bin/testivai.js.map +1 -1
- package/dist/browser/binding.d.ts.map +1 -1
- package/dist/browser/binding.js +173 -42
- package/dist/browser/binding.js.map +1 -1
- package/dist/browser/capture.d.ts.map +1 -1
- package/dist/browser/capture.js +86 -38
- package/dist/browser/capture.js.map +1 -1
- package/dist/commands/approve.d.ts +3 -0
- package/dist/commands/approve.d.ts.map +1 -0
- package/dist/commands/approve.js +94 -0
- package/dist/commands/approve.js.map +1 -0
- package/dist/commands/init.d.ts.map +1 -1
- package/dist/commands/init.js +53 -0
- package/dist/commands/init.js.map +1 -1
- package/dist/commands/run.d.ts.map +1 -1
- package/dist/commands/run.js +98 -0
- package/dist/commands/run.js.map +1 -1
- package/dist/config/index.d.ts +6 -0
- package/dist/config/index.d.ts.map +1 -0
- package/dist/config/index.js +14 -0
- package/dist/config/index.js.map +1 -0
- package/dist/config/local-config.d.ts +54 -0
- package/dist/config/local-config.d.ts.map +1 -0
- package/dist/config/local-config.js +130 -0
- package/dist/config/local-config.js.map +1 -0
- package/dist/diff/diff.d.ts +27 -0
- package/dist/diff/diff.d.ts.map +1 -0
- package/dist/diff/diff.js +216 -0
- package/dist/diff/diff.js.map +1 -0
- package/dist/diff/ignore.d.ts +22 -0
- package/dist/diff/ignore.d.ts.map +1 -0
- package/dist/diff/ignore.js +43 -0
- package/dist/diff/ignore.js.map +1 -0
- package/dist/diff/index.d.ts +16 -0
- package/dist/diff/index.d.ts.map +1 -0
- package/dist/diff/index.js +23 -0
- package/dist/diff/index.js.map +1 -0
- package/dist/diff/minimap.d.ts +23 -0
- package/dist/diff/minimap.d.ts.map +1 -0
- package/dist/diff/minimap.js +43 -0
- package/dist/diff/minimap.js.map +1 -0
- package/dist/diff/regions.d.ts +23 -0
- package/dist/diff/regions.d.ts.map +1 -0
- package/dist/diff/regions.js +129 -0
- package/dist/diff/regions.js.map +1 -0
- package/dist/diff/resize.d.ts +27 -0
- package/dist/diff/resize.d.ts.map +1 -0
- package/dist/diff/resize.js +82 -0
- package/dist/diff/resize.js.map +1 -0
- package/dist/diff/types.d.ts +79 -0
- package/dist/diff/types.d.ts.map +1 -0
- package/dist/diff/types.js +10 -0
- package/dist/diff/types.js.map +1 -0
- package/dist/index.d.ts +8 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +23 -2
- package/dist/index.js.map +1 -1
- package/dist/report/compare.d.ts +18 -0
- package/dist/report/compare.d.ts.map +1 -0
- package/dist/report/compare.js +163 -0
- package/dist/report/compare.js.map +1 -0
- package/dist/report/generator.d.ts +31 -0
- package/dist/report/generator.d.ts.map +1 -0
- package/dist/report/generator.js +123 -0
- package/dist/report/generator.js.map +1 -0
- package/dist/report/index.d.ts +10 -0
- package/dist/report/index.d.ts.map +1 -0
- package/dist/report/index.js +13 -0
- package/dist/report/index.js.map +1 -0
- package/dist/report/results.d.ts +35 -0
- package/dist/report/results.d.ts.map +1 -0
- package/dist/report/results.js +8 -0
- package/dist/report/results.js.map +1 -0
- package/dist/report/template.d.ts +14 -0
- package/dist/report/template.d.ts.map +1 -0
- package/dist/report/template.js +229 -0
- package/dist/report/template.js.map +1 -0
- package/package.json +58 -15
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* TestivAI Diff Engine — Core comparison loop
|
|
3
|
+
*
|
|
4
|
+
* Originally forked from pixel-buffer-diff (Pbd) by @p01, licensed under MIT.
|
|
5
|
+
* https://github.com/p01/pixel-buffer-diff
|
|
6
|
+
*
|
|
7
|
+
* The core pixel comparison algorithm is preserved exactly.
|
|
8
|
+
* Extended with: ignore regions, size mismatch handling, region detection,
|
|
9
|
+
* and enriched DiffResult.
|
|
10
|
+
*/
|
|
11
|
+
import { DiffOptions, DiffResult } from './types';
|
|
12
|
+
/**
|
|
13
|
+
* Compare two pixel buffers and produce a diff image.
|
|
14
|
+
*
|
|
15
|
+
* Drop-in compatible with pixelmatch when called as:
|
|
16
|
+
* diff(img1, img2, output, w, h) → returns DiffResult
|
|
17
|
+
*
|
|
18
|
+
* @param baseline8 - Baseline image pixel data (RGBA, 4 bytes per pixel)
|
|
19
|
+
* @param candidate8 - Candidate image pixel data (RGBA, 4 bytes per pixel)
|
|
20
|
+
* @param diff8 - Output buffer for the diff image (same size as inputs)
|
|
21
|
+
* @param width - Width of the images in pixels
|
|
22
|
+
* @param height - Height of the images in pixels
|
|
23
|
+
* @param options - Comparison options
|
|
24
|
+
* @returns DiffResult with counts, percentages, and optional regions
|
|
25
|
+
*/
|
|
26
|
+
export declare function diff(baseline8: Uint8Array | Uint8ClampedArray, candidate8: Uint8Array | Uint8ClampedArray, diff8: Uint8Array | Uint8ClampedArray, width: number, height: number, options?: DiffOptions): DiffResult;
|
|
27
|
+
//# sourceMappingURL=diff.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"diff.d.ts","sourceRoot":"","sources":["../../src/diff/diff.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,EAAE,WAAW,EAAE,UAAU,EAAgB,MAAM,SAAS,CAAC;AAqBhE;;;;;;;;;;;;;GAaG;AACH,wBAAgB,IAAI,CAClB,SAAS,EAAE,UAAU,GAAG,iBAAiB,EACzC,UAAU,EAAE,UAAU,GAAG,iBAAiB,EAC1C,KAAK,EAAE,UAAU,GAAG,iBAAiB,EACrC,KAAK,EAAE,MAAM,EACb,MAAM,EAAE,MAAM,EACd,OAAO,GAAE,WAAgB,GACxB,UAAU,CAgGZ"}
|
|
@@ -0,0 +1,216 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* TestivAI Diff Engine — Core comparison loop
|
|
4
|
+
*
|
|
5
|
+
* Originally forked from pixel-buffer-diff (Pbd) by @p01, licensed under MIT.
|
|
6
|
+
* https://github.com/p01/pixel-buffer-diff
|
|
7
|
+
*
|
|
8
|
+
* The core pixel comparison algorithm is preserved exactly.
|
|
9
|
+
* Extended with: ignore regions, size mismatch handling, region detection,
|
|
10
|
+
* and enriched DiffResult.
|
|
11
|
+
*/
|
|
12
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
13
|
+
exports.diff = diff;
|
|
14
|
+
const ignore_1 = require("./ignore");
|
|
15
|
+
const resize_1 = require("./resize");
|
|
16
|
+
const regions_1 = require("./regions");
|
|
17
|
+
const minimap_1 = require("./minimap");
|
|
18
|
+
// ── Pbd constants (unchanged) ───────────────────────────────────────────────
|
|
19
|
+
const MINIMAP_SCALE = 128;
|
|
20
|
+
const COLOR32_ADDED = 0x03f00cc00;
|
|
21
|
+
const COLOR32_REMOVED = 0x03f0000ff;
|
|
22
|
+
const COLOR32_MINIMAP = 0x0207f0000;
|
|
23
|
+
const HASH_SPREAD = 0x0f0731337;
|
|
24
|
+
// ── Default options ─────────────────────────────────────────────────────────
|
|
25
|
+
const DEFAULT_OPTIONS = {
|
|
26
|
+
threshold: 0.1,
|
|
27
|
+
cumulatedThreshold: 0.5,
|
|
28
|
+
enableMinimap: false,
|
|
29
|
+
detectRegions: false,
|
|
30
|
+
};
|
|
31
|
+
/**
|
|
32
|
+
* Compare two pixel buffers and produce a diff image.
|
|
33
|
+
*
|
|
34
|
+
* Drop-in compatible with pixelmatch when called as:
|
|
35
|
+
* diff(img1, img2, output, w, h) → returns DiffResult
|
|
36
|
+
*
|
|
37
|
+
* @param baseline8 - Baseline image pixel data (RGBA, 4 bytes per pixel)
|
|
38
|
+
* @param candidate8 - Candidate image pixel data (RGBA, 4 bytes per pixel)
|
|
39
|
+
* @param diff8 - Output buffer for the diff image (same size as inputs)
|
|
40
|
+
* @param width - Width of the images in pixels
|
|
41
|
+
* @param height - Height of the images in pixels
|
|
42
|
+
* @param options - Comparison options
|
|
43
|
+
* @returns DiffResult with counts, percentages, and optional regions
|
|
44
|
+
*/
|
|
45
|
+
function diff(baseline8, candidate8, diff8, width, height, options = {}) {
|
|
46
|
+
const opts = { ...DEFAULT_OPTIONS, ...options };
|
|
47
|
+
// ── Size mismatch handling ──────────────────────────────────────────────
|
|
48
|
+
let sizeMismatch;
|
|
49
|
+
let effectiveWidth = width;
|
|
50
|
+
let effectiveHeight = height;
|
|
51
|
+
let effectiveBaseline = baseline8;
|
|
52
|
+
let effectiveCandidate = candidate8;
|
|
53
|
+
// If caller provided handleSizeMismatch and dimensions were embedded,
|
|
54
|
+
// we need external width/height per buffer. For the simple API the caller
|
|
55
|
+
// is expected to have already normalized — but we expose normalizeDimensions
|
|
56
|
+
// as a public utility. Here we just validate.
|
|
57
|
+
const expectedLen = width * height * 4;
|
|
58
|
+
if (baseline8.length !== expectedLen || candidate8.length !== expectedLen) {
|
|
59
|
+
if (opts.handleSizeMismatch) {
|
|
60
|
+
// Infer baseline dimensions from baseline8.length and supplied width
|
|
61
|
+
const baselineHeight = baseline8.length / (width * 4);
|
|
62
|
+
const candidateHeight = candidate8.length / (width * 4);
|
|
63
|
+
// If widths differ, we need both dimensions — use normalizeDimensions
|
|
64
|
+
const bw = width;
|
|
65
|
+
const bh = Math.round(baselineHeight);
|
|
66
|
+
const cw = width;
|
|
67
|
+
const ch = Math.round(candidateHeight);
|
|
68
|
+
const normalized = (0, resize_1.normalizeDimensions)(baseline8, bw, bh, candidate8, cw, ch, opts.handleSizeMismatch);
|
|
69
|
+
effectiveBaseline = normalized.normalizedBaseline;
|
|
70
|
+
effectiveCandidate = normalized.normalizedCandidate;
|
|
71
|
+
effectiveWidth = normalized.width;
|
|
72
|
+
effectiveHeight = normalized.height;
|
|
73
|
+
sizeMismatch = normalized.sizeMismatch;
|
|
74
|
+
// Re-create diff buffer if size changed
|
|
75
|
+
if (diff8.length !== effectiveWidth * effectiveHeight * 4) {
|
|
76
|
+
diff8 = new Uint8ClampedArray(effectiveWidth * effectiveHeight * 4);
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
else {
|
|
80
|
+
throw new Error(`Buffer size mismatch: expected ${expectedLen} bytes (${width}×${height}×4), ` +
|
|
81
|
+
`got baseline=${baseline8.length}, candidate=${candidate8.length}. ` +
|
|
82
|
+
`Set handleSizeMismatch option to 'pad', 'crop', or 'error'.`);
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
// ── Ignore regions ──────────────────────────────────────────────────────
|
|
86
|
+
if (opts.ignoreRegions && opts.ignoreRegions.length > 0) {
|
|
87
|
+
// Clone buffers so we don't mutate originals
|
|
88
|
+
effectiveBaseline = new Uint8ClampedArray(effectiveBaseline);
|
|
89
|
+
effectiveCandidate = new Uint8ClampedArray(effectiveCandidate);
|
|
90
|
+
(0, ignore_1.applyIgnoreRegions)(effectiveBaseline, effectiveCandidate, effectiveWidth, effectiveHeight, opts.ignoreRegions);
|
|
91
|
+
}
|
|
92
|
+
// ── Core Pbd diff loop (basic mode — pixel-level YIQ comparison) ──────
|
|
93
|
+
const raw = pbdDiffCore(effectiveBaseline, effectiveCandidate, diff8, effectiveWidth, effectiveHeight, opts.threshold, opts.cumulatedThreshold, opts.enableMinimap);
|
|
94
|
+
// ── Compute extended result ─────────────────────────────────────────────
|
|
95
|
+
const totalPixels = effectiveWidth * effectiveHeight;
|
|
96
|
+
const diffPercent = totalPixels > 0 ? (raw.diff / totalPixels) * 100 : 0;
|
|
97
|
+
const isIdentical = raw.diff === 0;
|
|
98
|
+
const result = {
|
|
99
|
+
diffCount: raw.diff,
|
|
100
|
+
cumulatedDiff: raw.cumulatedDiff,
|
|
101
|
+
hash: raw.hash,
|
|
102
|
+
diffPercent,
|
|
103
|
+
totalPixels,
|
|
104
|
+
isIdentical,
|
|
105
|
+
};
|
|
106
|
+
if (sizeMismatch) {
|
|
107
|
+
result.sizeMismatch = sizeMismatch;
|
|
108
|
+
}
|
|
109
|
+
// ── Region detection ────────────────────────────────────────────────────
|
|
110
|
+
if (opts.detectRegions && !isIdentical) {
|
|
111
|
+
result.regions = (0, regions_1.detectRegions)(diff8, effectiveWidth, effectiveHeight);
|
|
112
|
+
}
|
|
113
|
+
return result;
|
|
114
|
+
}
|
|
115
|
+
/**
|
|
116
|
+
* Core Pbd diff loop — pixel-level YIQ comparison.
|
|
117
|
+
* Algorithm is preserved exactly from pixel-buffer-diff.
|
|
118
|
+
* @internal
|
|
119
|
+
*/
|
|
120
|
+
function pbdDiffCore(baseline8, candidate8, diff8, width, height, threshold, cumulatedThreshold, enableMinimap) {
|
|
121
|
+
const area = width * height;
|
|
122
|
+
const b8l = baseline8.length;
|
|
123
|
+
// Maximum acceptable square distance between two colors;
|
|
124
|
+
// 35215 is the maximum possible value for the YIQ difference metric
|
|
125
|
+
const deltaThreshold = threshold * threshold * 35215;
|
|
126
|
+
// Use ArrayBuffer views for 32-bit access
|
|
127
|
+
const bBuffer = baseline8.buffer;
|
|
128
|
+
const bOffset = baseline8.byteOffset;
|
|
129
|
+
const cBuffer = candidate8.buffer;
|
|
130
|
+
const cOffset = candidate8.byteOffset;
|
|
131
|
+
const dBuffer = diff8.buffer;
|
|
132
|
+
const dOffset = diff8.byteOffset;
|
|
133
|
+
const baseline32 = new Uint32Array(bBuffer, bOffset, area);
|
|
134
|
+
const candidate32 = new Uint32Array(cBuffer, cOffset, area);
|
|
135
|
+
const diff32 = new Uint32Array(dBuffer, dOffset, area);
|
|
136
|
+
let b8i = 0;
|
|
137
|
+
let b32i = 0;
|
|
138
|
+
let d32i = 0;
|
|
139
|
+
let diffCount = 0;
|
|
140
|
+
let hash = 0;
|
|
141
|
+
let hashStart = 0;
|
|
142
|
+
let cumulatedDiff = 0;
|
|
143
|
+
// Quick approx of color theme to figure if "new" pixels should be dark or light
|
|
144
|
+
let averageBrightness = 0;
|
|
145
|
+
const brightnessSamples = Math.ceil(Math.sqrt(area) / 128);
|
|
146
|
+
const b8iStep = (b8l / brightnessSamples) & -4;
|
|
147
|
+
let sampleIdx = 0;
|
|
148
|
+
for (let i = 0; i < brightnessSamples; i++) {
|
|
149
|
+
averageBrightness +=
|
|
150
|
+
(0.299 * (baseline8[sampleIdx] + candidate8[sampleIdx]) +
|
|
151
|
+
0.587 * (baseline8[sampleIdx + 1] + candidate8[sampleIdx + 1]) +
|
|
152
|
+
0.114 * (baseline8[sampleIdx + 2] + candidate8[sampleIdx + 2])) /
|
|
153
|
+
brightnessSamples /
|
|
154
|
+
2;
|
|
155
|
+
sampleIdx += b8iStep;
|
|
156
|
+
}
|
|
157
|
+
const isDarkTheme = averageBrightness < 128;
|
|
158
|
+
const color32Added = isDarkTheme ? COLOR32_ADDED : COLOR32_REMOVED;
|
|
159
|
+
const color32Removed = isDarkTheme ? COLOR32_REMOVED : COLOR32_ADDED;
|
|
160
|
+
// Minimap tracking
|
|
161
|
+
const miniHeight = Math.ceil(height / MINIMAP_SCALE);
|
|
162
|
+
const miniWidth = Math.ceil(width / MINIMAP_SCALE);
|
|
163
|
+
const miniMap = new Uint8ClampedArray(miniWidth * miniHeight);
|
|
164
|
+
const maxDimension = Math.max(width, height);
|
|
165
|
+
const maxMiniDimension = Math.max(miniWidth, miniHeight);
|
|
166
|
+
const axisMiniIndex = new Uint32Array(maxDimension);
|
|
167
|
+
let miniIndex = 0;
|
|
168
|
+
for (let i = 0; i < maxMiniDimension; i++) {
|
|
169
|
+
axisMiniIndex.fill(i, miniIndex, Math.min(miniIndex + MINIMAP_SCALE, maxDimension));
|
|
170
|
+
miniIndex += MINIMAP_SCALE;
|
|
171
|
+
}
|
|
172
|
+
// ── Per-pixel comparison ────────────────────────────────────────────────
|
|
173
|
+
for (let y = 0; y < height; y++) {
|
|
174
|
+
const miniIndexY = axisMiniIndex[y] * miniWidth;
|
|
175
|
+
let hashIndex = (y ^ HASH_SPREAD) * HASH_SPREAD;
|
|
176
|
+
for (let x = 0; x < width; x++, d32i++, b32i++, b8i += 4, hashIndex++) {
|
|
177
|
+
// Quick check against the Uint32
|
|
178
|
+
if (baseline32[b32i] === candidate32[b32i]) {
|
|
179
|
+
continue;
|
|
180
|
+
}
|
|
181
|
+
// Get the r,g,b -> y,i,q => YIQ square delta
|
|
182
|
+
const dr = candidate8[b8i] - baseline8[b8i];
|
|
183
|
+
const dg = candidate8[b8i + 1] - baseline8[b8i + 1];
|
|
184
|
+
const db = candidate8[b8i + 2] - baseline8[b8i + 2];
|
|
185
|
+
const dy = dr * 0.29889531 + dg * 0.58662247 + db * 0.11448223;
|
|
186
|
+
const di = dr * 0.59597799 - dg * 0.27417610 - db * 0.32180189;
|
|
187
|
+
const dq = dr * 0.21147017 - dg * 0.52261711 + db * 0.31114694;
|
|
188
|
+
const delta = dy * dy * 0.5053 + di * di * 0.299 + dq * dq * 0.1957;
|
|
189
|
+
if (delta > deltaThreshold) {
|
|
190
|
+
miniMap[miniIndexY + axisMiniIndex[x]]++;
|
|
191
|
+
diffCount++;
|
|
192
|
+
const dyAbs = Math.abs(dy);
|
|
193
|
+
cumulatedDiff += dyAbs;
|
|
194
|
+
diff32[d32i] =
|
|
195
|
+
(dy > 0 ? color32Added : color32Removed) +
|
|
196
|
+
(Math.min(192, dyAbs * 8) << 24);
|
|
197
|
+
if (hash === 0) {
|
|
198
|
+
hashStart = hashIndex;
|
|
199
|
+
}
|
|
200
|
+
hash += hashIndex;
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
hash -= hashStart;
|
|
205
|
+
cumulatedDiff /= 256;
|
|
206
|
+
// Apply minimap overlay
|
|
207
|
+
if (enableMinimap) {
|
|
208
|
+
(0, minimap_1.applyMinimap)(diff32, miniMap, miniWidth, miniHeight, width, height, MINIMAP_SCALE, COLOR32_MINIMAP);
|
|
209
|
+
}
|
|
210
|
+
// If cumulated diff is within threshold, treat as identical
|
|
211
|
+
if (cumulatedDiff <= cumulatedThreshold) {
|
|
212
|
+
return { diff: 0, cumulatedDiff: 0, hash: 0 };
|
|
213
|
+
}
|
|
214
|
+
return { diff: diffCount, cumulatedDiff, hash };
|
|
215
|
+
}
|
|
216
|
+
//# sourceMappingURL=diff.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"diff.js","sourceRoot":"","sources":["../../src/diff/diff.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* TestivAI Diff Engine — Ignore regions
|
|
3
|
+
*
|
|
4
|
+
* Before the diff loop runs, copy candidate pixel values into the
|
|
5
|
+
* baseline buffer for ignored regions. This makes ignored areas
|
|
6
|
+
* appear identical to the differ.
|
|
7
|
+
*/
|
|
8
|
+
import { IgnoreRegion } from './types';
|
|
9
|
+
/**
|
|
10
|
+
* Mask ignored regions by copying candidate pixels into baseline.
|
|
11
|
+
* After this, the diff loop will see no difference in those areas.
|
|
12
|
+
*
|
|
13
|
+
* Mutates `baseline` in place.
|
|
14
|
+
*
|
|
15
|
+
* @param baseline - Baseline pixel buffer (will be mutated)
|
|
16
|
+
* @param candidate - Candidate pixel buffer
|
|
17
|
+
* @param width - Image width
|
|
18
|
+
* @param height - Image height
|
|
19
|
+
* @param regions - Regions to ignore
|
|
20
|
+
*/
|
|
21
|
+
export declare function applyIgnoreRegions(baseline: Uint8Array | Uint8ClampedArray, candidate: Uint8Array | Uint8ClampedArray, width: number, height: number, regions: IgnoreRegion[]): void;
|
|
22
|
+
//# sourceMappingURL=ignore.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ignore.d.ts","sourceRoot":"","sources":["../../src/diff/ignore.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AAEvC;;;;;;;;;;;GAWG;AACH,wBAAgB,kBAAkB,CAChC,QAAQ,EAAE,UAAU,GAAG,iBAAiB,EACxC,SAAS,EAAE,UAAU,GAAG,iBAAiB,EACzC,KAAK,EAAE,MAAM,EACb,MAAM,EAAE,MAAM,EACd,OAAO,EAAE,YAAY,EAAE,GACtB,IAAI,CAoBN"}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* TestivAI Diff Engine — Ignore regions
|
|
4
|
+
*
|
|
5
|
+
* Before the diff loop runs, copy candidate pixel values into the
|
|
6
|
+
* baseline buffer for ignored regions. This makes ignored areas
|
|
7
|
+
* appear identical to the differ.
|
|
8
|
+
*/
|
|
9
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
10
|
+
exports.applyIgnoreRegions = applyIgnoreRegions;
|
|
11
|
+
/**
|
|
12
|
+
* Mask ignored regions by copying candidate pixels into baseline.
|
|
13
|
+
* After this, the diff loop will see no difference in those areas.
|
|
14
|
+
*
|
|
15
|
+
* Mutates `baseline` in place.
|
|
16
|
+
*
|
|
17
|
+
* @param baseline - Baseline pixel buffer (will be mutated)
|
|
18
|
+
* @param candidate - Candidate pixel buffer
|
|
19
|
+
* @param width - Image width
|
|
20
|
+
* @param height - Image height
|
|
21
|
+
* @param regions - Regions to ignore
|
|
22
|
+
*/
|
|
23
|
+
function applyIgnoreRegions(baseline, candidate, width, height, regions) {
|
|
24
|
+
for (const region of regions) {
|
|
25
|
+
// Clamp to image bounds
|
|
26
|
+
const x0 = Math.max(0, Math.min(region.x, width));
|
|
27
|
+
const y0 = Math.max(0, Math.min(region.y, height));
|
|
28
|
+
const x1 = Math.max(0, Math.min(region.x + region.width, width));
|
|
29
|
+
const y1 = Math.max(0, Math.min(region.y + region.height, height));
|
|
30
|
+
for (let y = y0; y < y1; y++) {
|
|
31
|
+
const rowOffset = y * width * 4;
|
|
32
|
+
for (let x = x0; x < x1; x++) {
|
|
33
|
+
const pixelOffset = rowOffset + x * 4;
|
|
34
|
+
// Copy RGBA from candidate to baseline
|
|
35
|
+
baseline[pixelOffset] = candidate[pixelOffset];
|
|
36
|
+
baseline[pixelOffset + 1] = candidate[pixelOffset + 1];
|
|
37
|
+
baseline[pixelOffset + 2] = candidate[pixelOffset + 2];
|
|
38
|
+
baseline[pixelOffset + 3] = candidate[pixelOffset + 3];
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
//# sourceMappingURL=ignore.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ignore.js","sourceRoot":"","sources":["../../src/diff/ignore.ts"],"names":[],"mappings":";AAAA;;;;;;GAMG;;AAgBH,gDA0BC;AAtCD;;;;;;;;;;;GAWG;AACH,SAAgB,kBAAkB,CAChC,QAAwC,EACxC,SAAyC,EACzC,KAAa,EACb,MAAc,EACd,OAAuB;IAEvB,KAAK,MAAM,MAAM,IAAI,OAAO,EAAE,CAAC;QAC7B,wBAAwB;QACxB,MAAM,EAAE,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC,CAAC;QAClD,MAAM,EAAE,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,EAAE,MAAM,CAAC,CAAC,CAAC;QACnD,MAAM,EAAE,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,GAAG,MAAM,CAAC,KAAK,EAAE,KAAK,CAAC,CAAC,CAAC;QACjE,MAAM,EAAE,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC;QAEnE,KAAK,IAAI,CAAC,GAAG,EAAE,EAAE,CAAC,GAAG,EAAE,EAAE,CAAC,EAAE,EAAE,CAAC;YAC7B,MAAM,SAAS,GAAG,CAAC,GAAG,KAAK,GAAG,CAAC,CAAC;YAChC,KAAK,IAAI,CAAC,GAAG,EAAE,EAAE,CAAC,GAAG,EAAE,EAAE,CAAC,EAAE,EAAE,CAAC;gBAC7B,MAAM,WAAW,GAAG,SAAS,GAAG,CAAC,GAAG,CAAC,CAAC;gBACtC,uCAAuC;gBACvC,QAAQ,CAAC,WAAW,CAAC,GAAG,SAAS,CAAC,WAAW,CAAC,CAAC;gBAC/C,QAAQ,CAAC,WAAW,GAAG,CAAC,CAAC,GAAG,SAAS,CAAC,WAAW,GAAG,CAAC,CAAC,CAAC;gBACvD,QAAQ,CAAC,WAAW,GAAG,CAAC,CAAC,GAAG,SAAS,CAAC,WAAW,GAAG,CAAC,CAAC,CAAC;gBACvD,QAAQ,CAAC,WAAW,GAAG,CAAC,CAAC,GAAG,SAAS,CAAC,WAAW,GAAG,CAAC,CAAC,CAAC;YACzD,CAAC;QACH,CAAC;IACH,CAAC;AACH,CAAC"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* TestivAI Diff Engine
|
|
3
|
+
*
|
|
4
|
+
* Pixel-level visual comparison engine forked from pixel-buffer-diff (Pbd)
|
|
5
|
+
* by @p01 (MIT license). Extended with ignore regions, size mismatch
|
|
6
|
+
* handling, region detection, and TypeScript support.
|
|
7
|
+
*
|
|
8
|
+
* @see https://github.com/p01/pixel-buffer-diff
|
|
9
|
+
*/
|
|
10
|
+
export { diff } from './diff';
|
|
11
|
+
export { applyIgnoreRegions } from './ignore';
|
|
12
|
+
export { applyMinimap } from './minimap';
|
|
13
|
+
export { normalizeDimensions } from './resize';
|
|
14
|
+
export { detectRegions } from './regions';
|
|
15
|
+
export type { DiffOptions, DiffResult, DiffRegion, IgnoreRegion, SizeMismatch, PbdRawResult, } from './types';
|
|
16
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/diff/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,EAAE,IAAI,EAAE,MAAM,QAAQ,CAAC;AAC9B,OAAO,EAAE,kBAAkB,EAAE,MAAM,UAAU,CAAC;AAC9C,OAAO,EAAE,YAAY,EAAE,MAAM,WAAW,CAAC;AACzC,OAAO,EAAE,mBAAmB,EAAE,MAAM,UAAU,CAAC;AAC/C,OAAO,EAAE,aAAa,EAAE,MAAM,WAAW,CAAC;AAC1C,YAAY,EACV,WAAW,EACX,UAAU,EACV,UAAU,EACV,YAAY,EACZ,YAAY,EACZ,YAAY,GACb,MAAM,SAAS,CAAC"}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* TestivAI Diff Engine
|
|
4
|
+
*
|
|
5
|
+
* Pixel-level visual comparison engine forked from pixel-buffer-diff (Pbd)
|
|
6
|
+
* by @p01 (MIT license). Extended with ignore regions, size mismatch
|
|
7
|
+
* handling, region detection, and TypeScript support.
|
|
8
|
+
*
|
|
9
|
+
* @see https://github.com/p01/pixel-buffer-diff
|
|
10
|
+
*/
|
|
11
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
|
+
exports.detectRegions = exports.normalizeDimensions = exports.applyMinimap = exports.applyIgnoreRegions = exports.diff = void 0;
|
|
13
|
+
var diff_1 = require("./diff");
|
|
14
|
+
Object.defineProperty(exports, "diff", { enumerable: true, get: function () { return diff_1.diff; } });
|
|
15
|
+
var ignore_1 = require("./ignore");
|
|
16
|
+
Object.defineProperty(exports, "applyIgnoreRegions", { enumerable: true, get: function () { return ignore_1.applyIgnoreRegions; } });
|
|
17
|
+
var minimap_1 = require("./minimap");
|
|
18
|
+
Object.defineProperty(exports, "applyMinimap", { enumerable: true, get: function () { return minimap_1.applyMinimap; } });
|
|
19
|
+
var resize_1 = require("./resize");
|
|
20
|
+
Object.defineProperty(exports, "normalizeDimensions", { enumerable: true, get: function () { return resize_1.normalizeDimensions; } });
|
|
21
|
+
var regions_1 = require("./regions");
|
|
22
|
+
Object.defineProperty(exports, "detectRegions", { enumerable: true, get: function () { return regions_1.detectRegions; } });
|
|
23
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/diff/index.ts"],"names":[],"mappings":";AAAA;;;;;;;;GAQG;;;AAEH,+BAA8B;AAArB,4FAAA,IAAI,OAAA;AACb,mCAA8C;AAArC,4GAAA,kBAAkB,OAAA;AAC3B,qCAAyC;AAAhC,uGAAA,YAAY,OAAA;AACrB,mCAA+C;AAAtC,6GAAA,mBAAmB,OAAA;AAC5B,qCAA0C;AAAjC,wGAAA,aAAa,OAAA"}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* TestivAI Diff Engine — Minimap overlay
|
|
3
|
+
*
|
|
4
|
+
* Applies a low-resolution overlay on the diff buffer to help
|
|
5
|
+
* spot isolated pixel changes at a glance.
|
|
6
|
+
*
|
|
7
|
+
* Ported from pixel-buffer-diff by @p01, licensed under MIT.
|
|
8
|
+
*/
|
|
9
|
+
/**
|
|
10
|
+
* Apply minimap overlay to the diff buffer.
|
|
11
|
+
* Regions with any changed pixels get a colored tint.
|
|
12
|
+
*
|
|
13
|
+
* @param diff32 - Diff image as Uint32Array
|
|
14
|
+
* @param miniMap - Minimap cell hit counts
|
|
15
|
+
* @param miniWidth - Number of minimap columns
|
|
16
|
+
* @param miniHeight - Number of minimap rows
|
|
17
|
+
* @param width - Full image width
|
|
18
|
+
* @param height - Full image height
|
|
19
|
+
* @param scale - Pixels per minimap cell (e.g. 128)
|
|
20
|
+
* @param color - 32-bit ABGR color to OR into diff pixels
|
|
21
|
+
*/
|
|
22
|
+
export declare function applyMinimap(diff32: Uint32Array, miniMap: Uint8ClampedArray, miniWidth: number, miniHeight: number, width: number, height: number, scale: number, color: number): void;
|
|
23
|
+
//# sourceMappingURL=minimap.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"minimap.d.ts","sourceRoot":"","sources":["../../src/diff/minimap.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH;;;;;;;;;;;;GAYG;AACH,wBAAgB,YAAY,CAC1B,MAAM,EAAE,WAAW,EACnB,OAAO,EAAE,iBAAiB,EAC1B,SAAS,EAAE,MAAM,EACjB,UAAU,EAAE,MAAM,EAClB,KAAK,EAAE,MAAM,EACb,MAAM,EAAE,MAAM,EACd,KAAK,EAAE,MAAM,EACb,KAAK,EAAE,MAAM,GACZ,IAAI,CAkBN"}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* TestivAI Diff Engine — Minimap overlay
|
|
4
|
+
*
|
|
5
|
+
* Applies a low-resolution overlay on the diff buffer to help
|
|
6
|
+
* spot isolated pixel changes at a glance.
|
|
7
|
+
*
|
|
8
|
+
* Ported from pixel-buffer-diff by @p01, licensed under MIT.
|
|
9
|
+
*/
|
|
10
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
11
|
+
exports.applyMinimap = applyMinimap;
|
|
12
|
+
/**
|
|
13
|
+
* Apply minimap overlay to the diff buffer.
|
|
14
|
+
* Regions with any changed pixels get a colored tint.
|
|
15
|
+
*
|
|
16
|
+
* @param diff32 - Diff image as Uint32Array
|
|
17
|
+
* @param miniMap - Minimap cell hit counts
|
|
18
|
+
* @param miniWidth - Number of minimap columns
|
|
19
|
+
* @param miniHeight - Number of minimap rows
|
|
20
|
+
* @param width - Full image width
|
|
21
|
+
* @param height - Full image height
|
|
22
|
+
* @param scale - Pixels per minimap cell (e.g. 128)
|
|
23
|
+
* @param color - 32-bit ABGR color to OR into diff pixels
|
|
24
|
+
*/
|
|
25
|
+
function applyMinimap(diff32, miniMap, miniWidth, miniHeight, width, height, scale, color) {
|
|
26
|
+
for (let i = 0; i < miniWidth * miniHeight; i++) {
|
|
27
|
+
if (miniMap[i] > 0) {
|
|
28
|
+
const miniX = i % miniWidth;
|
|
29
|
+
const miniY = (i / miniWidth) | 0;
|
|
30
|
+
const x0 = miniX * scale;
|
|
31
|
+
const x1 = Math.min(x0 + scale, width);
|
|
32
|
+
const y0 = miniY * scale;
|
|
33
|
+
const y1 = Math.min(y0 + scale, height);
|
|
34
|
+
for (let y = y0; y < y1; y++) {
|
|
35
|
+
let d32i = x0 + y * width;
|
|
36
|
+
for (let x = x0; x < x1; x++) {
|
|
37
|
+
diff32[d32i++] |= color;
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
//# sourceMappingURL=minimap.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"minimap.js","sourceRoot":"","sources":["../../src/diff/minimap.ts"],"names":[],"mappings":";AAAA;;;;;;;GAOG;;AAeH,oCA2BC;AAxCD;;;;;;;;;;;;GAYG;AACH,SAAgB,YAAY,CAC1B,MAAmB,EACnB,OAA0B,EAC1B,SAAiB,EACjB,UAAkB,EAClB,KAAa,EACb,MAAc,EACd,KAAa,EACb,KAAa;IAEb,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,SAAS,GAAG,UAAU,EAAE,CAAC,EAAE,EAAE,CAAC;QAChD,IAAI,OAAO,CAAC,CAAC,CAAC,GAAG,CAAC,EAAE,CAAC;YACnB,MAAM,KAAK,GAAG,CAAC,GAAG,SAAS,CAAC;YAC5B,MAAM,KAAK,GAAG,CAAC,CAAC,GAAG,SAAS,CAAC,GAAG,CAAC,CAAC;YAClC,MAAM,EAAE,GAAG,KAAK,GAAG,KAAK,CAAC;YACzB,MAAM,EAAE,GAAG,IAAI,CAAC,GAAG,CAAC,EAAE,GAAG,KAAK,EAAE,KAAK,CAAC,CAAC;YACvC,MAAM,EAAE,GAAG,KAAK,GAAG,KAAK,CAAC;YACzB,MAAM,EAAE,GAAG,IAAI,CAAC,GAAG,CAAC,EAAE,GAAG,KAAK,EAAE,MAAM,CAAC,CAAC;YAExC,KAAK,IAAI,CAAC,GAAG,EAAE,EAAE,CAAC,GAAG,EAAE,EAAE,CAAC,EAAE,EAAE,CAAC;gBAC7B,IAAI,IAAI,GAAG,EAAE,GAAG,CAAC,GAAG,KAAK,CAAC;gBAC1B,KAAK,IAAI,CAAC,GAAG,EAAE,EAAE,CAAC,GAAG,EAAE,EAAE,CAAC,EAAE,EAAE,CAAC;oBAC7B,MAAM,CAAC,IAAI,EAAE,CAAC,IAAI,KAAK,CAAC;gBAC1B,CAAC;YACH,CAAC;QACH,CAAC;IACH,CAAC;AACH,CAAC"}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* TestivAI Diff Engine — Region bounding box detection
|
|
3
|
+
*
|
|
4
|
+
* Scans the diff output buffer for non-zero (changed) pixels
|
|
5
|
+
* and groups them into rectangular bounding boxes using a simple
|
|
6
|
+
* connected-component labeling approach.
|
|
7
|
+
*/
|
|
8
|
+
import { DiffRegion } from './types';
|
|
9
|
+
/**
|
|
10
|
+
* Detect regions of change in the diff buffer.
|
|
11
|
+
*
|
|
12
|
+
* Scans for non-transparent pixels (any pixel with alpha > 0 in
|
|
13
|
+
* the diff output), groups adjacent changed pixels into rectangular
|
|
14
|
+
* bounding boxes, and filters out regions smaller than minSize.
|
|
15
|
+
*
|
|
16
|
+
* @param diff8 - Diff image pixel buffer (RGBA)
|
|
17
|
+
* @param width - Image width
|
|
18
|
+
* @param height - Image height
|
|
19
|
+
* @param minSize - Minimum pixels to include a region (default: 10)
|
|
20
|
+
* @returns Array of DiffRegion bounding boxes
|
|
21
|
+
*/
|
|
22
|
+
export declare function detectRegions(diff8: Uint8Array | Uint8ClampedArray, width: number, height: number, minSize?: number): DiffRegion[];
|
|
23
|
+
//# sourceMappingURL=regions.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"regions.d.ts","sourceRoot":"","sources":["../../src/diff/regions.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AAErC;;;;;;;;;;;;GAYG;AACH,wBAAgB,aAAa,CAC3B,KAAK,EAAE,UAAU,GAAG,iBAAiB,EACrC,KAAK,EAAE,MAAM,EACb,MAAM,EAAE,MAAM,EACd,OAAO,GAAE,MAAW,GACnB,UAAU,EAAE,CAkHd"}
|
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* TestivAI Diff Engine — Region bounding box detection
|
|
4
|
+
*
|
|
5
|
+
* Scans the diff output buffer for non-zero (changed) pixels
|
|
6
|
+
* and groups them into rectangular bounding boxes using a simple
|
|
7
|
+
* connected-component labeling approach.
|
|
8
|
+
*/
|
|
9
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
10
|
+
exports.detectRegions = detectRegions;
|
|
11
|
+
/**
|
|
12
|
+
* Detect regions of change in the diff buffer.
|
|
13
|
+
*
|
|
14
|
+
* Scans for non-transparent pixels (any pixel with alpha > 0 in
|
|
15
|
+
* the diff output), groups adjacent changed pixels into rectangular
|
|
16
|
+
* bounding boxes, and filters out regions smaller than minSize.
|
|
17
|
+
*
|
|
18
|
+
* @param diff8 - Diff image pixel buffer (RGBA)
|
|
19
|
+
* @param width - Image width
|
|
20
|
+
* @param height - Image height
|
|
21
|
+
* @param minSize - Minimum pixels to include a region (default: 10)
|
|
22
|
+
* @returns Array of DiffRegion bounding boxes
|
|
23
|
+
*/
|
|
24
|
+
function detectRegions(diff8, width, height, minSize = 10) {
|
|
25
|
+
// Build a binary grid: 1 = changed pixel, 0 = unchanged
|
|
26
|
+
const changed = new Uint8Array(width * height);
|
|
27
|
+
for (let y = 0; y < height; y++) {
|
|
28
|
+
for (let x = 0; x < width; x++) {
|
|
29
|
+
const idx = (y * width + x) * 4;
|
|
30
|
+
// A pixel is considered "changed" if it has any non-zero alpha
|
|
31
|
+
// in the diff buffer (the diff engine writes colored pixels for changes)
|
|
32
|
+
if (diff8[idx + 3] > 0) {
|
|
33
|
+
changed[y * width + x] = 1;
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
// Connected-component labeling using union-find
|
|
38
|
+
const labels = new Int32Array(width * height).fill(-1);
|
|
39
|
+
const parent = [];
|
|
40
|
+
let nextLabel = 0;
|
|
41
|
+
function find(x) {
|
|
42
|
+
while (parent[x] !== x) {
|
|
43
|
+
parent[x] = parent[parent[x]]; // path compression
|
|
44
|
+
x = parent[x];
|
|
45
|
+
}
|
|
46
|
+
return x;
|
|
47
|
+
}
|
|
48
|
+
function union(a, b) {
|
|
49
|
+
const ra = find(a);
|
|
50
|
+
const rb = find(b);
|
|
51
|
+
if (ra !== rb) {
|
|
52
|
+
parent[rb] = ra;
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
// First pass: assign labels
|
|
56
|
+
for (let y = 0; y < height; y++) {
|
|
57
|
+
for (let x = 0; x < width; x++) {
|
|
58
|
+
const idx = y * width + x;
|
|
59
|
+
if (!changed[idx])
|
|
60
|
+
continue;
|
|
61
|
+
const neighbors = [];
|
|
62
|
+
// Check left
|
|
63
|
+
if (x > 0 && labels[idx - 1] >= 0) {
|
|
64
|
+
neighbors.push(labels[idx - 1]);
|
|
65
|
+
}
|
|
66
|
+
// Check above
|
|
67
|
+
if (y > 0 && labels[idx - width] >= 0) {
|
|
68
|
+
neighbors.push(labels[idx - width]);
|
|
69
|
+
}
|
|
70
|
+
if (neighbors.length === 0) {
|
|
71
|
+
// New label
|
|
72
|
+
labels[idx] = nextLabel;
|
|
73
|
+
parent.push(nextLabel);
|
|
74
|
+
nextLabel++;
|
|
75
|
+
}
|
|
76
|
+
else {
|
|
77
|
+
// Use the smallest label
|
|
78
|
+
const minLabel = Math.min(...neighbors.map(find));
|
|
79
|
+
labels[idx] = minLabel;
|
|
80
|
+
// Union all neighbor labels
|
|
81
|
+
for (const n of neighbors) {
|
|
82
|
+
union(minLabel, n);
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
// Second pass: collect bounding boxes per component
|
|
88
|
+
const boxes = new Map();
|
|
89
|
+
for (let y = 0; y < height; y++) {
|
|
90
|
+
for (let x = 0; x < width; x++) {
|
|
91
|
+
const idx = y * width + x;
|
|
92
|
+
if (labels[idx] < 0)
|
|
93
|
+
continue;
|
|
94
|
+
const root = find(labels[idx]);
|
|
95
|
+
const box = boxes.get(root);
|
|
96
|
+
if (box) {
|
|
97
|
+
box.x0 = Math.min(box.x0, x);
|
|
98
|
+
box.y0 = Math.min(box.y0, y);
|
|
99
|
+
box.x1 = Math.max(box.x1, x);
|
|
100
|
+
box.y1 = Math.max(box.y1, y);
|
|
101
|
+
box.count++;
|
|
102
|
+
}
|
|
103
|
+
else {
|
|
104
|
+
boxes.set(root, { x0: x, y0: y, x1: x, y1: y, count: 1 });
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
// Convert to DiffRegion array, filtering by minSize
|
|
109
|
+
const regions = [];
|
|
110
|
+
for (const box of boxes.values()) {
|
|
111
|
+
if (box.count < minSize)
|
|
112
|
+
continue;
|
|
113
|
+
const regionWidth = box.x1 - box.x0 + 1;
|
|
114
|
+
const regionHeight = box.y1 - box.y0 + 1;
|
|
115
|
+
const regionArea = regionWidth * regionHeight;
|
|
116
|
+
regions.push({
|
|
117
|
+
x: box.x0,
|
|
118
|
+
y: box.y0,
|
|
119
|
+
width: regionWidth,
|
|
120
|
+
height: regionHeight,
|
|
121
|
+
diffPixels: box.count,
|
|
122
|
+
diffPercent: regionArea > 0 ? (box.count / regionArea) * 100 : 0,
|
|
123
|
+
});
|
|
124
|
+
}
|
|
125
|
+
// Sort by position (top-left first)
|
|
126
|
+
regions.sort((a, b) => a.y - b.y || a.x - b.x);
|
|
127
|
+
return regions;
|
|
128
|
+
}
|
|
129
|
+
//# sourceMappingURL=regions.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"regions.js","sourceRoot":"","sources":["../../src/diff/regions.ts"],"names":[],"mappings":"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"}
|