Methods & Scientific References
This page documents all scientific methods, algorithms, and standards implemented in Hexcode. All formulas are grounded in the actual source code with file references for verification.
1. Color Space Conversions
sRGB to CIE XYZ (D65 Illuminant)
The transformation from linear sRGB to CIE XYZ uses the standard D65 illuminant matrix. Input RGB values must first be linearized using gamma correction.
\[ \begin{bmatrix} X \\ Y \\ Z \end{bmatrix} = \begin{bmatrix} 0.4124564 & 0.3575761 & 0.1804375 \\ 0.2126729 & 0.7151522 & 0.0721750 \\ 0.0193339 & 0.1191920 & 0.9503041 \end{bmatrix} \begin{bmatrix} R_{linear} \\ G_{linear} \\ B_{linear} \end{bmatrix} \]
Implementation: src/utils/colorMath.ts → srgbToXyz()
Standard: IEC 61966-2-1:1999 (sRGB)
CIE XYZ to sRGB
The inverse transformation from XYZ back to linear sRGB. Results are gamma-encoded and clamped to the [0, 255] range.
\[ \begin{bmatrix} R_{linear} \\ G_{linear} \\ B_{linear} \end{bmatrix} = \begin{bmatrix} 3.2404542 & -1.5371385 & -0.4985314 \\ -0.9692660 & 1.8760108 & 0.0415560 \\ 0.0556434 & -0.2040259 & 1.0572252 \end{bmatrix} \begin{bmatrix} X \\ Y \\ Z \end{bmatrix} \]
Implementation: src/utils/colorMath.ts → xyzToSrgb()
2. Gamma Correction (sRGB Transfer Function)
Linearization (Gamma Decoding)
Converts sRGB gamma-encoded values [0, 1] to linear light values for accurate color calculations.
\[ \operatorname{toLinear}(u) = \begin{cases} \dfrac{u}{12.92}, & u \le 0.04045 \\[8pt] \left(\dfrac{u + 0.055}{1.055}\right)^{2.4}, & u > 0.04045 \end{cases} \]
Implementation: src/utils/colorMath.ts → toLinear()
Gamma Encoding
Converts linear light values back to sRGB gamma-encoded values for display.
\[ \operatorname{toGamma}(u) = \begin{cases} 12.92 \cdot u, & u \le 0.0031308 \\[8pt] 1.055 \cdot u^{1/2.4} - 0.055, & u > 0.0031308 \end{cases} \]
Implementation: src/utils/colorMath.ts → toGamma()
3. CIE Lab and LCH Color Spaces
XYZ to CIE Lab (D65)
Transforms XYZ to the perceptually uniform CIE L*a*b* color space using D65 white point reference values.
\[ L^* = 116 \cdot f\left(\frac{Y}{Y_n}\right) - 16 \] \[ a^* = 500 \cdot \left[f\left(\frac{X}{X_n}\right) - f\left(\frac{Y}{Y_n}\right)\right] \] \[ b^* = 200 \cdot \left[f\left(\frac{Y}{Y_n}\right) - f\left(\frac{Z}{Z_n}\right)\right] \] \[ \text{where } f(t) = \begin{cases} t^{1/3}, & t > \epsilon \\[4pt] \dfrac{\kappa \cdot t + 16}{116}, & t \le \epsilon \end{cases} \quad \epsilon = \frac{216}{24389}, \quad \kappa = \frac{24389}{27} \]
White Point (D65): Xn = 0.95047, Yn = 1.0, Zn = 1.08883
Implementation: src/utils/colorMath.ts → xyzToLab()
Standard: CIE 15:2004
Lab to LCH (Cylindrical Lab)
Converts rectangular Lab coordinates to cylindrical LCH (Lightness, Chroma, Hue) for intuitive hue manipulation.
\[ C^* = \sqrt{a^{*2} + b^{*2}} \] \[ h = \arctan2(b^*, a^*) \cdot \frac{180}{\pi} \quad (\text{normalized to } [0, 360)) \]
Implementation: src/utils/colorMath.ts → labToLch(), lchToLab()
4. OKLab and OKLCH Color Spaces
OKLab is a perceptually uniform color space designed by Björn Ottosson for improved color blending and manipulation. Hexcode implements the full OKLab specification with proper LMS cone response matrices.
Transformation Pipeline
- Linear sRGB → LMS (using M1 matrix)
- LMS → L′M′S′ (cube root)
- L′M′S′ → OKLab (using M2 matrix)
[0.4122, 0.5363, 0.0514] [0.2119, 0.6807, 0.1074] [0.0883, 0.2817, 0.6300]
[0.2105, 0.7936, -0.0041] [1.9780, -2.4286, 0.4506] [0.0259, 0.7828, -0.8087]
Implementation: src/utils/oklab.ts → rgbToOKLab(), okLabToRgb(), rgbToOKLCH(), oklchToRgb()
Reference: Ottosson, B. (2020). “A perceptual color space for image processing”
5. Color Difference (ΔE00 / CIEDE2000)
Hexcode implements the full CIEDE2000 color difference formula (ΔE00), the industry standard for perceptually uniform color difference measurement. The algorithm accounts for:
- Lightness weighting (SL)
- Chroma weighting (SC)
- Hue weighting (SH)
- Chroma-Hue rotation term (RT)
Parametric Factors (default unity)
kL = kC = kH = 1
Implementation: src/utils/colorMath.ts → deltaE00() (lines 315-377)
Standard: CIE 142-2001 / ISO 11664-6:2014
6. Contrast Calculations
WCAG 2.2 Contrast Ratio
Standard WCAG luminance-based contrast ratio for accessibility compliance.
\[ \text{Contrast Ratio} = \frac{L_1 + 0.05}{L_2 + 0.05} \] \[ \text{where } L_1 \ge L_2 \text{ are relative luminances} \]
Relative Luminance:
\[ L = 0.2126 \cdot R_{linear} + 0.7152 \cdot G_{linear} + 0.0722 \cdot B_{linear} \]
WCAG AA Requirements
- Normal text: ≥ 4.5:1
- Large text (18pt+): ≥ 3:1
- UI components: ≥ 3:1
WCAG AAA Requirements
- Normal text: ≥ 7:1
- Large text (18pt+): ≥ 4.5:1
Implementation: src/utils/colorMath.ts → relativeLuminance(), contrastRatio()
Standard: WCAG 2.2 Success Criteria 1.4.3 & 1.4.6
APCA (Advanced Perceptual Contrast Algorithm)
Hexcode implements APCA via the official apca-w3 library for more accurate perceptual readability predictions. APCA considers:
- Polarity-aware contrast (dark-on-light vs light-on-dark)
- Non-linear perceptual response
- Font size and weight relationships
Return Values
- Lc (Lightness Contrast): Absolute contrast value (0-106+)
- Polarity: ‘dark-on-light’ or ‘light-on-dark’
Implementation: src/utils/apca.ts → apcaLc()
Library: apca-w3 (WCAG 3.0 candidate)
Reference: Somers, A. (2022). “APCA Readability Criterion”
7. Color Blindness Simulation
Hexcode implements three scientifically validated color vision deficiency (CVD) simulation models, allowing users to choose the most appropriate algorithm for their needs.
Machado et al. (2009)
Physiologically-based LMS cone response model. The default simulation method in Hexcode.
Algorithm
- Convert sRGB to linear RGB
- Apply 3×3 CVD simulation matrix
- Interpolate with original for severity control
- Convert back to sRGB with gamma encoding
Implementation: src/utils/cvdModels.ts → simulateMachado()
Matrices: src/utils/colorMath.ts → colorblindnessMatrices
Reference: Machado, G.M., Oliveira, M.M., Fernandes, L.A.F. (2009). “A Physiologically-based Model for Simulation of Color Vision Deficiency”
Brettel et al. (1997)
Dichromat simulation via color plane projection. Uses two projection planes selected by a separation plane normal for improved accuracy.
Key Feature
Two-plane projection: Selects appropriate matrix based on dot product with CVD-type-specific separation plane normal. Matrices sourced from libDaltonLens.
Implementation: src/utils/cvdModels.ts → simulateBrettel()
Reference: Brettel, H., Viénot, F., Mollon, J.D. (1997). “Computerized simulation of color appearance for dichromats”
Viénot et al. (1999)
Linear transformation model. Fast and accurate for protanopia/deuteranopia, but less accurate for tritanopia.
Note: Viénot 1999 is not recommended for tritanopia simulation. Hexcode uses a fallback approximation for tritanopia with this model.
Implementation: src/utils/cvdModels.ts → simulateVienot()
Reference: Viénot, F., Brettel, H., Mollon, J.D. (1999). “Digital video colourmaps for checking the legibility of displays by dichromats”
Supported CVD Types
Dichromacy (Complete)
- Protanopia: L-cone (red) absent
- Deuteranopia: M-cone (green) absent
- Tritanopia: S-cone (blue) absent
Anomalous Trichromacy (Partial)
- Protanomaly: Shifted L-cone response
- Deuteranomaly: Shifted M-cone response (most common)
- Tritanomaly: Shifted S-cone response
Monochromacy
- Achromatopsia: Complete color blindness (rod monochromacy)
- Achromatomaly: Incomplete achromatopsia (blue cone monochromacy approximation)
8. Additional Color Conversions
HSL (Hue, Saturation, Lightness)
Cylindrical representation with lightness-based saturation model.
Implementation: colorMath.ts → rgbToHsl(), hslToRgb()
HSV (Hue, Saturation, Value)
Cylindrical representation with value-based saturation model.
Implementation: colorMath.ts → rgbToHsv(), hsvToRgb()
HWB (Hue, Whiteness, Blackness)
CSS Color Level 4 color model based on tinting and shading.
Implementation: colorMath.ts → rgbToHwb()
CMYK (Cyan, Magenta, Yellow, Key)
Device-independent subtractive color approximation.
Implementation: colorMath.ts → rgbToCmyk()
Linear RGB Mixing
Perceptually-correct color blending in linear light space.
Implementation: colorMath.ts → mixColors()
Color Similarity
Euclidean distance in normalized RGB for quick similarity metrics.
Implementation: colorMath.ts → calculateSimilarity()
9. Constants & Standards
CIE Standard Illuminant D65
| Color Temperature: | 6504K |
| White Point Xn: | 0.95047 |
| White Point Yn: | 1.00000 |
| White Point Zn: | 1.08883 |
| Chromaticity x: | 0.31272 |
| Chromaticity y: | 0.32903 |
Lab Conversion Constants
| ε (epsilon): | 216/24389 ≈ 0.008856 |
| κ (kappa): | 24389/27 ≈ 903.3 |
sRGB Gamma Constants
| Linear threshold: | 0.04045 |
| Gamma exponent: | 2.4 |
| Linear slope: | 12.92 |
| Offset: | 0.055 |
ΔE Perception Thresholds
| Just noticeable: | ΔE ≤ 1.0 |
| Perceptible: | 1.0 < ΔE ≤ 3.0 |
| Acceptable: | 3.0 < ΔE ≤ 6.0 |
| Different colors: | ΔE > 6.0 |
10. Source Code References
Core Implementation Files
src/utils/colorMath.ts
Primary color mathematics module containing:
- Gamma correction functions (
toLinear,toGamma) - sRGB ↔ XYZ conversions with D65 matrices
- XYZ ↔ Lab ↔ LCH conversions
- HSL, HSV, HWB, CMYK conversions
- ΔE00 (CIEDE2000) implementation
- WCAG relative luminance and contrast ratio
- Linear RGB color mixing
- Color blindness simulation matrices (Machado)
src/utils/oklab.ts
OKLab/OKLCH color space implementation:
- Full OKLab specification with proper matrices
- RGB ↔ OKLab ↔ OKLCH conversions
src/utils/apca.ts
APCA contrast calculation wrapper:
- Uses official apca-w3 library
- Returns Lc value and polarity
src/utils/cvdModels.ts
Color vision deficiency simulation models:
- Machado (2009): LMS cone response model
- Brettel (1997): Two-plane projection model
- Viénot (1999): Linear transformation model
- Matrices validated against libDaltonLens
src/__tests__/colorMath.spec.ts
Comprehensive test suite validating all color math implementations with round-trip conversions, edge cases, and industry standard comparisons.
Testing & Validation
All color calculations are validated using Vitest with comprehensive test coverage including:
- Round-trip conversion accuracy (RGB → XYZ → Lab → LCH → Lab → XYZ → RGB)
- Edge case handling (black, white, primaries, neutrals)
- Comparison with reference implementations and industry tools
- ΔE00 validation against published test datasets
Academic References
- Machado, G.M., Oliveira, M.M., Fernandes, L.A.F. (2009). “A Physiologically-based Model for Simulation of Color Vision Deficiency.”IEEE Transactions on Visualization and Computer Graphics, 15(6), 1291-1298.
- Brettel, H., Viénot, F., Mollon, J.D. (1997). “Computerized simulation of color appearance for dichromats.”Journal of the Optical Society of America A, 14(10), 2647-2655.
- Viénot, F., Brettel, H., Mollon, J.D. (1999). “Digital video colourmaps for checking the legibility of displays by dichromats.”Color Research & Application, 24(4), 243-252.
- Ottosson, B. (2020). “A perceptual color space for image processing.”bottosson.github.io/posts/oklab/
- CIE (2001). “Improvement to industrial colour-difference evaluation.”CIE 142-2001 (CIEDE2000).
- W3C (2023). “Web Content Accessibility Guidelines (WCAG) 2.2.”w3.org/TR/WCAG22/
- Somers, A. (2022). “APCA Readability Criterion.”github.com/Myndex/SAPC-APCA