Skip to main content
Auric Artisan · Documentation

Chromatic Adaptation Developer Reference

Architecture and maintenance notes for the standalone chromatic adaptation lab, including the page shell, state object, CAT matrices, image pipeline, chart rendering, batch analysis, exports, URL state, public API, and Library preset binding.

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

Overview

Chromatic Adaptation is a standalone IIFE-based browser tool. The HTML shell owns SEO, tab structure, controls, result canvases, and documentation panes. The JS module owns the CAT math, image processing, timeline state, chart rendering, exports, URL restore, and the small page API used by integrations; spectra and the adaptation time course come from js/tool/cad/cad-sources.js. There is no build-time dependency and no network math path.

Table of contents

  1. 1. File map
  2. 2. Page shell and UI contract
  3. 3. State model and inputs
  4. 4. Color math and CAT matrices
  5. 5. Image pipeline and timeline
  6. 6. Charts 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/chromatic-adaptation-dynamic/index.html contains metadata, hero copy, tabs, controls, result canvases, the Reference view (standards, formulas, references, research notes), and script imports.
  • Tool engine: js/tool/chromatic-adaptation-dynamic.js is a standalone IIFE that owns utilities, CAT matrices, illuminants, color conversions, render state, image loading, adaptation, charts, exports, events, URL restore, and public API. It is loaded after js/tool/illuminants/il-tables.js, js/tool/illuminants/il-core.js, and js/tool/cad/cad-sources.js (spectra, dataset register, time course), and before js/tool/chromatic-adaptation-views.js (Dynamics, Matrix, Data, and Reference views).
  • Library integration: js/library/tool-bindings.js registers the path as tool id chromatic-adaptation with asset type preset.
  • Shared shell CSS: the page imports main, color science, unified, dark mode, legal, color science lab, analyzer shell, and chromatic adaptation shell styles.
  • Discovery: documentation metadata lives in data/documentation.json and generated RSS, sitemap, PWA, and search files after docs are added.

2. Page shell and UI contract

+
  • App root: #cad-app is the application container and #main is the tool workspace.
  • Tabs: buttons use data-cad-tab and panels use ids p-cad-lab, p-cad-dynamics, p-cad-matrix, p-cad-data, p-cad-actions, and p-cad-reference.
  • Empty state: #cad-empty covers the Lab canvases until an image or the sample is loaded; its buttons forward to cad-sample-btn and cad-choose-btn.
  • Controls: hidden inputs under custom dropdowns are the source of truth for illuminants and CAT method.
  • Canvas ids: output canvases are cad-orig-canvas, cad-adapt-canvas, cad-hist-canvas, cad-curve-canvas, cad-state-canvas, cad-lms-canvas, cad-spd-canvas, and cad-compare-canvas.
  • Action ids: exports and analysis use cad-export-json, cad-export-frame, cad-share-btn, cad-copy-share, cad-copy-link, cad-compare-btn, and cad-batch-run.

3. State model and inputs

+

The module-level S object is the single runtime state store. Most UI events update S, then call onParamChange() or runAdaptation().

  • Illuminant state: srcIllum defaults to D65 and dstIllum defaults to D50.
  • Model state: catMethod defaults to bradford.
  • Timing state: timeModel (default measured), tauFast, weightFast, tauSlow, strength, initAdapt, time, and fps define the animation and adaptation curve; delay and tau apply only to the legacy single-exponential model.
  • Local adaptation state: tauLocal, delayLocal, and mix drive luminance-weighted per-pixel state blending.
  • Stored experiment state: gamma, radius, localStrength, and tile are synchronized and exported, but radius, localStrength and tile are read nowhere else, so they do not change the image (the page says so); useGPU is kept in state only. The current CPU render path primarily uses sRGB conversion, luminance modulation, mix, and HDR tonemap.
  • Runtime state: srcImageData, animating, animId, and lastFrameTime should not be serialized directly except through the public API's filtered copy.
  • Sync: syncAllInputs() pushes state into DOM controls and labels after URL restore or API restore.

