Skip to main content
Auric Artisan · Documentation

Gamut Explorer Developer Reference

Architecture and maintenance notes for the standalone Gamut Explorer tool, including page structure, runtime state, color-space metadata, matrix derivation, chromaticity renderers, transfer functions, Lab and OKLab slices, Monte Carlo volume, custom local library storage, exports, share URLs, 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 Explorer is implemented as a self-contained browser IIFE in js/tool/gamut.js. The engine owns the color-space registry, 380-780 nm CMF data (the drawn spectral locus keeps 380-715 nm), CIE xy and u-prime v-prime conversion, RGB to XYZ matrix derivation, transfer functions, canvas renderers, Lab and OKLab slices, wireframes, Halton-sampled volume and overlap metrics, local storage library exchange, URL state, exports, and window.AAGamutLab. The HTML shell in tool/general/gamut-and-rendering/gamut/index.html declares all controls and reference content. js/tool/gt/gt-sources.js holds the dataset register, and js/tool/gamut-views.js draws the Transfer, Compare, Data, Export, and Reference views.

Table of contents

  1. 1. File map
  2. 2. Page shell and UI contract
  3. 3. State model
  4. 4. Color-space registry
  5. 5. Color math and matrices
  6. 6. Rendering pipeline
  7. 7. Exports, share state, and local library
  8. 8. Public API and library binding
  9. 9. Extension checklist
  10. 10. Testing and risk notes

1. File map

+
  • Tool shell: tool/general/gamut-and-rendering/gamut/index.html contains metadata, hero content, tab navigation, control panels, canvases, the export and library panels, the Reference view (standards, formulas, references, research notes), and fullscreen chart overlay.
  • Tool engine: js/tool/gamut.js contains the standalone IIFE that implements color math, state, rendering, exports, local library management, URL state, and the public API.
  • Library integration: js/library/tool-bindings.js registers the /tool/general/gamut-and-rendering/gamut/ route as tool id gamut.
  • Generated page helpers: the page loads generated inline scripts and /js/unified.js for shared site behavior and chart interactions.
  • Documentation discovery: guide and reference entries are sourced from data/documentation.json and generated into RSS, sitemaps, PWA cache manifest, and search outputs.

2. Page shell and UI contract

+
  • App root: #gt-app wraps the Gamut Explorer interface.
  • Tabs: buttons use data-gt-tab; panels use p-gt-lab, p-gt-transfer, p-gt-compare, p-gt-data, p-gt-actions, and p-gt-reference.
  • Primary selectors: gtActiveSpace, gtDiagramMode, gtObserver, gtTransferPreset, gtVolumeRef, gtVolumeTarget, and gtSliceMode.
  • Overlay checkboxes: gtShowSpectral, gtShowGrid, gtShowMacAdam, gtShowLabels, gtShowAllSpaces, and gtShowFill.
  • Probe outputs: gtVertexX, gtVertexY, gtVertexLumi, gtVertexChip, gtVertexSRGB, gtVertexHex, gtVertexLab, and gtVertexMembership.
  • Primary inputs: gtPrimRx, gtPrimRy, gtPrimGx, gtPrimGy, gtPrimBx, gtPrimBy, gtPrimWx, and gtPrimWy.
  • Matrix and metric outputs: gtWhiteX, gtWhiteY, gtWhiteZ, gtMatrixRgb2Xyz, gtMatrixXyz2Rgb, gtAreaMetrics, gtVolumeMetrics, and gtSliceMetrics.
  • Canvas outputs: gtMainCanvas, gtTransferCanvas, gtSliceCanvas, and gtWireCanvas.
  • Action controls: gtExportPng, gtExportSvg, the Export tab's gtTakeSeg, gtFormatSeg, gtTakeIt, and gtCopyIt, and gtImportFromText.
  • Exchange outputs: gtPreview, gtExportStatus, gtLibraryBody, gtImportText, and gtExchangeStatus.

3. State model

+

Runtime state is declared inside boot(). Event handlers mutate the object, then call targeted renderers. window.AAGamutLab.getState() returns a JSON clone of this state.

  • Diagram state: mode is xy, upvp, or 3d. The page also renders separate slice and wireframe canvases regardless of the main diagram mode.
  • Space state: spaces starts as sRGB, DisplayP3, and Rec2020. Selecting a working space moves that key to the front of the active list.
  • Overlay state: showLocus, showGrid, showLabels, showMacAdam, showFill, and showAllSpaces mirror the checkbox controls.
  • Probe state: probeX and probeY store the latest clicked or dragged coordinate.
  • Transfer state: transferPreset selects the color-space metadata used by drawTransferCurve().
  • Custom state: customPrimaries stores editable red, green, blue, and white xy values.
  • Volume state: volumeRef and volumeTarget select the comparison pair for Monte Carlo volume and overlap.
  • Slice state: sliceMode chooses Lstar or OKLab, while sliceLevel controls the lightness slider.
  • URL restore: the s query parameter is decoded with decodeState() and merged into state before rendering.

