renderdiff 0.0.0-stage → 0.1.0

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.
@@ -0,0 +1,86 @@
1
+ import type { Shot } from "./capture.ts";
2
+ /**
3
+ * Pixel diff between two shots. sharp decodes/pads/encodes, pixelmatch compares.
4
+ *
5
+ * No pngjs: it exists to bridge PNG<->raw RGBA, and sharp already is that bridge.
6
+ *
7
+ * pixelmatch rather than sharp's `composite({blend:"difference"})`, which yields a
8
+ * per-channel mean rather than a thresholded count and has no anti-aliasing
9
+ * tolerance. That tolerance is the point — two DOM structures painting the same text
10
+ * in the same place still disagree on subpixels, so `includeAA:false` is what keeps
11
+ * the score from being noise.
12
+ */
13
+ /**
14
+ * A connected patch of differing pixels, snapped outward to the 16px grid, in left page px.
15
+ * With bands it comes from the realigned rows, so content a band merely pushed down isn't one.
16
+ */
17
+ export interface Region {
18
+ x: number;
19
+ y: number;
20
+ w: number;
21
+ h: number;
22
+ /** Differing pixels inside it. */
23
+ pixels: number;
24
+ }
25
+ /** Rows one side has that the other lacks, at `y` in that side's own coordinates. */
26
+ export interface Band {
27
+ side: "left" | "right";
28
+ y: number;
29
+ h: number;
30
+ }
31
+ /** Left is the changed version, right the reference: `added` is on left only, `removed` on right only. */
32
+ export interface TextDiff {
33
+ added: string[];
34
+ removed: string[];
35
+ }
36
+ export interface Diff {
37
+ /** 0..1, share of pixels that match. */
38
+ score: number;
39
+ diffPixels: number;
40
+ totalPixels: number;
41
+ /** Painted-height and -width deltas (left − right), straight from the PNGs. */
42
+ heightDelta: number;
43
+ widthDelta: number;
44
+ /** Largest first, within the area both shots cover; padding is the deltas and bands. */
45
+ regions: Region[];
46
+ /** Null when the rows were too different to align. */
47
+ bands: Band[] | null;
48
+ /** Share of matching pixels over the rows the alignment pairs. Null unless there are bands. */
49
+ alignedScore: number | null;
50
+ text: TextDiff;
51
+ diffPng: Buffer;
52
+ /** What to crop: bands, largest first, then regions. */
53
+ spots: Spot[];
54
+ }
55
+ export interface Box {
56
+ x: number;
57
+ y: number;
58
+ w: number;
59
+ h: number;
60
+ }
61
+ /** A change located on each side, in that side's page px. `h` 0 is where the other side's band would go. */
62
+ export interface Spot {
63
+ kind: "band" | "region";
64
+ left: Box;
65
+ right: Box;
66
+ }
67
+ export declare function compare(left: Shot, right: Shot): Promise<Diff>;
68
+ export declare const MAX_CROPS = 3;
69
+ export interface Crop {
70
+ png: Buffer;
71
+ kind: Spot["kind"];
72
+ left: Box;
73
+ right: Box;
74
+ /** Left on top (`stacked`) or on the left (`side`), always. */
75
+ layout: "stacked" | "side";
76
+ scale: number;
77
+ /** Only the top rows (or left columns) of the change fit the budget at `MIN_SCALE`. */
78
+ clipped: boolean;
79
+ }
80
+ /**
81
+ * Up to `MAX_CROPS` PNGs, one per spot in order: left and right at native scale (never below
82
+ * `MIN_SCALE`, clipped instead), each padded for context with a 1px red box around the change,
83
+ * or a 2px red seam where the other side's band would go. A full-page shot Read by an agent is
84
+ * downscaled past legibility; a crop isn't.
85
+ */
86
+ export declare function crops(left: Buffer, right: Buffer, spots: Spot[]): Promise<Crop[]>;
@@ -0,0 +1,486 @@
1
+ import pixelmatch from "pixelmatch";
2
+ import sharp, {} from "sharp";
3
+ import { MASK_COLOR } from "./config.js";
4
+ const PIXELMATCH = { threshold: 0.1, includeAA: false, alpha: 0.25 };
5
+ /** Edit-distance cap for `myers`: past it, memory is O(D²) and the answer is "unrelated" anyway. */
6
+ const MAX_EDIT = 2000;
7
+ const CELL = 16;
8
+ /** `MASK_COLOR` (#FF00FF, opaque) as one little-endian RGBA word. */
9
+ const MAGENTA = 0xffff00ff;
10
+ /**
11
+ * Pad a shot onto a common (w, h) canvas so both frames are the same size for
12
+ * pixelmatch, with the image top-left and magenta everywhere else.
13
+ *
14
+ * Composited onto a created canvas rather than `sharp.extend()`, which rejects any
15
+ * single edge past 10 000px. Two pages can easily differ by more than that — one long
16
+ * scrolling page against a short one — and that is exactly the case worth diffing.
17
+ */
18
+ const toRaw = (png, w, h) => sharp({
19
+ create: { width: w, height: h, channels: 4, background: MASK_COLOR },
20
+ })
21
+ .composite([{ input: png, left: 0, top: 0 }])
22
+ .raw()
23
+ .ensureAlpha()
24
+ .toBuffer();
25
+ export async function compare(left, right) {
26
+ // Real PNG dimensions, not the `scrollHeight` we measured: that can disagree with
27
+ // what Chromium actually painted.
28
+ const [lm, rm] = await Promise.all([
29
+ sharp(left.png).metadata(),
30
+ sharp(right.png).metadata(),
31
+ ]);
32
+ const lw = lm.width, lh = lm.height, rw = rm.width, rh = rm.height;
33
+ const w = Math.max(lw, rw);
34
+ const h = Math.max(lh, rh);
35
+ const [l, r] = await Promise.all([
36
+ toRaw(left.png, w, h),
37
+ toRaw(right.png, w, h),
38
+ ]);
39
+ const text = textDiff(left.text, right.text);
40
+ const out = Buffer.alloc(w * h * 4);
41
+ // Identical shots skip pixelmatch's grey drawing and leave the diff PNG fully transparent.
42
+ // `l`/`r`/`out` are Buffers, i.e. Uint8Arrays — pixelmatch takes them directly.
43
+ const diffPixels = l.equals(r) ? 0 : pixelmatch(l, r, out, w, h, PIXELMATCH);
44
+ // Default zlib level: the diff PNG is a local intermediate (mostly transparent with
45
+ // sparse red), so max compression buys little size for noticeably more CPU per job.
46
+ const diffPng = await sharp(out, {
47
+ raw: { width: w, height: h, channels: 4 },
48
+ })
49
+ .png()
50
+ .toBuffer();
51
+ const cw = Math.min(lw, rw);
52
+ const aligned = diffPixels
53
+ ? align(l, r, w, cw, lh, rh)
54
+ : { bands: [], alignedScore: null, regions: [], spots: [] };
55
+ const found = aligned.regions ?? regions(out, w, cw, Math.min(lh, rh));
56
+ const spots = aligned.regions
57
+ ? aligned.spots
58
+ : [
59
+ ...aligned.spots,
60
+ ...found.map(({ pixels, ...box }) => ({ kind: "region", left: box, right: box })),
61
+ ];
62
+ // Padding is magenta against real content, so a height difference lands in
63
+ // `diffPixels` and drags the score down. Intended: a page 400px shorter than the
64
+ // one it's compared against has not reached parity. `heightDelta` names the cause.
65
+ return {
66
+ score: 1 - diffPixels / (w * h),
67
+ diffPixels,
68
+ totalPixels: w * h,
69
+ heightDelta: lh - rh,
70
+ widthDelta: lw - rw,
71
+ regions: found,
72
+ bands: aligned.bands,
73
+ alignedScore: aligned.alignedScore,
74
+ text,
75
+ diffPng,
76
+ spots,
77
+ };
78
+ }
79
+ /**
80
+ * Myers' O((N+M)·D) diff: the matched index pairs of a shortest edit script, in order.
81
+ * Null once the edit distance passes `maxD`, unless the edit is one pure insertion or deletion.
82
+ */
83
+ function myers(a, b, maxD = MAX_EDIT) {
84
+ const n = a.length, m = b.length;
85
+ let p = 0, s = 0;
86
+ while (p < n && p < m && a[p] === b[p])
87
+ p++;
88
+ while (s < n - p && s < m - p && a[n - 1 - s] === b[m - 1 - s])
89
+ s++;
90
+ if (p + s === n || p + s === m) {
91
+ const pairs = [];
92
+ for (let i = 0; i < p; i++)
93
+ pairs.push([i, i]);
94
+ for (let i = s; i > 0; i--)
95
+ pairs.push([n - i, m - i]);
96
+ return pairs;
97
+ }
98
+ const max = Math.min(n + m, maxD), off = max + 1;
99
+ const v = new Int32Array(2 * max + 3);
100
+ // trace[d][k + d] is v[k] after round d.
101
+ const trace = [];
102
+ for (let d = 0; d <= max; d++) {
103
+ for (let k = -d; k <= d; k += 2) {
104
+ let x = k === -d || (k !== d && v[off + k - 1] < v[off + k + 1])
105
+ ? v[off + k + 1]
106
+ : v[off + k - 1] + 1;
107
+ let y = x - k;
108
+ while (x < n && y < m && a[x] === b[y])
109
+ x++, y++;
110
+ v[off + k] = x;
111
+ if (x >= n && y >= m)
112
+ return backtrack(trace, n, m, d);
113
+ }
114
+ trace.push(v.slice(off - d, off + d + 1));
115
+ }
116
+ return null;
117
+ }
118
+ function backtrack(trace, n, m, D) {
119
+ const pairs = [];
120
+ let x = n, y = m;
121
+ for (let d = D; d > 0; d--) {
122
+ const p = trace[d - 1];
123
+ const at = (k) => p[k + d - 1];
124
+ const k = x - y;
125
+ const pk = k === -d || (k !== d && at(k - 1) < at(k + 1)) ? k + 1 : k - 1;
126
+ const px = at(pk), py = px - pk;
127
+ while (x > px && y > py)
128
+ pairs.push([--x, --y]);
129
+ x = px;
130
+ y = py;
131
+ }
132
+ while (x > 0 && y > 0)
133
+ pairs.push([--x, --y]);
134
+ return pairs.reverse();
135
+ }
136
+ function textDiff(a, b) {
137
+ const pairs = myers(a, b);
138
+ if (!pairs) {
139
+ // Too different to align: fall back to plain membership.
140
+ const inA = new Set(a), inB = new Set(b);
141
+ return {
142
+ added: a.filter((s) => !inB.has(s)),
143
+ removed: b.filter((s) => !inA.has(s)),
144
+ };
145
+ }
146
+ const ka = new Set(pairs.map((p) => p[0])), kb = new Set(pairs.map((p) => p[1]));
147
+ return {
148
+ added: a.filter((_, i) => !ka.has(i)),
149
+ removed: b.filter((_, i) => !kb.has(i)),
150
+ };
151
+ }
152
+ /**
153
+ * Connected components (8-way) over 16px cells holding any pixel pixelmatch painted as a diff,
154
+ * within the top-left `w`×`h` of the `stride`-wide diff.
155
+ */
156
+ function regions(out, stride, w, h) {
157
+ const cw = Math.ceil(w / CELL), ch = Math.ceil(h / CELL);
158
+ const cells = new Uint32Array(cw * ch);
159
+ for (let y = 0; y < h; y++) {
160
+ const row = ((y / CELL) | 0) * cw;
161
+ for (let x = 0, o = y * stride * 4; x < w; x++, o += 4) {
162
+ // diffColor red; unchanged pixels are grey and AA ones yellow, so neither matches.
163
+ if (out[o] === 255 && out[o + 1] === 0 && out[o + 2] === 0) {
164
+ cells[row + ((x / CELL) | 0)]++;
165
+ }
166
+ }
167
+ }
168
+ const seen = new Uint8Array(cells.length);
169
+ const found = [];
170
+ for (let s = 0; s < cells.length; s++) {
171
+ if (!cells[s] || seen[s])
172
+ continue;
173
+ let x0 = cw, y0 = ch, x1 = 0, y1 = 0, pixels = 0;
174
+ const stack = [s];
175
+ seen[s] = 1;
176
+ while (stack.length) {
177
+ const c = stack.pop(), cx = c % cw, cy = (c / cw) | 0;
178
+ pixels += cells[c];
179
+ x0 = Math.min(x0, cx);
180
+ x1 = Math.max(x1, cx);
181
+ y0 = Math.min(y0, cy);
182
+ y1 = Math.max(y1, cy);
183
+ for (let ny = Math.max(0, cy - 1); ny <= Math.min(ch - 1, cy + 1); ny++) {
184
+ for (let nx = Math.max(0, cx - 1); nx <= Math.min(cw - 1, cx + 1); nx++) {
185
+ const nc = ny * cw + nx;
186
+ if (cells[nc] && !seen[nc]) {
187
+ seen[nc] = 1;
188
+ stack.push(nc);
189
+ }
190
+ }
191
+ }
192
+ }
193
+ found.push({
194
+ x: x0 * CELL,
195
+ y: y0 * CELL,
196
+ w: Math.min(w, (x1 + 1) * CELL) - x0 * CELL,
197
+ h: Math.min(h, (y1 + 1) * CELL) - y0 * CELL,
198
+ pixels,
199
+ });
200
+ }
201
+ return found.sort((a, b) => b.pixels - a.pixels);
202
+ }
203
+ /** FNV-1a over each row's RGBA words. */
204
+ function rowHashes(raw, w, rows) {
205
+ const px = new Uint32Array(raw.buffer, raw.byteOffset, w * rows);
206
+ const out = new Uint32Array(rows);
207
+ for (let y = 0; y < rows; y++) {
208
+ let hash = 0x811c9dc5;
209
+ for (let i = y * w, end = i + w; i < end; i++) {
210
+ hash = Math.imul(hash ^ px[i], 16777619);
211
+ }
212
+ out[y] = hash;
213
+ }
214
+ return out;
215
+ }
216
+ /**
217
+ * Myers can place an insertion anywhere along a stretch of identical rows (whitespace, a
218
+ * repeated border) and split one insertion in two. As git does, slide each run of unmatched
219
+ * rows up as far as it goes, then down, merging runs that meet, so it settles in one piece at
220
+ * the bottom of that stretch. The matched rows still read the same values in the same order.
221
+ */
222
+ function compact(hash, changed) {
223
+ const n = changed.length;
224
+ for (let s = 0; s < n; s++) {
225
+ if (!changed[s])
226
+ continue;
227
+ let e = s;
228
+ while (e < n && changed[e])
229
+ e++;
230
+ for (;;) {
231
+ while (s > 0 && !changed[s - 1] && hash[s - 1] === hash[e - 1]) {
232
+ changed[--s] = 1;
233
+ changed[--e] = 0;
234
+ }
235
+ if (!(s > 0 && changed[s - 1]))
236
+ break;
237
+ while (s > 0 && changed[s - 1])
238
+ s--;
239
+ }
240
+ for (;;) {
241
+ while (e < n && !changed[e] && hash[s] === hash[e]) {
242
+ changed[s++] = 0;
243
+ changed[e++] = 1;
244
+ }
245
+ if (!(e < n && changed[e]))
246
+ break;
247
+ while (e < n && changed[e])
248
+ e++;
249
+ }
250
+ s = e;
251
+ }
252
+ }
253
+ /**
254
+ * Pair rows across the two shots by Myers over row hashes. Each gap between matched rows
255
+ * pairs its rows top-down; whatever one side has left over is a band. Paired rows are
256
+ * restacked and pixelmatched for the aligned score and for regions, mapped back to each side.
257
+ * `regions` is null when there is nothing realigned to take them from.
258
+ */
259
+ function align(l, r, w, cw, lh, rh) {
260
+ const ha = rowHashes(l, w, lh), hb = rowHashes(r, w, rh);
261
+ const matched = myers(ha, hb);
262
+ if (!matched) {
263
+ return { bands: lh === rh ? [] : null, alignedScore: null, regions: null, spots: [] };
264
+ }
265
+ const ca = new Uint8Array(lh).fill(1), cb = new Uint8Array(rh).fill(1);
266
+ for (const [i, j] of matched)
267
+ ca[i] = cb[j] = 0;
268
+ const raw = pairUp(ca, cb);
269
+ compact(ha, ca);
270
+ compact(hb, cb);
271
+ const packed = pairUp(ca, cb);
272
+ // Compacting each side alone can misalign their gaps and turn an in-place change into a band pair.
273
+ const height = (p) => p.bands.reduce((t, b) => t + b.h, 0);
274
+ const { bands, at, rows } = inPlace(height(packed) <= height(raw) ? packed : raw, ha, hb);
275
+ // A band is rows on one side and a zero-height seam on the other, as wide as what's drawn in it.
276
+ const spots = bands
277
+ .map((b, i) => {
278
+ const { x, w: bw } = inkX(b.side === "left" ? l : r, w, cw, b.y, b.y + b.h);
279
+ const here = { x, y: b.y, w: bw, h: b.h };
280
+ const seam = { x, y: at[i], w: bw, h: 0 };
281
+ return { kind: "band", left: b.side === "left" ? here : seam, right: b.side === "right" ? here : seam };
282
+ })
283
+ .sort((a, b) => b.left.h + b.right.h - (a.left.h + a.right.h));
284
+ if (!bands.length || !rows.length)
285
+ return { bands, alignedScore: null, regions: null, spots };
286
+ const stride = w * 4;
287
+ const a = Buffer.alloc(rows.length * stride), b = Buffer.alloc(rows.length * stride);
288
+ rows.forEach(([ly, ry], j) => {
289
+ l.copy(a, j * stride, ly * stride, (ly + 1) * stride);
290
+ r.copy(b, j * stride, ry * stride, (ry + 1) * stride);
291
+ });
292
+ // Unstable pixels and masks are magenta at page coordinates, which a band shifts apart.
293
+ const pa = new Uint32Array(a.buffer, a.byteOffset, rows.length * w), pb = new Uint32Array(b.buffer, b.byteOffset, rows.length * w);
294
+ let masked = 0;
295
+ for (let i = 0; i < pa.length; i++) {
296
+ if (pa[i] === MAGENTA || pb[i] === MAGENTA) {
297
+ pa[i] = pb[i] = MAGENTA;
298
+ masked++;
299
+ }
300
+ }
301
+ const out = Buffer.alloc(rows.length * stride);
302
+ const diff = pixelmatch(a, b, out, w, rows.length, PIXELMATCH);
303
+ const measured = rows.length * w - masked;
304
+ const found = diff ? regions(out, w, cw, rows.length) : [];
305
+ const side = (g, s) => {
306
+ const y = rows[g.y][s];
307
+ return { y, h: rows[g.y + g.h - 1][s] + 1 - y };
308
+ };
309
+ for (const { pixels, ...g } of found) {
310
+ spots.push({ kind: "region", left: { ...g, ...side(g, 0) }, right: { ...g, ...side(g, 1) } });
311
+ }
312
+ return {
313
+ bands,
314
+ alignedScore: measured > 0 ? 1 - diff / measured : null,
315
+ regions: found.map((g) => ({ ...g, ...side(g, 0) })),
316
+ spots,
317
+ };
318
+ }
319
+ /**
320
+ * A recolour inside a run of identical rows comes out of Myers as a left band and a right band
321
+ * of the same height. When pairing the span straight leaves every row outside the two bands
322
+ * identical, that is one change in place: pair it row for row, so it reads as a region. A
323
+ * block removed at one place and another added elsewhere fails that test and stays two bands.
324
+ */
325
+ function inPlace(p, ha, hb) {
326
+ let { bands, at, rows } = p;
327
+ for (let i = 0; i + 1 < bands.length; i++) {
328
+ const [a, b] = [bands[i], bands[i + 1]];
329
+ if (a.side === b.side || a.h !== b.h)
330
+ continue;
331
+ const ls = a.side === "left" ? a.y : at[i], rs = a.side === "right" ? a.y : at[i];
332
+ const le = b.side === "left" ? b.y + b.h : at[i + 1], re = b.side === "right" ? b.y + b.h : at[i + 1];
333
+ if (le - ls !== re - rs)
334
+ continue;
335
+ const span = Array.from({ length: le - ls }, (_, k) => [ls + k, rs + k]);
336
+ const inBand = (side, y) => [a, b].some((n) => n.side === side && y >= n.y && y < n.y + n.h);
337
+ // Matched rows always hash alike, so test the straight pairing about to replace them.
338
+ if (!span.every(([ly, ry]) => inBand("left", ly) || inBand("right", ry) || ha[ly] === hb[ry]))
339
+ continue;
340
+ rows = [...rows.filter(([ly]) => ly < ls), ...span, ...rows.filter(([ly]) => ly >= le)];
341
+ bands = bands.filter((_, j) => j !== i && j !== i + 1);
342
+ at = at.filter((_, j) => j !== i && j !== i + 1);
343
+ i--;
344
+ }
345
+ return { bands, at, rows };
346
+ }
347
+ /** Columns holding anything but each row's x=0 colour, over rows `y0..y1`; the full width if none. */
348
+ function inkX(raw, stride, w, y0, y1) {
349
+ const px = new Uint32Array(raw.buffer, raw.byteOffset, raw.length / 4);
350
+ let x0 = w, x1 = -1;
351
+ for (let y = y0; y < y1; y++) {
352
+ const bg = px[y * stride];
353
+ for (let x = 0; x < w; x++) {
354
+ if (px[y * stride + x] !== bg) {
355
+ x0 = Math.min(x0, x);
356
+ x1 = Math.max(x1, x);
357
+ }
358
+ }
359
+ }
360
+ return x1 < 0 ? { x: 0, w } : { x: x0, w: x1 - x0 + 1 };
361
+ }
362
+ /** Pair each side's kept rows in order; each gap pairs top-down and its leftover is a band. */
363
+ function pairUp(ca, cb) {
364
+ const lh = ca.length, rh = cb.length;
365
+ const ka = [...ca.keys()].filter((i) => !ca[i]), kb = [...cb.keys()].filter((j) => !cb[j]);
366
+ const bands = [];
367
+ /** Where each band sits on the other side. */
368
+ const at = [];
369
+ const rows = [];
370
+ let x = 0, y = 0;
371
+ for (const [px, py] of [...ka.map((i, n) => [i, kb[n]]), [lh, rh]]) {
372
+ const k = Math.min(px - x, py - y);
373
+ for (let j = 0; j < k; j++)
374
+ rows.push([x + j, y + j]);
375
+ if (px - x > k)
376
+ bands.push({ side: "left", y: x + k, h: px - x - k }), at.push(py);
377
+ if (py - y > k)
378
+ bands.push({ side: "right", y: y + k, h: py - y - k }), at.push(px);
379
+ if (px < lh)
380
+ rows.push([px, py]);
381
+ x = px + 1;
382
+ y = py + 1;
383
+ }
384
+ return { bands, at, rows };
385
+ }
386
+ const CROP_PAD = 48;
387
+ const CROP_GAP = 8;
388
+ /** Narrower than this, a crop loses the context that says where on the page it is. */
389
+ const CROP_MIN_W = 320;
390
+ /** Claude's image budget: past either limit, `Read` downscales the image. */
391
+ const CROP_EDGE = 1568;
392
+ const CROP_TOKENS = 1568;
393
+ const TILE = 28;
394
+ /** Below this, text stops being legible; clip the crop instead. */
395
+ const MIN_SCALE = 0.75;
396
+ const SEAM = 2;
397
+ export const MAX_CROPS = 3;
398
+ const tokens = (w, h) => Math.ceil(w / TILE) * Math.ceil(h / TILE);
399
+ /** Largest scale ≤ 1 at which a `w`×`h` sheet fits the budget. */
400
+ function fit(w, h) {
401
+ let s = Math.min(1, CROP_EDGE / Math.max(w, h));
402
+ while (tokens(Math.floor(w * s), Math.floor(h * s)) > CROP_TOKENS)
403
+ s -= 0.005;
404
+ return s;
405
+ }
406
+ /** The sheet size for two panels of `w` × `lh` / `rh`. */
407
+ const sheet = (stacked, w, lh, rh) => stacked ? { w, h: lh + CROP_GAP + rh } : { w: 2 * w + CROP_GAP, h: Math.max(lh, rh) };
408
+ const fits = (s) => fit(s.w, s.h) >= MIN_SCALE;
409
+ /**
410
+ * Up to `MAX_CROPS` PNGs, one per spot in order: left and right at native scale (never below
411
+ * `MIN_SCALE`, clipped instead), each padded for context with a 1px red box around the change,
412
+ * or a 2px red seam where the other side's band would go. A full-page shot Read by an agent is
413
+ * downscaled past legibility; a crop isn't.
414
+ */
415
+ export async function crops(left, right, spots) {
416
+ if (!spots.length)
417
+ return [];
418
+ const [lm, rm] = await Promise.all([sharp(left).metadata(), sharp(right).metadata()]);
419
+ const cw = Math.min(lm.width, rm.width);
420
+ const heights = [lm.height, rm.height];
421
+ return Promise.all(spots.slice(0, MAX_CROPS).map(async (g) => {
422
+ const boxes = [g.left, g.right];
423
+ const bx = Math.min(g.left.x, g.right.x);
424
+ const bw = Math.max(g.left.x + g.left.w, g.right.x + g.right.w) - bx;
425
+ const want = Math.min(cw, Math.max(CROP_MIN_W, bw + 2 * CROP_PAD));
426
+ let x0 = Math.max(0, Math.min(cw - want, Math.round(bx + bw / 2 - want / 2)));
427
+ let width = want;
428
+ const top = boxes.map((b, i) => Math.max(0, Math.min(b.y, heights[i] - 1) - CROP_PAD));
429
+ const tall = boxes.map((b, i) => Math.min(heights[i], b.y + b.h + CROP_PAD) - top[i] + (b.h ? 0 : SEAM));
430
+ const stacked = width >= Math.max(...tall);
431
+ let clipped = false;
432
+ // Too wide even at MIN_SCALE: keep the left columns, starting at the change.
433
+ const maxW = Math.floor((stacked ? CROP_EDGE : (CROP_EDGE - CROP_GAP) / 2) / MIN_SCALE);
434
+ if (width > maxW) {
435
+ x0 = Math.max(0, bx - CROP_PAD);
436
+ width = Math.min(maxW, cw - x0);
437
+ clipped = true;
438
+ }
439
+ // Too tall: keep the top rows, trimming the taller panel first.
440
+ while (!fits(sheet(stacked, width, tall[0], tall[1]))) {
441
+ const i = tall[0] >= tall[1] ? 0 : 1;
442
+ tall[i] = Math.floor(tall[i] * 0.95);
443
+ clipped = true;
444
+ }
445
+ const panels = await Promise.all([left, right].map((png, i) => panel(png, boxes[i], x0, top[i], width, tall[i])));
446
+ const { w: W, h: H } = sheet(stacked, width, tall[0], tall[1]);
447
+ const scale = fit(W, H);
448
+ let png = await sharp({ create: { width: W, height: H, channels: 4, background: "#808080" } })
449
+ .composite([
450
+ { input: panels[0], left: 0, top: 0 },
451
+ { input: panels[1], ...(stacked ? { left: 0, top: tall[0] + CROP_GAP } : { left: width + CROP_GAP, top: 0 }) },
452
+ ])
453
+ .png()
454
+ .toBuffer();
455
+ if (scale < 1)
456
+ png = await sharp(png).resize(Math.floor(W * scale), Math.floor(H * scale)).png().toBuffer();
457
+ return { png, kind: g.kind, left: g.left, right: g.right, layout: stacked ? "stacked" : "side", scale: Math.round(scale * 100) / 100, clipped };
458
+ }));
459
+ }
460
+ /** One side's `width`×`height` panel from page row `top`: a box round the change, or a seam inserted at it. */
461
+ async function panel(png, b, x0, top, width, height) {
462
+ const layers = [];
463
+ if (b.h === 0) {
464
+ // Rows above the seam, the seam, then rows from `b.y` down: nothing on the page is hidden.
465
+ const above = Math.min(height, b.y - top);
466
+ const below = Math.min(height - above - SEAM, (await sharp(png).metadata()).height - b.y);
467
+ if (above > 0)
468
+ layers.push({ input: await sharp(png).extract({ left: x0, top, width, height: above }).toBuffer(), left: 0, top: 0 });
469
+ if (above + SEAM <= height) {
470
+ layers.push({ input: { create: { width, height: SEAM, channels: 4, background: "#ff0000" } }, left: 0, top: above });
471
+ }
472
+ if (below > 0)
473
+ layers.push({ input: await sharp(png).extract({ left: x0, top: b.y, width, height: below }).toBuffer(), left: 0, top: above + SEAM });
474
+ }
475
+ else {
476
+ const h = Math.min(height, (await sharp(png).metadata()).height - top);
477
+ layers.push({ input: await sharp(png).extract({ left: x0, top, width, height: h }).toBuffer(), left: 0, top: 0 });
478
+ // One pixel outside the change, so the outline covers none of it.
479
+ const [rx, ry] = [b.x - x0 - 1, b.y - top - 1];
480
+ const svg = `<svg xmlns="http://www.w3.org/2000/svg" width="${width}" height="${height}">` +
481
+ `<rect x="${rx + 0.5}" y="${ry + 0.5}" width="${b.w + 1}" height="${b.h + 1}" fill="none" stroke="#ff0000" stroke-width="1" shape-rendering="crispEdges"/></svg>`;
482
+ layers.push({ input: Buffer.from(svg), left: 0, top: 0 });
483
+ }
484
+ return sharp({ create: { width, height, channels: 4, background: "#808080" } }).composite(layers).png().toBuffer();
485
+ }
486
+ //# sourceMappingURL=compare.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"compare.js","sourceRoot":"","sources":["../src/compare.ts"],"names":[],"mappings":"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"}