Tone Mapping Developer Reference
Architecture and maintenance notes for the Tone Mapping Lab, including page structure, helper behavior, state, transfer functions, tone operators, color-space matrices, Bradford adaptation, CPU image processing, scopes, exports, URL state, public API, Library integration and testing risks.
Overview
Tone Mapping Lab is implemented as a browser-only CPU pipeline in
js/tool/tone-mapping.js, with page-level tab, guide, dropdown and fullscreen helpers in
js/tool/tone-mapping-page.js. The runtime owns EOTF/OETF conversion, tone mapping
operators, color-space transforms, Bradford white-point adaptation, procedural and uploaded sources,
grading, gamut mapping, scopes, LUT exports, batch analysis, compact URL state,
window.AAToneMapping and window.AAToneEngine, which
js/tool/tone-mapping-views.js reads to render the Lab, Operators, Scopes, Data, Export
and Reference views.
1. File map
+- Tool shell:
tool/general/gamut-and-rendering/tone-mapping/index.htmldeclares metadata, hero content, the six tab panels, controls, canvases, hidden action buttons and fullscreen overlay. - Page helper:
js/tool/tone-mapping-page.jshandles guide dismissal, tabs, dropdown label synchronization and fullscreen chart copying. - Runtime:
js/tool/tone-mapping.jscontains transfer functions, operators, matrices, state, processing, scopes, exports, batch analysis and public API.js/tool/tone-mapping-views.jsrenders the six views andjs/tool/tm/tm-sources.jsholds the dataset register aswindow.AAToneSources. - Library binding:
js/library/tool-bindings.jsregisters the route astone-mapping, nameTone Mapping, categoryGamut & Renderingand asset typepreset. - Runtime Library hooks: shared capture maps
toneMappingtowindow.AAToneMapping.getStateand restore towindow.AAToneMapping.restoreState.
2. Page shell and helper contract
+- App root:
tm-appwraps all tool controls and panels. - Tabs: the helper activates panels by
data-tm-taband panel idsp-tm-lab,p-tm-operators,p-tm-scopes,p-tm-data,p-tm-exportandp-tm-reference. - Guide: the helper still stores
tm-guidedismissal in local storage underaa_tm_guide_dismissed, but the current shell has no guide element. - Dropdown sync:
tone-mapping-page.jspatches the value setter for hidden dropdown inputs such astm-source,tm-src-encoding,tm-op,tm-working,tm-target-primandtm-oetf. The current shell uses native selects and a segmented operator control, so the patch finds no custom dropdown to sync. - Fullscreen charts: the helper copies source canvases into
tnm-chart-fs-canvasfortm-view,tm-curve,tm-hist,tm-waveform,tm-vectorscopeandtm-compare-canvas. - Control contract: the runtime depends on stable ids. Rename controls only with
matching updates to
readState(),restoreState(), event binding, URL state, exports and docs.
3. State model
+The authoritative settings object is produced by readState().
- Source:
source,srcEnc,srcPrim,srcWhite,srcPeakandexposure. - Operators:
op,lowOp,lowAandlowB. - CDL and creative grading:
contrast,saturation,lift,gamma,gain,temp,tint,hueandvibrance. - Working and output:
working,gamutMap,targetPrim,targetWhite,peakandoetf. - Custom curve:
useCustom,knee,midandshoulder. - Overlays and split:
showOog,dither,falseColor,splitEnableandsplitPos. - Runtime globals:
hdrImgstores the current source,mappedImgstores the processed RGBA result andstateA/stateBstore A/B split buffers.
4. Transfer functions and operators
+- Transfer functions:
srgbEotf(),srgbOetf(),gammaEotf(),gammaOetf(),pqEotf(),pqOetf(),hlgOetf()andhlgEotf(). - Encoding dispatch:
toLinear()andfromLinear()map UI encodings to linear scene values and output code values. - Tone operators:
tmReinhard(),tmReinhardExt(),tmHable(),tmACES(),tmUchimura(),tmGammaScale(),tmScaledReinhard(),tmLog()andapplyCustomCurve(). - Main dispatch:
applyTM()selectsnone,reinhard,uchimura,hable,aces,bt2446a(orgamma-scale),bt2446c(orscaled-reinhard),logorcustom. The two former BT.2446 ids are not tone curves;OPERATORSmarks themisCurve: false, so the Lab offers seven and they stay reachable only by saved links. - Low-level dispatch:
applyLowOp()handles add, multiply, softclip, power, sigmoid, exp, log and tanh before the main tone mapper. - Curve drawing:
drawCurveCanvas()plotsapplyTM()from input 0 through 5 against the current operator configuration.
5. Color spaces and adaptation
+- Matrix helper:
MUL3()multiplies row-major 3x3 matrices by RGB or XYZ vectors. - Supported spaces: sRGB/Rec.709, Display P3, Rec.2020 and ACEScg have forward-to-XYZ and inverse-from-XYZ matrices.
- White points:
ILLUMINANT_XYZdefines D65, D60 and D50. - Conversion:
toXYZ()andfromXYZ()convert between RGB working spaces and XYZ. - Bradford adaptation:
BRAD_M,BRAD_MIandbradfordAdapt()adapt source and target white points. - Gamut mapping:
processPixel()implements clip, preserve hue and soft compression after conversion into target primaries.
6. Image pipeline
+- Sources:
genHDRScene()creates the default HDR test scene,genGradient()creates the procedural HDR ramp,genPatches()creates color-checker patches and uploads are decoded through a temporary canvas intoFloat32Arraydata. - Pixel path:
processPixel()linearizes, converts to working space, adapts white point, applies exposure, low operator, tone mapping, CDL, temperature/tint, hue, vibrance, target conversion, gamut mapping, output OETF and optional dithering. - Image pass:
processImage()loops over every pixel, writes an 8-bit mapped RGBA buffer and counts, and masks, pixels that leave the target gamut. - Viewport:
renderViewport()writes the mapped buffer, false color buffer, out-of-gamut overlay or A/B split intotm-view. - Scheduling:
scheduleUpdate()debounces work throughrequestAnimationFrame, processes the image, renders the viewport, updates scopes, chips and numeric labels.
7. Scopes and rendering
+- Histogram:
computeHistogram()anddrawHistCanvas()draw RGB channel histograms from mapped display data. - Waveform:
computeWaveform()anddrawWaveCanvas()bin luma by image column. - Vectorscope:
computeVectorscope()anddrawVecCanvas()render Cb/Cr distribution. - HUD chips:
updateChipInfo()updates processing time, working and target spaces, operator, resolution, OOG warning, adjustment domain and behavior label. - Value labels:
updateValueDisplays()refreshes exposure, source peak, low op parameters, contrast, saturation, peak, custom curve values and intent label. - Page fullscreen: fullscreen chart display is handled outside the runtime by
tone-mapping-page.js.
8. Exports, batch and URL state
+- PNG:
exportPNG()serializestm-viewas PNG, behind the hiddentm-export-pngbutton. - JSON:
exportJSON()downloadsreadState()andimportJSON()maps JSON keys back totm-*ids, behind hidden buttons. - 1D LUT: the Export tab uses
exportCurveCube()(a 33-entry 1D.cubewithDOMAIN_MIN/DOMAIN_MAXand a header naming the steps it omits) andexportCurveCSV()(1024 samples over 0–1 or 0–12). The olderexport1DLUT(), 1024 samples over 0–5 totone-map-1d.csv, sits behind a hidden button. - 3D LUT:
exportPipelineCube()writes a 17-point.cubethat runs every pipeline step. The olderexport3DLUT(), a 33 point.cubewith per-channel curve mapping, sits behind a hidden button. - URL:
saveURL()storesop,exp,src,peak,oetfandtp.loadURL()restores those fields. - Batch:
runBatch()parses six-digit HEX colors, appliesprocessPixel()and writes source, mapped color and OOG status.exportBatchCSV()serializes the resulting table. - Presets:
applyPreset()configures SDR 100, HDR 1000 and P3 600. - Benchmarks:
runBench()repeatedly runsprocessImage()and reports average milliseconds per frame. - Operator comparison: the Operators tab builds its table from
compareOperators()and draws every curve ontm-compare-canvas. The olderrunOperatorComparison(), which times each operator and draws a bar chart, sits behind the hiddentm-compare-runbutton.
9. Public API and library binding
+- API:
window.AAToneMapping = { getState, restoreState }. getState(): returns settings, whether the current source is an uploaded image, image size, whether a mapped buffer exists, whether A/B buffers exist and batch textarea input.restoreState(saved): accepts a full object or bare settings, applies known ids, restores batch input, rebuilds the procedural source when needed, schedules an update and returnstrue.- Simple binding:
attachTool()captures the first available canvas asTone mapping outputwith asset typeimage, otherwise falls back toTone mapping preset. - Generic restore: the simple binding triggers
tm-render,tm-applyandtone-mapping-render. Preferwindow.AAToneMapping.restoreState()for exact state restore. - Upload limitation: runtime state records upload presence and image size, not uploaded image bytes. Persist source images separately when needed.
10. Extension checklist
+- When adding a tone operator, update
applyTM(), theOPERATORSlist, behavior labels, curve drawing, operator comparison, formulas, docs and tests. - When adding a low-level operator, update
applyLowOp(), low-op dropdown labels, parameter ranges and examples. - When adding a color space, provide forward and inverse XYZ matrices, white-point behavior, dropdown entries, gamut mapping expectations and LUT tests.
- When changing state fields, update
readState(),restoreState(), JSON export/import, URL state if appropriate, Library documentation and smoke tests. - When changing scope math, verify histogram, waveform and vectorscope remain coherent for both procedural and uploaded sources.
- When changing LUT export, document whether the LUT represents only the curve or the full color pipeline.
- When changing page ids, update page helper dropdown sync, fullscreen map, runtime binding and Library binding.
- When changing uploaded image handling, test large images and memory use because CPU processing is linear in pixel count.
- Regenerate documentation discovery outputs after docs changes with
scripts/generate-discovery.mjs,scripts/generate-pwa-cache-manifest.mjsandsearch/client/build-index.js. - Keep user-facing copy clear that this is a diagnostic and design tool, not official ACES, Dolby Vision or calibrated measurement software.
11. Testing and risk notes
+- Boot: verify the HDR test scene appears, tone curve, histogram, waveform and vectorscope draw, and chips update.
- Sources: test the HDR test scene, exposure gradient, color checker and uploaded images.
- Operators: test none, Reinhard, Uchimura, Hable, the Narkowicz fit, Log and Custom, plus the two former BT.2446 ids through a saved link.
- Pipeline controls: test source encoding, primaries, white points, exposure, low ops, CDL, working space, gamut map, target primaries, target white, peak and OETF.
- Actions: test presets, every Export tab selection (the tone curve as
.cubeand CSV at both domains, the whole pipeline, a link), A/B split, custom curve presets and benchmarks. - Research: test operator comparison, batch table, batch CSV and false color.
- Library: save a canvas preset, capture full state, restore state and confirm batch input returns.
- Numerical risk: transfer constants, matrices, Bradford adaptation, tone operators and gamut mapping changes will alter viewport pixels, scopes, LUTs and exported JSON.
- Performance risk: large uploaded images can block the main thread. Recheck interaction latency when expanding scope resolution or processing complexity.
- Interpretation risk: the ACES option is a Narkowicz fit, the two operators once labelled BT.2446 do not implement BT.2446, and LUT exports are diagnostic approximations.