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.