Open source · C++20 · CPU reference
Ten thousand nits in, one hundred out.
NitsBridge tone-maps PQ HDR video to SDR through an open, testable, CPU-first pipeline. Early days. Come build it.
A black box bothered me
I watch HDR video and keep meeting the same sealed component. Players and TVs each ship a tone mapper, tuned in private. When highlights crush or colors drift, nobody outside the vendor can point at the stage that failed.
NitsBridge handles one slice of that problem in the open. It maps PQ video to SDR with ITU-R BT.2446-1 Method A, written as an explicit chain of stages. Anchor vectors and golden tests pin every constant, and the same tests will judge the GPU backends to come.
This is a hobby project, built for the pleasure of getting color right. A complete HDR to SDR pipeline comes first, and SDR to HDR is the likely sequel. Both are still exploratory. If color math, pipelines, or GPUs sound like fun, there is room for you here.
The chain, stage by stage
PQ signal in, SDR BT.2020 out. Each stage names the standard it implements, and the CPU code is the reference contract every backend must match.
-
PQ decode
Constants kept as exact rationals. Signal in [0, 1] becomes linear light up to 10,000 cd/m².
BT.2100-2, Table 4 -
Scale to the operating point
Method A expects 1,000 cd/m² peak. Linear light divides by 1,000, and anything brighter returns an error rather than a silent clamp.
BT.2446-1, Section 4.1 -
Tone map
Gamma domain, log normalization, the piecewise knee, then color correction on the chroma. The strict operator also returns a trace of every intermediate value.
BT.2446-1, Tables 2 and 3 -
Rebuild RGB
The Y'C'bC'r result goes through the BT.2020 inverse to SDR RGB' in the gamma domain.
BT.2020-2, Table 4 -
Quantize
BT.2100 rounds half away from zero, BT.2020 truncates. Explicit floor arithmetic keeps CPU and GPU results bit-identical.
BT.2100-2 Table 9, BT.2020-2 Table 5
Where this goes
-
now
CPU reference core
The platform-independent pipeline, its test vectors, and the ffmpeg demo tool. This layer defines the contract.
-
next
macOS and Metal
A Metal backend plus a small demo player, validated against the same vectors.
-
later
Windows and beyond
A second GPU backend, once the core contract stops moving.
Common questions
What does NitsBridge do?
It converts PQ HDR video, up to 10,000 cd/m², down to SDR BT.2020 using ITU-R BT.2446-1 Method A. It is a portable C++20 library: no platform SDK types in the core, so you can read it, test it, and embed it anywhere a C++20 compiler runs.
Which standards does it implement?
BT.2100-2 Table 4 for the PQ EOTF and Table 9 for quantization, BT.2446-1 Section 4 with Tables 2 and 3 for the Method A tone mapping itself, and BT.2020-2 Tables 4 and 5 for the color matrix and SDR quantization. Every constant is pinned by anchor vectors and golden tests.
Can I convert an HDR video to SDR with it today?
Yes. Build the repo and run tools/hdr_to_sdr.sh input_hdr.mp4 output_sdr.mp4. ffmpeg handles container decode and encode; every frame of color math runs through the NitsBridge CPU pipeline. The output is 10-bit HEVC, SDR BT.2020 gamut.
Why BT.2446-1 Method A?
It is a published, fully specified ITU-R method rather than a private recipe, which makes it a good reference contract: the CPU implementation defines exact expected values, and any future GPU backend must reproduce them bit for bit.
The interesting decisions are still open
The project is young, which means the fun parts are unclaimed. Knee behavior beyond Method A, GPU architecture, test methodology, the SDR to HDR strategy: bring opinions and references.
Open an issuegit clone https://github.com/jhuanxx44/NitsBridge.git
cd NitsBridge
cmake -S . -B build && cmake --build build
ctest --test-dir build --output-on-failure
tools/hdr_to_sdr.sh input_hdr.mp4 output_sdr.mp4