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.

  1. 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
  2. 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
  3. 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
  4. 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
  5. 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 issue
build and test
git clone https://github.com/jhuanxx44/NitsBridge.git
cd NitsBridge
cmake -S . -B build && cmake --build build
ctest --test-dir build --output-on-failure
tone-map a video, with local ffmpeg
tools/hdr_to_sdr.sh input_hdr.mp4 output_sdr.mp4