Color and HDR
alpha2 renders in one well-defined color space and exports SDR. This page explains how each kind of source gets into that space, what the engine does with HDR video, and how blending and gradients behave. After reading it you know what colors to expect out of an export and how to correct a source with wrong color tags.
The working space
Section titled “The working space”The engine composites in display-referred linear light with BT.709 primaries, where 1.0 is SDR white (100 nits). Compositing is always premultiplied.
Every export is SDR BT.709. In the browser, export frames come back as planar I420, BT.709, limited range. Natively, alpha2-host encodes them with the codec you choose; bitDepth: 10 asks for 10-bit pictures.
Bringing sources in
Section titled “Bringing sources in”| Source | How it is read |
|---|---|
| SDR video | Decoded through the sRGB EOTF; wide-gamut primaries are converted to BT.709. |
| Stills | Always read as sRGB code values. |
| HDR video (PQ or HLG) | Linearized, converted to BT.709 and tone-mapped to SDR, or refused, as settings.color says. |
| OpenEXR (an extension source) | Linear-light RGB in the file’s primaries, or the primaries the source names: bt709, bt2020, p3_d65, aces_ap0 or aces_ap1. |
| Colors in the document (fills, text, layout) | Straight (not premultiplied) sRGB, as { red, green, blue, alpha } in 0..1 or CSS hex. |
In the browser, uploadRgbaImage takes premultiplied sRGB RGBA8 pixels, uploadYuvFrame converts planar YUV with the project’s color pipeline (which controls tone mapping), and alpha2/hdr-frames uploads planar and HDR VideoFrames.
HDR sources
Section titled “HDR sources”settings.color decides what an HDR source does:
{ "width": 1920, "height": 1080, "frame_rate": { "num": 30, "den": 1 }, "sample_rate": 48000, "color": { "hdr": "tone_map", "hdr_peak_nits": 1000 }, "blend_space": "linear_light"}hdr:tone_map(the default) brings HDR sources into the SDR working space.rejectrefuses to render them.hdr_peak_nits: the luminance HDR sources are taken to peak at, 1000 by default, from 100 to 10,000. PQ above it is clipped, HLG is displayed at it, and the tone map brings it to SDR white.
The tone map is the ITU-R BT.2390 EETF, applied to each pixel’s largest component so that hue is preserved.
When hdr is reject, the linter reports each HDR source as hdr_source, so you find out before an export fails.
Correcting color tags
Section titled “Correcting color tags”A video’s color usually comes from the tags in its stream and frames. When those are missing or wrong, set color_metadata on the source. It overrides frame and stream tags on every host, so every target reads the source the same way:
{ "id": "drone", "kind": "video", "locator": "file:///media/drone-hlg.mov", "color_metadata": { "primaries": "bt2020", "transfer": "hlg", "matrix": "bt2020_ncl", "range": "limited", "dynamic_range": "hdr" }}| Field | Values |
|---|---|
primaries |
bt601, bt709, bt2020 |
transfer |
bt709, srgb, pq, hlg |
matrix |
bt601, bt709, bt2020_ncl, rgb (already RGB) |
range |
limited, full |
dynamic_range |
sdr or hdr: hdr exactly when transfer is pq or hlg |
Stills ignore it: they are always read as sRGB.
Blending and gradients
Section titled “Blending and gradients”settings.blend_space chooses the space blend modes are evaluated in:
linear_light(the default): physically meaningful blending.srgb_encoded: blending on sRGB-encoded values, as design tools and CSS blend. Contrast modes such as overlay and soft-light match design tools only here.
Gradients interpolate their premultiplied stops in linear light, so a gradient between two colors passes through their physical mix. Effect color parameters are straight (not premultiplied) sRGB RGBA, as a color picker shows them.
