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,
mapping methods, slice rendering, batch mapping, exports, URL restore, and the public
window.AAGamutMap API. js/tool/gm/gm-sources.js holds the dataset register
and method catalogue, and js/tool/gamut-map-views.js draws the Boundary, Methods, Data, and
Reference views. It has no runtime network dependency for its color math.
1. File map
+- Tool shell:
tool/general/colorimetry/gamut-map/index.htmlcontains metadata, hero, tabs, controls, result canvases, and the Reference view (standards, formulas, references, and research notes). - 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 the fullscreen chart overlay for the page's canvases. - 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-boundary,p-gm-methods,p-gm-data,p-gm-actions, andp-gm-reference. - Primary controls:
gm-base-picker,gm-base-hex,gm-l,gm-src-gamut,gm-dst-gamut,gm-strength,gm-res, andgm-sampler. - Method controls: radio inputs named
gm-intentexposecompress,clip,scale, andadapt-clip. The older valuesperceptual,relative,saturation, andabsoluteare still accepted;relativeruns adapt-clip andabsoluteruns clip. - 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, andgm-compare-canvas. - Action controls:
gm-export-png-src,gm-export-png-dst,gm-export-json,gm-share-btn,gm-copy-share, andgm-batch-run; the Boundary tab'sgmVolRunmeasures volumes.
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 iscompress. - 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, per-space transfer curves
(
TRC: sRGB, Adobe RGB, ROMM, and BT.2020, applied throughdecodeIn()andencodeIn()), 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 the adapt-then-clip method's source-to-target white-point adaptation and adapts a D50 space onto the source space's Lab white.
5. Boundary slicing and mapping
+- Membership:
isInGamut()Bradford-adapts XYZ to the target's white when it differs from the source space's white, converts it 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*. - Chroma compression (
compress):mapColorIntent()bisects LCh chroma to the largest in-gamut value at the same L* and hue; strength 1 lands on that boundary, and 0 keeps the original chroma for the final clip. - Clip in target RGB (
clip): converts into target linear RGB and clips channels withclamp01(), with no white-point adaptation. - Adapt white, then clip (
adapt-clip): Bradford-adapts source white to destination white, then clips target RGB. - Uniform RGB scale (
scale): 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 and returns it with its standard error, sampling a box thatgamutBox()fits to each space.
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. - Boundary slices: the Boundary tab, drawn by
js/tool/gamut-map-views.js, plots the a*b* boundary at L* 20, 40, 65, 80, and 90 for the spaces you choose. - Volume comparison: the Boundary tab's Measure the five runs
gamutVolumeMC()for all five spaces at the chosen sample count (5,000 to 200,000, 20,000 by default) and shows each volume with its standard error. - 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 mapping method, update
mapColorIntent(),renderMappedSlice(), theMETHODScatalogue injs/tool/gm/gm-sources.js, 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, 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 the chroma compression, clip, uniform scale, and adapt-then-clip methods on highly saturated red, green, blue, yellow, and brand colors.
- Actions: PNG export, JSON export, share URL restore, Measure the five, and Run the list 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.