Skip to main content
Auric Artisan · Documentation

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.

Published: May 24, 2026 Updated: May 24, 2026 Category: Reference Author: Chirag Bansal
Back to Documentation Auric Artisan Home

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.

Table of contents

  1. 1. File map
  2. 2. Page shell and UI contract
  3. 3. State model
  4. 4. Color math and RGB spaces
  5. 5. Boundary slicing and mapping
  6. 6. Canvas rendering and diagnostics
  7. 7. Exports, share URL, and batch
  8. 8. Public API and library binding
  9. 9. Extension checklist
  10. 10. Testing and risk notes

1. File map

+
  • Tool shell: tool/general/colorimetry/gamut-map/index.html contains metadata, hero, tabs, controls, result canvases, and the Reference view (standards, formulas, references, and research notes).
  • Tool engine: js/tool/gamut-map.js contains all math, state, rendering, interaction, export, restore, and API logic.
  • Library integration: js/library/tool-bindings.js registers /tool/general/colorimetry/gamut-map/ as tool id gamut-map.
  • Generated inline helper: js/generated-inline/02ca5af1478c73a2406b.js provides the fullscreen chart overlay for the page's canvases.
  • Discovery metadata: docs are indexed from data/documentation.json and generated RSS, sitemap, PWA, and search files.

2. Page shell and UI contract

+
  • App root: #gm-app wraps the Gamut Map application.
  • Tabs: buttons use data-gm-tab; panels use p-gm-lab, p-gm-boundary, p-gm-methods, p-gm-data, p-gm-actions, and p-gm-reference.
  • Primary controls: gm-base-picker, gm-base-hex, gm-l, gm-src-gamut, gm-dst-gamut, gm-strength, gm-res, and gm-sampler.
  • Method controls: radio inputs named gm-intent expose compress, clip, scale, and adapt-clip. The older values perceptual, relative, saturation, and absolute are still accepted; relative runs adapt-clip and absolute runs clip.
  • Overlay controls: gm-overlay-oog, gm-overlay-base, gm-overlay-grid, gm-overlay-bounds, gm-overlay-axis, and gm-adaptive.
  • Canvas outputs: gm-canvas-src, gm-canvas-dst, and gm-compare-canvas.
  • Action controls: gm-export-png-src, gm-export-png-dst, gm-export-json, gm-share-btn, gm-copy-share, and gm-batch-run; the Boundary tab's gmVolRun measures 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: baseHex is #247DEB, lStar is 65, source is sRGB, target is P3, and intent is compress.
  • Mapping controls: strength, resolution, sampler, and adaptive are stored with the state.
  • Overlays: overlay.oog, overlay.base, overlay.grid, overlay.boundaries, and overlay.axis mirror the checkbox controls.
  • Probe: probe stores the clicked Lab a and b point, or null when no point has been selected.
  • Delta E formula: deFormula stores 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 through decodeIn() and encodeIn()), 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(), and lchToLab() support gamut slicing, mapping, probes, and Delta E.
  • Delta E: deltaE76(), deltaE94(), and deltaE00() 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 to isInGamut().
  • 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 with clamp01(), 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 that gamutBox() 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 via toDataURL("image/png").
  • JSON export: exportJSON() writes source space, target space, intent, strength, L*, resolution, sampler, and timestamp.
  • Share URL: generateShareURL() encodes src, dst, int, l, res, sam, str, and hex.
  • 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, applies mapColorIntent(), 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.AAGamutMap after 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.js matches /tool/general/colorimetry/gamut-map/.
  • Library metadata: id gamut-map, name Gamut Map, href /tool/general/colorimetry/gamut-map/, category Colorimetry, and asset type preset.
  • Capture: the binding tries firstToolCanvas() and saves a Gamut map snapshot through captureCanvasAsImage(). If no canvas is found, it saves a Gamut map preset through captureFormPreset().
  • Restore: the current binding uses generic form restore triggers gm-render, gm-update, and gamut-map-render. Richer restore can call window.AAGamutMap.restoreState() directly.

9. Extension checklist

+
  1. Add a new RGB space with defSpace(), stable key, display name, xy primaries, white point, and chart color.
  2. Update source and target dropdown HTML whenever a new space key is added.
  3. Confirm RGB to XYZ and XYZ to RGB matrices are invertible before exposing a space.
  4. When adding a mapping method, update mapColorIntent(), renderMappedSlice(), the METHODS catalogue in js/tool/gm/gm-sources.js, radio controls, share URL behavior, batch output, and docs.
  5. Wire new state fields into ST, syncUI(), exports, share URL, public API restore, and Library capture if relevant.
  6. Keep rendering deterministic when users need screenshots; random samplers should be clearly labeled.
  7. Update Delta E output if the formula dropdown becomes a true single-formula selector.
  8. Update generated docs JSON, RSS, sitemaps, PWA cache manifest, and search index after documentation changes.
  9. Test with narrow-to-wide and wide-to-narrow conversions, including ProPhoto D50 cases.
  10. 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.