Skip to main content

Rust-accelerated pixelmatch and SSIM for PNG bytes

Project description

pixelhog

Fast visual regression primitives for Python, implemented in Rust.

pixelhog compares screenshots in two complementary ways:

  • diff: exact pixel-level differences (with anti-alias handling), optional diff image output
  • ssim: perceptual similarity score in [0.0, 1.0]

It also generates WebP thumbnails for overview grids, optionally piggybacking on an already-decoded image buffer during a compare call.

Install (local dev)

uv venv .venv --python 3.12
source .venv/bin/activate
uv pip install -U pip maturin
maturin develop --release

Quickstart

from pixelhog import diff, ssim, compare, thumbnail

# 1) Pixel-level diff + diff PNG
diff_png, diff_count, width, height = diff(baseline_png, current_png)

# 2) Perceptual similarity
score = ssim(baseline_png, current_png)

# 3) One-call gate: count + SSIM + optional diff + optional thumbnail
diff_count, score, width, height, diff_png, thumb = compare(
    baseline_png,
    current_png,
    return_diff=True,
    thumbnail_width=200,
    thumbnail_height=150,
)

# 4) Standalone thumbnail (lossless WebP, Lanczos3 downscale, top-crop)
thumb = thumbnail(current_png, width=200, height=150)

API at a glance

Function Input Output Use when
thumbnail PNG bytes bytes (WebP) You need a preview thumbnail
diff PNG bytes (diff_png, diff_count, width, height) You need a visual diff artifact
diff_count PNG bytes (diff_count, width, height) You only need the mismatch count
ssim PNG bytes float You need perceptual similarity
compare PNG bytes (diff_count, ssim, w, h, diff_png?, thumb?) You want both metrics in one call
diff_rgba RGBA bytes + sizes (diff_rgba, diff_count, width, height) You already decoded images in Python/Rust
diff_count_rgba RGBA bytes + sizes (diff_count, width, height) Count-only on pre-decoded buffers
ssim_rgba RGBA bytes + sizes float SSIM on pre-decoded buffers
compare_rgba RGBA bytes + sizes (diff_count, ssim, w, h, diff_rgba?, thumb?) Combined metrics on pre-decoded buffers
diff_batch list[(baseline, current)] list[diff result] Run many diffs in one call
diff_count_batch list[(baseline, current)] list[count result] Batch count-only checks
ssim_batch list[(baseline, current)] list[float] Batch SSIM checks
compare_batch list[(baseline, current)] list[compare result] Batch combined checks

Behavior

  • High-level APIs accept PNG bytes and decode internally.
  • Smaller images are padded to the larger dimensions with transparent pixels.
  • diff always generates a diff image.
  • diff_count and compare(..., return_diff=False) skip diff-image generation.
  • SSIM uses 11x11 uniform windows with reflect padding.
  • For images smaller than 11x11, SSIM falls back to global SSIM.
  • No SSIM visualization image is produced.

Correctness and tests

The test suite is designed to validate both algorithm fidelity and practical product behavior.

  • Rust unit/integration tests cover:
    • identical/completely different/partial-diff images
    • threshold behavior
    • different-size padding behavior
    • SSIM behavior (identical, slight change, large change, small-image fallback)
  • Canonical pixelmatch fixture tests use the official Mapbox test set:
    • 8 fixture pairs with exact expected mismatch counts
    • expected diff image comparison against golden outputs
    • decoded RGBA byte equality checks to ensure pixel-perfect output matching
  • Python integration tests cover:
    • high-level API contracts and error behavior
    • tall-page and subtle-change scenarios
    • cross-validation against a pure-Python reference implementation
      • pixel diff counts must match exactly
      • SSIM must stay within tolerance

Run the full correctness suite:

# Rust core only
cargo test -p pixelhog

# Full suite including Python integration tests
cargo test
uv run --python 3.12 --with maturin --with pytest --with pillow bash -lc \
  "maturin develop --release && pytest -q"

Benchmarks

The repo includes both Criterion benches and pipeline breakdown tools.

  • cargo bench runs Criterion API benchmarks (PNG-bytes entry points).
  • Breakdown binaries in examples/ measure where time goes:
    • breakdown.rs: decode vs core diff vs encode vs API call
    • ssim_breakdown.rs: decode/pad vs core SSIM vs API call
    • combined_estimate.rs: separate calls vs combined single-decode flow

Run:

cargo bench -p pixelhog
cargo run -p pixelhog --release --example breakdown
cargo run -p pixelhog --release --example ssim_breakdown
cargo run -p pixelhog --release --example combined_estimate

