Lomont.org

(Also lomonster.com and clomont.com)

Color and HDR Notes: Reference Tables

Published

Reference Tables: Color Spaces and HDR

Chris Lomont, with Claude Fable 5.2

What this article is. Lookup tables for the articles on color and HDR: RGB spaces and matrices, transfer functions, Y′CbCr variants, chroma subsampling, code points, HDR formats, pixel formats and stops.

Related articles. Expert notes: Color and HDR Notes . General-audience summary: Color and HDR Notes Summary . Error guide: Best Practices and Gotchas .

Contents

Matrices and derived numbers are computed from the published primaries [Code]; check against the standard before relying on the last digit.

[Code]: private test code written for these articles; not published.

1. RGB spaces

Space Red xy Green xy Blue xy White Transfer Typical use
BT.709 / sRGB 0.640, 0.330 0.300, 0.600 0.150, 0.060 D65 BT.1886 (video); sRGB (computer) HD video, the web
BT.601 (525-line) 0.630, 0.340 0.310, 0.595 0.155, 0.070 D65 BT.1886 SD video, NTSC regions
BT.601 (625-line) 0.640, 0.330 0.290, 0.600 0.150, 0.060 D65 BT.1886 SD video, PAL regions
Adobe RGB (1998) 0.640, 0.330 0.210, 0.710 0.150, 0.060 D65 γ 2.2 (563/256) photography, print
DCI-P3 0.680, 0.320 0.265, 0.690 0.150, 0.060 0.314, 0.351 γ 2.6 digital cinema
Display P3 0.680, 0.320 0.265, 0.690 0.150, 0.060 D65 sRGB phones, laptops
BT.2020 / BT.2100 0.708, 0.292 0.170, 0.797 0.131, 0.046 D65 BT.1886, PQ or HLG UHD and HDR
ACES AP0 (ACES2065-1) 0.7347, 0.2653 0.0000, 1.0000 0.0001, −0.0770 ≈D60 linear archival interchange
ACES AP1 (ACEScg, ACEScct) 0.713, 0.293 0.165, 0.830 0.128, 0.044 ≈D60 linear / log CG and grading
ProPhoto (ROMM) 0.7347, 0.2653 0.1596, 0.8404 0.0366, 0.0001 D50 γ 1.8 photo editing

White points: D65 = (0.3127, 0.3290); D50 = (0.3457, 0.3585); D60 ≈ (0.32168, 0.33767); DCI = (0.314, 0.351).

“P3” is three different things: DCI-P3 (greenish white, γ 2.6, 48 cd/m²), P3-D65 (same primaries, D65, usually γ 2.6 or PQ in mastering) and Display P3 (D65, sRGB curve).

Linear conversion matrices (D65 to D65, no adaptation needed)

BT.709 → BT.2020:

1
2
3
 0.6274  0.3293  0.0433
 0.0691  0.9195  0.0114
 0.0164  0.0880  0.8956

BT.2020 → BT.709:

1
2
3
 1.6605 -0.5876 -0.0728
-0.1246  1.1329 -0.0083
-0.0182 -0.1006  1.1187

Display P3 → BT.709:

1
2
3
 1.2249 -0.2249  0.0000
-0.0421  1.0421  0.0000
-0.0196 -0.0786  1.0983

Apply to linear values only. Negative results are real out-of-gamut colors, not errors.

Luminance weights (the Y row)

Space R G B
BT.601 (luma convention) 0.299 0.587 0.114
BT.709 / sRGB 0.2126 0.7152 0.0722
Display P3 0.2290 0.6917 0.0793
BT.2020 0.2627 0.6780 0.0593

2. Transfer functions

