Gamut Map Developer Reference
Architecture and maintenance notes for the standalone Gamut Map tool, including the HTML shell, state model, RGB space registry, Lab and LCh math, Delta E formulas, CIELAB boundary slicing, rendering intents, canvas rendering, exports, URL state, public API, and Library binding.
Overview
Gamut Map is implemented as a self-contained browser IIFE. The page shell declares the full UI and
research content, while js/tool/gamut-map.js owns color conversions, gamut membership,
rendering intents, slice rendering, batch mapping, exports, URL restore, and the public
window.AAGamutMap API. It has no runtime network dependency for its color math.
1. File map
+- Tool shell:
tool/general/colorimetry/gamut-map/index.htmlcontains metadata, hero, guide, tabs, controls, result canvases, standards, formulas, references, and research panels. - Tool engine:
js/tool/gamut-map.jscontains all math, state, rendering, interaction, export, restore, and API logic. - Library integration:
js/library/tool-bindings.jsregisters/tool/general/colorimetry/gamut-map/as tool idgamut-map. - Generated inline helper:
js/generated-inline/02ca5af1478c73a2406b.jsprovides canvas accessibility naming for the page. - Discovery metadata: docs are indexed from
data/documentation.jsonand generated RSS, sitemap, PWA, and search files.
2. Page shell and UI contract
+- App root:
#gm-appwraps the Gamut Map application. - Tabs: buttons use
data-gm-tab; panels usep-gm-lab,p-gm-actions,p-gm-standards,p-gm-formulas,p-gm-refs, andp-gm-research. - Primary controls:
gm-base-picker,gm-base-hex,gm-l,gm-src-gamut,gm-dst-gamut,gm-strength,gm-res, andgm-sampler. - Intent controls: radio inputs named
gm-intentexposeperceptual,relative,saturation, andabsolute. - Overlay controls:
gm-overlay-oog,gm-overlay-base,gm-overlay-grid,gm-overlay-bounds,gm-overlay-axis, andgm-adaptive. - Canvas outputs:
gm-canvas-src,gm-canvas-dst,gm-compare-canvas, andgm-multi-canvas. - Action controls:
gm-export-png-src,gm-export-png-dst,gm-export-json,gm-share-btn,gm-copy-share,gm-compare-btn,gm-volume-btn, andgm-batch-run.
3. State model
+
The module-level ST object is the single runtime state store. Event handlers update
ST, then call refresh() or the relevant output function.
- Defaults:
baseHexis#247DEB,lStaris 65, source issRGB, target isP3, and intent isperceptual. - Mapping controls:
strength,resolution,sampler, andadaptiveare stored with the state. - Overlays:
overlay.oog,overlay.base,overlay.grid,overlay.boundaries, andoverlay.axismirror the checkbox controls. - Probe:
probestores the clicked Labaandbpoint, ornullwhen no point has been selected. - Delta E formula:
deFormulastores the dropdown value, although the current summary output reports all three formulas together. - syncUI:
syncUI()pushes state into inputs, labels, radios, and checkboxes after boot, URL restore, swap, random, and API restore.
4. Color math and RGB spaces
+- Utilities: helpers cover HEX parsing, sRGB transfer, clamp, rounding, 3x3 matrix multiply, and 3x3 inverse.
- RGB spaces:
defSpace()creates metadata and matrices for sRGB, Display P3, Rec.2020, Adobe RGB, and ProPhoto RGB. - White points: D65 is used for sRGB, P3, Rec.2020, and Adobe RGB. D50 is used for ProPhoto RGB.
- Matrix build:
buildMatrices()derives RGB to XYZ and XYZ to RGB matrices from xy primaries and white point. - Lab conversion:
xyzToLab(),labToXyz(),labToLch(), andlchToLab()support gamut slicing, mapping, probes, and Delta E. - Delta E:
deltaE76(),deltaE94(), anddeltaE00()provide legacy and perceptual difference metrics. - Bradford:
bradfordAdapt()supports absolute colorimetric source-to-target white-point adaptation.
5. Boundary slicing and mapping
+- Membership:
isInGamut()converts XYZ into the target RGB space and checks whether all linear channels fall between 0 and 1. - Lab membership:
labInGamut()converts Lab to XYZ and delegates toisInGamut(). - Boundary slice:
gamutBoundarySlice(L, space, hueSteps)walks hue angles and bisects chroma to find the maximum in-gamut boundary at fixed L*. - Perceptual mapping:
mapColorIntent()reduces LCh chroma by bisection until the mapped color fits the destination gamut. - Relative mapping: converts into target linear RGB and clips channels with
clamp01(). - Absolute mapping: Bradford-adapts source white to destination white, then clips target RGB.
- Saturation mapping: scales target linear RGB toward an in-range result and falls back to clipping when needed.
- Area and volume:
gamutAreaXY()measures chromaticity triangle area;gamutVolumeMC()estimates CIELAB volume using Monte Carlo sampling.
6. Canvas rendering and diagnostics
+- Source render:
renderSourceSlice()samples Lab a*b* positions, fills points that are in the source gamut, and draws optional boundaries, base marker, and hue ticks. - Mapped render:
renderMappedSlice()samples source-gamut points and maps out-of-target points through the active intent before drawing the target preview. - Samplers: grid uses cell centers, stratified jitters inside each cell, and Halton uses base 2 and base 3 low-discrepancy coordinates.
- Stats:
renderStats()computes source and target boundary area at the current L* using a 72-point boundary and shoelace area. - Probe: canvas clicks translate pixel position into Lab a*b* coordinates and
updateProbe()reports LCh, HEX preview, and gamut status. - Base panel:
updateBasePanel()reports Lab, LCh, and in-gamut status for the selected base HEX. - Before/after:
renderBeforeAfter()maps 12 test colors through the active state and draws paired swatches. - Refresh:
refresh()resets logical canvas sizes and reruns the main render, stats, probe, Delta E, and base-panel updates.
7. Exports, share URL, and batch
+- PNG export:
exportPNG(canvasId)downloads the selected canvas viatoDataURL("image/png"). - JSON export:
exportJSON()writes source space, target space, intent, strength, L*, resolution, sampler, and timestamp. - Share URL:
generateShareURL()encodessrc,dst,int,l,res,sam,str, andhex. - URL restore:
restoreURL()reads those query params during boot before syncing the UI. - Area comparison:
renderComparison()creates a CIE xy area table and bar chart for all RGB spaces. - Volume comparison:
renderVolumeComparison()schedules Monte Carlo volume estimates with a small timeout so the UI can show a computing message. - Batch mapping:
runBatch()parses up to 50 valid HEX values, appliesmapColorIntent(), and reports output HEX, out-of-gamut status, Delta E 2000, and Lab values. - Clipboard: share URL copy uses
navigator.clipboard.writeText().
8. Public API and library binding
+- Namespace: the tool exposes
window.AAGamutMapafter boot. - getState: returns a JSON-cloned copy of
ST. - restoreState: merges a saved object into
ST, syncs controls, and runs a full refresh. - Library match:
js/library/tool-bindings.jsmatches/tool/general/colorimetry/gamut-map/. - Library metadata: id
gamut-map, nameGamut Map, href/tool/general/colorimetry/gamut-map/, categoryColorimetry, and asset typepreset. - Capture: the binding tries
firstToolCanvas()and saves aGamut map snapshotthroughcaptureCanvasAsImage(). If no canvas is found, it saves aGamut map presetthroughcaptureFormPreset(). - Restore: the current binding uses generic form restore triggers
gm-render,gm-update, andgamut-map-render. Richer restore can callwindow.AAGamutMap.restoreState()directly.
9. Extension checklist
+- Add a new RGB space with
defSpace(), stable key, display name, xy primaries, white point, and chart color. - Update source and target dropdown HTML whenever a new space key is added.
- Confirm RGB to XYZ and XYZ to RGB matrices are invertible before exposing a space.
- When adding a rendering intent, update
mapColorIntent(),renderMappedSlice(), radio controls, share URL behavior, batch output, and docs. - Wire new state fields into
ST,syncUI(), exports, share URL, public API restore, and Library capture if relevant. - Keep rendering deterministic when users need screenshots; random samplers should be clearly labeled.
- Update Delta E output if the formula dropdown becomes a true single-formula selector.
- Update generated docs JSON, RSS, sitemaps, PWA cache manifest, and search index after documentation changes.
- Test with narrow-to-wide and wide-to-narrow conversions, including ProPhoto D50 cases.
- Document any mathematical behavior that differs from full ICC profile conversions.
10. Testing and risk notes
+- Boot: the page loads, the guide appears, tabs switch, source and mapped slices render, stats populate, and before/after output is nonblank.
- Controls: base color, random, L*, source, target, swap, intent, strength, resolution, sampler, overlays, and probe clicks update state and output.
- Color math: smoke test sRGB, P3, Rec.2020, Adobe RGB, ProPhoto, Lab/LCh, Bradford adaptation, Delta E 76, Delta E 94, and Delta E 2000.
- Mapping: compare perceptual, relative, saturation, and absolute intents on highly saturated red, green, blue, yellow, and brand colors.
- Actions: PNG export, JSON export, share URL restore, Compare All, Estimate Volumes, and Batch Gamut Mapping should work after multiple state changes.
- Library: save a canvas snapshot, restore a preset, and confirm the page can refresh afterward.
- Performance: test low and high resolution on desktop and mobile widths. 512 by 512 sampling can be expensive.
- Risk: changes to matrices, white points, Lab conversion, transfer functions, or Delta E formulas will shift charts, batch output, exports, documentation examples, and saved asset expectations.