1 /**
2     This module defines "standard" colorspace compatible with typical 
3     D library with implicit sRGB and then adds colorspace as defined 
4     by CSS.
5     Copyright: Copyright Guillaume Piolat 2023-2024.
6     License:   $(LINK2 http://www.boost.org/LICENSE_1_0.txt, BSL-1.0)
7 */
8 module colors.colorspace;
9 
10 
11 /** 
12     The Predefined Color Spaces. For now, no custom space.
13 */
14 enum Colorspace
15 {
16     /** 
17         A 8-bit tristimulus sRGB color, with alpha.
18         This is the most common encoding, and is here to avoid 
19         needless conversion for this case.
20     */
21     rgba8,
22 
23     /** 
24         A 16-bit tristimulus sRGB color, with alpha.
25         This is not a CSS colorspace, and it here for completeness.
26     */
27     rgba16,
28 
29     
30     // Below: CSS-compatible color spaces.
31 
32     /** 
33         A 32-bit float tristimulus sRGB color, with alpha. Called 
34         "srgb" in CSS. CSS functions such as rgb() return that.
35     */
36     rgbaf32,
37 
38     /** 
39         A 32-bit float Hue Saturation Luminance space that is 
40         based-upon sRGB. "hsl" in CSS.
41     */
42     hslaf32,
43 
44 
45     // much work remain
46 
47 /+
48     /// The sRGB-linear predefined color space is the same as srgb 
49     ///except that the transfer 
50     /// function is linear-light (there is no gamma-encoding).
51     srgb_linear,
52 
53     display_p3,
54 
55     a98_rgb,
56 
57     prophoto_rgb,
58 
59     xyz,
60     xyz_D50,
61     xyz_D65,
62 
63     hsl,
64     hwb,
65     lch,
66     oklch,
67     lab,
68     oklab
69     +/
70 
71     unknown // used as special value for unsupported conversions
72 }
73 
74 
75 
76 // All monomorphic color types defined here.
77 // Typically you would use `Color` instead of those directly.
78 
79 
80 /** 
81     A 8-bit luminance sRGB value.
82 */
83 align(1) struct L8
84 {
85     align(1):
86     ubyte l = 0;
87 }
88 static assert(L8.sizeof == 1);
89 unittest
90 {
91     // Create such a color like this
92     L8 midgrey = L8(128);
93 }
94 
95 /**
96     A 8-bit luminance sRGB value, with alpha.
97 */
98 align(1) struct LA8
99 {
100 align(1):
101     ubyte l = 0;
102     ubyte a = 0;
103 }
104 static assert(LA8.sizeof == 2);
105 unittest
106 {
107     // Create such a color like this
108     LA8 transparentWhite = LA8(255, 0);
109 }
110 
111 /** 
112     A 8-bit tristimulus sRGB color.
113     TODO: `rgb8` convenience function to create one such color.
114 */
115 align(1) struct RGB8
116 {
117 align(1):
118     ubyte r = 0, 
119           g = 0, 
120           b = 0;
121 }
122 unittest
123 {
124     // Create such a color like this
125     RGB8 yellow = RGB8(255, 255, 0);
126 }
127 
128 /** 
129     A 16-bit tristimulus sRGB color.
130     TODO: `rgb16` convenience function to create one such color.
131 */
132 align(1) struct RGB16
133 {
134     align(1):
135     ushort r = 0, 
136            g = 0, 
137            b = 0;
138 }
139 unittest
140 {
141     // Create such a color like this
142     RGB16 yellow = RGB16(65535, 65535, 0);
143 }
144 
145 /** 
146    A 8-bit tristimulus sRGB color, with alpha.
147     This is the most common encoding, and is here to avoid needless 
148     conversion for this case.
149     TODO: `rgba8` convenience function to create one such color.
150 */
151 align(1) struct RGBA8
152 {
153 align(1):
154     ubyte r = 0, 
155           g = 0, 
156           b = 0,
157           a = 0;
158 }
159 unittest
160 {
161     assert(RGBA8.init == RGBA8(0, 0, 0, 0)); // transparent black by default
162 }
163 
164 /** 
165     A 16-bit tristimulus sRGB color, with alpha.
166     This is the most common encoding, and is here to avoid needless
167     conversion for this case.
168     TODO: `rgba16` convenience function to create one such color.
169 */
170 align(1) struct RGBA16
171 {
172     align(1):
173     ushort r = 0, 
174            g = 0, 
175            b = 0,
176            a = 0;
177 }
178 unittest
179 {
180     // transparent black by default
181     assert(RGBA16.init == RGBA16(0, 0, 0, 0)); 
182 }
183 
184 /** 
185     A 32-bit float tristimulus sRGB color, with alpha.
186     This is the most common encoding, and is here to avoid needless 
187     conversion for this case.
188     This is what most CSS functions resolve to, because of precision 
189     needs.
190     Warning: `r`, `g` and `b` have a range 0 to 1, unlike in CSS.
191              but `a` has a range 0 to 1. All can be `float.nan` 
192              ("none" in CSS).
193     See_also: `rgb` and `rgba` functions to create one such color.
194 */
195 struct RGBAf
196 {
197     float r = 0, 
198           g = 0, 
199           b = 0, 
200           a = 0;
201 }
202 
203 /**
204     A 32-bit float Hue Saturation Luminance space that is based-upon 
205     sRGB. "hsl" in CSS.
206     Warning: `h` is in a degrees modulo space (0 to 360)
207               `s`, `l` and `a` have a range 0 to 1.
208               All can be `float.nan` ("none" in CSS).
209     See_also: `hsl` and `hsla` functions to create one such color.
210 */
211 struct HSLAf
212 {
213     float h = 0, 
214           s = 0, 
215           l = 0, 
216           a = 0;
217 }