4. Color-space registry

+
  • Registry object: SPACES stores all standard and runtime custom spaces.
  • Required fields: each space stores r, g, b, w, label, and gamma.
  • Supported standard keys: sRGB, DisplayP3, DCI-P3, Rec2020, Rec2100-PQ, Rec2100-HLG, AdobeRGB, ProPhotoRGB, AdobeWideGamut, ACES AP0, ACES AP1, NTSC-1953, and PAL-SECAM.
  • Custom key: solving editable primaries registers SPACES.custom.
  • Local library keys: imported custom definitions register their def.name inside SPACES during import and restore.
  • Matrix cache: _matCache stores derived matrices by space name. Custom updates must delete stale cache entries.
  • Chart colors: GAMUT_COLORS provides reusable stroke colors for diagrams and comparison overlays.

5. Color math and matrices

+
  • CMF grid: LAMBDA spans 380 to 780 nm in 5 nm steps, with CIE 1931 CMF_X, CMF_Y, and CMF_Z arrays.
  • Chromaticity: xyToUpVp(), xyzFromXy(), and xyzToXy() provide xy, XYZ, and u-prime v-prime conversions.
  • Lab: xyzToLab(), labToXyz(), and lchToLab() support volume, slices, probe output, and wireframe construction.
  • OKLab: oklabToSrgb() supports OKLab slice boundary searches.
  • Matrix helpers: mat3inv(), mat3mulv(), mat3mul(), and mat3diag() implement the small matrix operations.
  • Matrix derivation: deriveMatrices(sp) converts primary xy to XYZ columns, solves scale factors against the white point, builds rgb2xyz, and inverts it for xyz2rgb.
  • Transfer functions: sRGB, gamma, BT.2020, ROMM, PQ, and HLG functions are provided through srgbEOTF(), srgbOETF(), gammaEOTF(), gammaOETF(), bt2020EOTF(), bt2020OETF(), rommEOTF(), rommOETF(), pqEOTF(), pqOETF(), hlgEOTF(), and hlgOETF().
  • Transfer dispatch: resolveTransferLabel(), eotfForSpace(), and oetfForSpace() map registry gamma values to UI labels and functions; transferFidelity() marks HLG as partial because only the inverse OETF runs.
  • In-gamut tests: isInGamutLinear() checks linear RGB bounds, while isInGamut() converts XYZ through the target matrix before checking channels.

6. Rendering pipeline

+
  • Spectral locus: buildSpectralLocus() derives xy and u-prime v-prime locus arrays from CMFs, cached by getLocusXY() and getLocusUpVp().
  • Coordinate mapping: xyToCanvas() and canvasToXy() use bounds objects for xy, u-prime v-prime, Lab a*b*, and OKLab a/b canvases.
  • Shared drawing: drawGrid(), drawLocus(), drawGamutTriangle(), and drawMacAdamEllipses() build the 2D chromaticity layers.
  • Main diagram: renderChromaticityDiagram() clears the canvas, optionally fills the locus with WebGL2, draws grid, locus, MacAdam ellipses, space triangles, and probe marker.
  • WebGL fill: renderWebGLFill() compiles a compact WebGL2 shader pipeline that fills visible chromaticity coordinates inside the spectral locus.
  • Transfer curve: drawTransferCurve() draws axes, active EOTF, and linear reference. PQ is displayed on a log-scaled luminance axis.
  • Slice renderer: renderSliceDiagram() draws CIELAB or OKLab gamut boundary rings for active spaces.
  • Boundary solvers: gamutSliceLab() and gamutSliceOKLab() search chroma by bisection at each hue angle.
  • Wireframe: buildWireframe() creates Lab rings and meridians; drawWireframe() projects them to 2D with fixed view angles.
  • Comparison rows: buildComparisonTable() combines xy area, percent of sRGB, u-prime v-prime locus share, Monte Carlo volume with its spread, transfer label, and white point into table data.
  • Probe: queryPoint() converts a point to XYZ, Lab, sRGB preview HEX, and per-space triangle membership.

7. Exports, share state, and local library