For screenshot-style workloads, the practical guidance is:

  • diff_count is cheaper than diff when you do not need an artifact.
  • compare(..., return_diff=False) avoids duplicate decode work when you need both diff-count and SSIM.

Development

# Rust tests (includes canonical Mapbox fixture tests)
cargo test

# Python extension + tests
uv run --python 3.12 --with maturin --with pytest --with pillow bash -lc \
  "maturin develop --release && pytest -q"

# Lint/format/type-check
uv run --python 3.12 --with ruff ruff format --check .
uv run --python 3.12 --with ruff ruff check .
uv run --python 3.12 --with ty --with pytest --with pillow ty check . --python .venv

License

This repository is MIT licensed. See LICENSE.

Algorithm attribution for pixelmatch is documented in THIRD_PARTY_NOTICES.md.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

pixelhog-1.1.0.tar.gz (22.5 kB view details)

Uploaded Source

Built Distributions

If you're not sure about the file name format, learn more about wheel file names.

pixelhog-1.1.0-cp312-abi3-win_amd64.whl (537.8 kB view details)

Uploaded CPython 3.12+Windows x86-64

pixelhog-1.1.0-cp312-abi3-musllinux_1_2_x86_64.whl (855.1 kB view details)

Uploaded CPython 3.12+musllinux: musl 1.2+ x86-64

pixelhog-1.1.0-cp312-abi3-musllinux_1_2_aarch64.whl (801.0 kB view details)

Uploaded CPython 3.12+musllinux: musl 1.2+ ARM64

pixelhog-1.1.0-cp312-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (659.1 kB view details)

Uploaded CPython 3.12+manylinux: glibc 2.17+ x86-64

pixelhog-1.1.0-cp312-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl (624.5 kB view details)

Uploaded CPython 3.12+manylinux: glibc 2.17+ ARM64

pixelhog-1.1.0-cp312-abi3-macosx_11_0_arm64.whl (589.5 kB view details)

Uploaded CPython 3.12+macOS 11.0+ ARM64

pixelhog-1.1.0-cp312-abi3-macosx_10_12_x86_64.whl (598.7 kB view details)

Uploaded CPython 3.12+macOS 10.12+ x86-64

File details

Details for the file pixelhog-1.1.0.tar.gz.