4. Color math and CAT matrices

+
  • Utility math: helpers cover clamp, rounding, HEX parsing, sRGB transfer, 3x3 matrix multiplication, matrix inverse, determinant, and Frobenius norm.
  • CAT registry: CATS stores Bradford, Von Kries, CAT02, CAT16, Sharp, CMCCAT2000, HPE, and XYZ Scaling matrices. Inverses are cached during bootstrap.
  • Illuminants: ILLUM stores CIE xy, CCT, and label data for D65, D50, D55, D60, D75, A, B, C, E, F2, F7, and F11.
  • White conversion: illumXYZ(name) converts xy white points into normalized XYZ with Y = 1.
  • Adapt matrix: buildAdaptMatrix(catKey, srcIllum, dstIllum, degree) projects source and destination whites into the CAT response space, builds a partial diagonal scale, and returns the full matrix plus LMS diagnostics.
  • Lab and LCh: xyzToLab() and labToLCh() support batch output and color-difference analysis.
  • CIEDE2000: deltaE00() implements the color-difference metric used by batch and multi-method comparison.
  • SPD helpers: illuminantSPD() delegates to window.AACadSources.spdFor(), which reconstructs the D series from the CIE daylight basis, computes A with Planck's law and E as a flat spectrum, and returns null for B, C, F2, F7, and F11, whose spectra are not held.

5. Image pipeline and timeline

+
  • Image loading: loadImage() reads a local data URL, scales to a maximum 480 by 320, draws to cad-orig-canvas, stores ImageData, and syncs the adapted canvas size.
  • Sample image: loadSample() creates a 360 by 240 HSL gradient via generateSampleImage().
  • Adaptation curve: adaptationState(t, A0, Ainf, tau, delay) moves from A0 toward Ainf by the fraction from AACadSources.adaptationAt(), the two-component Fairchild & Reniff model (a fast 1 s phase carrying half, a slow phase with a 30 s half-life). tau and delay are used only when S.timeModel is legacy.
  • Render loop: runAdaptation() iterates each pixel, converts sRGB to linear RGB, converts to XYZ, applies the active CAT matrix, converts back through inverse sRGB, and writes the adapted canvas.
  • Local modulation: per-pixel Y luminance scales tau and delay (tauLocal, delayLocal), so darker pixels adapt later and more slowly on the measured model's time axis; the global curve is unchanged. The final degree blends local state and global state through S.mix.
  • HDR option: reinhardTonemap() compresses linear output when HDR Tonemap is enabled.
  • Animation: startAnimation(), animLoop(), stopAnimation(), and resetAnimation() run a five-second requestAnimationFrame timeline; animLoop() skips frames that arrive sooner than 1 / S.fps, and the time display follows the scrubber and the animation.

6. Charts and diagnostics

+
  • Histogram: drawHistogram(imageData) builds RGB channel histograms from the adapted frame.
  • State map: drawStateMap(srcData, globalAt) visualizes local adaptation degree as grayscale image data.
  • Curve: drawAdaptCurve() plots A(t) over the fixed five-second timeline and marks the current time.
  • LMS bars: drawLMSBars(adapt) compares source and destination cone-response channels for the active CAT.
  • SPD overlay: drawSPD() draws source and destination spectral power distributions from illuminantSPD().
  • Matrix panel: renderMatrixInfo() writes the active 3x3 matrix, determinant, Frobenius norm, LMS values, and scale factors into cad-matrix-output, but the page no longer has that element; the Matrix tab is drawn by js/tool/chromatic-adaptation-views.js.
  • Responsive redraw: window resize redraws SPD and adaptation curve after a short debounce.

7. Exports, share URL, and batch

