@vizzly-testing/honeydiff 0.0.3 → 0.1.1

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 CHANGED
@@ -2,12 +2,17 @@
2
2
 
3
3
  [![npm version](https://img.shields.io/npm/v/@vizzly-testing/honeydiff.svg)](https://www.npmjs.com/package/@vizzly-testing/honeydiff)
4
4
  [![npm downloads](https://img.shields.io/npm/dm/@vizzly-testing/honeydiff.svg)](https://www.npmjs.com/package/@vizzly-testing/honeydiff)
5
- [![CI](https://github.com/vizzly-testing/honeydiff/workflows/Node.js%20Bindings/badge.svg)](https://github.com/vizzly-testing/honeydiff/actions)
6
- [![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)](../../LICENSE)
5
+ [![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)](https://github.com/vizzly-testing/honeydiff/blob/main/LICENSE)
7
6
 
8
- Fast image diffing for Node.js with native Rust performance (1.1B pixels/sec). Supports anti-aliasing detection, SSIM, clustering, and variable-height screenshots.
7
+ Blazingly fast image comparison for Node.js. Perfect for visual regression testing, screenshot
8
+ validation, and detecting visual changes.
9
9
 
10
- **Features:** File paths or Buffers • Async + sync APIs • TypeScript types • Pre-built binaries (macOS/Linux/Windows)
10
+ **Why Honeydiff?**
11
+ - **Fast:** Native performance processing 230M+ pixels/sec
12
+ - **Smart:** Intelligent anti-aliasing detection filters rendering artifacts
13
+ - **Flexible:** File paths or Buffers, async or sync APIs
14
+ - **Complete:** TypeScript types, pre-built binaries for all platforms
15
+ - **Advanced:** SSIM perceptual scoring, spatial clustering, variable-height screenshots
11
16
 
12
17
  ## Installation
13
18
 
@@ -15,7 +20,10 @@ Fast image diffing for Node.js with native Rust performance (1.1B pixels/sec). S
15
20
  npm install @vizzly-testing/honeydiff
16
21
  ```
17
22
 
18
- Requires Node.js 22+. Ships with pre-built binaries for macOS (ARM64), Linux (x64/ARM64), and Windows (x64). No Rust toolchain needed.
23
+ **Requirements:** Node.js 22+
24
+
25
+ Pre-built binaries included for macOS (ARM64), Linux (x64/ARM64), and Windows (x64). No compilation
26
+ required.
19
27
 
20
28
  ## Quick Start
21
29
 
@@ -35,6 +43,7 @@ const result = await compare('baseline.png', 'current.png', {
35
43
  });
36
44
 
37
45
  console.log(`Diff: ${result.diffPercentage.toFixed(2)}%, SSIM: ${result.perceptualScore}`);
46
+ // Output: Diff: 3.55%, SSIM: 0.9234
38
47
  ```
39
48
 
40
49
  **TypeScript**
@@ -51,6 +60,7 @@ const result: DiffResult = await compare('img1.png', 'img2.png', {
51
60
  if (result.diffClusters) {
52
61
  console.log(`Found ${result.diffClusters.length} diff regions`);
53
62
  }
63
+ // Output: Found 3 diff regions
54
64
  ```
55
65
 
56
66
  ## API
@@ -58,10 +68,12 @@ if (result.diffClusters) {
58
68
  **Async (recommended)**
59
69
  - `compare(img1, img2, options?): Promise<DiffResult>` - Full comparison
60
70
  - `quickCompare(img1, img2): Promise<boolean>` - Quick check
71
+ - `getDimensions(img): Promise<{ width: number, height: number }>` - Get image dimensions
61
72
 
62
73
  **Sync (blocks event loop)**
63
74
  - `compareSync(img1, img2, options?): DiffResult`
64
75
  - `quickCompareSync(img1, img2): boolean`
76
+ - `getDimensionsSync(img): { width: number, height: number }` - Get image dimensions
65
77
 
66
78
  Inputs: `string` (file path) or `Buffer`
67
79
 
@@ -111,6 +123,24 @@ interface DiffResult {
111
123
 
112
124
  ## Examples
113
125
 
126
+ **Get Image Dimensions**
127
+ ```javascript
128
+ const { getDimensions, getDimensionsSync } = require('@vizzly-testing/honeydiff');
129
+
130
+ // Async
131
+ let dims = await getDimensions('screenshot.png');
132
+ console.log(`Image is ${dims.width}x${dims.height} pixels`);
133
+ // Output: Image is 1920x1080 pixels
134
+
135
+ // Sync
136
+ let dims = getDimensionsSync('screenshot.png');
137
+ console.log(`Image is ${dims.width}x${dims.height} pixels`);
138
+
139
+ // Works with buffers too
140
+ let buffer = fs.readFileSync('image.png');
141
+ let dims = await getDimensions(buffer);
142
+ ```
143
+
114
144
  **Buffers**
115
145
  ```javascript
116
146
  const fs = require('fs');
@@ -146,37 +176,130 @@ if (result.diffClusters) {
146
176
  console.log(`Region ${i + 1}: ${c.pixelCount} pixels at (${c.centerOfMass[0]}, ${c.centerOfMass[1]})`);
147
177
  });
148
178
  }
179
+ // Output:
180
+ // Region 1: 12450 pixels at (245, 189)
181
+ // Region 2: 3891 pixels at (672, 401)
182
+ // Region 3: 1023 pixels at (1156, 823)
149
183
 
150
184
  // SSIM score
151
185
  if (result.perceptualScore !== null) {
152
186
  console.log(`SSIM: ${result.perceptualScore.toFixed(3)}`);
153
187
  }
188
+ // Output: SSIM: 0.923
154
189
 
155
190
  // Intensity stats
156
191
  if (result.intensityStats) {
157
192
  console.log(`Range: ${result.intensityStats.min}-${result.intensityStats.max}, Mean: ${result.intensityStats.mean.toFixed(1)}`);
158
193
  }
194
+ // Output: Range: 12-255, Mean: 87.3
195
+ ```
196
+
197
+ **Complete Result Example**
198
+ ```javascript
199
+ let result = await compare('baseline.png', 'current.png', {
200
+ pixelTolerance: 10,
201
+ includeClusters: true
202
+ });
203
+
204
+ console.log(JSON.stringify(result, null, 2));
205
+ ```
206
+
207
+ <details>
208
+ <summary>Example output (click to expand)</summary>
209
+
210
+ ```json
211
+ {
212
+ "isDifferent": true,
213
+ "diffPercentage": 3.55,
214
+ "totalPixels": 18309000,
215
+ "diffPixels": 650086,
216
+ "aaPixelsIgnored": 1952904,
217
+ "aaPercentage": 10.67,
218
+ "boundingBox": {
219
+ "x": 124,
220
+ "y": 89,
221
+ "width": 1456,
222
+ "height": 2301
223
+ },
224
+ "heightDiff": {
225
+ "height1": 24162,
226
+ "height2": 24412,
227
+ "extraPixels": 187500
228
+ },
229
+ "diffPixelsList": null,
230
+ "diffClusters": [
231
+ {
232
+ "pixelCount": 12450,
233
+ "centerOfMass": [245, 189]
234
+ },
235
+ {
236
+ "pixelCount": 3891,
237
+ "centerOfMass": [672, 401]
238
+ }
239
+ ],
240
+ "intensityStats": {
241
+ "min": 12,
242
+ "max": 255,
243
+ "mean": 87.3,
244
+ "median": 76,
245
+ "stdDev": 45.2
246
+ },
247
+ "perceptualScore": null
248
+ }
159
249
  ```
250
+ </details>
251
+ ```
252
+
253
+ ## Use Cases
254
+
255
+ - **Visual Regression Testing:** Detect unintended UI changes in your test suite
256
+ - **Screenshot Validation:** Compare generated screenshots against baselines
257
+ - **Design QA:** Validate UI implementations match designs
258
+ - **Cross-browser Testing:** Detect rendering differences across browsers
259
+ - **Scrollable Content:** Compare full-page screenshots with variable heights
160
260
 
161
261
  ## Performance
162
262
 
163
- | Image Size | Time | Throughput |
164
- |------------|------|------------|
165
- | 1920x1080 (Full HD) | ~2ms | 1.1B pixels/sec |
166
- | 3840x2160 (4K) | ~3ms | 3.0B pixels/sec |
263
+ Tested on real-world tall screenshots (750 x 24,162 pixels = 18.3M pixels):
167
264
 
168
- With artifacts: ~30-35ms for Full HD. Benchmarked on Apple M-series Mac.
265
+ | Operation | Time | Throughput |
266
+ |-----------|------|------------|
267
+ | Basic comparison | ~79ms | 231.8M pixels/sec |
268
+ | With artifacts (diff/mask/overlay) | ~432ms | 42.4M pixels/sec |
169
269
 
170
- ## Building from Source
270
+ **6x faster than odiff** on large screenshots with excellent multi-core parallelization.
171
271
 
172
- Only needed for contributing or modifying native code. Requires Rust toolchain and Node.js 22+.
272
+ *Benchmarked on Apple M-series Mac.*
173
273
 
174
- ```bash
175
- git clone https://github.com/vizzly-testing/honeydiff
176
- cd honeydiff/crates/honeydiff-node
177
- npm install && npm run build
178
- ```
274
+ ## Advanced Features
275
+
276
+ **Variable Height Screenshots**
277
+ Compare scrollable content with different heights. Overlapping regions are compared pixel-by-pixel,
278
+ extra rows counted as differences.
279
+
280
+ **Color Spaces**
281
+ - RGB mode (default): Exact matching, fastest performance
282
+ - YIQ mode: Perceptual matching weighted for human vision
283
+
284
+ **Spatial Clustering**
285
+ Group nearby differences into regions using 8-connectivity clustering. Useful for identifying distinct changed areas.
286
+
287
+ **SSIM Scoring**
288
+ Structural Similarity Index (0.0-1.0) provides perceptual similarity measurement beyond pixel differences.
289
+
290
+ ## Troubleshooting
291
+
292
+ **Module not found errors**
293
+ Ensure you're on Node.js 22+ and your platform is supported (macOS ARM64, Linux x64/ARM64, Windows x64).
294
+
295
+ **Large memory usage with `includeDiffPixels`**
296
+ This option stores every different pixel's position and intensity. Disable for large images with many differences.
297
+
298
+ **Slow performance with `includeSSIM`**
299
+ SSIM calculation is O(width × height × window²). Only enable when perceptual scoring is needed.
179
300
 
180
301
  ## License
181
302
 
182
- MIT - See [LICENSE](../../LICENSE) for details. Built for [Vizzly](https://github.com/vizzly-testing/vizzly) visual regression testing.
303
+ MIT License
304
+
305
+ Built with native Rust for maximum performance.
package/index.d.ts CHANGED
@@ -274,3 +274,50 @@ export function quickCompareSync(
274
274
  img1: ImageInput,
275
275
  img2: ImageInput
276
276
  ): boolean;
277
+
278
+ // ============================================================================
279
+ // Dimensions API
280
+ // ============================================================================
281
+
282
+ export interface ImageDimensions {
283
+ /** Image width in pixels */
284
+ width: number;
285
+ /** Image height in pixels */
286
+ height: number;
287
+ }
288
+
289
+ /**
290
+ * Get image dimensions asynchronously (recommended)
291
+ *
292
+ * Fast utility to retrieve image width and height without loading the full image data.
293
+ * Useful for pre-flight checks before comparison.
294
+ *
295
+ * @param img - Image (file path or Buffer)
296
+ * @returns Promise resolving to { width, height } in pixels
297
+ *
298
+ * @example
299
+ * ```typescript
300
+ * const dims = await getDimensions('screenshot.png');
301
+ * console.log(`Image is ${dims.width}x${dims.height} pixels`);
302
+ * // Output: Image is 1920x1080 pixels
303
+ * ```
304
+ */
305
+ export function getDimensions(img: ImageInput): Promise<ImageDimensions>;
306
+
307
+ /**
308
+ * Get image dimensions synchronously (blocks event loop)
309
+ *
310
+ * Fast utility to retrieve image width and height without loading the full image data.
311
+ * Use this only when you need blocking behavior.
312
+ *
313
+ * @param img - Image (file path or Buffer)
314
+ * @returns { width, height } in pixels
315
+ *
316
+ * @example
317
+ * ```typescript
318
+ * const dims = getDimensionsSync('screenshot.png');
319
+ * console.log(`Image is ${dims.width}x${dims.height} pixels`);
320
+ * // Output: Image is 1920x1080 pixels
321
+ * ```
322
+ */
323
+ export function getDimensionsSync(img: ImageInput): ImageDimensions;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vizzly-testing/honeydiff",
3
- "version": "0.0.3",
3
+ "version": "0.1.1",
4
4
  "description": "High-performance image diffing for Node.js - Native bindings to Honeydiff Rust library",
5
5
  "main": "index.js",
6
6
  "types": "index.d.ts",
@@ -50,6 +50,16 @@
50
50
  "index.d.ts",
51
51
  "load-platform.js",
52
52
  "platforms/*.node",
53
+ "README.md",
54
+ "index.js",
55
+ "index.d.ts",
56
+ "load-platform.js",
57
+ "platforms/*.node",
58
+ "README.md",
59
+ "index.js",
60
+ "index.d.ts",
61
+ "load-platform.js",
62
+ "platforms/*.node",
53
63
  "README.md"
54
64
  ],
55
65
  "engines": {