Name Kind Formula (E = linear, V = signal, both 0–1 unless noted)
sRGB encode piecewise V = 12.92 E for E ≤ 0.0031308; else 1.055 E^(1/2.4) − 0.055
sRGB decode piecewise E = V/12.92 for V ≤ 0.04045; else ((V + 0.055)/1.055)^2.4
BT.709 OETF (camera) scene → signal V = 4.5 E for E < 0.018; else 1.099 E^0.45 − 0.099
BT.1886 EOTF (display) signal → cd/m² L = a·max(V + b, 0)^2.4, a and b from white and black luminance
PQ EOTF (ST 2084) signal → cd/m² L = 10000·(max(V^(1/m2) − c1, 0)/(c2 − c3 V^(1/m2)))^(1/m1)
PQ constants m1 = 2610/16384 = 0.1593; m2 = 2523/4096 × 128 = 78.84; c1 = 3424/4096 = 0.8359; c2 = 2413/4096 × 32 = 18.85; c3 = 2392/4096 × 32 = 18.69
HLG OETF scene → signal V = √(3E) for E ≤ 1/12; else a·ln(12E − b) + c; a = 0.17883277, b = 0.28466892, c = 0.55991073
HLG OOTF scene → display L = α·Ys^(γ−1)·E per channel; γ = 1.2 + 0.42·log10(Lw/1000)
DCI display L = 48·V^2.6 cd/m² (on X′Y′Z′)
Adobe RGB display E = V^2.19921875

Signal levels worth memorizing

Thing PQ HLG SDR (BT.1886)
Reference (diffuse/graphics) white, 203 cd/m² 58% (10-bit narrow code 573) 75% 100% at 100 cd/m²
18% gray card (BT.2408) 38% 38% ≈ 41–46%
100 cd/m² 50.8% — 100%
1000 cd/m² 75.2% 100% on a 1000 cd/m² display —
10,000 cd/m² 100% — —

Camera log curves (scene-referred)

Curve Code for 18% gray Code for 0 Stops above gray at code 1.0
S-Log3 0.411 0.093 7.7
LogC3 (EI 800) 0.391 0.093 8.3
LogC4 0.278 (per ARRI) — 11.4
ACEScct 0.414 0.073 10.3

3. Luma/chroma forms (“YUV flavors”)

Name Built from Coefficients Where
Y′UV encoded R′G′B′ BT.601, scaled for analog PAL analog only; the name is misused for everything below
Y′IQ encoded R′G′B′ BT.601, rotated 33° analog NTSC
Y′PbPr encoded R′G′B′ 601 or 709 analog component
Y′CbCr BT.601 encoded R′G′B′ 0.299, 0.587, 0.114 SD video, JPEG/JFIF (full range)
Y′CbCr BT.709 encoded R′G′B′ 0.2126, 0.7152, 0.0722 HD video
Y′CbCr BT.2020 NCL encoded R′G′B′ 0.2627, 0.6780, 0.0593 UHD, HDR10, HLG
Y′cCbcCrc BT.2020 CL luminance computed in linear, then encoded same rare
ICtCp LMS, PQ- or HLG-encoded BT.2100 Table 7 Dolby Vision profile 5, analysis, ΔE_ITP
YCgCo, YCgCo-R R′G′B′ integer, reversible H.264/HEVC lossless RGB, screen content
XYB LMS-like, cube-root JPEG XL JPEG XL
IPT, Oklab, Jzazbz LMS with a nonlinearity — perceptual processing, not transport

Range

Bit depth Narrow (“limited”, “video”, “TV”) luma Narrow chroma Full (“PC”)
8 16–235 16–240 (128 = zero) 0–255
10 64–940 64–960 (512 = zero) 0–1023
12 256–3760 256–3840 (2048 = zero) 0–4095

Narrow-range scaling between bit depths is a shift (×4 from 8 to 10 bits), not a rescale to the full code range.

Chroma subsampling

Notation Horizontal Vertical Bits per pixel at 8 / 10 bits Notes
4:4:4 1 1 24 / 30 no subsampling
4:2:2 ½ 1 16 / 20 production
4:2:0 ½ ½ 12 / 15 distribution
4:1:1 ¼ 1 12 / 15 DV NTSC
4:1:0 ¼ ½ 10 / — legacy
4:0:0 — — 8 / 10 monochrome
4:4:4:4 1 1 32 / 40 with alpha

