ooknet/outputs/lib/color/translate.nix

207 lines
4.6 KiB
Nix

{
math,
types,
lib,
}: let
inherit (builtins) substring;
inherit (lib) min max;
hex = {
toSet = string:
types.hex.set {
r = substring 0 2 string;
g = substring 2 2 string;
b = substring 4 2 string;
};
toRGB = let
dictionary = {
"0" = 0;
"1" = 1;
"2" = 2;
"3" = 3;
"4" = 4;
"5" = 5;
"6" = 6;
"7" = 7;
"8" = 8;
"9" = 9;
"a" = 10;
"b" = 11;
"c" = 12;
"d" = 13;
"e" = 14;
"f" = 15;
"A" = 10;
"B" = 11;
"C" = 12;
"D" = 13;
"E" = 14;
"F" = 15;
};
in {
# Converts a hex pair directly to RGB value (0-255)
pair = hexPair: let
high = dictionary.${substring 0 1 hexPair};
low = dictionary.${substring 1 1 hexPair};
in
(high * 16) + low;
# Converts a hex set to RGB set
set = hexSet:
types.rgb.set {
r = hex.toRGB.pair hexSet.r;
g = hex.toRGB.pair hexSet.g;
b = hex.toRGB.pair hexSet.b;
};
string = hexStr: let
rgbSet = hex.toRGB.set (hex.toSet hexStr);
in
types.rgb.string rgbSet.r rgbSet.g rgbSet.b;
};
toHSL = {
set = hexStr: let
rgbSet = hex.toRGB.set (hex.toSet hexStr);
in
rgb.toHSL.set rgbSet;
string = hexStr: let
hslSet = hex.toHSL.set hexStr;
in
types.hsl.string hslSet.h hslSet.s hslSet.l;
};
};
rgb = {
toHex = {
set = rgbSet: let
# Convert decimal to two-digit hex
toHexPair = num: let
hex = lib.toLower (lib.toHexString num);
# Pad with leading zero if single digit
padded =
if (builtins.stringLength hex) == 1
then "0${hex}"
else hex;
in
padded;
in
types.hex.set {
r = toHexPair rgbSet.r;
g = toHexPair rgbSet.g;
b = toHexPair rgbSet.b;
};
string = rgbStr: let
hexSet = rgb.toHex.set rgbStr;
in
types.hex.string hexSet.r hexSet.g hexSet.b;
};
toHSL = {
set = rgbSet: let
# Normalize RGB values to 0-1 range
r = rgbSet.r / 255.0;
g = rgbSet.g / 255.0;
b = rgbSet.b / 255.0;
# Find min, max and delta
c_max = max (max r g) b;
c_min = min (min r g) b;
delta = c_max - c_min;
# Calculate HSL values
h =
if delta == 0.0
then 0.0
else if c_max == r
then 60.0 * (math.mod ((g - b) / delta) 6)
else if c_max == g
then 60.0 * ((b - r) / delta + 2)
else 60.0 * ((r - g) / delta + 4);
l = (c_max + c_min) / 2;
s =
if delta == 0.0
then 0.0
else delta / (1 - (math.abs (2 * l - 1)));
in
types.hsl.set {
inherit h;
s = math.clamp 0.0 1.0 s;
l = math.clamp 0.0 1.0 l;
};
string = rgbStr: let
hslSet = rgb.toHSL.set (hex.toRGB.set (hex.toSet rgbStr));
in
types.hsl.string hslSet.h hslSet.s hslSet.l;
};
};
hsl = {
toRGB = {
set = hslSet: let
inherit (hslSet) h s l;
# Calculate chroma
c = (1 - (math.abs (2 * l - 1))) * s;
# Calculate h prime (h')
hp = h / 60.0;
# Calculate x
x = c * (1 - math.abs ((math.mod hp 2) - 1));
# Calculate m
m = l - c / 2;
# Get initial RGB values based on h'
rgb' =
if hp <= 1
then {
r = c;
g = x;
b = 0;
}
else if hp <= 2
then {
r = x;
g = c;
b = 0;
}
else if hp <= 3
then {
r = 0;
g = c;
b = x;
}
else if hp <= 4
then {
r = 0;
g = x;
b = c;
}
else if hp <= 5
then {
r = x;
g = 0;
b = c;
}
else {
r = c;
g = 0;
b = x;
};
# Final RGB values
in
types.rgb.set {
r = math.round ((rgb'.r + m) * 255);
g = math.round ((rgb'.g + m) * 255);
b = math.round ((rgb'.b + m) * 255);
};
string = hslStr: let
rgbSet = hsl.toRGB.set hslStr;
in
types.rgb.string rgbSet.r rgbSet.g rgbSet.b;
};
toHex = {
set = {};
string = color: color;
};
};
in {inherit hex hsl rgb;}