Skip to content

Use OKLab HyAB perceptual color difference#169

Merged
mourner merged 7 commits into
mainfrom
oklab
Jul 5, 2026
Merged

Use OKLab HyAB perceptual color difference#169
mourner merged 7 commits into
mainfrom
oklab

Conversation

@mourner

@mourner mourner commented Jul 3, 2026

Copy link
Copy Markdown
Member

Closes #127. Replaces the perceptual color difference metric at the heart of pixelmatch — YIQ Euclidean distance (Kotsarenko & Ramos 2010) — with the vastly better HyAB distance in the OKLab color space (with toe-corrected lightness) (Ottosson 2020; Abasi et al. 2019).

The threshold semantics are preserved: distances are scaled so that 1.0 is the black↔white difference, and the default threshold: 0.1 is unchanged.

Why

  • OKLab is a modern perceptual space fit to color-appearance data, with far better hue uniformity than YIQ (a 1960s NTSC transmission space never designed for measuring color difference).
  • HyAB (|ΔL| + √(Δa² + Δb²)) is a city-block/Euclidean hybrid shown to track human judgment of large color differences better than pure Euclidean metrics — and large differences are exactly what a diff threshold operates on.
  • The Lr toe fixes OKLab's one weakness for image diffing: its cube-root lightness over-expands near-black. The fix reduces sensitivity near black and increases sensitivity in midtones and highlights, which matches how humans perceive color difference better.

Behavioral changes

  • Diffs are re-ranked, which is the point: pairs the old metric conflated are now ordered by perceptual difference. Some previously missed differences (notably hue shifts at similar luma) are now caught; some previously flagged imperceptible ones no longer are.
  • Sampling color pairs that sat exactly on the old 0.1 boundary, their median distance under the new metric is ~0.12 — i.e. the same threshold value is on average ~20% more sensitive than before. Sensitivity is now nearly uniform across the lightness range (band medians 0.118–0.124), which the old metric never achieved.
  • Test fixtures are regenerated accordingly. The AA detector is untouched and intentionally stays on gamma-space Rec.601 luma.

Performance

The new metric is more math per pixel (sRGB linearization, LMS transform, cube roots), offset by various performance optimizations:

  • an sRGB→linear LUT and premultiplied LMS contribution tables (per-byte);
  • an interpolated cube-root LUT (Math.cbrt is a slow library call);
  • a specialized opaque-pixel path with the rare transparent path split out-of-line, keeping the dispatch inlineable;
  • a 4096-entry direct-mapped cache of cube-rooted LMS + Lr values keyed by packed RGB (screenshots repeat colors heavily);
  • the threshold test folded into the HyAB comparison so the sqrt is skipped entirely;

Net result on the benchmark: comparable to the old YIQ implementation despite the heavier color model.

@mourner mourner changed the title Switch OKLab HyAB perceptual color difference Use OKLab HyAB perceptual color difference Jul 3, 2026
@mourner mourner marked this pull request as ready for review July 5, 2026 20:23
@mourner mourner requested a review from a team as a code owner July 5, 2026 20:23
@mourner mourner requested review from ibesora and removed request for a team July 5, 2026 20:23
@mourner mourner merged commit 4cad52e into main Jul 5, 2026
5 checks passed
@mourner mourner deleted the oklab branch July 5, 2026 21:24
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Weird comparator behaviour.

1 participant