Common pixel-format names: NV12 (8-bit 4:2:0, interleaved chroma), I420/YV12 (8-bit 4:2:0 planar), P010 (10-bit 4:2:0 in the high bits of 16), yuv420p10le (10-bit 4:2:0 in the low bits of 16), UYVY/YUY2 (8-bit 4:2:2 packed), v210 (10-bit 4:2:2, three samples per 32-bit word), Y410 (10-bit 4:4:4 + 2-bit alpha).

Chroma siting: center (JPEG, MPEG-1); left (MPEG-2, H.264, HEVC default); top-left (BT.2020/BT.2100 UHD).

4. H.273 / CICP code points (the common ones)

Field Code Meaning
Primaries 1 BT.709 / sRGB
5, 6 BT.601 625-line, 525-line
9 BT.2020 / BT.2100
11 DCI-P3 (DCI white)
12 P3-D65 (Display P3 primaries)
Transfer 1, 6, 14, 15 BT.709-type OETF (functionally identical)
4 γ 2.2
8 linear
13 sRGB
16 PQ (ST 2084)
18 HLG
Matrix 0 identity (RGB / GBR)
1 BT.709
5, 6 BT.601
9 BT.2020 non-constant luminance
10 BT.2020 constant luminance
14 ICtCp
Range flag 0 / 1 narrow / full

Typical triples: sRGB still image 1-13-0 full; HD video 1-1-1 narrow; HDR10 9-16-9 narrow; HLG 9-18-9 narrow; Display P3 image 12-13-0 full. Code 2 means “unspecified”, and decoders then guess.

5. HDR formats

Format Transfer Bits Gamut Metadata Notes
HDR10 PQ 10 BT.2020 static: ST 2086 mastering display, MaxCLL, MaxFALL baseline for UHD Blu-ray and streaming
HDR10+ PQ 10 BT.2020 dynamic, ST 2094-40 scene-by-scene tone-mapping hints
Dolby Vision PQ (some profiles HLG or SDR base) 10 or 12 (via enhancement or reshaping) BT.2020, ICtCp in profile 5 dynamic, proprietary several incompatible profiles
HLG HLG 10 BT.2020 none required broadcast; backward compatible with SDR BT.2020 displays
PQ10 / HLG10 PQ / HLG 10 BT.2020 none bare signal
Gain-map stills (Ultra HDR, ISO 21496-1) SDR base + log gain 8 + 8 from the base profile gain range, offsets, gamma, headroom limits JPEG, also HEIC, AVIF, JPEG XL
HDR stills without gain map PQ or HLG 10–12 BT.2020 or P3 CICP AVIF, HEIC, JPEG XL, PNG (cICP)
OpenEXR linear 16 float or 32 float any (chromaticities attribute) free-form scene-referred production

6. Pixel formats for HDR data

Format Bits/pixel Layout Range Relative step Sign Notes
float32 RGB 96 IEEE binary32 ×3 254 stops 0.00001% yes working format
half RGB(A) 48 / 64 1 + 5 + 10 30 stops normal, 40 with denormals; max 65,504 0.05–0.1% yes OpenEXR, GPU render targets
R11G11B10F 32 5 + 6, 5 + 6, 5 + 5 30 stops; max ≈ 65,000 1.6% (R, G), 3.1% (B) no GPU HDR targets
RGB9E5 32 9, 9, 9 mantissas + 5 shared exponent 40 stops; max ≈ 65,408 0.2–0.4% of the largest channel no GPU textures
Radiance RGBE (.hdr) 32 8, 8, 8 + 8 shared exponent 263 stops 0.4–0.8% of the largest channel no legacy HDR stills
LogLuv32 32 1 sign + 15 log L + 8 u′ + 8 v′ 128 stops 0.27% (luminance sign) TIFF
LogLuv24 24 10 log L + 14 indexed u′v′ 16 stops 1.1% no TIFF
RGB10_A2 with PQ 32 10, 10, 10, 2 0 to 10,000 cd/m² 0.9–2% above 1 cd/m² no HDR10 swap chains
scRGB half 64 half float, BT.709 primaries, 1.0 = 80 cd/m² — — yes, used for wide gamut Windows

