Inverity
Quality & Measurement

Just-Noticeable Difference in Image and Video Quality

Date Published

A just-noticeable-difference threshold rail crosses a staircase of one-JND steps; a fixed-quality line overshoots the threshold on smooth images and undershoots on complex ones, while per-image targeting places every image on the threshold.
TL;DR >- A just-noticeable difference (JND) is "the smallest distortion perceivable by the human visual system," and it is the unit compression should target (ACM MMSys, 2022).- Roughly 6 VMAF points equal one JND, the smallest change most viewers notice more than half the time (Netflix via Fora Soft).- libjxl expresses its distance control directly in JND units: 0.0 is lossless, 1.0 is visually lossless, and the useful lossy range is 0.5 to 3.0 (libjxl encoder API).- Netflix's Dynamic Optimizer cut bitrate at equal VMAF by 28.0% on x264, 37.6% on VP9, and 33.5% on x265, by targeting quality per shot instead of per file (Streaming Learning Center).- Per-image quality targeting is the still-image version of that idea: encode each image to a perceptual JND target so bytes track content complexity.

Fixed quality settings assume every image has the same perceptual headroom, and that assumption is wrong at the level of physics. A smooth sky and a dense street scene do not hide distortion equally, so spending the same quantization budget on both wastes bits on one and starves the other. The concept that explains this, and the one that fixes it, is the just-noticeable difference. Get JND right and you stop guessing at quality settings. You start targeting the threshold where a human first notices a change.

This post builds the full chain: JND theory grounded in Weber's law, the datasets that measured it, the operational thresholds that make it usable, and per-image quality targeting for still images on the web. For the broader context, see our complete guide to image compression. This is the theory that turns a quality slider into a perceptual target.

What is a just-noticeable difference in compression?

A JND is the smallest distortion the human visual system can perceive, and it is widely used as the unit for optimizing compression (ACM MMSys, 2022). Below one JND, a change is invisible; at one JND, a typical viewer notices it more than half the time. It is the natural boundary between compression you can get away with and compression you cannot.

The idea is old and well grounded. JND rests on Weber's law, the classic finding that the smallest perceptible change in a stimulus is proportional to the stimulus itself, expressed as the ratio of change to baseline staying roughly constant (Weber-Fechner modeling, arXiv 1807.00681). Applied to images, this means the amount of distortion you can hide depends on what is already there. Bright, busy, high-contrast content masks more error than flat, dim, smooth content.

Weber's law is the physics reason fixed quantization is inefficient, and almost no compression tutorial says so out loud. If the perceptible change is proportional to the local signal, then a single global quantization step is guaranteed to be wrong nearly everywhere: too coarse where the signal is weak, too fine where the signal is strong. Perceptual headroom is not a constant you can set once; it varies per image and per region. That single fact is the entire case against a fixed quality number, and it connects to how encoders exploit local masking in how lossy compression decides what to discard.

Citation capsule: A just-noticeable difference is "the smallest distortion perceivable by the human visual system," the standard unit for optimizing compression (ACM MMSys, 2022). It rests on Weber's law, which holds that the smallest perceptible change is proportional to the baseline stimulus (arXiv 1807.00681).

From JND theory to JND datasets

Theory only became actionable once researchers measured JND points on real content with real viewers. Two datasets anchor the field. MCL-JCI measured JND on 50 source images compressed with JPEG using 150 participants, and VideoSet extended the approach to 220 five-second video sources at four resolutions, 1080p, 720p, 540p, and 360p, with measured JND points throughout (USC MCL, MCL-JCI).

These datasets did something quantization tables never could: they recorded where actual humans first see compression. In MCL-JCI, each of the 50 images was encoded across the JPEG quality range while participants marked the point at which they noticed a difference from the previous quality level. The result is a distribution of JND points per image, not a single guess baked into a static table (USC MCL, VideoSet).

That per-content distribution is the key output, and it has a clean statistical shape. The Satisfied User Ratio, or SUR, is the probability that distortion at a given bitrate is not noticeable, and per-content JND points across subjects are well modeled by a normal distribution (arXiv 2206.09854). So "visually lossless for most people" becomes a specific point on a curve: the bitrate where the SUR crosses a chosen threshold, say 75% of viewers satisfied.

Illustrative Satisfied User Ratio curve of satisfied-user percentage against bitrate, with a 75% threshold line and the first JND point marked

"Visually lossless for most people" is the bitrate where the SUR curve crosses a chosen threshold (arXiv 2206.09854, 2022).

How many VMAF points equal one JND?

About six, though it is content-dependent. Netflix's guidance places roughly 6 VMAF points at one JND, the smallest change most viewers notice more than half the time, with a practical range of 2 to 6 points depending on content (Netflix via Fora Soft). That single conversion is what makes an abstract metric operational. Treat this figure as secondary and confirm against the Netflix Tech Blog for critical decisions.

The rule of thumb has direct engineering consequences. Adjacent rungs on an adaptive bitrate ladder should sit no more than about 2 VMAF apart so that quality switches during playback stay imperceptible, since roughly 3 VMAF is about half a JND (Fora Soft). Space the rungs wider and viewers see the quality pop when the player switches streams. The JND is the unit that tells you how finely to space quality levels.

For still images, the equivalent anchors live in the encoder and the verifier. libjxl expresses its distance control directly in JND units, where 0 is lossless, the useful lossy range is 0.5 to 3.0, and distance 1.0 is visually lossless (libjxl encoder API). On the verification side, SSIMULACRA2 anchors distance 0.5 or quality 95 at "not noticeable in a flicker test at 1:1 normal viewing distance," and 90 at visually lossless (SSIMULACRA2 README, Cloudinary).

