Skip to Content
New: @blazediff/core-native now includes interpret - structured diff analysis to understand what changed. Read more →
Documentationblazediff

blazediff (Rust)

The Rust crate that powers the entire BlazeDiff stack. 3-4x faster than odiff , 8x faster than pixelmatch on 4K images. Block-based diff algorithm with SIMD-accelerated YIQ color comparison; the same engine drives @blazediff/core-native (Node.js) and blazediff (Python).

View Detailed Benchmarks 

Installation

As a CLI

cargo install blazediff

As a library

# Cargo.toml [dependencies] blazediff = "*"

Pre-built binaries (via cargo install) and crate sources are available on crates.io .

Features

  • PNG, JPEG & QOI support with vendored libspng, libjpeg-turbo, and qoi-rust (no system dependencies)
  • SIMD-accelerated - NEON on ARM, SSE4.1 on x86
  • Block-based optimization - skips unchanged 8x8 blocks via 32-bit integer compare before perceptual diff
  • Interpret mode - region detection, classification, severity scoring, human-readable summaries
  • Cargo features - opt into napi (Node.js bindings) or python (PyO3 bindings) when building from source

CLI Usage

# Basic diff blazediff image1.png image2.png diff.png # Custom threshold (0.0 - 1.0) blazediff image1.png image2.png diff.png -t 0.05 # JPEG comparison blazediff a.jpg b.jpg diff.jpg -q 85 # QOI diff output (12x smaller than PNG, faster encode) blazediff a.png b.png diff.qoi # Structured interpretation (JSON) blazediff a.png b.png --interpret # HTML interpret report blazediff a.png b.png report.html --output-format html

CLI Options

blazediff [OPTIONS] <IMAGE1> <IMAGE2> [OUTPUT] Arguments: <IMAGE1> First image path (PNG, JPEG, or QOI) <IMAGE2> Second image path (PNG, JPEG, or QOI) [OUTPUT] Output diff image path (optional, format detected from extension) Options: -t, --threshold <THRESHOLD> Color difference threshold (0.0-1.0) [default: 0.1] -a, --antialiasing Enable anti-aliasing detection --diff-mask Output only differences (transparent background) -c, --compression <LEVEL> PNG compression level (0-9) [default: 0] -q, --quality <QUALITY> JPEG quality (1-100) [default: 90] --interpret Run structured interpretation after diff --output-format <FORMAT> Output format (json, text, or html for interpret) [default: json] -h, --help Print help -V, --version Print version

Exit Codes

  • 0 - Images are identical
  • 1 - Images differ (includes layout/size mismatch)
  • 2 - Error (file not found, invalid format, etc.)

Library Usage

The crate exposes diff() plus codec helpers for PNG, JPEG, and QOI. Decode once, diff in memory, encode if you want a diff image.

use blazediff::{diff, load_pngs, save_png, DiffOptions, Image}; let (img1, img2) = load_pngs("expected.png", "actual.png")?; let options = DiffOptions { threshold: 0.1, include_aa: true, ..Default::default() }; let mut output = Image::new_uninit(img1.width, img1.height); let result = diff(&img1, &img2, Some(&mut output), &options)?; println!("{} pixels differ ({:.2}%)", result.diff_count, result.diff_percentage); if !result.identical { save_png(&output, "diff.png")?; }

Types

pub struct DiffOptions { pub threshold: f64, // 0.0-1.0, default 0.1 pub include_aa: bool, // count anti-aliased pixels as diffs pub alpha: f64, // background opacity, default 0.1 pub aa_color: [u8; 3], // default yellow [255, 255, 0] pub diff_color: [u8; 3], // default red [255, 0, 0] pub diff_color_alt: Option<[u8; 3]>, pub diff_mask: bool, // transparent background mode pub compression: u8, // PNG compression 0-9 (0 = fastest) } pub struct DiffResult { pub diff_count: u32, pub diff_percentage: f64, pub identical: bool, }

Codec helpers

FunctionFormat
load_png / load_pngs / save_png / encode_pngPNG
load_jpeg / load_jpegs / save_jpegJPEG
load_qoi / load_qois / save_qoiQOI

All decoders return Image (RGBA8, tightly packed). Inputs can be mixed formats - decode each side with the matching helper, then call diff().

Threshold guidelines:

  • 0.0 - Exact match only
  • 0.05 - Strict comparison
  • 0.1 - Default balanced comparison
  • 0.2 - Lenient comparison

Cargo Features

FeaturePurpose
(default)Pure Rust library + CLI
napiN-API bindings used by @blazediff/core-native on NPM
pythonPyO3 bindings used by the blazediff package on PyPI

The napi and python features are mutually exclusive build modes for distributing prebuilt artifacts; you don’t need them when consuming the crate as a Rust dependency.

Interpret

Structured diff analysis. Takes two images, returns classified change regions with human-readable summaries.

Pipeline: change mask -> morph close -> connected components -> per-region evidence extraction -> classify -> describe

Six-label decision tree:

TypeSignal
RenderingNoiseTiny (<=25px) or sparse + low color delta
AdditionBlends with background in img1, distinct in img2
DeletionDistinct in img1, blends with background in img2
ColorChangeEdge structure preserved across both images + uniform color shift
ContentChangeFallback - structural change
ShiftPost-hoc: matched Addition+Deletion pair with similar luminance
blazediff a.png b.png --interpret blazediff a.png b.png report.html --output-format html

Severity tiers: Low (<1%), Medium (1-10%), High (>10%). See Interpret example → for the interactive demo, and INTERPRET.md  for the full algorithm spec.

Vendored libraries

No system C dependencies; the crate builds standalone with a recent Rust toolchain.

Last updated on