7. Stops, decades, ratios, bits

Stops Ratio Decades (log₁₀) dB (20 log₁₀)
1 2:1 0.30 6.0
3.32 10:1 1 20
6.64 100:1 2 40
10 1,024:1 3.0 60
12.3 5,000:1 3.7 74
14 16,384:1 4.2 84
17.6 200,000:1 5.3 106
20 1,048,576:1 6.0 120
26.6 10⁸:1 8 160

Sensor makers quote dB (20 log₁₀ of the electron ratio): 84 dB is 14 stops.

The same signal under different definitions (stops)

Encoding First code to peak Step ≤ 5% Step ≤ 2%
8-bit linear 8.0 3.7 2.4
8-bit sRGB 11.7 5.9 2.8
10-bit γ 2.4 narrow 23.5 10.0 6.9
10-bit HLG at 1000 cd/m² 25.4 11.9 8.8
10-bit PQ 27.5 17.1 12.5
12-bit PQ 30.9 21.8 18.9
12-bit linear 12.0 7.7 6.4
14-bit linear 14.0 9.7 8.4
16-bit linear 16.0 11.7 10.4

Typical luminance ranges

Thing Low (cd/m²) High (cd/m²) Stops Basis
Vision, all adaptation states 10⁻⁶ 10⁸ 46 textbook
Vision, one adaptation state 11–12.3 3.3–3.7 log units
Print 0.8 80 6.6 100:1 paper
DCI cinema 0.024 48 11 2000:1
SDR reference monitor 0.01 100 13.3 BT.1886 practice
HDR reference monitor 0.005 1000 17.6 BT.2100 minimum
OLED TV, dark room 0.0005 1000 21 native black
Any TV, lit room 0.5 1000 11 reflections
Sensor, 50,000 e⁻ / 3 e⁻ 14.0 / 13.8 / 8.9 ratio / SNR 1 / SNR 10

8. Color float candidates (from §8 of the expert notes)

Name Layout Top value Smallest nonzero Step Worst step ÷ threshold
e5m3 8-bit 10,000 6×10⁻⁷ 12.5% 63
e5m5 10-bit 10,000 1.5×10⁻⁷ 3.1% 16
e5m7 12-bit 10,000 4×10⁻⁸ 0.78% 3.9
e5m9 14-bit 10,000 9×10⁻⁹ 0.20% 0.99
e4m12 16-bit 10,000 7×10⁻⁵ 0.024% 0.49
tapered, 21 binades ≈ 12.6-bit (6,327 codes) 10,000 0.005 3% down to 0.2% 1.0
10-bit PQ 10,000 5×10⁻⁵ 0.9–2% 5.6
12-bit PQ 10,000 4×10⁻⁶ 0.23–0.5% 1.4

Threshold: the Barten-model implementation of the expert notes (see the caveat at Figure 10 of the expert notes).

9. Perceptual spaces and difference metrics

Space / metric Built for Strength Weakness
CIELAB, ΔE*ab (1976) reflective SDR universal blue hue bend; poor uniformity
ΔE2000 small differences, SDR best-validated for surfaces discontinuities; defined for the 10° observer; not for HDR
CIECAM02, CAM16 (CIE 248:2022) appearance under viewing conditions adaptation, surround photopic SDR; no H–K
Oklab SDR image processing hue linearity, simple not validated as a difference metric; SDR
IPT, ICtCp HDR, wide gamut hue linearity, luminance separation no H–K; fixed adaptation
ΔE_ITP (BT.2124) HDR display differences 1 unit ≈ 1 JND by design validated over limited conditions
Jzazbz HDR uniformity wide luminance range less adopted

10. Formulas to implement

Constants are exact unless marked. Sources: BT.2100 for PQ, HLG and ICtCp; BT.2124 for the color difference; CIE 015 for CIELAB; BT.2446 for the tone curve; the Ultra HDR and Adobe gain-map specifications. The Oklab constants are from its author’s publication and were not rechecked here.

PQ (ST 2084), exact rationals