Operational JND thresholds you can actually use

Here is the whole theory reduced to numbers you can set. Across video and still images, three thresholds recur: roughly 6 VMAF points per JND, SSIMULACRA2 90 for visually lossless, and cjxl distance 1.0 as the visually-lossless encode target. Each is a different tool pointing at the same perceptual boundary, the point where a viewer first notices.

Domain

JND-based threshold

Meaning

Source

Video (VMAF)

~6 points per JND

Smallest change most viewers notice

Netflix via Fora Soft

Video ladder spacing

~2 VMAF between rungs

Keeps switches imperceptible

Fora Soft

Still image (verify)

SSIMULACRA2 90

Visually lossless

SSIMULACRA2 README

Still image (verify)

SSIMULACRA2 85 / -d 0.5

Imperceptible in flicker test

SSIMULACRA2 README

Still image (encode)

cjxl -d 1.0

Visually lossless target

libjxl encoder API

Thresholds compiled from the sources listed per row.

Three unit scales aligned on one visually-lossless boundary: about 6 VMAF points per JND, SSIMULACRA2 90, and cjxl distance 1.0

One perceptual boundary, three units: ~6 VMAF per JND, SSIMULACRA2 90, and cjxl distance 1.0 (Netflix via Fora Soft; SSIMULACRA2 README; libjxl encoder API).

Notice how the encode-side and verify-side thresholds pair up. You encode to cjxl distance 1.0, then verify the result landed at SSIMULACRA2 90, using the encoder to hit the target and an independent metric to confirm it. That optimizer-and-verifier pairing is the same discipline covered in Butteraugli and SSIMULACRA2 explained, and it is what keeps a "visually lossless" claim honest rather than assumed. The related VMAF mechanics are in VMAF explained.

What does per-image quality targeting change?

It makes bytes track content complexity instead of a fixed setting, which is the still-image analogue of per-title and per-shot video encoding. Netflix moved from per-title encoding in 2015 to the Dynamic Optimizer in March 2018, which cut bitrate at equal VMAF by 28.0% on x264, 37.6% on VP9, and 33.5% on x265, with per-shot optimization adding another 10 to 15% over per-title (Streaming Learning Center). Treat those figures as secondary and content-specific.

The mechanism transfers directly to images. Per-title encoding asked why a cartoon and a gritty thriller should share one bitrate ladder; per-image quality targeting asks why a flat logo and a dense photograph should share one quality setting. In both cases the answer is to target a JND-based quality and let the bit budget follow the content: JND-aware schemes target a JND quality and space ladder rungs one JND apart, predicting quality from spatial and temporal complexity (ResearchGate, 2023).

The failure we see when teams try this is targeting a fixed byte budget and a JND quality at once, then acting surprised when they conflict. They cannot both bind. Either quality floats to hit a size cap, or size floats to hit a JND target. Per-image targeting deliberately chooses the second, because the whole point is uniform perceived quality across a library, with file size as the free variable. A smooth image lands small, a complex image lands larger, and both sit at the same JND. Fixed quality gets this exactly backward.

There is also a cost-prediction angle worth naming. Because per-content JND points follow a normal distribution, you can predict the full Satisfied User Ratio curve without running exhaustive subjective tests, which is what makes per-image targeting affordable at scale rather than a research exercise (arXiv 2206.09854). The operational trade-offs of running this across a real library are in content-adaptive per-image quality and why a quality of 95 means nothing.

This chain, JND theory to datasets to thresholds to per-image targeting, is precisely the seam Inverity works: encoding each image to a JND-anchored perceptual target, then verifying and recording it with a pinned metric, so "visually lossless" is a measured claim rather than a hopeful setting. A quality target you cannot verify against a JND is not a target. It is a preference. The scale-up version is in measure true image quality at scale.

FAQ

What is a JND in image and video compression?

A just-noticeable difference is the smallest distortion the human visual system can perceive, used as the unit for optimizing compression (ACM MMSys, 2022). It rests on Weber's law: the smallest perceptible change is proportional to the baseline signal (arXiv 1807.00681). Below one JND, a change is invisible to a typical viewer.

How many VMAF points equal one JND?

Roughly 6 VMAF points, the smallest change most viewers notice more than half the time, with a practical, content-dependent range of 2 to 6 (Netflix via Fora Soft). Because about 3 VMAF is half a JND, adaptive ladder rungs should sit near 2 VMAF apart to keep quality switches imperceptible.

What is per-title or per-shot encoding, and how does JND drive it?

Per-title encoding assigns each title its own settings; per-shot goes finer, per scene. Netflix's Dynamic Optimizer cut bitrate at equal quality by up to 37.6% on VP9 (Streaming Learning Center). JND drives it by setting the quality target and spacing ladder rungs about one JND apart (ResearchGate, 2023).

What threshold means "visually lossless" for still images?

Two anchors agree. SSIMULACRA2 90 is labeled visually lossless, and cjxl distance 1.0 is the visually-lossless encode target expressed in JND units (SSIMULACRA2 README; libjxl encoder API). Encode to distance 1.0, then verify the result reached SSIMULACRA2 90 with an independent metric.

How is per-image quality targeting different from a fixed quality?

A fixed quality applies one quantization budget to every image, wasting bits on smooth content and starving complex content, because perceptual headroom varies by Weber's law (arXiv 1807.00681). Per-image targeting instead encodes each image to a JND-based perceptual score, so file size tracks content complexity while perceived quality stays uniform across the library.