@vizzly-testing/honeydiff 0.11.1 → 0.13.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.
- package/CHANGELOG.md +35 -0
- package/README.md +27 -11
- package/index.d.ts +27 -5
- package/index.js +4 -1
- package/package.json +2 -1
- package/platforms/index-aarch64-apple-darwin.node +0 -0
- package/platforms/index-aarch64-unknown-linux-gnu.node +0 -0
- package/platforms/index-x86_64-pc-windows-msvc.node +0 -0
- package/platforms/index-x86_64-unknown-linux-gnu.node +0 -0
package/CHANGELOG.md
CHANGED
|
@@ -7,6 +7,41 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
7
7
|
|
|
8
8
|
## [Unreleased]
|
|
9
9
|
|
|
10
|
+
## [0.13.0] - 2026-07-23
|
|
11
|
+
|
|
12
|
+
### Added
|
|
13
|
+
- Exposed `effectiveDiffPixels`, `effectiveMaskComplete`,
|
|
14
|
+
`maskSemanticsVersion`, and the installed package `version` for auditable
|
|
15
|
+
mask consumers.
|
|
16
|
+
|
|
17
|
+
### Fixed
|
|
18
|
+
- Kept binary mask alpha opaque even when a transparent display diff color is
|
|
19
|
+
requested.
|
|
20
|
+
- Kept requested pixel and cluster diagnostics from changing the effective mask
|
|
21
|
+
or variable-height classification.
|
|
22
|
+
|
|
23
|
+
**Full Changelog**: https://github.com/vizzly-testing/honeydiff/compare/v0.12.0...v0.13.0
|
|
24
|
+
|
|
25
|
+
## [0.12.0] - 2026-07-19
|
|
26
|
+
|
|
27
|
+
### Fixed
|
|
28
|
+
- Prevented AA filtering from hiding thin border and divider recoloring by
|
|
29
|
+
requiring cross-image raster displacement.
|
|
30
|
+
- Compared rendered RGBA appearance, including opacity changes, while ignoring
|
|
31
|
+
hidden RGB under full transparency.
|
|
32
|
+
- Kept zero-threshold results and artifact masks consistent for low-alpha RGBA.
|
|
33
|
+
- Kept optional metrics independent from threshold and AA-filtered diff counts.
|
|
34
|
+
- Corrected small-image SSIM/MS-SSIM, GMSD boundaries, and exact artifact masks.
|
|
35
|
+
- Matched the authors' MS-SSIM pyramid, pooling, and direct weight semantics,
|
|
36
|
+
plus GMSD's exact normalized constant and sample-deviation pooling.
|
|
37
|
+
- Made capped comparisons classify from observed pixel evidence regardless of
|
|
38
|
+
cluster policy, preventing early exit from reporting false identity.
|
|
39
|
+
- Kept diff pixels and clusters null unless callers request them.
|
|
40
|
+
- Added Node boundary coverage for transparency, evidence privacy, exact RGBA,
|
|
41
|
+
and metric independence.
|
|
42
|
+
|
|
43
|
+
**Full Changelog**: https://github.com/vizzly-testing/honeydiff/compare/v0.11.1...v0.12.0
|
|
44
|
+
|
|
10
45
|
## [0.11.1] - 2026-06-20
|
|
11
46
|
|
|
12
47
|
## What's Changed
|
package/README.md
CHANGED
|
@@ -53,8 +53,11 @@ Most image diff packages stop at basic pixel comparison. Honeydiff gives you the
|
|
|
53
53
|
pieces visual regression systems usually need once screenshots get real:
|
|
54
54
|
|
|
55
55
|
- CIEDE2000 perceptual color thresholds, with `2.0` as the default.
|
|
56
|
-
-
|
|
56
|
+
- Zero perceptual tolerance with `threshold: 0`; disable AA and set
|
|
57
|
+
`minClusterSize: 1` for strict rendered-pixel matching.
|
|
57
58
|
- Conservative anti-aliasing detection for font and sub-pixel rendering noise.
|
|
59
|
+
- RGBA-aware comparison that detects opacity changes and ignores RGB payload
|
|
60
|
+
hidden behind full transparency.
|
|
58
61
|
- Variable-height screenshot support for full-page comparisons.
|
|
59
62
|
- Diff, mask, and overlay image artifacts for debugging failures.
|
|
60
63
|
- Spatial clusters, intensity stats, SSIM, GMSD, and diff fingerprints.
|
|
@@ -162,9 +165,9 @@ await saveColorBlindnessSimulation(
|
|
|
162
165
|
|
|
163
166
|
| Option | Default | Notes |
|
|
164
167
|
| --- | --- | --- |
|
|
165
|
-
| `threshold` | `2.0` | CIEDE2000 Delta E threshold. Use `0` for
|
|
168
|
+
| `threshold` | `2.0` | CIEDE2000 Delta E threshold. Use `0` for zero perceptual tolerance. |
|
|
166
169
|
| `antialiasing` | `true` | Ignore likely anti-aliased pixels. |
|
|
167
|
-
| `maxDiffs` | unlimited | Stop after a maximum number of differing pixels. |
|
|
170
|
+
| `maxDiffs` | unlimited | Stop after a maximum number of differing pixels. Capped results classify from the pixels observed before early exit, without cluster filtering. |
|
|
168
171
|
| `includeDiffPixels` | `false` | Return individual differing pixel positions and intensities. |
|
|
169
172
|
| `includeClusters` | `false` | Return connected regions of visual change. |
|
|
170
173
|
| `minClusterSize` | `2` | Filter tiny isolated clusters as noise. |
|
|
@@ -184,6 +187,9 @@ interface DiffResult {
|
|
|
184
187
|
diffPercentage: number;
|
|
185
188
|
totalPixels: number;
|
|
186
189
|
diffPixels: number;
|
|
190
|
+
effectiveDiffPixels: number;
|
|
191
|
+
effectiveMaskComplete: boolean;
|
|
192
|
+
maskSemanticsVersion: string;
|
|
187
193
|
aaPixelsIgnored: number;
|
|
188
194
|
aaPercentage: number;
|
|
189
195
|
boundingBox: BoundingBox | null;
|
|
@@ -196,6 +202,16 @@ interface DiffResult {
|
|
|
196
202
|
}
|
|
197
203
|
```
|
|
198
204
|
|
|
205
|
+
`diffPixels` is the raw post-threshold/anti-aliasing count.
|
|
206
|
+
`effectiveDiffPixels` is the retained count represented by the binary mask after
|
|
207
|
+
`minClusterSize` filtering. It always matches the mask's nontransparent pixel
|
|
208
|
+
count. If `effectiveMaskComplete` is `false`, `maxDiffs` stopped the scan early;
|
|
209
|
+
the partial mask is useful for diagnostics but not complete spatial proof.
|
|
210
|
+
Requesting `diffPixelsList` or `diffClusters` never changes that retained result.
|
|
211
|
+
|
|
212
|
+
The package also exports `version` from its installed manifest and
|
|
213
|
+
`maskSemanticsVersion` from the native comparison engine.
|
|
214
|
+
|
|
199
215
|
See [index.d.ts](./index.d.ts) for the full API surface.
|
|
200
216
|
|
|
201
217
|
## Thresholds
|
|
@@ -204,7 +220,7 @@ Honeydiff uses CIEDE2000 Delta E for perceptual color difference.
|
|
|
204
220
|
|
|
205
221
|
| Threshold | Meaning |
|
|
206
222
|
| --- | --- |
|
|
207
|
-
| `0` |
|
|
223
|
+
| `0` | No Delta E tolerance; AA and cluster filtering still apply if enabled. |
|
|
208
224
|
| `1` | Barely noticeable color changes. |
|
|
209
225
|
| `2` | Recommended default for UI screenshots. |
|
|
210
226
|
| `3+` | More tolerant of rendering differences. |
|
|
@@ -213,7 +229,7 @@ The default is intentionally practical for browser and app screenshots: it
|
|
|
213
229
|
filters tiny rendering variance while still catching meaningful UI changes.
|
|
214
230
|
|
|
215
231
|
The cited algorithms and standards are listed in the repo's
|
|
216
|
-
[References](
|
|
232
|
+
[References](https://github.com/vizzly-testing/honeydiff/blob/main/docs/REFERENCES.md), including CIEDE2000, SSIM, MS-SSIM,
|
|
217
233
|
GMSD, Brettel CVD simulation, sRGB, and WCAG contrast math.
|
|
218
234
|
|
|
219
235
|
## Performance
|
|
@@ -222,12 +238,12 @@ Current local benchmark snapshots:
|
|
|
222
238
|
|
|
223
239
|
| Scenario | Result |
|
|
224
240
|
| --- | ---: |
|
|
225
|
-
|
|
|
226
|
-
|
|
|
227
|
-
|
|
|
228
|
-
|
|
|
229
|
-
|
|
|
230
|
-
|
|
|
241
|
+
| Vizzly screenshot default comparison | ~2.81ms |
|
|
242
|
+
| Vizzly screenshot strict/no-AA comparison | ~2.18ms |
|
|
243
|
+
| Tall screenshot default comparison | ~147ms |
|
|
244
|
+
| Tall screenshot strict/no-AA comparison | ~4.34ms |
|
|
245
|
+
| 1080p isolated SSIM | ~14.7ms |
|
|
246
|
+
| 1080p isolated GMSD | ~10.9ms |
|
|
231
247
|
|
|
232
248
|
See [benchmarks/BENCHMARK_RESULTS.md](https://github.com/vizzly-testing/honeydiff/blob/main/benchmarks/BENCHMARK_RESULTS.md)
|
|
233
249
|
for the current benchmark notes.
|
package/index.d.ts
CHANGED
|
@@ -75,6 +75,12 @@ export interface DiffResult {
|
|
|
75
75
|
* Note: This may be > 0 even when isDifferent is false if small clusters were filtered as noise
|
|
76
76
|
*/
|
|
77
77
|
diffPixels: number;
|
|
78
|
+
/** Number of retained pixels represented by the effective diff mask */
|
|
79
|
+
effectiveDiffPixels: number;
|
|
80
|
+
/** False when maxDiffs stopped the scan before the full image was evaluated */
|
|
81
|
+
effectiveMaskComplete: boolean;
|
|
82
|
+
/** Version of the pixel-retention semantics used by the effective mask */
|
|
83
|
+
maskSemanticsVersion: string;
|
|
78
84
|
/** Number of pixels ignored due to anti-aliasing detection */
|
|
79
85
|
aaPixelsIgnored: number;
|
|
80
86
|
/** Percentage of pixels ignored as anti-aliasing (0.0 - 100.0) */
|
|
@@ -89,7 +95,7 @@ export interface DiffResult {
|
|
|
89
95
|
diffClusters: DiffCluster[] | null;
|
|
90
96
|
/** Statistical metrics about difference intensities (null unless includeDiffPixels is enabled) */
|
|
91
97
|
intensityStats: IntensityStats | null;
|
|
92
|
-
/** SSIM
|
|
98
|
+
/** SSIM score, approximately -1.0 to 1.0 (null unless includeSSIM is enabled) */
|
|
93
99
|
perceptualScore: number | null;
|
|
94
100
|
/**
|
|
95
101
|
* GMSD (Gradient Magnitude Similarity Deviation) score (null unless includeGMSD is enabled)
|
|
@@ -99,6 +105,12 @@ export interface DiffResult {
|
|
|
99
105
|
gmsdScore: number | null;
|
|
100
106
|
}
|
|
101
107
|
|
|
108
|
+
/** Installed @vizzly-testing/honeydiff package version */
|
|
109
|
+
export const version: string;
|
|
110
|
+
|
|
111
|
+
/** Native effective-mask semantics implemented by this package */
|
|
112
|
+
export const maskSemanticsVersion: string;
|
|
113
|
+
|
|
102
114
|
// ============================================================================
|
|
103
115
|
// Options
|
|
104
116
|
// ============================================================================
|
|
@@ -157,7 +169,7 @@ export interface CompareOptions {
|
|
|
157
169
|
* Perceptual color difference threshold using CIEDE2000 (Delta E units)
|
|
158
170
|
*
|
|
159
171
|
* The CIEDE2000 standard provides intuitive, perceptually uniform thresholds:
|
|
160
|
-
* - 0.0 =
|
|
172
|
+
* - 0.0 = No Delta E tolerance; AA and cluster filtering remain independent
|
|
161
173
|
* - 1.0 = Just Noticeable Difference (JND) - barely perceptible to trained observers
|
|
162
174
|
* - 2.0 = Recommended default - ignores sub-pixel rendering variance, catches real differences
|
|
163
175
|
* - 3.0+ = Permissive - high tolerance for rendering variations
|
|
@@ -168,12 +180,17 @@ export interface CompareOptions {
|
|
|
168
180
|
|
|
169
181
|
/**
|
|
170
182
|
* Enable anti-aliasing detection to ignore AA differences
|
|
183
|
+
*
|
|
184
|
+
* Suppression requires a luminance ramp plus strict cross-image evidence that
|
|
185
|
+
* raster coverage moved to a neighboring pixel. Stable edge recolors remain differences.
|
|
171
186
|
* @default true
|
|
172
187
|
*/
|
|
173
188
|
antialiasing?: boolean;
|
|
174
189
|
|
|
175
190
|
/**
|
|
176
191
|
* Maximum number of differences to detect before stopping
|
|
192
|
+
* Capped comparisons classify from observed pixel evidence because early
|
|
193
|
+
* exit cannot determine whether a complete cluster meets minClusterSize.
|
|
177
194
|
* @default undefined (unlimited)
|
|
178
195
|
*/
|
|
179
196
|
maxDiffs?: number;
|
|
@@ -194,7 +211,10 @@ export interface CompareOptions {
|
|
|
194
211
|
|
|
195
212
|
/**
|
|
196
213
|
* Calculate SSIM (Structural Similarity Index) perceptual score
|
|
197
|
-
*
|
|
214
|
+
* This metric measures the source images independently of threshold and AA
|
|
215
|
+
* filtering. Transparent inputs are evaluated over black and white mattes,
|
|
216
|
+
* keeping the more conservative score.
|
|
217
|
+
* WARNING: SSIM can use substantial memory on large images.
|
|
198
218
|
* @default false
|
|
199
219
|
*/
|
|
200
220
|
includeSSIM?: boolean;
|
|
@@ -205,6 +225,8 @@ export interface CompareOptions {
|
|
|
205
225
|
* GMSD is very fast and highly sensitive to edge/structural changes.
|
|
206
226
|
* Useful for detecting border thickness changes, font weight shifts,
|
|
207
227
|
* and icon updates.
|
|
228
|
+
* A score of 0 does not prove image identity; uniform changes can have no
|
|
229
|
+
* spatial variation in gradient degradation.
|
|
208
230
|
*
|
|
209
231
|
* **Note:** For variable-height comparisons, GMSD is calculated on the
|
|
210
232
|
* overlapping region shared by both images.
|
|
@@ -223,9 +245,9 @@ export interface CompareOptions {
|
|
|
223
245
|
* This helps ignore run-to-run rendering variance (scattered single pixels)
|
|
224
246
|
* while still catching real visual changes (grouped pixel differences).
|
|
225
247
|
*
|
|
226
|
-
* - 1 =
|
|
248
|
+
* - 1 = Any surviving diff pixel counts
|
|
227
249
|
* - 2 = Default - filters single isolated pixels as noise
|
|
228
|
-
* - 3+ = More
|
|
250
|
+
* - 3+ = More aggressive noise filtering
|
|
229
251
|
*
|
|
230
252
|
* When set to a value > 1, clustering is automatically enabled.
|
|
231
253
|
* @default 2
|
package/index.js
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
* @vizzly-testing/honeydiff - Native Node.js bindings for Honeydiff
|
|
3
3
|
*/
|
|
4
4
|
|
|
5
|
-
import { existsSync } from 'node:fs';
|
|
5
|
+
import { existsSync, readFileSync } from 'node:fs';
|
|
6
6
|
import { createRequire } from 'node:module';
|
|
7
7
|
import { dirname, join } from 'node:path';
|
|
8
8
|
import { fileURLToPath } from 'node:url';
|
|
@@ -11,6 +11,7 @@ const require = createRequire(import.meta.url);
|
|
|
11
11
|
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
12
12
|
|
|
13
13
|
let addon;
|
|
14
|
+
let packageMetadata = JSON.parse(readFileSync(new URL('./package.json', import.meta.url), 'utf8'));
|
|
14
15
|
|
|
15
16
|
// Try to load the native addon:
|
|
16
17
|
// 1. First try load-platform.cjs (exists in published npm package with multi-platform binaries)
|
|
@@ -41,6 +42,8 @@ export const compareSync = addon.compareSync;
|
|
|
41
42
|
export const quickCompareSync = addon.quickCompareSync;
|
|
42
43
|
export const getDimensions = addon.getDimensions;
|
|
43
44
|
export const getDimensionsSync = addon.getDimensionsSync;
|
|
45
|
+
export const maskSemanticsVersion = addon.maskSemanticsVersion;
|
|
46
|
+
export const version = packageMetadata.version;
|
|
44
47
|
|
|
45
48
|
// Image Metadata API
|
|
46
49
|
export const getImageMetadata = addon.getImageMetadata;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@vizzly-testing/honeydiff",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.13.0",
|
|
4
4
|
"description": "High-performance image diffing for Node.js - Native bindings to Honeydiff Rust library",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "index.js",
|
|
@@ -59,6 +59,7 @@
|
|
|
59
59
|
"devDependencies": {
|
|
60
60
|
"@biomejs/biome": "2.3.8",
|
|
61
61
|
"@types/node": "^24.10.1",
|
|
62
|
+
"pngjs": "^7.0.0",
|
|
62
63
|
"typescript": "^5.9.3"
|
|
63
64
|
},
|
|
64
65
|
"bugs": {
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|