+
  • JSON export: exportJSON() serializes state, active matrix, LMS values, scale factors, and determinant to a downloadable JSON file.
  • Frame export: exportFrame() downloads cad-adapt-canvas as a PNG using toDataURL().
  • Share URL: shareURL() encodes src, dst, cat, tau, delay, str, init, and t query parameters.
  • URL restore: restoreURL() reads those query parameters at boot and validates illuminant and CAT keys before applying them.
  • Batch: runBatch() accepts valid HEX rows, caps analysis at 50 colors, transforms each value, and reports adapted HEX, Delta E 2000, L*, C*, and hue.
  • Comparison: runComparison() evaluates all CAT methods on eight standard test colors and reports mean, median, min, max, determinant, and matrix norm.
  • Clipboard: copy actions use navigator.clipboard.writeText() and report status through the toast surface.

8. Public API and library binding

+
  • Namespace: the page exposes window.AAChromaticAdaptation.
  • getState: returns a JSON-safe copy of S, removes srcImageData and animId, and adds hasSourceImage plus animating flags.
  • restoreState: merges saved object values into S, preserves the current image data, stops animation, syncs DOM controls, and re-renders through onParamChange().
  • Library match: attachTool() matches /tool/general/colorimetry/chromatic-adaptation-dynamic/.
  • Library metadata: tool id is chromatic-adaptation, name is Chromatic Adaptation, category is Colorimetry, and asset type is preset.
  • Capture: the current binding uses captureFormPreset() with name Adaptation preset and preview label Chromatic adaptation.
  • Restore: the current binding uses generic form restore triggers cad-apply, cad-render, and cad-update. If richer restore is needed, bridge directly to window.AAChromaticAdaptation.restoreState().

9. Extension checklist

+
  1. Add new CAT methods to CATS with name, short, and 3x3 matrix values, then confirm the inverse is not singular.
  2. Add new illuminants to ILLUM with xy, CCT, and display label data, add a SPD_KIND entry in js/tool/cad/cad-sources.js, then update the HTML dropdowns.
  3. Keep hidden dropdown inputs and labels synchronized when adding values or changing ids.
  4. Wire any new state field into S, slider maps, value labels, JSON export, getState(), and restore paths.
  5. If a control should affect rendering, route it through runAdaptation(), drawStateMap(), or the relevant chart function, not only through export state.
  6. Keep URL parameters compact and backward compatible; do not place image data in share URLs.
  7. Update batch analysis when new color spaces or metrics are added.
  8. Update Library capture if richer canvas thumbnails or direct API restore becomes necessary.
  9. Update user and developer documentation, documentation JSON, RSS, sitemaps, PWA cache manifest, and search index.
  10. Run rendering, export, restore, and accessibility smoke tests after any math or UI change.

10. Testing and risk notes

+
  • Boot: page loads, tabs switch, the empty state clears, sample loads, and initial SPD, curve, LMS, and matrix diagnostics render.
  • Inputs: source and destination illuminants, swap, CAT method, timing sliders, local modulation, time scrubber, FPS, Live, HDR, and stored experimental toggles sync correctly.
  • Animation: Space, Animate, Pause, Reset, and end-of-timeline behavior do not leave stale animation frames running.
  • Rendering: sample and uploaded images produce nonblank original and adapted canvases, histogram, state map, LMS, SPD, and curve output at multiple viewport sizes.
  • Math: smoke test D65 to D50 Bradford, CAT16, CAT02, XYZ Scaling, determinant output, Delta E 2000 values, LCh conversion, and HDR tonemap paths.
  • Actions: JSON export includes state and matrix data, PNG export downloads a current frame, share URL restores parameters, comparison table renders, and batch caps at 50 valid HEX rows.
  • Library: save the preset, restore saved controls, and confirm the tool can rerender after restore.
  • Risk: CAT matrix, sRGB transfer, Lab, or Delta E changes will shift all image output, batch tables, comparisons, and exported JSON. Keep any mathematical change deliberate and documented.