Skip to Content
New: ssim-native brings SSIM, MS-SSIM and Hitchhiker's to Node, and interpret-native ships diff interpretation on its own. Read more β†’
APIs@blazediff/interpret-native

@blazediff/interpret-native

Native Rust structured interpretation of image diffs: what changed, where, and how much β€” not just which pixels differ.

Installation

npm install @blazediff/interpret-native

The platform binary installs as an optional dependency; there is no compile step.

Usage

import { interpret } from "@blazediff/interpret-native"; const result = await interpret("expected.png", "actual.png"); console.log(result.summary); // "Low-impact visual change detected (0.18% of image, 2 regions). // Content added: 2 regions (center, bottom-right)." for (const region of result.regions) { console.log(`${region.position}: ${region.changeType} (${region.pixelCount}px)`); }

Choosing how regions are found

The classifier is independent of whatever locates the change, so the locator is a parameter:

sourceHow it finds regionsWhen
pixel (default)connected components over a per-pixel diffexact boxes; the usual choice
ssim, ms-ssim, hitchhikers-ssimthresholding a structural-similarity maptolerant of imperceptible noise
const loose = await interpret("expected.png", "actual.png", undefined, { source: "ms-ssim", });

A metric’s map is far coarser than a pixel, so its boxes are blocky. Its numbers are not: every box is refined against the source pixels before anything is measured, so pixelCount and diffCount count actually-changed pixels on every source, never map windows. On a real fixture pair the pixel diff reports 776 changed pixels and MS-SSIM-located regions report 792.

Regions you already have

If something else already knows where to look β€” DOM rectangles from a layout pass, a crop list β€” skip the search entirely:

import { interpretRegions } from "@blazediff/interpret-native"; const result = await interpretRegions("expected.png", "actual.png", [ { x: 16, y: 16, width: 32, height: 32 }, ]);

Boxes may be coarse; they are refined the same way. A box outside the image is rejected rather than read past.

Result

interface InterpretResult { summary: string; // human-readable diffCount: number; // actually-changed pixels totalRegions: number; regions: ChangeRegion[]; severity: string; diffPercentage: number; width: number; height: number; }

Each ChangeRegion carries a changeType, shape, position, confidence, and the statistics behind them β€” colour delta, gradient/edge correlation, fill ratios, and the classifier’s signals.

Options

{ source?: "pixel" | "ssim" | "ms-ssim" | "hitchhikers-ssim", // pixel source threshold?: number, // Default: 0.1 antialiasing?: boolean, // exclude AA pixels. Default: false compression?: number, // PNG level for a written diff. Default: 0 quality?: number, // JPEG quality for a written diff. Default: 90 // metric sources windowSize?: number, // Default: 11 regionFloor?: number, // window score at/below which it counts as changed. Default: 0.99 }

Passing a third argument to interpret writes the diff visualization to that path (pixel source only). Encoded PNG/JPEG/QOI buffers work in place of paths on the pixel source; the metric sources need paths.

Relationship to the other packages

@blazediff/core-native answers where pixels differ. @blazediff/ssim-native answers how alike two images look. This package answers what changed, and is the only one of the three that depends on the other two β€” they know nothing about interpretation.

Platforms

macOS (arm64, x64), Linux (arm64, x64), Windows (arm64, x64). The binding is required; there is no JS fallback.

Last updated on