BlazeDiff vs ssim.js
@blazediff/ssim is ~21% faster
than ssim.js on standard SSIM, and the native @blazediff/ssim-native is
~19.8x faster. Both
take RGBA pixels and return a similarity score from 0 to 1. ssim.js is archived on
GitHub, and its last release was 3.5.0 in 2020.
ssim.js is a JavaScript port of the Wang et al. MATLAB reference. It offers
several variants, and its default (weber) trades accuracy for speed. BlazeDiff
ships standard SSIM that matches MATLAB ssim.m with an error below 0.01%, plus
MS-SSIM and Hitchhikerβs SSIM.
At a glance
| ssim.js | BlazeDiff | |
|---|---|---|
| License | MIT | MIT |
| Status | Archived, last release 2020 | Maintained |
| Runtimes | Node, browsers | Node, browsers, Deno, Bun (ssim); native Node (ssim-native) |
| Input | ImageData-like { data, width, height } | RGBA buffers (ssim); file paths or encoded bytes (ssim-native) |
| Variants | original, fast, bezkrovny, weber | SSIM, MS-SSIM, Hitchhikerβs SSIM; perceptual SSIM in native |
| Score map | Yes (ssim_map) | Yes (grayscale map image) |
| Pass or fail result | No, you compare the score | ssim-native takes minScore and returns match |
Benchmarks
The first chart compares standard SSIM against ssim.js fast. The second
compares Hitchhikerβs SSIM against ssim.js weber, its fastest mode. Decode is
excluded.
Fast Original ( @blazediff/ssim using ssim vs ssim.js using fast algorithm) (image IO excluded)
TOTAL TIME Β· 22 FIXTURES Β· MEAN OF 25 RUNS Β· IO EXCLUDED
Apple M1 Max Β· darwin/arm64 Β· Node v22.14.0 Β· rustc 1.97.1 (8bab26f4f 2026-07-14) Β· 2026-10-22 Β· 234b300-dirty Β· pnpm benchmark ssim
Per-fixture results (22)
| Fixture | ssim.js | BlazeDiff | BlazeDiff (ssim-native) | BlazeDiff vs ssim.js | BlazeDiff (ssim-native) vs ssim.js |
|---|---|---|---|---|---|
| blazediff/1 | 92.94ms | 65.98ms | 5.36ms | 1.41x | 17.33x |
| blazediff/1 (identical) | 99.29ms | 65.49ms | 7.92ms | 1.52x | 12.54x |
| blazediff/2 | 39.45ms | 23.49ms | 1.55ms | 1.68x | 25.42x |
| blazediff/2 (identical) | 36.44ms | 24.04ms | 1.60ms | 1.52x | 22.77x |
| blazediff/3 | 112ms | 98.71ms | 5.47ms | 1.13x | 20.44x |
| blazediff/3 (identical) | 106ms | 100ms | 5.03ms | 1.06x | 21.14x |
| blazediff/4 | 259ms | 226ms | 12.26ms | 1.15x | 21.10x |
| blazediff/4 (identical) | 268ms | 229ms | 11.99ms | 1.17x | 22.31x |
| pixelmatch/1 | 28.25ms | 20.13ms | 1.63ms | 1.40x | 17.29x |
| pixelmatch/1 (identical) | 30.38ms | 19.79ms | 1.57ms | 1.54x | 19.34x |
| pixelmatch/2 | 13.92ms | 10.90ms | 0.87ms | 1.28x | 16.05x |
| pixelmatch/2 (identical) | 14.40ms | 9.96ms | 0.76ms | 1.45x | 19.06x |
| pixelmatch/3 | 30.00ms | 19.92ms | 1.60ms | 1.51x | 18.74x |
| pixelmatch/3 (identical) | 28.97ms | 19.86ms | 1.63ms | 1.46x | 17.73x |
| pixelmatch/4 | 19.65ms | 11.76ms | 0.79ms | 1.67x | 24.77x |
| pixelmatch/4 (identical) | 20.60ms | 11.88ms | 0.81ms | 1.73x | 25.50x |
| pixelmatch/5 | 14.34ms | 10.15ms | 0.76ms | 1.41x | 18.93x |
| pixelmatch/5 (identical) | 15.07ms | 9.94ms | 0.78ms | 1.52x | 19.33x |
| pixelmatch/6 | 14.38ms | 9.98ms | 0.76ms | 1.44x | 18.95x |
| pixelmatch/6 (identical) | 13.79ms | 10.70ms | 0.77ms | 1.29x | 17.89x |
| pixelmatch/7 | 27.20ms | 16.64ms | 1.32ms | 1.63x | 20.65x |
| pixelmatch/7 (identical) | 27.96ms | 16.63ms | 1.10ms | 1.68x | 25.41x |
| TOTAL | 1.31s | 1.03s | 66.34ms | 1.27x | 19.77x |
Hitchhikers SSIM SSIM (@blazediff/ssim using hitchhikers-ssim vs ssim.js using weber algorithm) (image IO excluded)
TOTAL TIME Β· 22 FIXTURES Β· MEAN OF 25 RUNS Β· IO EXCLUDED
Apple M1 Max Β· darwin/arm64 Β· Node v22.14.0 Β· rustc 1.97.1 (8bab26f4f 2026-07-14) Β· 2026-10-22 Β· 234b300-dirty Β· pnpm benchmark hitchhikers-ssim
Per-fixture results (22)
| Fixture | ssim.js | BlazeDiff | BlazeDiff (ssim-native) | BlazeDiff vs ssim.js | BlazeDiff (ssim-native) vs ssim.js |
|---|---|---|---|---|---|
| blazediff/1 | 77.27ms | 12.38ms | 2.92ms | 6.24x | 26.42x |
| blazediff/1 (identical) | 77.43ms | 12.44ms | 3.06ms | 6.22x | 25.33x |
| blazediff/2 | 35.29ms | 10.04ms | 2.33ms | 3.52x | 15.16x |
| blazediff/2 (identical) | 40.30ms | 10.45ms | 2.50ms | 3.86x | 16.12x |
| blazediff/3 | 123ms | 47.14ms | 10.91ms | 2.62x | 11.31x |
| blazediff/3 (identical) | 125ms | 47.55ms | 11.03ms | 2.62x | 11.29x |
| blazediff/4 | 302ms | 112ms | 25.70ms | 2.69x | 11.73x |
| blazediff/4 (identical) | 316ms | 110ms | 25.09ms | 2.88x | 12.59x |
| pixelmatch/1 | 22.72ms | 3.75ms | 0.84ms | 6.07x | 27.10x |
| pixelmatch/1 (identical) | 23.13ms | 3.91ms | 0.88ms | 5.91x | 26.17x |
| pixelmatch/2 | 11.31ms | 1.88ms | 0.40ms | 6.02x | 28.14x |
| pixelmatch/2 (identical) | 11.50ms | 1.91ms | 0.40ms | 6.01x | 28.48x |
| pixelmatch/3 | 22.96ms | 3.75ms | 0.84ms | 6.12x | 27.40x |
| pixelmatch/3 (identical) | 23.90ms | 3.75ms | 0.84ms | 6.38x | 28.36x |
| pixelmatch/4 | 18.61ms | 5.15ms | 1.16ms | 3.61x | 15.97x |
| pixelmatch/4 (identical) | 18.70ms | 5.44ms | 1.18ms | 3.44x | 15.88x |
| pixelmatch/5 | 11.38ms | 1.92ms | 0.41ms | 5.94x | 27.75x |
| pixelmatch/5 (identical) | 11.78ms | 1.86ms | 0.40ms | 6.32x | 29.19x |
| pixelmatch/6 | 11.37ms | 1.96ms | 0.43ms | 5.81x | 26.69x |
| pixelmatch/6 (identical) | 11.91ms | 1.89ms | 0.40ms | 6.29x | 29.62x |
| pixelmatch/7 | 24.87ms | 8.65ms | 1.71ms | 2.87x | 14.55x |
| pixelmatch/7 (identical) | 25.05ms | 7.20ms | 1.64ms | 3.48x | 15.24x |
| TOTAL | 1.34s | 414ms | 95.09ms | 3.24x | 14.14x |
Hitchhikerβs SSIM is ~3.2x faster
than ssim.js weber in JavaScript.
Switching
ssim.js takes two image objects. @blazediff/ssim takes the two pixel buffers
and the size, in the same order as a pixel diff.
// Before
import ssim from "ssim.js";
const { mssim } = ssim(img1, img2);
// After
import ssim from "@blazediff/ssim/ssim";
const score = ssim(img1.data, img2.data, undefined, img1.width, img1.height);Scores from different SSIM variants are not interchangeable. If you gated
tests on an ssim.js weber score, measure your fixtures again before you
copy the threshold.
When to keep ssim.js
- You depend on the
bezkrovnyorwebervariant scores exactly. - You use its UQI mode (
k1andk2set to 0).