File metadata

  • Download URL: pixelhog-1.1.0.tar.gz
  • Upload date:
  • Size: 22.5 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: uv/0.11.7 {"installer":{"name":"uv","version":"0.11.7","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

File hashes

Hashes for pixelhog-1.1.0.tar.gz
Algorithm Hash digest
SHA256 c0a2635dbda09bf45ab14c082688ba602caa25666db765f13a091747bbfd6ced
MD5 8eb50785289552788dde67ff41e44932
BLAKE2b-256 8894896a3aa2d6e10d68371c5e996d4dd163a6b865cebe41f169f91a83243116

See more details on using hashes here.

File details

Details for the file pixelhog-1.1.0-cp312-abi3-win_amd64.whl.

File metadata

  • Download URL: pixelhog-1.1.0-cp312-abi3-win_amd64.whl
  • Upload date:
  • Size: 537.8 kB
  • Tags: CPython 3.12+, Windows x86-64
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: uv/0.11.7 {"installer":{"name":"uv","version":"0.11.7","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

File hashes

Hashes for pixelhog-1.1.0-cp312-abi3-win_amd64.whl
Algorithm Hash digest
SHA256 39e07af50de54b589cff1f249209d7c68eaf243c99e7c1478d003d225e829fc1
MD5 2a8774c8907594ac95d188cc8aa57f0b
BLAKE2b-256 d8c6f75c90929f33c013ff7ce6c220872fc59b044ae3a7f424a8bede6ba89e0a

See more details on using hashes here.

File details

Details for the file pixelhog-1.1.0-cp312-abi3-musllinux_1_2_x86_64.whl.

File metadata

  • Download URL: pixelhog-1.1.0-cp312-abi3-musllinux_1_2_x86_64.whl
  • Upload date:
  • Size: 855.1 kB
  • Tags: CPython 3.12+, musllinux: musl 1.2+ x86-64
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: uv/0.11.7 {"installer":{"name":"uv","version":"0.11.7","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

File hashes

Hashes for pixelhog-1.1.0-cp312-abi3-musllinux_1_2_x86_64.whl
Algorithm Hash digest
SHA256 ac0e60fd7cd7358f71b076a8e89c83b656fe4491f8813d7b9c370e6da2aa9c38
MD5 4a71fb73dd4c6fd247587afc63f37c24
BLAKE2b-256 9949f2fd98acda01eefa84a318d6ba6a1f50fd4529eb208b34848e2010927930

See more details on using hashes here.

File details

Details for the file pixelhog-1.1.0-cp312-abi3-musllinux_1_2_aarch64.whl.

File metadata

  • Download URL: pixelhog-1.1.0-cp312-abi3-musllinux_1_2_aarch64.whl
  • Upload date:
  • Size: 801.0 kB
  • Tags: CPython 3.12+, musllinux: musl 1.2+ ARM64
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: uv/0.11.7 {"installer":{"name":"uv","version":"0.11.7","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

File hashes

Hashes for pixelhog-1.1.0-cp312-abi3-musllinux_1_2_aarch64.whl
Algorithm Hash digest
SHA256 3911397ea6401c557c4877e61e393f280cfe188f1f22917d0512318187c91c55
MD5 933d7f2b47e4d749faccc86df9175e87
BLAKE2b-256 0ac7be1bb07fbfda9e4f4c20d82428dcfc3da23c5d0e22d4e41c89ad507069ab

See more details on using hashes here.

File details

Details for the file pixelhog-1.1.0-cp312-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.

File metadata

  • Download URL: pixelhog-1.1.0-cp312-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
  • Upload date:
  • Size: 659.1 kB
  • Tags: CPython 3.12+, manylinux: glibc 2.17+ x86-64
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: uv/0.11.7 {"installer":{"name":"uv","version":"0.11.7","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

File hashes

Hashes for pixelhog-1.1.0-cp312-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Algorithm Hash digest
SHA256 f193e6e06bcb57b03ffb6c71a8e937e8c88b9f720b8a6633e5e4753f4bc54ed2
MD5 a04e280250fdb5c88a352de5f6f9a4d1
BLAKE2b-256 2011b8c7f8510dd0ab44b14223f17fffc998b5c0ea0afb94dde2c47173900c43

See more details on using hashes here.

File details

Details for the file pixelhog-1.1.0-cp312-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl.

File metadata

  • Download URL: pixelhog-1.1.0-cp312-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
  • Upload date:
  • Size: 624.5 kB
  • Tags: CPython 3.12+, manylinux: glibc 2.17+ ARM64
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: uv/0.11.7 {"installer":{"name":"uv","version":"0.11.7","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

File hashes

Hashes for pixelhog-1.1.0-cp312-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
Algorithm Hash digest
SHA256 c43918a0d432c5d571ff24ca5e8594bdf1bd709c1d8a46909a97d59c1c547465
MD5 9272c760993ca388120aef6b24403d5e
BLAKE2b-256 97a98541660036ad13be00c986a8d66540b1908d8b2769be62b021f86c1cf4eb

See more details on using hashes here.

File details

Details for the file pixelhog-1.1.0-cp312-abi3-macosx_11_0_arm64.whl.

File metadata

  • Download URL: pixelhog-1.1.0-cp312-abi3-macosx_11_0_arm64.whl
  • Upload date:
  • Size: 589.5 kB
  • Tags: CPython 3.12+, macOS 11.0+ ARM64
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: uv/0.11.7 {"installer":{"name":"uv","version":"0.11.7","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

File hashes

Hashes for pixelhog-1.1.0-cp312-abi3-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 4b2d2080ef04672fefcd6b0e421335a19c81d23bee1ac074cb52cc8324de40d9
MD5 fc965529a235cfae4e70e7b4a1beefc8
BLAKE2b-256 d9945827891ea895c99e3bd941023619c181a1bfeb4b9e3f154e6fbc357a1e57

See more details on using hashes here.

File details

Details for the file pixelhog-1.1.0-cp312-abi3-macosx_10_12_x86_64.whl.

File metadata

  • Download URL: pixelhog-1.1.0-cp312-abi3-macosx_10_12_x86_64.whl
  • Upload date:
  • Size: 598.7 kB
  • Tags: CPython 3.12+, macOS 10.12+ x86-64
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: uv/0.11.7 {"installer":{"name":"uv","version":"0.11.7","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

File hashes

Hashes for pixelhog-1.1.0-cp312-abi3-macosx_10_12_x86_64.whl
Algorithm Hash digest
SHA256 2c88337bde847b99ca7f357b2776dac152ca3cf26574d96922e945156a6642e1
MD5 6acd61b923095d0c91fe09e779f9dd8a
BLAKE2b-256 9485dfeea1e8ca9724ba0015e43814a408b5b51199750ee9eb772d39b2c99723

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page