or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

tessl/npm-pixelmatch

The smallest and fastest pixel-level image comparison library with anti-aliasing detection.

Workspace
tessl
Visibility
Public
Created
Last updated
Describes
npmpkg:npm/pixelmatch@7.1.x

To install, run

npx @tessl/cli install tessl/npm-pixelmatch@7.1.0

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