or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

docs

index.md
tile.json

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

index.mddocs/

Pixelmatch

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.

Package Information

  • Package Name: pixelmatch
  • Package Type: npm
  • Language: JavaScript (ES Modules)
  • Installation: npm install pixelmatch
  • TypeScript Support: TypeScript definitions generated from JSDoc comments (index.d.ts)

Core Imports

import pixelmatch from 'pixelmatch';

For CommonJS environments:

const pixelmatch = require('pixelmatch');

Basic Usage

import pixelmatch from 'pixelmatch';
import fs from 'fs';
import {PNG} from 'pngjs';

// Load images
const img1 = PNG.sync.read(fs.readFileSync('img1.png'));
const img2 = PNG.sync.read(fs.readFileSync('img2.png'));
const {width, height} = img1;
const diff = new PNG({width, height});

// Compare images
const numDiffPixels = pixelmatch(img1.data, img2.data, diff.data, width, height, {
  threshold: 0.1
});

console.log(`Found ${numDiffPixels} different pixels`);

// Save diff image
fs.writeFileSync('diff.png', PNG.sync.write(diff));

For browser environments using Canvas:

import pixelmatch from 'pixelmatch';

const img1 = img1Context.getImageData(0, 0, width, height);
const img2 = img2Context.getImageData(0, 0, width, height);
const diff = diffContext.createImageData(width, height);

const numDiffPixels = pixelmatch(img1.data, img2.data, diff.data, width, height, {
  threshold: 0.1
});

diffContext.putImageData(diff, 0, 0);

Capabilities

Image Comparison

Core pixel-level image comparison functionality that compares two equally sized images and returns the number of mismatched pixels.

/**
 * Compare two equally sized images, pixel by pixel.
 * @param {Uint8Array | Uint8ClampedArray} img1 - First image data.
 * @param {Uint8Array | Uint8ClampedArray} img2 - Second image data.
 * @param {Uint8Array | Uint8ClampedArray | void} output - Image data to write the diff to, if provided.
 * @param {number} width - Input images width.
 * @param {number} height - Input images height.
 * @param {PixelmatchOptions} [options] - Configuration options.
 * @returns {number} The number of mismatched pixels.
 */
function pixelmatch(img1, img2, output, width, height, options = {});

Usage Examples:

// Basic comparison without diff output
const differences = pixelmatch(img1.data, img2.data, null, 800, 600);

// Comparison with diff output and custom threshold
const differences = pixelmatch(
  img1.data, 
  img2.data, 
  diff.data, 
  800, 
  600, 
  { threshold: 0.2 }
);

// Comparison with anti-aliasing detection disabled
const differences = pixelmatch(
  img1.data, 
  img2.data, 
  diff.data, 
  800, 
  600, 
  { includeAA: true, threshold: 0.1 }
);

// Comparison with custom diff colors and transparency
const differences = pixelmatch(
  img1.data, 
  img2.data, 
  diff.data, 
  800, 
  600, 
  {
    threshold: 0.1,
    alpha: 0.5,
    aaColor: [0, 192, 0],        // Green for anti-aliased pixels
    diffColor: [255, 0, 255],    // Magenta for different pixels
    diffColorAlt: [0, 255, 0]    // Green for dark-on-light differences
  }
);

// Create a transparent diff mask
const differences = pixelmatch(
  img1.data, 
  img2.data, 
  diff.data, 
  800, 
  600, 
  { diffMask: true }
);

Command Line Interface

Pixelmatch provides a command-line interface for comparing PNG images directly from the terminal.

pixelmatch image1.png image2.png [diff.png] [threshold] [includeAA]

Parameters:

  • image1.png - Path to the first PNG image
  • image2.png - Path to the second PNG image
  • diff.png (optional) - Path where the diff image will be saved
  • threshold (optional) - Matching threshold as a number (0 to 1)
  • includeAA (optional) - Whether to include anti-aliasing detection ("true" or "false")

Exit Codes:

  • 0 - Success, no differences found
  • 64 - Invalid arguments (insufficient parameters)
  • 65 - Image dimensions do not match
  • 66 - Differences found between images

Usage Examples:

# Basic comparison
pixelmatch before.png after.png

# Generate diff image with default settings
pixelmatch before.png after.png diff.png

# Custom threshold (more sensitive)
pixelmatch before.png after.png diff.png 0.05

# Disable anti-aliasing detection
pixelmatch before.png after.png diff.png 0.1 true

CLI Output Format:

The command-line interface provides performance timing, difference count, and error percentage:

matched in: 15.123ms
different pixels: 143
error: 0.15%

Types

/**
 * Configuration options for pixelmatch comparison
 */
interface PixelmatchOptions {
  /** Matching threshold (0 to 1). Smaller values make comparison more sensitive. Default: 0.1 */
  threshold?: number;
  
  /** If true, disables detecting and ignoring anti-aliased pixels. Default: false */
  includeAA?: boolean;
  
  /** Blending factor of unchanged pixels in diff output (0 to 1). Default: 0.1 */
  alpha?: number;
  
  /** Color of anti-aliased pixels in diff output [R, G, B]. Default: [255, 255, 0] */
  aaColor?: [number, number, number];
  
  /** Color of differing pixels in diff output [R, G, B]. Default: [255, 0, 0] */
  diffColor?: [number, number, number];
  
  /** Alternative color for dark-on-light differences [R, G, B]. If not provided, uses diffColor. Default: undefined */
  diffColorAlt?: [number, number, number];
  
  /** Draw diff over transparent background (mask) rather than original image. Default: false */
  diffMask?: boolean;
}

