Structural Image Comparison
Pixel-by-pixel diffing answers โhow many pixels changedโ. Structural metrics answer โhow different do these lookโ - they tolerate imperceptible noise (compression artifacts, sub-pixel shifts) and score perceived similarity instead. Reach for them when an exact pixel match is too strict.
BlazeDiff ships two: GMSD (gradient-based, fast) and SSIM (the classic structural index, with a 4ร faster Hitchhikerโs variant).
Installation
npm install @blazediff/gmsd @blazediff/ssimGMSD (Gradient Magnitude Similarity Deviation)
Scores gradient (edge) similarity. Returns 0 for identical images; lower is
better, typically in the 0โ0.35 range.
Basic Comparison

Image 1

Image 2
Result
import gmsd from "@blazediff/gmsd";
const img1 = await loadImage(
"https://raw.githubusercontent.com/teimurjan/blazediff/refs/heads/main/fixtures/blazediff/3a.png"
);
const img2 = await loadImage(
"https://raw.githubusercontent.com/teimurjan/blazediff/refs/heads/main/fixtures/blazediff/3b.png"
);
const width = img1.width;
const height = img1.height;
const score = gmsd(img1, img2, undefined, width, height);See the GMSD API reference โ.
SSIM (Structural Similarity Index)
Scores luminance, contrast, and structure. Returns 1 for identical images;
higher is better, in the 0โ1 range. The Hitchhikerโs variant uses
non-overlapping windows for ~4ร the throughput at near-identical accuracy.
Original SSIM

Image 1

Image 2
SSIM Map
import ssim from "@blazediff/ssim/ssim";
const img1 = await loadImage(
"https://raw.githubusercontent.com/teimurjan/blazediff/refs/heads/main/fixtures/blazediff/3a.png"
);
const img2 = await loadImage(
"https://raw.githubusercontent.com/teimurjan/blazediff/refs/heads/main/fixtures/blazediff/3b.png"
);
const output = new Uint8Array(img1.width * img1.height * 4);
const width = img1.width;
const height = img1.height;
const score = ssim(img1, img2, output, width, height);See the SSIM API reference โ.