Skip to Content
New: codec-png-native and codec-png-wasm bring the blazediff-png codec to Node and WebAssembly, faster than spng and jSquash. Read more β†’
Comparevs pixelmatch

BlazeDiff vs pixelmatch

@blazediff/core runs the pixelmatch algorithm with the pixelmatch call signature, and it is ~3.2x faster over our 34 fixtures. The WebAssembly build is ~4.3x faster. Switching is a one-line import change.

pixelmatch is the reference pixel diff for JavaScript: a few hundred lines, anti-aliasing detection, and a YIQ color delta. BlazeDiff started as a faster implementation of the same algorithm. It skips identical blocks of pixels before it runs the per-pixel delta, so unchanged areas cost almost nothing.

At a glance

pixelmatchBlazeDiff
LicenseISCMIT
ImplementationsJavaScript (plus a C++ port)JavaScript, WebAssembly, native Node, Python, Rust
InputRaw RGBA buffersRaw RGBA (core, core-wasm), or file paths and encoded bytes (core-native)
Decodes images itselfNo (CLI reads PNG through pngjs)core-native and Python decode PNG, JPEG and QOI
Color metricYIQ in 7.x, OKLab + HyAB in 8.0YIQ
Anti-aliasingDetected (VyΕ‘niauskas 2009)Detected, same method
OutputDiff pixel count, diff imageDiff pixel count, diff image
Beyond pixel countsNoSSIM, GMSD, MILO scores and region analysis in sibling packages

Benchmarks

Decode is excluded for the JavaScript and WebAssembly charts, so they measure the diff kernel only. The charts use pixelmatch 7.2.0.

JavaScript (@blazediff/core vs pixelmatch) (image IO excluded)

TOTAL TIME Β· 34 FIXTURES Β· MEAN OF 50 RUNS Β· IO EXCLUDED

BlazeDiffOther librariesLower is better

Apple M1 Max Β· darwin/arm64 Β· Node v22.14.0 Β· rustc 1.97.1 (8bab26f4f 2026-07-14) Β· 2026-10-22 Β· 234b300-dirty Β· pnpm benchmark core

Per-fixture results (34)
FixturePixelmatchBlazeDiffBlazeDiff vs Pixelmatch
4k/1325ms95.14ms3.42x
4k/1 (identical)23.07ms2.86ms8.07x
4k/2326ms104ms3.12x
4k/2 (identical)23.41ms3.48ms6.72x
4k/3411ms126ms3.26x
4k/3 (identical)34.26ms4.31ms7.94x
blazediff/11.24ms0.69ms1.79x
blazediff/1 (identical)0.49ms0.06ms8.71x
blazediff/21.79ms0.94ms1.90x
blazediff/2 (identical)0.40ms0.06ms6.40x
blazediff/310.52ms7.51ms1.40x
blazediff/3 (identical)1.86ms0.23ms8.22x
blazediff/413.96ms7.36ms1.90x
blazediff/4 (identical)4.39ms0.65ms6.76x
page/1161ms94.51ms1.70x
page/1 (identical)69.46ms10.40ms6.68x
page/2524ms152ms3.44x
page/2 (identical)48.55ms6.87ms7.07x
pixelmatch/10.58ms0.31ms1.91x
pixelmatch/1 (identical)0.27ms0.02ms16.17x
pixelmatch/22.19ms1.61ms1.36x
pixelmatch/2 (identical)0.07ms0.01ms8.90x
pixelmatch/30.37ms0.23ms1.63x
pixelmatch/3 (identical)0.15ms0.02ms9.50x
pixelmatch/44.24ms2.88ms1.47x
pixelmatch/4 (identical)0.21ms0.03ms8.12x
pixelmatch/50.18ms0.12ms1.58x
pixelmatch/5 (identical)0.07ms0.01ms8.01x
pixelmatch/60.80ms0.57ms1.40x
pixelmatch/6 (identical)0.07ms0.01ms7.88x
pixelmatch/71.26ms0.81ms1.55x
pixelmatch/7 (identical)0.28ms0.03ms9.40x
same/13.16ms0.24ms13.26x
same/1 (identical)3.40ms0.24ms14.17x
TOTAL2.00s625ms3.19x

JavaScript with output buffer (@blazediff/core vs pixelmatch) (image IO excluded)

TOTAL TIME Β· 34 FIXTURES Β· MEAN OF 50 RUNS Β· IO EXCLUDED

