0
# Pixelmatch
1
2
Pixelmatch is the smallest, simplest and fastest JavaScript pixel-level image comparison library, originally created to compare screenshots in tests. It features accurate anti-aliased pixels detection and perceptual color difference metrics with zero dependencies.
3
4
## Package Information
5
6
- **Package Name**: pixelmatch
7
- **Package Type**: npm
8
- **Language**: JavaScript (ES Modules)
9
- **Installation**: `npm install pixelmatch`
10
- **TypeScript Support**: TypeScript definitions generated from JSDoc comments (`index.d.ts`)
11
12
## Core Imports
13
14
```javascript
15
import pixelmatch from 'pixelmatch';
16
```
17
18
For CommonJS environments:
19
20
```javascript
21
const pixelmatch = require('pixelmatch');
22
```
23
24
## Basic Usage
25
26
```javascript
27
import pixelmatch from 'pixelmatch';
28
import fs from 'fs';
29
import {PNG} from 'pngjs';
30
31
// Load images
32
const img1 = PNG.sync.read(fs.readFileSync('img1.png'));
33
const img2 = PNG.sync.read(fs.readFileSync('img2.png'));
34
const {width, height} = img1;
35
const diff = new PNG({width, height});
36
37
// Compare images
38
const numDiffPixels = pixelmatch(img1.data, img2.data, diff.data, width, height, {
39
threshold: 0.1
40
});
41
42
console.log(`Found ${numDiffPixels} different pixels`);
43
44
// Save diff image
45
fs.writeFileSync('diff.png', PNG.sync.write(diff));
46
```
47
48
For browser environments using Canvas:
49
50
```javascript
51
import pixelmatch from 'pixelmatch';
52
53
const img1 = img1Context.getImageData(0, 0, width, height);
54
const img2 = img2Context.getImageData(0, 0, width, height);
55
const diff = diffContext.createImageData(width, height);
56
57
const numDiffPixels = pixelmatch(img1.data, img2.data, diff.data, width, height, {
58
threshold: 0.1
59
});
60
61
diffContext.putImageData(diff, 0, 0);
62
```
63
64
## Capabilities
65
66
### Image Comparison
67
68
Core pixel-level image comparison functionality that compares two equally sized images and returns the number of mismatched pixels.
69
70
```javascript { .api }
71
/**
72
* Compare two equally sized images, pixel by pixel.
73
* @param {Uint8Array | Uint8ClampedArray} img1 - First image data.
74
* @param {Uint8Array | Uint8ClampedArray} img2 - Second image data.
75
* @param {Uint8Array | Uint8ClampedArray | void} output - Image data to write the diff to, if provided.
76
* @param {number} width - Input images width.
77
* @param {number} height - Input images height.
78
* @param {PixelmatchOptions} [options] - Configuration options.
79
* @returns {number} The number of mismatched pixels.
80
*/
81
function pixelmatch(img1, img2, output, width, height, options = {});
82
```
83
84
**Usage Examples:**
85
86
```javascript
87
// Basic comparison without diff output
88
const differences = pixelmatch(img1.data, img2.data, null, 800, 600);
89
90
// Comparison with diff output and custom threshold
91
const differences = pixelmatch(
92
img1.data,
93
img2.data,
94
diff.data,
95
800,
96
600,
97
{ threshold: 0.2 }
98
);
99
100
// Comparison with anti-aliasing detection disabled
101
const differences = pixelmatch(
102
img1.data,
103
img2.data,
104
diff.data,
105
800,
106
600,
107
{ includeAA: true, threshold: 0.1 }
108
);
109
110
// Comparison with custom diff colors and transparency
111
const differences = pixelmatch(
112
img1.data,
113
img2.data,
114
diff.data,
115
800,
116
600,
117
{
118
threshold: 0.1,
119
alpha: 0.5,
120
aaColor: [0, 192, 0], // Green for anti-aliased pixels
121
diffColor: [255, 0, 255], // Magenta for different pixels
122
diffColorAlt: [0, 255, 0] // Green for dark-on-light differences
123
}
124
);
125
126
// Create a transparent diff mask
127
const differences = pixelmatch(
128
img1.data,
129
img2.data,
130
diff.data,
131
800,
132
600,
133
{ diffMask: true }
134
);
135
```
136
137
### Command Line Interface
138
139
Pixelmatch provides a command-line interface for comparing PNG images directly from the terminal.
140
141
```bash { .api }
142
pixelmatch image1.png image2.png [diff.png] [threshold] [includeAA]
143
```
144
145
**Parameters:**
146
- `image1.png` - Path to the first PNG image
147
- `image2.png` - Path to the second PNG image
148
- `diff.png` (optional) - Path where the diff image will be saved
149
- `threshold` (optional) - Matching threshold as a number (0 to 1)
150
- `includeAA` (optional) - Whether to include anti-aliasing detection ("true" or "false")
151
152
**Exit Codes:**
153
- `0` - Success, no differences found
154
- `64` - Invalid arguments (insufficient parameters)
155
- `65` - Image dimensions do not match
156
- `66` - Differences found between images
157
158
**Usage Examples:**
159
160
```bash
161
# Basic comparison
162
pixelmatch before.png after.png
163
164
# Generate diff image with default settings
165
pixelmatch before.png after.png diff.png
166
167
# Custom threshold (more sensitive)
168
pixelmatch before.png after.png diff.png 0.05
169
170
# Disable anti-aliasing detection
171
pixelmatch before.png after.png diff.png 0.1 true
172
```
173
174
**CLI Output Format:**
175
176
The command-line interface provides performance timing, difference count, and error percentage:
177
178
```bash
179
matched in: 15.123ms
180
different pixels: 143
181
error: 0.15%
182
```
183
184
## Types
185
186
```javascript { .api }
187
/**
188
* Configuration options for pixelmatch comparison
189
*/
190
interface PixelmatchOptions {
191
/** Matching threshold (0 to 1). Smaller values make comparison more sensitive. Default: 0.1 */
192
threshold?: number;
193
194
/** If true, disables detecting and ignoring anti-aliased pixels. Default: false */
195
includeAA?: boolean;
196
197
/** Blending factor of unchanged pixels in diff output (0 to 1). Default: 0.1 */
198
alpha?: number;
199
200
/** Color of anti-aliased pixels in diff output [R, G, B]. Default: [255, 255, 0] */
201
aaColor?: [number, number, number];
202
203
/** Color of differing pixels in diff output [R, G, B]. Default: [255, 0, 0] */
204
diffColor?: [number, number, number];
205
206
/** Alternative color for dark-on-light differences [R, G, B]. If not provided, uses diffColor. Default: undefined */
207
diffColorAlt?: [number, number, number];
208
209
/** Draw diff over transparent background (mask) rather than original image. Default: false */
210
diffMask?: boolean;
211
}
212
```
213
214
## Error Handling
215
216
Pixelmatch throws errors for the following conditions:
217
218
```javascript
219
// Invalid image data format
220
throw new Error('Image data: Uint8Array, Uint8ClampedArray or Buffer expected.');
221
222
// Mismatched image dimensions
223
throw new Error('Image sizes do not match.');
224
225
// Image data doesn't match specified width/height
226
throw new Error('Image data size does not match width/height.');
227
```
228
229
**Error Handling Examples:**
230
231
```javascript
232
try {
233
const differences = pixelmatch(img1.data, img2.data, diff.data, width, height);
234
console.log(`Found ${differences} different pixels`);
235
} catch (error) {
236
if (error.message.includes('Image sizes do not match')) {
237
console.error('Images must have the same dimensions');
238
} else if (error.message.includes('Image data size does not match')) {
239
console.error('Image data length doesn\'t match width × height × 4');
240
} else if (error.message.includes('Uint8Array')) {
241
console.error('Invalid image data format - must be Uint8Array or Uint8ClampedArray');
242
} else {
243
console.error('Unexpected error:', error.message);
244
}
245
}
246
```
247
248
## Advanced Features
249
250
### Anti-Aliasing Detection
251
252
Pixelmatch implements advanced anti-aliasing detection based on the "Anti-aliased Pixel and Intensity Slope Detector" paper by V. Vysniauskas (2009). This feature automatically identifies and handles anti-aliased pixels to reduce false positives in image comparisons.
253
254
```javascript
255
// Enable anti-aliasing detection (default behavior)
256
const differences = pixelmatch(img1.data, img2.data, diff.data, width, height, {
257
includeAA: false // Anti-aliased pixels are ignored in diff count
258
});
259
260
// Disable anti-aliasing detection to count all pixel differences
261
const differences = pixelmatch(img1.data, img2.data, diff.data, width, height, {
262
includeAA: true // Anti-aliased pixels are counted as differences
263
});
264
```
265
266
### Perceptual Color Difference
267
268
The library uses perceptual color difference calculation based on the YIQ NTSC transmission color space, implementing research from "Measuring perceived color difference using YIQ NTSC transmission color space in mobile applications" by Y. Kotsarenko and F. Ramos (2010).
269
270
**YIQ Color Space Implementation:**
271
- Uses specific coefficients for luminance (Y): 0.29889531, 0.58662247, 0.11448223
272
- In-phase (I) coefficients: 0.59597799, -0.27417610, -0.32180189
273
- Quadrature (Q) coefficients: 0.21147017, -0.52261711, 0.31114694
274
- Maximum possible YIQ difference value: 35215
275
- Final delta calculation: `0.5053 * y² + 0.299 * i² + 0.1957 * q²`
276
277
**Alpha Blending for Transparent Pixels:**
278
When comparing images with transparency, pixelmatch uses a sophisticated background pattern:
279
- Red background component: `48 + 159 * (position % 2)`
280
- Green background: `48 + 159 * ((position / φ | 0) % 2)` where φ = 1.618033988749895
281
- Blue background: `48 + 159 * ((position / (φ + 1) | 0) % 2)`
282
283
### Fast Path Optimization
284
285
Pixelmatch includes an optimized fast path for identical images:
286
- Uses `Uint32Array` views for 32-bit integer comparison instead of byte-by-byte
287
- Performs rapid pixel-perfect comparison before expensive perceptual analysis
288
- Returns immediately with 0 differences if images are pixel-identical
289
290
### Internal Algorithm Functions
291
292
The library implements several key internal algorithms:
293
294
**Anti-aliasing Detection (`antialiased`):**
295
- Analyzes 8 adjacent pixels around each difference
296
- Implements V. Vysniauskas (2009) slope detector algorithm
297
- Checks for brightness gradients and sibling pixel patterns
298
- Identifies anti-aliased pixels to reduce false positives
299
300
**Color Delta Calculation (`colorDelta`):**
301
- Converts RGB to YIQ color space for perceptual comparison
302
- Handles transparent pixels with background blending
303
- Returns signed delta indicating whether pixel lightens or darkens
304
305
**Pixel Validation (`isPixelData`):**
306
- Validates input arrays are proper typed arrays (Uint8Array/Uint8ClampedArray)
307
- Uses `ArrayBuffer.isView()` and `BYTES_PER_ELEMENT === 1` checks
308
- Compatible with Jest testing environments and various array types
309
310
### Diff Visualization Options
311
312
Pixelmatch provides extensive customization for visualizing differences:
313
314
```javascript
315
// Custom color scheme for medical imaging
316
const differences = pixelmatch(img1.data, img2.data, diff.data, width, height, {
317
threshold: 0.05,
318
alpha: 0.2, // More transparent background
319
aaColor: [0, 255, 0], // Green for anti-aliased pixels
320
diffColor: [255, 0, 0], // Red for general differences
321
diffColorAlt: [0, 0, 255] // Blue for dark-on-light differences
322
});
323
324
// Create a binary mask showing only differences
325
const differences = pixelmatch(img1.data, img2.data, diff.data, width, height, {
326
diffMask: true, // Transparent background
327
alpha: 0, // Fully transparent unchanged pixels
328
diffColor: [255, 255, 255] // White differences
329
});
330
```
331
332
## Performance Considerations
333
334
- **Zero Dependencies**: Pixelmatch has no runtime dependencies, making it lightweight and fast
335
- **Raw Array Processing**: Works directly with typed arrays for maximum performance
336
- **Optimized Algorithm**: Uses 32-bit integer comparisons for identical pixel detection
337
- **Memory Efficient**: Processes images in-place without additional memory allocation
338
- **Cross-Platform**: Runs efficiently in both Node.js and browser environments
339
340
**Performance Optimizations:**
341
342
1. **Fast Path for Identical Images:**
343
- Uses `Uint32Array` views to compare 4 pixels at once (32-bit chunks)
344
- Avoids expensive perceptual analysis when images are pixel-perfect matches
345
- Provides immediate return for identical input data
346
347
2. **Efficient Memory Access:**
348
- Processes images in single pass with linear memory access
349
- Uses typed array buffer views to avoid memory copying
350
- Minimal memory allocation during comparison process
351
352
3. **Algorithmic Efficiency:**
353
- Pre-calculates maximum acceptable delta threshold (35215 * threshold²)
354
- Uses integer arithmetic where possible to avoid floating-point operations
355
- Anti-aliasing detection optimized with early termination conditions
356
357
**Typical Performance:**
358
- Comparing two 1920×1080 images: ~50-100ms on modern hardware
359
- Memory usage scales linearly with image size (width × height × 4 bytes per image)
360
- Fast path identical comparison: ~5-15ms for same size images
361
- CLI includes built-in performance timing for benchmarking