Saturon LogoSaturon

🚧 This documentation covers a pre-1.0 release. Expect breaking changes.

RecipesRegister Color Spaces

HSI

A recipe to register the HSI color function in Saturon.

import { registerColorFunction } from "saturon/utils";

/**
 * @see {@link https://en.wikipedia.org/wiki/HSL_and_HSV|HSL and HSV}
 */
registerColorFunction("hsi", {
    components: {
        h: { index: 0, value: "angle", precision: 0 },
        s: { index: 1, value: "percentage", precision: 0 },
        i: { index: 2, value: "percentage", precision: 0 },
    },
    bridge: "rgb",
    toBridge: (hsi: number[]) => {
        const [h, s, i] = hsi.map((c, i) => (i === 0 ? c : c / 100));
        const H = (h % 360) * (Math.PI / 180);
        let r, g, b;
        if (H < (2 * Math.PI) / 3) {
            b = i * (1 - s);
            r = i * (1 + (s * Math.cos(H)) / Math.cos(Math.PI / 3 - H));
            g = 3 * i - (r + b);
        } else if (H < (4 * Math.PI) / 3) {
            H -= (2 * Math.PI) / 3;
            r = i * (1 - s);
            g = i * (1 + (s * Math.cos(H)) / Math.cos(Math.PI / 3 - H));
            b = 3 * i - (r + g);
        } else {
            H -= (4 * Math.PI) / 3;
            g = i * (1 - s);
            b = i * (1 + (s * Math.cos(H)) / Math.cos(Math.PI / 3 - H));
            r = 3 * i - (g + b);
        }
        return [r * 255, g * 255, b * 255];
    },
    fromBridge: (rgb: number[]) => {
        const [r, g, b] = rgb.map((c) => c / 255);
        const i = (r + g + b) / 3;
        const min = Math.min(r, g, b);
        const s = i === 0 ? 0 : 1 - min / i;
        let h = 0;
        if (s !== 0) {
            const num = 0.5 * (r - g + (r - b));
            const den = Math.sqrt((r - g) ** 2 + (r - b) * (g - b));
            let theta = Math.acos(Math.max(-1, Math.min(1, num / den)));
            if (b > g) theta = 2 * Math.PI - theta;
            h = (theta * 180) / Math.PI;
        }
        return [h, s * 100, i * 100];
    },
});