BlazeDiffOther librariesLower is better

Apple M1 Max Β· darwin/arm64 Β· Node v22.14.0 Β· rustc 1.97.1 (8bab26f4f 2026-07-14) Β· 2026-10-22 Β· 234b300-dirty Β· pnpm benchmark core

Per-fixture results (34)
FixturePixelmatchBlazeDiffBlazeDiff vs Pixelmatch
4k/1415ms142ms2.92x
4k/1 (identical)76.37ms48.86ms1.56x
4k/2382ms162ms2.37x
4k/2 (identical)84.56ms58.27ms1.45x
4k/3493ms190ms2.59x
4k/3 (identical)99.22ms66.46ms1.49x
blazediff/12.63ms1.97ms1.33x
blazediff/1 (identical)1.74ms1.26ms1.39x
blazediff/22.96ms1.95ms1.52x
blazediff/2 (identical)1.42ms0.98ms1.46x
blazediff/319.56ms12.32ms1.59x
blazediff/3 (identical)6.69ms4.48ms1.49x
blazediff/425.41ms18.26ms1.39x
blazediff/4 (identical)15.22ms10.37ms1.47x
page/1351ms267ms1.31x
page/1 (identical)242ms163ms1.49x
page/2642ms270ms2.38x
page/2 (identical)189ms114ms1.65x
pixelmatch/11.64ms0.68ms2.42x
pixelmatch/1 (identical)0.72ms0.35ms2.05x
pixelmatch/22.36ms1.95ms1.21x
pixelmatch/2 (identical)0.28ms0.18ms1.57x
pixelmatch/30.79ms0.63ms1.26x
pixelmatch/3 (identical)0.52ms0.35ms1.49x
pixelmatch/44.73ms3.43ms1.38x
pixelmatch/4 (identical)0.72ms0.49ms1.48x
pixelmatch/50.39ms0.32ms1.25x
pixelmatch/5 (identical)0.27ms0.18ms1.48x
pixelmatch/61.01ms0.84ms1.21x
pixelmatch/6 (identical)0.27ms0.18ms1.50x
pixelmatch/72.02ms1.54ms1.31x
pixelmatch/7 (identical)1.01ms0.67ms1.50x
same/17.27ms4.72ms1.54x
same/1 (identical)7.26ms4.79ms1.52x
TOTAL3.08s1.55s1.98x

WebAssembly (@blazediff/core-wasm vs pixelmatch) (image IO excluded)

TOTAL TIME Β· 34 FIXTURES Β· MEAN OF 25 RUNS Β· IO EXCLUDED

BlazeDiffOther librariesLower is better

Apple M1 Max Β· darwin/arm64 Β· Node v22.14.0 Β· rustc 1.97.1 (8bab26f4f 2026-07-14) Β· 2026-10-22 Β· 234b300-dirty Β· pnpm benchmark core-wasm

Per-fixture results (34)
FixturePixelmatchBlazeDiff (core-wasm)BlazeDiff (core-wasm) vs Pixelmatch
4k/1325ms35.95ms9.04x
4k/1 (identical)20.79ms16.16ms1.29x
4k/2321ms66.39ms4.83x
4k/2 (identical)23.47ms24.79ms0.95x
4k/3406ms44.62ms9.09x
4k/3 (identical)28.54ms20.69ms1.38x
blazediff/11.26ms0.27ms4.74x
blazediff/1 (identical)0.50ms0.22ms2.24x
blazediff/21.66ms0.50ms3.35x
blazediff/2 (identical)0.42ms0.17ms2.39x
blazediff/310.44ms6.25ms1.67x
blazediff/3 (identical)1.91ms0.94ms2.04x
blazediff/412.32ms4.38ms2.81x
blazediff/4 (identical)4.53ms2.43ms1.87x
page/1151ms50.48ms2.99x
page/1 (identical)67.52ms63.82ms1.06x
page/2519ms75.10ms6.91x
page/2 (identical)49.46ms37.86ms1.31x
pixelmatch/10.58ms0.11ms5.09x
pixelmatch/1 (identical)0.15ms0.07ms2.14x
pixelmatch/22.28ms1.47ms1.55x
pixelmatch/2 (identical)0.08ms0.03ms2.43x
pixelmatch/30.38ms0.12ms3.25x
pixelmatch/3 (identical)0.15ms0.07ms2.15x
pixelmatch/44.07ms2.96ms1.38x
pixelmatch/4 (identical)0.21ms0.10ms2.05x
pixelmatch/50.19ms0.06ms3.07x
pixelmatch/5 (identical)0.08ms0.03ms2.35x
pixelmatch/60.75ms0.65ms1.14x
pixelmatch/6 (identical)0.08ms0.03ms2.37x
pixelmatch/71.23ms0.60ms2.07x
pixelmatch/7 (identical)0.29ms0.13ms2.27x
same/12.15ms1.16ms1.85x
same/1 (identical)1.98ms0.96ms2.07x
TOTAL1.96s460ms4.26x

