Skip to content

Feature request: Adaptive local contrast enhancement for low-dynamic-range restoration (VHS/old film masters) #373

Description

@alfonslm

Use case
Content digitized from VHS, LaserDisc, and old broadcast/film masters frequently has flat, low-local-contrast images: raised blacks, compressed midtones, little separation. This is a characteristic of the source itself.
There are two legitimate places to correct it, and they serve different roles:

  • Mastering side: whoever creates the preservation/distribution copy (digitizing the tape, uploading to an archive) can bake the correction into the delivered encode — keeping an untouched mezzanine (e.g. ProRes) as the raw, and applying CLAHE to the distributed file (e.g. MKV). This is the correct place to re-encode.

  • Playback side: but the end user who only has the untouched source — a download with no corrected version, an old personal capture — shouldn't have to re-encode to view it correctly. This is where a live playback toggle belongs.

This is exactly the deinterlace model: the correction can be baked in at the mastering stage, yet players still offer a live toggle because the end user often has only the un-corrected source. Adaptive local contrast fits the same two-role pattern.

The gap in current playback tools
On the playback side, global contrast/gamma controls can't address this cleanly. Pushing global contrast enough to lift a murky scene clips highlights and crushes blacks in punchier scenes within the same content, and the "correct" global value shifts shot to shot or even within a shot, requiring constant manual adjustment. This is exactly what adaptive/local methods solve: per-region contrast stretching (CLAHE, local Laplacian) treats bright and dark areas of the same frame independently, avoiding global clipping and needing no per-shot babysitting.

Why this should be a built-in toggle, not a user shader
The natural response is "write a user shader," but I'd argue this belongs as a built-in for the same reasons deinterlacing is: it's a canonical correction for a source characteristic, not a stylistic embellishment. It's a common need across a whole class of old-source content, and there's a broadly correct way to do it. Built-ins earn their place by being both common and canonical, and adaptive local contrast for flat SD masters qualifies on both counts — it's part of faithfully reproducing this kind of source, the same way deinterlace is.

Why a deterministic operator rather than the AI-shader ecosystem
There's a growing set of neural/AI enhancement shaders, but those synthesize detail that was never in the master — which makes them unsuitable as a faithful default. CLAHE-style local contrast is different in kind: it's a deterministic, information-preserving operation that redistributes tonal information already latent in the signal per-region, rather than inventing new content. That principled, non-generative character is exactly what makes it appropriate as a restoration default, in a way generative upscaling isn't.

Anticipating "isn't tone-mapping already this?"
The existing adaptive tone-mapping is deterministic and adaptive too, so this may look redundant — but it targets a different problem. Tone-mapping handles dynamic-range conversion between color volumes (e.g. HDR→SDR). This request is within-range local contrast recovery on SDR→SDR content, which the tone-mapping path doesn't address. Different goal, different stage.
Not prescribing an implementation — CLAHE and local Laplacian are named as the well-understood examples; whatever fits the existing pipeline best. The ask is for the capability, framed as a restoration operator analogous to deinterlace: enable it for old-source playback and forget about it.

A possible second use case: SDR→HDR expansion, conditional on source quality
The same adaptive-local-contrast primitive is also a foundation for SDR→HDR inverse tone-mapping — but only where the source justifies it. Naive inverse tone-mapping produces the "fake HDR" look precisely because it expands range without recovering local contrast first; this operator is the missing building block. That said, it's garbage in, garbage out: on a degraded master, expanding a compromised signal just yields a compromised result, so this second use case applies to clean, well-preserved SDR source material, not the degraded captures the restoration case targets. Worth noting as a related application of the same primitive, with that caveat.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions