207 lines
		
	
	
	
		
			4.6 KiB
		
	
	
	
		
			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;}
 |