HDR Gamut Plot Developer Reference
Architecture and maintenance notes for the standalone HDR Gamut Plot Lab tool, including page structure, state, UI ids, RGB gamut metadata, PQ and HLG transfer math, ICtCp and JzAzBz conversions, canvas rendering, research panels, image analysis, batch conversion, exports, share URLs, public API, and Auric Library binding.
Overview
HDR Gamut Plot Lab is implemented as a browser-only IIFE in
js/tool/hdr-gamut-plot.js. The engine owns color-space constants, spectral locus data,
sRGB and BT.2020 matrices, PQ and HLG transfer functions, ICtCp and JzAzBz conversions, CIE diagram
rendering, tone curves, perceptual planes, EOTF comparison, gamut boundary rings, image analysis,
batch conversion, copy/export helpers, URL state, and window.AAHdrGamutPlot. The HTML
shell in tool/general/gamut-and-rendering/hdr-gamut-plot/index.html declares the controls,
canvases, tabs, standards copy, formulas, references, and research panels.
1. File map
+- Tool shell:
tool/general/gamut-and-rendering/hdr-gamut-plot/index.htmlcontains metadata, hero content, guide banner, tab navigation, controls, canvases, action controls, standards, formulas, references, research panels, toast node, fullscreen chart overlay, and script includes. - Tool engine:
js/tool/hdr-gamut-plot.jscontains the standalone runtime, rendering code, transfer math, exports, state, URL restore, and public API. - Library binding:
js/library/tool-bindings.jsregisters/tool/general/gamut-and-rendering/hdr-gamut-plot/as tool idhdr-gamut-plot, categoryGamut & Rendering, asset typepreset. - Shared runtime capture:
js/library/tool-bindings.jsalso mapshdrGamuttowindow.AAHdrGamutPlot.getStateand restore towindow.AAHdrGamutPlot.restoreState. - Discovery outputs: documentation changes must be reflected in
data/documentation.json, RSS, feed, sitemaps, PWA cache manifest, and search index by running the discovery scripts.
2. Page shell and UI contract
+- Application root:
hg-appwraps the tool withrole="application". - Tabs: tab buttons use
data-hg-taband panel idsp-hg-lab,p-hg-actions,p-hg-standards,p-hg-formulas,p-hg-refs, andp-hg-research. - Control ids: the engine reads
hg-color-space,hg-overlay-toggles,hg-adv-toggles,hg-axes,hg-observer,hg-peak,hg-curve-type,hg-hlg-env,hg-signal-level,hg-plot-mode, andhg-tmo. - Label ids: runtime labels include
hg-peak-val,hg-curve-peak-label,hg-axes-label,hg-axes-status,hg-hlg-gamma, andhg-ictcp-I-label. - Canvas ids: primary render targets are
hg-gamut-canvas,hg-curve-canvas,hg-ictcp-canvas,hg-compare-canvas,hg-eotf-canvas, andhg-boundary-canvas. - Action ids: buttons include
hg-copy-json,hg-copy-css,hg-copy-csv,hg-export-diagram,hg-export-curve,hg-export-ictcp,hg-copy-link,hg-compare-btn,hg-boundary-btn,hg-upload-btn,hg-batch-run, andhg-batch-csv. - Do not rename ids casually: the engine uses direct id lookups. Any id change must be reflected in event binding, restore, export handlers, Library capture expectations, and tests.
3. State model
+The authoritative state is produced by readState() in
js/tool/hdr-gamut-plot.js.
colorSpace: active working key, defaultRec2020in the page andsRGBfallback in the engine.overlays: object keyed bysRGB,P3, andRec2020with boolean checkbox state.spectral: whether to draw the spectral locus.purples: whether to draw the line of purples.ictcpMarker: whether the ICtCp sample marker option is active.axes:xyoruvp.observer: observer label state, currently1931-2or2015-10.peakNits: display or mastering peak in nits, parsed fromhg-peak.curveType:gamma22,gamma24,pq, orhlg.hlgEnv:dark,dim, orbright.signalLevel: normalized 0 to 1 sample level.plotMode:ictcporjzazbz.tmo:reinhard,hable,aces, oruchimura.
updateAll() debounces redraw with requestAnimationFrame, refreshes labels,
redraws the three primary canvases, updates metrics, and writes the share URL field.
4. Color data and transfer functions
+SPACES: built-in gamut registry with sRGB/Rec.709, Display-P3, and Rec.2020 labels, RGB primary xy coordinates, and D65 white point.SP_CLR: display colors for the three gamuts.- Spectral locus:
L2is a flat CIE 1931 2 degree xy array from 380 nm to 700 nm in 5 nm steps. - sRGB matrices:
M_S2XandM_X2Sconvert D65 sRGB values to and from XYZ. - BT.2020 matrix:
M_BT_XYZsupports HDR perceptual conversion paths and JzAzBz calculations. - ICtCp matrices:
M_BT_LMSandM_LMS_BTsupport BT.2100-style LMS conversion before PQ encoding. - PQ constants:
PQ_M1,PQ_M2,PQ_C1,PQ_C2,PQ_C3, andPQ_MAXdrivepqEotf(),pqOetf(), andpqEncode(). - HLG helpers:
hlgOetf(),hlgEotf(), andhlgSysGamma()drive curve generation and HLG environment labeling. - Tone curves:
curvePoints()creates plotted samples for gamma, PQ, and HLG modes. - Tone mapping:
tmReinhard(),tmHable(),tmAces(),tmUchimura(), andapplyTMO()provide the operator options exposed in the UI.
5. Perceptual conversions
+- sRGB helpers:
srgbGamma(),srgbLinear(),rgbToXyz(),xyzToSrgb(),hexToRgb(), andrgbToHex()support hover, batch, and color fill workflows. - CIELAB:
xyzToLab()is used by hover sampling and batch output. - Chromaticity:
xyToUpVp()converts xy into u-prime v-prime, whilecoordForAxes()returns coordinates for the active diagram mode. - ICtCp:
pqEncodeLMS(),rgbToICtCp(), andictcpToRgb()convert HDR RGB values into intensity and chroma components. - JzAzBz:
xyzToJzAzBz()converts absolute XYZ values into Jz, Az, and Bz for the perceptual plane and boundary calculations. - Gamut area:
triArea()andgamutArea()calculate triangle area in the selected axes and power metrics, CSV, CSS, and comparison output.
6. Rendering pipeline
+- Theme helpers: canvas renderers use theme color helpers so diagrams remain legible in light and dark modes.
- Chromaticity diagram:
drawChromDiagram()renders background fill, spectral locus, line of purples, visible gamut triangles, labels, current working space context, and hover-ready coordinates. - Fill cache: changing overlay checkboxes or axes clears
fillCacheso chromaticity fill can be recomputed safely. - Tone curve:
drawToneCurve()plots the selected curve and labels output luminance against the selected peak. - Perceptual plane:
drawPerceptualPlane()renders ICtCp Ct/Cp or JzAzBz Az/Bz output using the active plot mode, signal level, peak, and tone mapping context. - Metrics table:
updateMetrics()fillshg-metrics-bodywith transformed primaries, white point coordinates, Rec.2020-normalized coverage, and reference labeling. - Hover sampler: mouse movement over
hg-gamut-canvasmaps screen position back to xy, derives XYZ and Lab, computes ICtCp from the current signal level, and writeshg-hover-info.
7. Research tools
+- EOTF comparison:
drawEotfComparison()draws PQ, HLG at 1000 nits, and gamma 2.2 on a log luminance grid from 0.1 to 10000 nits. - Boundary rings:
drawGamutBoundary()draws ICtCp or JzAzBz rings at 0.1, 1, 10, 100, 500, 1000, 4000, and 10000 nits for enabled overlays. - Comparison chart:
compareSpaces()renders a normalized bar chart andupdateCompareTable()fillshg-compare-tbody. - Batch conversion:
runBatch()parses six-digit hex colors from comma-separated or line-separated input, calculates Lab, ICtCp, and JzAzBz values, writes an HTML table, and returns rows for CSV copy. - Image analysis:
analyseImage()samples every fourth pixel from a local canvas, estimates peak and average luminance frompeakNits, and writes estimated gamut coverage tohg-image-results. - Image cap: uploaded image canvases are capped to 1024 pixels in each dimension before analysis to keep the browser responsive.
8. Exports and URL state
+- PNG export:
exportPNG()serializes the selected canvas withtoDataURL("image/png")and downloads it through a temporary anchor. - Clipboard helper:
copyText()usesnavigator.clipboard.writeText()and reports success or failure through the toast. - JSON export:
buildGamutJSON()exports all built-in gamut definitions plus metadata for axes, peak nits, curve type, and tool name. - CSV export:
buildCSV()exports RGB primary coordinates, white point, area, and Rec.2020-normalized coverage. - CSS export:
buildCSSVars()exports coverage variables, primary coordinate variables, peak nits, and selected curve type. - Share state:
stateToURL()storesaxes,peak,curve, andmode. - URL restore:
loadFromURL()applies those four query parameters before event binding and initial render. - Share limitation: overlays, observer, HLG environment, signal level, and tone mapping operator are not encoded in the share URL. Full Library restore handles a wider state object.
9. Public API and library binding
+- Boot:
boot()loads URL state, binds events, renders the tool, then exposeswindow.AAHdrGamutPlot. - API shape:
window.AAHdrGamutPlot = { getState, restoreState }.getState()returnsreadState().restoreState(saved)applies known fields, restores overlay checkboxes, callsupdateAll(), and returnstruefor valid objects. - Restored fields: restore maps
colorSpace,axes,observer,peakNits,curveType,hlgEnv,signalLevel,plotMode, andtmoto their matching control ids. - Overlay restore: if
saved.overlaysexists, each checkbox inhg-overlay-togglesis set from the matching key. - Simple binding:
attachTool()matches the HDR route, uses tool idhdr-gamut-plot, nameHDR Gamut Plot, href/tool/general/gamut-and-rendering/hdr-gamut-plot/, categoryGamut & Rendering, and asset typepreset. - Capture fallback: Library capture first calls
firstToolCanvas()and savesHDR gamut plotas a canvas image. If no canvas exists, it falls back tocaptureFormPreset({ name: "HDR gamut preset" }). - Binding restore: the generic form binding triggers
hdr-renderandhdr-update. Prefer the public API restore when a full saved state object is available.
10. Extension checklist
+- Add new RGB gamuts to
SPACESwith a stable key, label, red, green, blue, and white xy arrays. - Add a display color to
SP_CLRand update overlay controls if the new gamut should be user-toggleable. - Update metrics, JSON, CSS, CSV, comparison, and docs if the new gamut should appear in exports.
- When adding a transfer curve, update
curvePoints(), keyboard shortcuts, labels, formula copy, share URL expectations, and tests. - When adding a perceptual model, update
drawPerceptualPlane(),drawGamutBoundary(), batch conversion, result headings, and exports. - When changing state fields, update
readState(),restoreState(),stateToURL()if appropriate, Library capture notes, and documentation. - When changing canvas ids or dimensions, update export handlers, Library canvas capture behavior, fullscreen helpers, responsive CSS, and smoke tests.
- When changing image analysis, document whether pixels are assumed SDR, display-referred, or scene-referred so users do not treat estimates as calibrated measurements.
- Regenerate documentation discovery outputs after article edits with
scripts/generate-discovery.mjs,scripts/generate-pwa-cache-manifest.mjs, andsearch/client/build-index.js. - Keep standard names exact: Rec.709, Display-P3, Rec.2020, BT.2100, ST 2084 PQ, HLG, ICtCp, and JzAzBz.
11. Testing and risk notes
+- Boot: verify the Lab tab appears, controls have defaults, the three primary canvases render, and the metrics table populates.
- Controls: exercise every color space, overlay toggle, advanced toggle, axes mode, observer value, peak value, curve type, HLG environment, signal level, plot mode, and tone mapping operator.
- Keyboard: test
1,2,3,4, andAoutside form controls. - Hover: move over the chromaticity diagram in xy and u-prime v-prime modes and verify the coordinate readout updates without console errors.
- Actions: test JSON, CSS, CSV, link copy, compare chart, diagram PNG, curve PNG, and perceptual plane PNG.
- Research: open the Research tab, confirm EOTF comparison draws, compute gamut boundary, upload a sample image, run batch conversion, and copy batch CSV.
- URL: create a share URL, reload it, and verify axes, peak, curve, and plot mode restore before first render.
- Library: save a preset snapshot, confirm the canvas preview, restore full runtime state, and verify overlay checkboxes return to saved values.
- Numerical risk: changes to PQ constants, HLG gamma, matrices, spectral locus, or JzAzBz constants will alter diagrams, batch output, exported JSON, and comparison metrics.
- Interpretation risk: xy area, u-prime v-prime area, ICtCp/JzAzBz plots, and browser image estimates answer different questions. Keep UI copy and docs explicit about what each result means.