Developer Portal
Everything you need to build with color — algorithms, code examples, best practices and integration guides.
What You Will Find Here
OmniColor does not offer a public REST API — every tool runs in your browser. However, our color algorithms are standard and thoroughly documented, and you can implement them in any language.
This developer portal provides:
- Open color conversion algorithms (HEX, RGB, HSL, HSV, CMYK)
- WCAG contrast ratio calculation
- Color harmony generation
- Delta E (perceptual difference) calculation
- Best practices for building color tools
Color Conversion Algorithms
HEX to RGB
function hexToRgb(hex) {
const h = hex.replace('#', '');
return {
r: parseInt(h.substring(0, 2), 16),
g: parseInt(h.substring(2, 4), 16),
b: parseInt(h.substring(4, 6), 16)
};
}
RGB to HEX
function rgbToHex(r, g, b) {
return '#' + [r, g, b]
.map(v => Math.max(0, Math.min(255, v))
.toString(16).padStart(2, '0'))
.join('')
.toUpperCase();
}
RGB to HSL
function rgbToHsl(r, g, b) {
r /= 255; g /= 255; b /= 255;
const max = Math.max(r, g, b);
const min = Math.min(r, g, b);
const l = (max + min) / 2;
let h = 0, s = 0;
if (max !== min) {
const d = max - min;
s = l > 0.5 ? d / (2 - max - min) : d / (max + min);
switch (max) {
case r: h = (g - b) / d + (g < b ? 6 : 0); break;
case g: h = (b - r) / d + 2; break;
case b: h = (r - g) / d + 4; break;
}
h /= 6;
}
return {
h: Math.round(h * 360),
s: Math.round(s * 100),
l: Math.round(l * 100)
};
}
HSL to RGB
function hslToRgb(h, s, l) {
h = ((h % 360) + 360) % 360 / 360;
s = Math.max(0, Math.min(100, s)) / 100;
l = Math.max(0, Math.min(100, l)) / 100;
if (s === 0) {
const v = Math.round(l * 255);
return { r: v, g: v, b: v };
}
const 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;
};
const q = l < 0.5 ? l * (1 + s) : l + s - l * s;
const p = 2 * l - q;
return {
r: Math.round(hue2rgb(p, q, h + 1/3) * 255),
g: Math.round(hue2rgb(p, q, h) * 255),
b: Math.round(hue2rgb(p, q, h - 1/3) * 255)
};
}
WCAG Contrast Ratio
The WCAG 2.2 contrast formula (required for accessibility compliance):
function relativeLuminance(r, g, b) {
const f = (c) => {
c /= 255;
return c <= 0.03928 ? c / 12.92 : Math.pow((c + 0.055) / 1.055, 2.4);
};
return 0.2126 * f(r) + 0.7152 * f(g) + 0.0722 * f(b);
}
function contrastRatio(rgb1, rgb2) {
const L1 = relativeLuminance(rgb1.r, rgb1.g, rgb1.b);
const L2 = relativeLuminance(rgb2.r, rgb2.g, rgb2.b);
const lighter = Math.max(L1, L2);
const darker = Math.min(L1, L2);
return (lighter + 0.05) / (darker + 0.05);
}
Color Harmony Generation
All harmonies are hue rotations in HSL space:
// Given base HSL {h, s, l}
const complementary = (hsl) => [
hsl,
{ ...hsl, h: (hsl.h + 180) % 360 }
];
const analogous = (hsl, step = 30) => [
{ ...hsl, h: (hsl.h - step + 360) % 360 },
hsl,
{ ...hsl, h: (hsl.h + step) % 360 }
];
const triadic = (hsl) => [
hsl,
{ ...hsl, h: (hsl.h + 120) % 360 },
{ ...hsl, h: (hsl.h + 240) % 360 }
];
const tetradic = (hsl) => [
hsl,
{ ...hsl, h: (hsl.h + 90) % 360 },
{ ...hsl, h: (hsl.h + 180) % 360 },
{ ...hsl, h: (hsl.h + 270) % 360 }
];
Delta E (Perceptual Difference)
Delta E CIE76 formula — the standard metric for color difference:
// Convert RGB to CIE Lab, then compute Euclidean distance
function deltaE(hex1, hex2) {
const lab1 = hexToLab(hex1);
const lab2 = hexToLab(hex2);
return Math.sqrt(
Math.pow(lab1.L - lab2.L, 2) +
Math.pow(lab1.a - lab2.a, 2) +
Math.pow(lab1.b - lab2.b, 2)
);
}
// Interpretation:
// < 1: imperceptible
// 1-2: only noticeable side-by-side
// 2-10: perceptible at a glance
// 10-20: clearly different
// > 20: substantially different
Building Color Tools — Best Practices
Use HSL for UI, RGB/HEX for storage
HSL is intuitive for users to adjust; RGB is what graphics APIs consume. Convert between them for the best experience.
Never do color math in the DOM
Compute colors in JavaScript and set the result via style properties. Do not repeatedly query computed styles during animation.
Preserve precision until final output
Work in float internally, round only when displaying. Repeatedly rounding to integers accumulates error.
Test with a real accessibility tool
Always test WCAG contrast with the exact formula. Eyeballing fails for mid-tone colors.
Validate user input
Never assume HEX strings are valid. Regex validation: /^#?[0-9a-f]{3,8}$/i
Respect the display gamut
sRGB cannot reproduce all of Display P3 or Adobe RGB. If your tool supports wide-gamut output, warn users.
Integration with OmniColor
You do not need permission to link to OmniColor or use it as a reference implementation for your own color tools. If you want to:
- Build a similar tool: Do so — colors and color math are not copyrightable.
- Embed OmniColor: Contact hello@omnicolor.pages.dev for licensing.
- Contribute a tool: We are not currently accepting tool contributions, but feedback is welcome.
- Link to OmniColor: Freely, no permission needed.
API Documentation
For complete documentation of every algorithm, see our API documentation.
Questions?
For developer inquiries, email developers@omnicolor.pages.dev.