1
2
3
4
5
6
7
m1 = 2610/16384        = 0.1593017578125
m2 = 2523/4096 * 128   = 78.84375
c1 = 3424/4096         = 0.8359375      (= c3 - c2 + 1)
c2 = 2413/4096 * 32    = 18.8515625
c3 = 2392/4096 * 32    = 18.6875
EOTF:     Y = 10000 * ( max(E^(1/m2) - c1, 0) / (c2 - c3 * E^(1/m2)) )^(1/m1)     cd/m2
Inverse:  E = ( (c1 + c2 * y^m1) / (1 + c3 * y^m1) )^m2,   y = Y/10000

Landmarks: signal 0.5 is 92.25 cd/m²; 0.5807 is 203; 0.75 is 983; 0.9 is 3906.

HLG (BT.2100)

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
a = 0.17883277,  b = 1 - 4a = 0.28466892,  c = 0.5 - a*ln(4a) = 0.55991073
OETF:     E' = sqrt(3E)              for E <= 1/12
          E' = a*ln(12E - b) + c     otherwise            (E scene light in [0,1])
Inverse:  E  = E'^2 / 3              for E' <= 1/2
          E  = (exp((E' - c)/a) + b) / 12   otherwise
OOTF:     Ys = 0.2627 R + 0.6780 G + 0.0593 B;   Rd = Lw * Ys^(gamma - 1) * R   (same for G, B)
gamma:    1.2 + 0.42*log10(Lw/1000)          for 400 <= Lw <= 2000
          1.2 * 1.111^log2(Lw/1000)          outside that range
Black:    beta = sqrt(3 * (Lb/Lw)^(1/gamma));  use max(0, (1 - beta)*E' + beta) as the signal
75% signal as display light:  Lw * 0.26496^gamma

ICtCp and ΔE ITP

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
From linear BT.2020 RGB, 1.0 = 10000 cd/m2:
L = (1688 R + 2146 G +  262 B) / 4096
M = ( 683 R + 2951 G +  462 B) / 4096
S = (  99 R +  309 G + 3688 B) / 4096
L', M', S' = PQ inverse EOTF of L, M, S          (HLG OETF for the HLG variant)
I  = 0.5 L' + 0.5 M'
PQ:   Ct = ( 6610 L' - 13613 M' + 7003 S') / 4096     Cp = (17933 L' - 17390 M' - 543 S') / 4096
HLG:  Ct = ( 3625 L' -  7465 M' + 3840 S') / 4096     Cp = ( 9500 L' -  9212 M' - 288 S') / 4096

Delta E ITP = 720 * sqrt( dI^2 + (0.5 dCt)^2 + dCp^2 )      always from the PQ form, on display light

About 1 is one just-noticeable difference in the most critical viewing state. BT.2124 suggests that a tolerance below 3 may be acceptable for a reference display. Older papers scale the same quantity differently; check before comparing numbers.

CIELAB, exact constants

1
2
3
f(t) = t^(1/3)                 for t > (6/29)^3 = 216/24389
f(t) = (841/108) t + 4/29      otherwise
L = 116 f(Y/Yn) - 16;   a = 500 [f(X/Xn) - f(Y/Yn)];   b = 200 [f(Y/Yn) - f(Z/Zn)]

For display light, $Y_n$ is the diffuse white (203 cd/m² by BT.2408), not the peak.

Oklab

1
2
3
4
5
6
7
8
From linear sRGB:
l = 0.4122214708 r + 0.5363325363 g + 0.0514459929 b
m = 0.2119034982 r + 0.6806995451 g + 0.1073969566 b
s = 0.0883024619 r + 0.2817188376 g + 0.6299787005 b
l', m', s' = cube roots
L = 0.2104542553 l' + 0.7936177850 m' - 0.0040720468 s'
a = 1.9779984951 l' - 2.4285922050 m' + 0.4505937099 s'
b = 0.0259040371 l' + 0.7827717662 m' - 0.8086757660 s'

Luma and chroma, general form

1
2
3
4
5
6
7
8
9
Y'  = KR R' + (1 - KR - KB) G' + KB B'
Cb  = 0.5 (B' - Y') / (1 - KB)
Cr  = 0.5 (R' - Y') / (1 - KR)
          KR       KB
BT.601    0.299    0.114
BT.709    0.2126   0.0722
BT.2020   0.2627   0.0593
Narrow range, n bits:  Y code = (219 Y' + 16) * 2^(n-8);   C code = (224 C + 128) * 2^(n-8)
Full range,   n bits:  Y code = (2^n - 1) Y';              C code = (2^n - 1) C + 2^(n-1)

For other primaries, KR and KB are the red and blue entries of the Y row of that space’s RGB-to-XYZ matrix.

Integer arithmetic that is exact

1
2
3
4
5
6
7
Float to 8-bit:         i = round(255 f), after clamping f to [0,1] in floating point
8-bit to float:         f = i / 255
a*b/255, rounded:       t = a*b + 128;   (t + (t >> 8)) >> 8
16-bit to 8-bit:        (v*255 + 32895) >> 16
8-bit to 16-bit:        v * 257
n to m bits, full range:   round(v * (2^m - 1) / (2^n - 1))
n to m bits, narrow range: v << (m - n)

Tone curve with an exact inverse (BT.2446 Method C, luminance in cd/m²)

This is the default parameter set printed in BT.2446-1, for HLG display light. Use the constants as printed; recomputing $k_2$ and $k_4$ from the rounded $k_1$ and $k_3$ gives slightly different values.

1
2
3
Y_sdr = k1 * Y_hdr                              for Y_hdr < Y_ip = 58.5 / k1
Y_sdr = k2 * ln(Y_hdr / Y_ip - k3) + k4         otherwise
k1 = 0.83802,  k2 = 15.09968,  k3 = 0.74204,  k4 = 78.99439

Gain maps

1
2
3
4
5
6
7
Make:   G = log2( (HDR + k_hdr) / (SDR + k_sdr) )        linear light, same primaries
        g = clamp( (G - Gmin) / (Gmax - Gmin), 0, 1 )^gamma;   code = floor(255 g + 0.5)
Apply:  g = code/255 (after resampling);   G = Gmin + (Gmax - Gmin) * g^(1/gamma)
        H = log2( display peak / display SDR white )
        W = clamp( (H - CapMin) / (CapMax - CapMin), 0, 1 )
        HDR = (SDR + k_sdr) * 2^(G * W) - k_hdr
Defaults: k_sdr = k_hdr = 1/64

Quantization and stops

1
2
3
4
5
Stops between two luminances:        log2(L2 / L1)
Relative step of a power-law code:   dL/L = (gamma / N) * L^(-1/gamma)      N codes over [0,1], L relative
Codes per stop at code v, gamma g:   v * (1 - 2^(-1/g))
Worst blend error in a power-law space, black over white at coverage f:   f^(1/g) - f
      peak at f = g^(-g/(g-1)):   g = 2.2 gives f = 0.236, error 0.283 (codes 60 against 132)

Lookup-table conventions

  • A “17-point” table for 8-bit data has two incompatible meanings: nodes at 0, 16, 32 and so on up to 256, where white (255) is not a node, or 17 nodes spread evenly from 0 to 255. Mixing them is a scale error of 256/255.
  • In .cube files red varies fastest. In the Common LUT Format blue varies fastest. Converting without reordering swaps red and blue.
  • A uniform grid on linear input spends its first cell on the darkest fifth of the lightness scale. Put a log or PQ shaper in front.
  • Tetrahedral interpolation always runs from the cell’s black corner to its white corner, so grays are interpolated only from gray nodes. For fractional position (r, g, b) with r ≥ g ≥ b the weights are 1 − r, r − g, g − b and b on corners 000, 100, 110 and 111; the other five orderings follow by permutation.
  • Reported table sizes for errors under one just-noticeable difference: about 33 per side for SDR with tetrahedral interpolation, and 55 to 85 per side for 12-bit PQ output depending on content. Sizes depend strongly on the test images, especially dark saturated ones.

Comments