API Documentation
Complete reference for every color algorithm used by OmniColor — conversion formulas, contrast calculation, harmony generation and more.
Overview
OmniColor does not have a hosted REST API — all tools run in your browser. This documentation describes the algorithms we use so you can implement them yourself in any programming language.
All algorithms use the sRGB color space (the standard for the web) unless otherwise noted. Formulas are per the W3C CSS Color Module Level 4 specification where applicable.
Color Conversions
HEX → RGB
Input: String, e.g. "#155EEF" or "155EEF"
Output: { r, g, b } — integers 0-255
Formula:
1. Strip the leading # if present
2. If 3 digits, expand each by doubling: "0AF" → "00AAFF"
3. Split into three 2-digit hex pairs (RR GG BB)
4. Convert each pair from hex to decimal (base 16 → base 10)
R = parseInt(RR, 16), G = parseInt(GG, 16), B = parseInt(BB, 16)
Example: #155EEF → { r: 21, g: 94, b: 239 }
RGB → HEX
Input: { r, g, b } — integers 0-255
Output: Uppercase HEX string with # prefix
Formula:
1. Clamp each channel to [0, 255] and round to integer
2. Convert each to 2-digit hex: value.toString(16).padStart(2, '0')
3. Concatenate: '#' + hexR + hexG + hexB
Example: { r: 21, g: 94, b: 239 } → "#155EEF"
RGB → HSL
Input: { r, g, b } — integers 0-255
Output: { h: 0-360, s: 0-100, l: 0-100 }
Formula:
1. Normalize: r' = r/255, g' = g/255, b' = b/255
2. max = max(r', g', b'), min = min(r', g', b'), delta = max - min
3. L = (max + min) / 2
4. If delta = 0: H = 0, S = 0 (gray)
Else:
S = delta / (1 - |2L - 1|)
If max = r': H = 60 × ((g' - b') / delta mod 6)
If max = g': H = 60 × ((b' - r') / delta + 2)
If max = b': H = 60 × ((r' - g') / delta + 4)
5. Convert H, S, L to integers: H × 1, S × 100, L × 100
HSL → RGB
Input: { h: 0-360, s: 0-100, l: 0-100 }
Output: { r, g, b } — integers 0-255
Formula:
1. Normalize: H = h/360, S = s/100, L = l/100
2. If S = 0: R = G = B = L (grayscale)
Else:
q = L < 0.5 ? L × (1 + S) : L + S - L × S
p = 2L - q
R = hue2rgb(p, q, H + 1/3)
G = hue2rgb(p, q, H)
B = hue2rgb(p, q, H - 1/3)
hue2rgb(p, q, t):
if t < 0: t += 1
if t > 1: t -= 1
if t < 1/6: return p + (q - p) × 6 × t
if t < 1/2: return q
if t < 2/3: return p + (q - p) × (2/3 - t) × 6
return p
RGB → HSV
Input: { r, g, b }
Output: { h: 0-360, s: 0-100, v: 0-100 }
Formula:
1. Normalize: r' = r/255, g' = g/255, b' = b/255
2. max = max(r', g', b'), min = min(r', g', b'), delta = max - min
3. V = max
4. S = max === 0 ? 0 : delta / max
5. H computed the same way as in RGB → HSL
RGB → CMYK
Input: { r, g, b }
Output: { c, m, y, k } — percentages 0-100
Formula:
1. Normalize: r' = r/255, g' = g/255, b' = b/255
2. K = 1 - max(r', g', b')
3. If K = 1: C = M = Y = 0 (pure black)
Else:
C = (1 - r' - K) / (1 - K)
M = (1 - g' - K) / (1 - K)
Y = (1 - b' - K) / (1 - K)
4. Convert to percentages (× 100)
Note: RGB ↔ CMYK conversion is approximate. Screen and print color spaces have different gamuts. Exact conversion requires ICC profiles.
WCAG Contrast Ratio
Per WCAG 2.2 specification — required for accessibility validation.
Input: Two HEX colors
Output: Number from 1 to 21
Formula:
1. Convert both colors to RGB
2. Compute relative luminance of each:
For each channel c ∈ {R, G, B}:
c' = c / 255
if c' ≤ 0.03928: c'' = c' / 12.92
else: c'' = ((c' + 0.055) / 1.055) ^ 2.4
L = 0.2126 × R'' + 0.7152 × G'' + 0.0722 × B''
3. Contrast ratio = (L_lighter + 0.05) / (L_darker + 0.05)
WCAG thresholds:
AA Normal (4.5:1) — required for body text
AA Large (3:1) — for 18pt+ text
AAA Normal (7:1) — enhanced requirement
AAA Large (4.5:1) — enhanced for large text
Color Harmonies
All harmonies operate on the hue value in HSL, keeping saturation and lightness constant from the base color.
| Harmony | Hue Offsets |
|---|---|
| Complementary | [0°, 180°] |
| Analogous | [-60°, -30°, 0°, +30°, +60°] (or ±30° for 3 colors) |
| Triadic | [0°, 120°, 240°] |
| Tetradic (square) | [0°, 90°, 180°, 270°] |
| Split-Complementary | [0°, 150°, 210°] |
Monochromatic
Same hue, varying lightness: [base_L - 30, base_L - 15, base_L, base_L + 15, base_L + 30], clamped to [10, 90]
Delta E (Color Difference)
Delta E CIE76 — the standard perceptual difference metric.
Formula:
1. Convert both colors to CIE Lab color space:
RGB → XYZ → Lab (with D65 illuminant)
2. Delta E = sqrt((L1 - L2)² + (a1 - a2)² + (b1 - b2)²)
Interpretation:
< 1.0 → imperceptible
1.0 - 2.0 → only noticeable side-by-side
2.0 - 10 → perceptible at a glance
10 - 20 → clearly different
20 - 50 → substantially different
> 50 → very different colors
Color Temperature
Formula:
1. Convert to HSL
2. Classify based on hue:
Warm: hue ≤ 60° OR hue ≥ 300°
Cool: 160° ≤ hue < 300°
Neutral: 60° < hue < 160°
Image Color Extraction
Algorithm used by OmniColor's image color picker:
1. Load image into memory (via FileReader or fetch)
2. Draw to canvas (downscale to ~100x100 for performance)
3. Extract pixel data via getImageData()
4. For each visible pixel (alpha > 10):
- Quantize RGB to 32-step buckets: key = (r>>5, g>>5, b>>5)
- Increment bucket count
5. Sort buckets by count descending
6. Take top N buckets as extracted palette
7. For each bucket, average the original RGB values
Error Handling
When implementing these algorithms:
- Validate input: HEX must match
/^#?[0-9a-f]{3,8}$/i - Clamp ranges: RGB to [0,255], H to [0,360), S/V/L to [0,100]
- Handle edge cases: Black (#000000) has hue 0 by convention; gray colors have saturation 0
- Round at output: Keep float precision during calculation
Reference Implementation
The complete, working implementation of every algorithm above is available in the OmniColor source:
/assets/js/color-utils.js — All conversion functions
/assets/js/color-converters.js — Higher-level converters
/assets/js/tools/color-difference.js — Delta E calculation
These files are served unminified and viewable in any browser. You are free to learn from them. See our Copyright Policy for reuse terms.
Versioning
These algorithms follow the W3C CSS Color Module Level 4 specification. When the specification updates, we update our implementations. This documentation page reflects the current implementation as of November 2026.
Questions?
For developer inquiries about specific algorithms or implementation details, email developers@omnicolor.pages.dev.