BlazeDiff vs dssim
The blazediff-ssim crate computes MS-SSIM ~6.6x faster
than dssim, and it is MIT-licensed, while dssim is AGPL-3.0 or commercial. The
two answer related but different questions. dssim is a perceptual quality metric
for tuning image codecs. BlazeDiff SSIM is a similarity score for visual tests.
dssim computes multi-scale SSIM in L*a*b* color space, scales in linear light,
and reads color profiles. Its score is 1/SSIM β 1, so 0 means identical and the
value has no upper limit. blazediff-ssim computes luma SSIM that follows the
MATLAB reference implementations, and it scores from 0 to 1.
At a glance
| dssim | BlazeDiff (blazediff-ssim) | |
|---|---|---|
| License | AGPL-3.0, or a commercial license | MIT |
| Delivery | Rust crate, CLI, C library | Rust crate, Node addon (ssim-native), JavaScript, Python |
| Input | PNG and JPEG in the CLI; RGBA in the library | RGBA in the crate; PNG, JPEG and QOI in ssim-native |
| Color | L*a*b* with chroma, color profiles | Luma; perceptual-ssim adds L*a*b* chroma |
| Score | DSSIM, 0 = identical, unbounded | SSIM, 1 = identical |
| Variants | One multi-scale metric | SSIM, MS-SSIM, Hitchhikerβs SSIM, perceptual SSIM |
| Threads | Multi-core by default | Single-threaded; you run images in parallel |
Benchmarks
dssim runs single-threaded here, so both sides use one core. dssim is a different algorithm, so the chart compares cost, not scores. Decode is excluded.
Rust (blazediff-ssim vs dssim) (image IO excluded)
TOTAL TIME, BEST-OF Β· 16 FIXTURES Β· IO EXCLUDED
dssim is a different algorithm (multi-scale, Lab chroma), so this compares cost, not scores.
Apple M1 Max Β· darwin/arm64 Β· Node v22.14.0 Β· rustc 1.97.1 (8bab26f4f 2026-07-14) Β· best-of, iterations scaled by image size, dssim single-threaded Β· 2026-10-22 Β· 234b300-dirty Β· pnpm benchmark ssim-dssim
Per-fixture results (16)
| Fixture | MPx | dssim | ssim | ms-ssim | hitchhikers | ssim vs dssim | ms-ssim vs dssim | hitchhikers vs dssim |
|---|---|---|---|---|---|---|---|---|
| 4k/1 | 17.9 | 1.78s | 99.32ms | 250ms | 131ms | 17.93x | 7.13x | 13.63x |
| 4k/2 | 20.0 | 1.80s | 117ms | 279ms | 162ms | 15.35x | 6.45x | 11.12x |
| 4k/3 | 24.0 | 2.31s | 159ms | 331ms | 172ms | 14.55x | 6.98x | 13.46x |
| alpha/1 | 0.0 | 4.10ms | 0.47ms | 0.75ms | 0.23ms | 8.74x | 5.46x | 17.67x |
| blazediff/1 | 0.4 | 31.47ms | 5.15ms | 5.89ms | 2.88ms | 6.11x | 5.34x | 10.91x |
| blazediff/2 | 0.4 | 26.45ms | 1.54ms | 4.95ms | 2.29ms | 17.16x | 5.35x | 11.58x |
| blazediff/3 | 1.6 | 113ms | 5.07ms | 22.99ms | 11.21ms | 22.24x | 4.90x | 10.05x |
| blazediff/4 | 3.8 | 252ms | 12.28ms | 52.49ms | 24.92ms | 20.53x | 4.80x | 10.12x |
| pixelmatch/1 | 0.1 | 11.75ms | 1.54ms | 2.10ms | 0.82ms | 7.65x | 5.60x | 14.27x |
| pixelmatch/2 | 0.1 | 6.89ms | 0.76ms | 1.21ms | 0.42ms | 9.08x | 5.67x | 16.57x |
| pixelmatch/3 | 0.1 | 11.61ms | 1.59ms | 2.19ms | 0.87ms | 7.28x | 5.29x | 13.30x |
| pixelmatch/4 | 0.2 | 15.28ms | 0.78ms | 2.60ms | 1.17ms | 19.50x | 5.87x | 13.03x |
| pixelmatch/5 | 0.1 | 6.70ms | 0.76ms | 1.21ms | 0.41ms | 8.84x | 5.53x | 16.19x |
| pixelmatch/6 | 0.1 | 6.68ms | 0.75ms | 1.21ms | 0.41ms | 8.95x | 5.52x | 16.13x |
| pixelmatch/7 | 0.3 | 19.53ms | 1.07ms | 3.56ms | 1.64ms | 18.27x | 5.48x | 11.89x |
| same/1 | 1.7 | 120ms | 5.76ms | 24.75ms | 11.50ms | 20.86x | 4.85x | 10.45x |
| TOTAL | 6.51s | 413ms | 986ms | 523ms | 15.78x | 6.61x | 12.46x |
Switching
use blazediff_ssim::{ms_ssim, MsSsimOptions, Plane, Rgba8, SsimOptions};
let base = Plane::from_rgba8(Rgba8::new(&rgba1, width, height))?;
let current = Plane::from_rgba8(Rgba8::new(&rgba2, width, height))?;
let outcome = ms_ssim(&base, ¤t, &SsimOptions::default(), &MsSsimOptions::default())?;
println!("{:.6}", outcome.score); // 1.0 means identicalA dssim threshold does not convert to an SSIM threshold. Score your own fixtures with the new metric and pick the threshold from those scores.
When to keep dssim
- You tune image codecs or compression settings. dssim was validated on TID2013 for that job.
- You need color-profile handling, or errors that only show in chroma.
- Your project is already AGPL, or you bought the commercial license.