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

blazediff (Python)

PyO3 bindings to the same Rust core that powers @blazediff/core-native. 3-4x faster than odiff , shipped as abi3 wheels for CPython ≥ 3.8 across macOS, Linux, and Windows.

View Detailed Benchmarks 

Installation

pip install blazediff

uv pip install blazediff and poetry add blazediff work identically. Pre-built wheels are published for:

  • macOS ARM64 (Apple Silicon) & x86_64 (Intel)
  • Linux ARM64 & x86_64 (manylinux 2.17)
  • Windows ARM64 & x86_64

A single abi3-py38 wheel per platform serves every CPython ≥ 3.8 - no separate wheel per minor version.

Features

  • PNG, JPEG & QOI support - auto-detected by file extension
  • Path-based - pass file paths in, blazediff handles decode + compare + encode
  • SIMD-accelerated - NEON on ARM, SSE4.1 on x86
  • Block-based optimization - skips unchanged regions
  • Interpret mode - region detection, classification, severity scoring, human-readable summaries

API Reference

compare(base_path, compare_path, diff_output=None, *, ...)

Compares two images and optionally writes a diff image. All keyword arguments are optional.

from blazediff import compare result = compare( "expected.png", "actual.png", "diff.png", threshold=0.1, antialiasing=True, )

Parameters

ParameterTypeDefaultDescription
base_pathstr-Path to the base/expected image
compare_pathstr-Path to the comparison/actual image
diff_outputstr | NoneNonePath where the diff image (or HTML report) will be written
thresholdfloat0.1Color difference threshold (0.0-1.0). Lower = stricter
antialiasingboolFalseEnable anti-aliasing detection
diff_maskboolFalseOutput only differences with a transparent background
compressionint0PNG compression level (0-9, 0 = fastest, 9 = smallest)
qualityint90JPEG quality (1-100)
interpretboolFalseRun structured interpretation (region detection + classification)
output_format"png" | "html""png""html" writes an interactive interpret report to diff_output

Return value

compare() returns a DiffResult object with:

FieldTypeDescription
matchboolTrue when images are identical (within threshold)
reasonstr | None"layout-diff" or "pixel-diff" when match is False
diff_countint | NoneNumber of differing pixels (pixel-diff only)
diff_percentagefloat | NonePercentage of differing pixels (pixel-diff only)
interpretationInterpretResult | NonePopulated when interpret=True or output_format="html"

Threshold guidelines:

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

interpret_images(image1_path, image2_path, *, threshold=0.1, antialiasing=False)

Returns the full InterpretResult (regions, severity, summary) without writing any output file. Equivalent to compare(..., interpret=True) minus the diff image.

from blazediff import interpret_images result = interpret_images("expected.png", "actual.png") print(result.summary) print(f"{result.total_regions} regions, severity={result.severity}")

Usage

Basic comparison

from blazediff import compare result = compare("expected.png", "actual.png", "diff.png", threshold=0.1) if result.match: print("Images are identical!") elif result.reason == "pixel-diff": print(f"{result.diff_count} pixels differ ({result.diff_percentage:.2f}%)") elif result.reason == "layout-diff": print("Images have different dimensions")

pytest assertion

from blazediff import compare def test_homepage_matches_baseline(): result = compare("baseline.png", "rendered.png", "diff.png", threshold=0.05) assert result.match, ( f"{result.diff_count} pixels differ ({result.diff_percentage:.2f}%)" )

Mixed formats

compare() infers format from the file extension. Inputs and outputs can mix freely:

# PNG inputs, QOI diff output (12x smaller diff files) compare("expected.png", "actual.png", "diff.qoi") # JPEG comparison compare("expected.jpg", "actual.jpg", "diff.jpg", quality=85)
FormatExtensionsNotes
PNG.pngLossless, transparency
JPEG.jpg, .jpegLossy, smaller files
QOI.qoiFast lossless, ideal for diff outputs (~12x smaller than PNG)

Interpret mode

Structured analysis - change regions, classification (Addition, Deletion, Shift, ContentChange, ColorChange, RenderingNoise), severity scoring, and human-readable summaries.

from blazediff import compare, interpret_images # Programmatic result = interpret_images("expected.png", "actual.png") print(result.summary) # "Moderate visual change detected (1.87% of image, 10 regions). # Content changed: 4 regions (bottom, center). # Content added: 3 regions (right, bottom, bottom-left)." for region in result.regions: print(f" {region.region_type} @ {region.position}, severity={region.severity}") # Diff image + interpretation result = compare("expected.png", "actual.png", "diff.png", interpret=True) # Interactive HTML report compare("expected.png", "actual.png", "report.html", output_format="html")

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

Last updated on