Switching

The arguments, the options and the return value are the same as pixelmatch 7.x.

// Before import pixelmatch from "pixelmatch"; // After import pixelmatch from "@blazediff/core"; const diffCount = pixelmatch(img1, img2, diff, width, height, { threshold: 0.1 });

If your images come from files, @blazediff/core-native also decodes them, so the pngjs step goes away:

import { compare } from "@blazediff/core-native"; const result = await compare("baseline.png", "current.png", "diff.png", { threshold: 0.1, antialiasing: true, });

pixelmatch 8.0 changed its color metric to OKLab + HyAB, so its diff counts differ from 7.x. BlazeDiff matches the 7.x counts. If you upgraded to 8.0 and depend on its exact counts, re-baseline your thresholds after you switch.

Python

The PyPI pixelmatch package is a pure Python port by a different author. The blazediff wheel runs the Rust core and decodes the files itself. This chart includes image decode for both sides.

vs pixelmatch (pypi)

TOTAL TIME Β· 34 FIXTURES Β· MEAN OF 10 OR 25 RUNS Β· IO INCLUDED

BlazeDiffOther librariesLower is better

Apple M1 Max Β· darwin/arm64 Β· Node v22.14.0 Β· rustc 1.97.1 (8bab26f4f 2026-07-14) Β· Python 3.11.14 Β· 2026-10-22 Β· 234b300-dirty Β· pnpm benchmark python-pixelmatch

Per-fixture results (34)
Fixturepixelmatch (pypi)BlazeDiffBlazeDiff vs pixelmatch (pypi)
4k/120.20s216ms93.42x
4k/1 (identical)596ms192ms3.10x
4k/223.28s265ms87.76x
4k/2 (identical)734ms232ms3.16x
4k/326.30s273ms96.42x
4k/3 (identical)792ms241ms3.29x
blazediff/1261ms0.86ms305.75x
blazediff/1 (identical)4.18ms0.99ms4.22x
blazediff/2271ms1.00ms269.88x
blazediff/2 (identical)3.81ms0.95ms4.01x
blazediff/31.50s14.68ms102.40x
blazediff/3 (identical)46.32ms14.38ms3.22x
blazediff/42.48s5.17ms478.82x
blazediff/4 (identical)28.76ms4.94ms5.82x
page/140.25s268ms150.13x
page/1 (identical)872ms268ms3.25x
page/242.52s97.96ms434.01x
page/2 (identical)179ms55.83ms3.20x
pixelmatch/188.66ms1.15ms77.15x
pixelmatch/1 (identical)2.86ms1.09ms2.62x
pixelmatch/2179ms0.69ms258.08x
pixelmatch/2 (identical)0.89ms0.45ms1.99x
pixelmatch/386.57ms0.94ms91.86x
pixelmatch/3 (identical)2.25ms0.83ms2.71x
pixelmatch/4377ms2.66ms141.55x
pixelmatch/4 (identical)5.69ms1.98ms2.87x
pixelmatch/544.24ms0.56ms79.23x
pixelmatch/5 (identical)1.13ms0.60ms1.89x
pixelmatch/6109ms1.27ms85.25x
pixelmatch/6 (identical)1.59ms0.79ms2.00x
pixelmatch/7193ms0.72ms267.35x
pixelmatch/7 (identical)1.53ms0.63ms2.44x
same/123.42ms3.52ms6.65x
same/1 (identical)25.54ms3.14ms8.13x
TOTAL161.46s2.17s74.30x
from blazediff import compare result = compare("baseline.png", "current.png", "diff.png", threshold=0.1)

When to keep pixelmatch

  • You need the pixelmatch 8.0 features: windowSize noise filtering or ignoreMask.
  • You want the smallest possible dependency and diff speed does not matter.
  • Your project depends on pixelmatch 8.0 diff counts exactly.
Last updated on