Error Handling

Pixelmatch throws errors for the following conditions:

// Invalid image data format
throw new Error('Image data: Uint8Array, Uint8ClampedArray or Buffer expected.');

// Mismatched image dimensions
throw new Error('Image sizes do not match.');

// Image data doesn't match specified width/height
throw new Error('Image data size does not match width/height.');

Error Handling Examples:

try {
  const differences = pixelmatch(img1.data, img2.data, diff.data, width, height);
  console.log(`Found ${differences} different pixels`);
} catch (error) {
  if (error.message.includes('Image sizes do not match')) {
    console.error('Images must have the same dimensions');
  } else if (error.message.includes('Image data size does not match')) {
    console.error('Image data length doesn\'t match width × height × 4');
  } else if (error.message.includes('Uint8Array')) {
    console.error('Invalid image data format - must be Uint8Array or Uint8ClampedArray');
  } else {
    console.error('Unexpected error:', error.message);
  }
}

Advanced Features

Anti-Aliasing Detection

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.

// Enable anti-aliasing detection (default behavior)
const differences = pixelmatch(img1.data, img2.data, diff.data, width, height, {
  includeAA: false  // Anti-aliased pixels are ignored in diff count
});

// Disable anti-aliasing detection to count all pixel differences
const differences = pixelmatch(img1.data, img2.data, diff.data, width, height, {
  includeAA: true   // Anti-aliased pixels are counted as differences
});

Perceptual Color Difference

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).

YIQ Color Space Implementation:

  • Uses specific coefficients for luminance (Y): 0.29889531, 0.58662247, 0.11448223
  • In-phase (I) coefficients: 0.59597799, -0.27417610, -0.32180189
  • Quadrature (Q) coefficients: 0.21147017, -0.52261711, 0.31114694
  • Maximum possible YIQ difference value: 35215
  • Final delta calculation: 0.5053 * y² + 0.299 * i² + 0.1957 * q²

Alpha Blending for Transparent Pixels: When comparing images with transparency, pixelmatch uses a sophisticated background pattern:

  • Red background component: 48 + 159 * (position % 2)
  • Green background: 48 + 159 * ((position / φ | 0) % 2) where φ = 1.618033988749895
  • Blue background: 48 + 159 * ((position / (φ + 1) | 0) % 2)

Fast Path Optimization

Pixelmatch includes an optimized fast path for identical images:

  • Uses Uint32Array views for 32-bit integer comparison instead of byte-by-byte
  • Performs rapid pixel-perfect comparison before expensive perceptual analysis
  • Returns immediately with 0 differences if images are pixel-identical

Internal Algorithm Functions

The library implements several key internal algorithms:

Anti-aliasing Detection (antialiased):

  • Analyzes 8 adjacent pixels around each difference
  • Implements V. Vysniauskas (2009) slope detector algorithm
  • Checks for brightness gradients and sibling pixel patterns
  • Identifies anti-aliased pixels to reduce false positives

Color Delta Calculation (colorDelta):

  • Converts RGB to YIQ color space for perceptual comparison
  • Handles transparent pixels with background blending
  • Returns signed delta indicating whether pixel lightens or darkens

Pixel Validation (isPixelData):

  • Validates input arrays are proper typed arrays (Uint8Array/Uint8ClampedArray)
  • Uses ArrayBuffer.isView() and BYTES_PER_ELEMENT === 1 checks
  • Compatible with Jest testing environments and various array types

Diff Visualization Options

Pixelmatch provides extensive customization for visualizing differences:

// Custom color scheme for medical imaging
const differences = pixelmatch(img1.data, img2.data, diff.data, width, height, {
  threshold: 0.05,
  alpha: 0.2,           // More transparent background
  aaColor: [0, 255, 0], // Green for anti-aliased pixels  
  diffColor: [255, 0, 0], // Red for general differences
  diffColorAlt: [0, 0, 255] // Blue for dark-on-light differences
});

// Create a binary mask showing only differences
const differences = pixelmatch(img1.data, img2.data, diff.data, width, height, {
  diffMask: true,     // Transparent background
  alpha: 0,           // Fully transparent unchanged pixels
  diffColor: [255, 255, 255] // White differences
});

Performance Considerations

  • Zero Dependencies: Pixelmatch has no runtime dependencies, making it lightweight and fast
  • Raw Array Processing: Works directly with typed arrays for maximum performance
  • Optimized Algorithm: Uses 32-bit integer comparisons for identical pixel detection
  • Memory Efficient: Processes images in-place without additional memory allocation
  • Cross-Platform: Runs efficiently in both Node.js and browser environments

Performance Optimizations:

  1. Fast Path for Identical Images:

    • Uses Uint32Array views to compare 4 pixels at once (32-bit chunks)
    • Avoids expensive perceptual analysis when images are pixel-perfect matches
    • Provides immediate return for identical input data
  2. Efficient Memory Access:

    • Processes images in single pass with linear memory access
    • Uses typed array buffer views to avoid memory copying
    • Minimal memory allocation during comparison process
  3. Algorithmic Efficiency:

    • Pre-calculates maximum acceptable delta threshold (35215 * threshold²)
    • Uses integer arithmetic where possible to avoid floating-point operations
    • Anti-aliasing detection optimized with early termination conditions

Typical Performance:

  • Comparing two 1920×1080 images: ~50-100ms on modern hardware
  • Memory usage scales linearly with image size (width × height × 4 bytes per image)
  • Fast path identical comparison: ~5-15ms for same size images
  • CLI includes built-in performance timing for benchmarking