+
  • PNG export: exportCanvasPNG(canvas, filename) uses canvas.toDataURL("image/png") and a temporary anchor.
  • SVG export: exportCanvasSVG(canvas) wraps the canvas PNG data URL in an SVG image element.
  • JSON export: exportSpaceJSON(name) writes space name, label, primaries, white point, gamma, matrices, and xy area.
  • CSV export: exportComparisonCSV(rows) writes comparison rows for name, xy area, percent of sRGB, Lab volume, transfer, and white point.
  • Share encode: encodeState(state) Base64-encodes JSON state; buildShareURL(state) stores it as query parameter s.
  • Share decode: decodeState(str) parses the Base64 state and fails softly to null.
  • Local library key: custom spaces are stored under aa_gamut_library.
  • Library functions: loadLibrary(), saveLibrary(), addCustomSpace(), removeCustomSpace(), and restoreLibrary() manage custom definitions and runtime registry hydration.
  • Import format: import expects JSON with name, primaries.r, primaries.g, primaries.b, whitePoint, and optional gamma.
  • Reset behavior: Reset view restores xy mode, clears the probe, and restores primary overlay defaults without clearing custom library data.

8. Public API and library binding

+
  • Namespace: the tool exposes window.AAGamutLab after boot.
  • getState: returns a JSON-cloned copy of the internal runtime state.
  • restoreState: validates the input object, merges it into state, renders main, slice, transfer, and wireframe canvases, then updates the library table.
  • Shared runtime capture: js/library/tool-bindings.js includes gamutLab: window.AAGamutLab?.getState in full tool-state capture.
  • Shared runtime restore: restore routes include ["gamutLab", window.AAGamutLab?.restoreState].
  • Tool binding: the route matcher uses /tool/general/gamut-and-rendering/gamut/, id gamut, name Gamut Explorer, category Gamut & Rendering, and asset type preset.
  • Binding capture: the simple binding captures the first available tool canvas as a Gamut snapshot. If no canvas is available, it falls back to captureFormPreset().
  • Binding restore: the simple binding uses generic form restore triggers gamut-render, gamut-update, and gm-render. Prefer window.AAGamutLab.restoreState() when exact runtime state is available.
  • Storage note: the tool's custom local library is separate from Auric Library asset saves. The local color-space library uses browser localStorage.

9. Extension checklist

+
  1. Add new spaces to SPACES with stable key, primary xy arrays, white xy array, label, and gamma descriptor.
  2. Add matching dropdown entries in index.html for working space, transfer preset, volume references, or comparison targets as needed.
  3. Verify deriveMatrices() returns invertible matrices for the new space.
  4. When adding a transfer type, update resolveTransferLabel(), eotfForSpace(), oetfForSpace(), equation output, standards text, and tests.
  5. When changing state, update URL encode/decode expectations, public API restore, Library capture expectations, and documentation.
  6. When changing canvas sizes or ids, update export buttons, fullscreen helper assumptions, Library canvas capture behavior, and smoke tests.
  7. When adding import fields, keep exportSpaceJSON(), import validation, local library restore, and docs in sync.
  8. Regenerate discovery outputs after documentation changes with scripts/generate-discovery.mjs, scripts/generate-pwa-cache-manifest.mjs, and search/client/build-index.js.
  9. Document whether new gamut computations are xy-only, Lab volume, profile-based, or display-luminance-aware so users do not overread the result.
  10. Keep official standard names and transfer-function references accurate when adding or renaming spaces.

10. Testing and risk notes

+
  • Boot: the page loads, the Lab tab is active, all four canvases render, matrices populate, and the library table populates.
  • Selectors: test every working space, diagram mode, transfer preset, volume reference, volume target, and slice mode.
  • Overlays: toggle spectral locus, grid, MacAdam ellipses, labels, all spaces, and WebGL fill.
  • Probe: click and drag the main canvas in xy and u-prime v-prime modes and verify coordinates, HEX, Lab, and membership output.
  • Custom primaries: edit values, solve Custom, verify matrices, export JSON, import JSON, reload the page, and confirm the custom library restores.
  • Volume: compute sRGB, Display P3, Rec.2020, and ACES comparisons on desktop and mobile-class devices because Monte Carlo loops are CPU-bound.
  • Exports: test PNG, SVG, active JSON, comparison CSV, and share URL restore after multiple state changes.
  • Library: save a canvas snapshot through Auric Library, restore runtime state when available, and confirm local custom-space storage remains separate.
  • Numerical risk: changes to CMFs, matrix inversion, gamma functions, Lab conversion, or Halton sampling will shift diagrams, volume estimates, CSV output, JSON matrices, and saved expectations.
  • Interpretation risk: xy area, Lab volume, and display/rendering gamut are not interchangeable. Keep UI and docs explicit about what each metric measures.