1 /*
2  * Copyright (c) 2019-2020 Kevin Townsend (KTOWN)
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 /**
8  * @defgroup COLORIMETRY Colorimetry
9  *
10  * @brief Various conversion and mathematic functions to work with different color
11  * systems and values.
12  */
13 
14 /**
15  * @file
16  * @brief API header file for colorimetry in zscilib.
17  *
18  * This file contains the entry points to the colorimetry APIs.
19  */
20 
21 #ifndef ZEPHYR_INCLUDE_ZSL_COLORIMETRY_H_
22 #define ZEPHYR_INCLUDE_ZSL_COLORIMETRY_H_
23 
24 #include <stddef.h>
25 #include <stdint.h>
26 #include <zsl/zsl.h>
27 #include <zsl/matrices.h>
28 
29 #ifdef __cplusplus
30 extern "C" {
31 #endif
32 
33 /**
34  * @addtogroup COLOR_STRUCTS Structs and Enums
35  *
36  * @brief Common colorimetry-related structs and enums.
37  *
38  * @ingroup COLORIMETRY
39  *  @{ */
40 
41 /**
42  * @brief List of supported CIE standard observer models. All models cover
43  *        the 360 nm to 830 nm range in 5 nm steps.
44  *
45  * CIE standard observers define a model that enables the correlation of
46  * spectral data to human visual assessments of color. The older 2 degree
47  * model is widely used in scientific measurements and instruments, but the
48  * 10 degree model is considered a more accurate approximation of how normal
49  * human vision perceives color.
50  */
51 enum zsl_clr_obs {
52 	/**
53 	 * CIE 1931 2 degree standard observer color matching functions from
54 	 * 360nm to 830nm in 5 nm steps.
55 	 */
56 	ZSL_CLR_OBS_2_DEG = 0,
57 
58 	/**
59 	 * CIE 1964 10 degree standard observer color matching functions from
60 	 * 360nm to 830nm in 5 nm steps.
61 	 */
62 	ZSL_CLR_OBS_10_DEG
63 };
64 
65 /**
66  * @brief List of supported CIE standard illuminants.
67  */
68 enum zsl_clr_illum {
69 	/**
70 	 * XYZ tristimulus for the standard 'A' white point or 'illuminant',
71 	 * used with transmissive light measurements. This illuminant
72 	 * simulates tungsten-filament light with a CCT of 2856K.
73 	 */
74 	ZSL_CLR_ILLUM_A = 0,
75 
76 	/**
77 	 * XYZ tristimulus for the standard 'B' white point or 'illuminant',
78 	 * used with transmissive light measurements. This illuminant
79 	 * simulates noon sunlight with a CCT of 4874K.
80 	 */
81 	ZSL_CLR_ILLUM_B,
82 
83 	/**
84 	 * XYZ tristimulus for the standard 'C' white point or 'illuminant',
85 	 * used with transmissive light measurements. This illuminant simulates
86 	 * typical north sky daylight with a CCT of 6774K.
87 	 */
88 	ZSL_CLR_ILLUM_C,
89 
90 	/**
91 	 * XYZ tristimulus for the standard D50 white point or 'illuminant',
92 	 * used with transmissive light measurements.
93 	 */
94 	ZSL_CLR_ILLUM_D50,
95 
96 	/**
97 	 * XYZ tristimulus for the standard D55 white point or 'illuminant',
98 	 * used with transmissive light measurements.
99 	 */
100 	ZSL_CLR_ILLUM_D55,
101 
102 	/**
103 	 * XYZ tristimulus for the standard D65 white point or 'illuminant',
104 	 * used with transmissive light measurements.
105 	 */
106 	ZSL_CLR_ILLUM_D65,
107 
108 	/**
109 	 * XYZ tristimulus for the standard 'E' white point or 'illuminant',
110 	 * used with transmissive light measurements. This illuminant is an
111 	 * 'equal-energy radiator' and a theoretical reference value.
112 	 */
113 	ZSL_CLR_ILLUM_E,
114 
115 	/**
116 	 * XYZ tristimulus for the profile connection space (PCS) illuminant
117 	 * used in ICC profiles.
118 	 */
119 	ZSL_CLR_ILLUM_ICC
120 };
121 
122 /**
123  * @brief List of supported CIE luminous efficiency functions. All functions
124  * cover the 380 nm to 780 nm range in 5 nm steps.
125  *
126  * Luminous efficiency functions enable conversion from radiometric units,
127  * representing radiant or electromagnetic energy, into photometric units,
128  * representing luminous energy as perceived by the human eye.
129  *
130  * For example:
131  *
132  * Irradiance is a radiometric unit usually represented in W/m^2, and has a
133  * direct relationship to energy (watts). It is a measure of the
134  * electromagnetic energy within a specified area, visible or not.
135  *
136  * Luminance is a photometric unit, and indicates luminous intensity per unit
137  * area, as perceived by normal human vision, and is usually represented in
138  * cd/m^2.
139  *
140  * Irradiance can be converted to luminance by means of an appropriate
141  * luminous efficiency function, shaping the radiometric measurement into
142  * an approximation of how a human with normal vision would perceive the
143  * visible aspects of the radiometric phenomenon.
144  *
145  * Two major luminous efficiency functions are widely used, depending on if
146  * human vision is being modelled in normal daylight conditions, where color
147  * can be perceived, or in night-time conditions where sensitivity to
148  * brightness is dominant.
149  */
150 enum zsl_clr_lef {
151 	/**
152 	 * CIE 1988 Photopic Luminous Efficiency Function, which models typical
153 	 * human vision in well-lit conditions, and is based on the response of
154 	 * color-sensitive cones in the human eye.
155 	 */
156 	ZSL_CLR_LEF_CIE88_PHOTOPIC      = 0,
157 
158 	/**
159 	 * CIE 1951 Scotopic Luminous Efficiency Function, which models typical
160 	 * human vision in dark conditions, and is based on the response of
161 	 * rods in the human eye.
162 	 */
163 	ZSL_CLR_LEF_CIE51_SCOTOPIC      = 1,
164 };
165 
166 /**
167  * @brief List of included 3x3 XYZ to RGB color space correlation matrices.
168  */
169 enum zsl_clr_rgb_ccm {
170 	/** XYZ to linear sRGB (D65 white point). */
171 	ZSL_CLR_RGB_CCM_SRGB_D65 = 0,
172 
173 	/** XYZ to linear sRGB (D50 white point). */
174 	ZSL_CLR_RGB_CCM_SRGB_D50,
175 
176 	/** AdobeRGB98. */
177 	ZSL_CLR_RGB_CCM_ADOBERGB98,
178 
179 	/** Sony S-Gamut3.cine D65. */
180 	ZSL_CLR_RGB_CCM_SONY_SGAMUT3_CINE,
181 
182 	/** NTSC. */
183 	ZSL_CLR_RGB_CCM_NTSC,
184 
185 	/** PAL/SECAM. */
186 	ZSL_CLR_RGB_CCM_PAL_SECAM,
187 
188 	/** ITU-R BT.709. */
189 	ZSL_CLR_RGB_CCM_BT_709,
190 
191 	/** ITU-R BT.2020. */
192 	ZSL_CLR_RGB_CCM_BT_2020,
193 
194 	/** ACES Primaries #0 (AP0). */
195 	ZSL_CLR_RGB_CCM_ACES_P0,
196 
197 	/** ACES Primaries #1 (AP1). */
198 	ZSL_CLR_RGB_CCM_ACES_P1,
199 
200 	/** DCI-P3. */
201 	ZSL_CLR_RGB_CCM_DCI_P3,
202 
203 	/** DCI-P3+. */
204 	ZSL_CLR_RGB_CCM_DCI_P3_PLUS,
205 
206 	/** CIE linear RGB. */
207 	ZSL_CLR_RGB_CCM_CIE_RGB,
208 };
209 
210 /**
211  * @brief The algorithm to use when converting a CIE 1960 UV value to
212  * CCT, Duv.
213  */
214 enum zsl_clr_uv_cct_method {
215 	/**
216 	 * @brief McCamy's approximation.
217 	 *
218 	 * McCamy's approximation provides an approximate CCT using a CIE 1931
219 	 * xyY chromaticity:
220 	 *
221 	 *   CCT(x, y) = 449 * n^3 + 3525 * n^2 + 6823.3 * n + 5520.33
222 	 *
223 	 * Where:
224 	 *
225 	 *   n = (x − 0.3320) / (0.1858 - y)
226 	 *
227 	 * This is accurate for color temperatures between ~2800K-6500K.
228 	 */
229 	ZSL_CLR_UV_CCT_METHOD_MCCAMY,
230 
231 	/**
232 	 * @brief Yoshi Ohno 2011 CORM.
233 	 *
234 	 * Yoshi Ohno, "Calculation of CCT and Duv and Practical Conversion
235 	 * Formulae", CORM 2011.
236 	 *
237 	 * Highly accurate between 2,000 and 20,000 K, making it the ideal
238 	 * choice for artifical lighting.
239 	 */
240 	ZSL_CLR_UV_CCT_METHOD_OHNO2011,
241 
242 	/**
243 	 * @brief Yoshi Ohno 2014.
244 	 *
245 	 * Source: Yoshi Ohno (2014)
246 	 *         Practical Use and Calculation of CCT and Duv
247 	 *         LEUKOS, 10:1, 47-55, DOI: 10.1080/15502724.2014.839020
248 	 *
249 	 * Highly accurate between 2,600 and 20,000 K, making it the ideal
250 	 * choice for artifical lighting.
251 	 */
252 	ZSL_CLR_UV_CCT_METHOD_OHNO2014
253 };
254 
255 /**
256  * @brief CIE 1931 XYZ tristimulus values.
257  */
258 struct zsl_clr_xyz {
259 	/** The X component of the XYZ tristimulus. */
260 	zsl_real_t xyz_x;
261 	/** The Y component of the XYZ tristimulus. */
262 	zsl_real_t xyz_y;
263 	/** The Z component of the XYZ tristimulus. */
264 	zsl_real_t xyz_z;
265 	/** The standard observer model this data is based upon. */
266 	enum zsl_clr_obs observer;
267 	/** The reference illuminant for this data (default = ZSL_CLR_ILLUM_A). */
268 	enum zsl_clr_illum illuminant;
269 	/** If non-zero, indicates that the #xyz_x value is invalid. */
270 	uint8_t x_invalid : 1;
271 	/** If non-zero, indicates that the #xyz_y value is invalid. */
272 	uint8_t y_invalid : 1;
273 	/** If non-zero, indicates that the #xyz_z value is invalid. */
274 	uint8_t z_invalid : 1;
275 };
276 
277 /**
278  * @brief CIE 1931 xyY chromaticity coordinates.
279  */
280 struct zsl_clr_xyy {
281 	/** The x component of the xyY chromaticity coordinates. */
282 	zsl_real_t xyy_x;
283 	/** The y component of the xyY chromaticity coordinates. */
284 	zsl_real_t xyy_y;
285 	/** The Y component of the xyY chromaticity coordinates. */
286 	zsl_real_t xyy_Y;
287 	/** The standard observer model this data is based upon. */
288 	enum zsl_clr_obs observer;
289 	/** The reference illuminant for this data (default = ZSL_CLR_ILLUM_A). */
290 	enum zsl_clr_illum illuminant;
291 	/** If non-zero, indicates that the #xyy_x value is invalid. */
292 	uint8_t x_invalid : 1;
293 	/** If non-zero, indicates that the #xyy_y value is invalid. */
294 	uint8_t y_invalid : 1;
295 	/** If non-zero, indicates that the #xyy_Y value is invalid. */
296 	uint8_t Y_invalid : 1;
297 };
298 
299 /**
300  * @brief CIE 1960 UCS chromaticity coordinates.
301  */
302 struct zsl_clr_uv60 {
303 	/** The u component of the CIE 1960 (u, v) chromaticity coordinates. */
304 	zsl_real_t uv60_u;
305 	/** The v component of the CIE 1960 (u, v) chromaticity coordinates. */
306 	zsl_real_t uv60_v;
307 	/** The standard observer model this data is based upon. */
308 	enum zsl_clr_obs observer;
309 	/** The reference illuminant for this data (default = ZSL_CLR_ILLUM_A). */
310 	enum zsl_clr_illum illuminant;
311 	/** If non-zero, indicates that the #uv60_u value is invalid. */
312 	uint8_t u_invalid : 1;
313 	/** If non-zero, indicates that the #uv60_v value is invalid. */
314 	uint8_t v_invalid : 1;
315 };
316 
317 /**
318  * @brief CIE 1976 UCS chromaticity coordinates.
319  */
320 struct zsl_clr_uv76 {
321 	/** The u component of the CIE 1976 (u, v) chromaticity coordinates. */
322 	zsl_real_t uv76_u;
323 	/** The v component of the CIE 1976 (u, v) chromaticity coordinates. */
324 	zsl_real_t uv76_v;
325 	/** The standard observer model this data is based upon. */
326 	enum zsl_clr_obs observer;
327 	/** The reference illuminant for this data (default = ZSL_CLR_ILLUM_A). */
328 	enum zsl_clr_illum illuminant;
329 	/** If non-zero, indicates that the #uv76_u value is invalid. */
330 	uint8_t u_invalid : 1;
331 	/** If non-zero, indicates that the #uv76_v value is invalid. */
332 	uint8_t v_invalid : 1;
333 };
334 
335 /**
336  * @brief RGBA color using floating-space notation from 0.0 .. 1.0.
337  */
338 struct zsl_clr_rgbf {
339 	/** The relative red components of an RGBA color (0.0 .. 1.0). */
340 	zsl_real_t r;
341 	/** The relative green components of an RGBA color (0.0 .. 1.0). */
342 	zsl_real_t g;
343 	/** The relative blue components of an RGBA color (0.0 .. 1.0). */
344 	zsl_real_t b;
345 	/** The relative alpha channel component (0.0 .. 1.0). */
346 	zsl_real_t a;
347 	/** If non-zero, indicates that the #r value is invalid. */
348 	uint8_t r_invalid : 1;
349 	/** If non-zero, indicates that the #g value is invalid. */
350 	uint8_t g_invalid : 1;
351 	/** If non-zero, indicates that the #b value is invalid. */
352 	uint8_t b_invalid : 1;
353 	/** If non-zero, indicates that the #a value is invalid. */
354 	uint8_t a_invalid : 1;
355 };
356 
357 /**
358  * @brief RGBA color using 8-bit values.
359  */
360 struct zsl_clr_rgb8 {
361 	/** The 8-bit red components of an RGBA color. */
362 	uint8_t r;
363 	/** The 8-bit green components of an RGBA color. */
364 	uint8_t g;
365 	/** The 8-bit blue components of an RGBA color. */
366 	uint8_t b;
367 	/** The 8-bit alpha channel component. */
368 	uint8_t a;
369 	/** If non-zero, indicates that the #r value is invalid. */
370 	uint8_t r_invalid : 1;
371 	/** If non-zero, indicates that the #g value is invalid. */
372 	uint8_t g_invalid : 1;
373 	/** If non-zero, indicates that the #b value is invalid. */
374 	uint8_t b_invalid : 1;
375 	/** If non-zero, indicates that the #a value is invalid. */
376 	uint8_t a_invalid : 1;
377 };
378 
379 /**
380  * @brief RGBA color using 16-bit values.
381  */
382 struct zsl_clr_rgb16 {
383 	/** The 16-bit red components of an RGBA color. */
384 	uint16_t r;
385 	/** The 16-bit green components of an RGBA color. */
386 	uint16_t g;
387 	/** The 16-bit blue components of an RGBA color. */
388 	uint16_t b;
389 	/** The 16-bit alpha channel component. */
390 	uint16_t a;
391 	/** If non-zero, indicates that the #r value is invalid. */
392 	uint8_t r_invalid : 1;
393 	/** If non-zero, indicates that the #g value is invalid. */
394 	uint8_t g_invalid : 1;
395 	/** If non-zero, indicates that the #b value is invalid. */
396 	uint8_t b_invalid : 1;
397 	/** If non-zero, indicates that the #a value is invalid. */
398 	uint8_t a_invalid : 1;
399 	/** The bit-depth of color samples (typically 10, 12, or 16). */
400 	uint8_t bit_depth;
401 };
402 
403 /**
404  * @brief Data representing a single CIE 1960 CCT, Duv value pair.
405  */
406 struct zsl_clr_cct {
407 	/** @brief Correlated color temperature.
408 	 *
409 	 *  Indicates the color temperature that yields the minimum Euclidean
410 	 *  distance between u1,v1 and the Planckian chromaticity 'up, vp' of
411 	 *  the color temperature.
412 	 */
413 	zsl_real_t cct;
414 	/** @brief Distance of the measured chromaticity from the Planckian
415 	 *  locus (AKA black body curve).
416 	 *
417 	 *  A negative Duv indicates that the measured chromaticity is below
418 	 *  the Planckian locus (in the magenta and pink color range). A
419 	 *  positive Duv indicates a point above the locus (in the green or
420 	 *  yellow color range). */
421 	zsl_real_t duv;
422 	/** If non-zero, indicates that #cct is invalid. */
423 	uint8_t cct_invalid : 1;
424 	/** If non-zero, indicates that #duv is invalid. */
425 	uint8_t duv_invalid : 1;
426 };
427 
428 /**
429  * @brief CIE 1931 XYZ tristimulus values for a standard illuminant.
430  */
431 struct zsl_clr_illum_data {
432 	/** The CIE standard illuminant reference identifier. */
433 	enum zsl_clr_illum illuminant;
434 	/** The CIE standard observer model used. */
435 	enum zsl_clr_obs observer;
436 	/** Display name string for the illuminant. */
437 	char *name;
438 	/** The illuminant's XYZ tristimulus values. */
439 	struct {
440 		/** The CIE XYZ tristimulus X value. */
441 		zsl_real_t xyz_x;
442 		/** The CIE XYZ tristimulus Y value. */
443 		zsl_real_t xyz_y;
444 		/** The CIE XYZ tristimulus Z value. */
445 		zsl_real_t xyz_z;
446 	} data;
447 };
448 
449 /**
450  * @brief CIE 1931 XYZ tristimulus values for a standard observer model in
451  * 5 nm steps from 360-830 nm (95 steps).
452  */
453 struct zsl_clr_obs_data {
454 	/** The CIE standard observer model identifier. */
455 	enum zsl_clr_obs observer;
456 	/** Display name string for the standard observer model. */
457 	char *name;
458 	/**
459 	 * The observer model's XYZ tristimulus values in 5 nm increments
460 	 * from 360..830 nm (95 values).
461 	 */
462 	struct {
463 		/** The CIE XYZ tristimulus X value. */
464 		zsl_real_t xyz_x;
465 		/** The CIE XYZ tristimulus Y value. */
466 		zsl_real_t xyz_y;
467 		/** The CIE XYZ tristimulus Z value. */
468 		zsl_real_t xyz_z;
469 	} data[95];
470 };
471 
472 /**
473  * @brief Spectral power distribution for a specific illumination.
474  *
475  * This struct contains the illuminant power at given wavelength intervals.
476  *
477  * @b Example
478  *
479  * The following code defines a zsl_clr_spd instance for an illumnation
480  * that was captured on a spectrograph in 20 nm intervals between 380 and
481  * 780 nm, for a total of 21 data samples.
482  *
483  * CCT was calculated as 5983.00 K and 0.0033 Duv, with an output CIE 1931 XYZ
484  * tristimulus of X: 0.9516409, Y: 1.0000000, Z: 1.0059365.
485  *
486  * @code
487  * const struct zsl_clr_spd zsl_clr_test_spd_5983k = {
488  *     .size = 21,
489  *     .comps = {
490  *         { .nm = 380, .value = 0.290 },
491  *         { .nm = 400, .value = 0.471 },
492  *         { .nm = 420, .value = 0.719 },
493  *         { .nm = 440, .value = 0.826 },
494  *         { .nm = 460, .value = 1.006 },
495  *         { .nm = 480, .value = 0.989 },
496  *         { .nm = 500, .value = 0.955 },
497  *         { .nm = 520, .value = 0.910 },
498  *         { .nm = 540, .value = 0.950 },
499  *         { .nm = 560, .value = 0.912 },
500  *         { .nm = 580, .value = 0.848 },
501  *         { .nm = 600, .value = 0.814 },
502  *         { .nm = 620, .value = 0.827 },
503  *         { .nm = 640, .value = 0.771 },
504  *         { .nm = 660, .value = 0.749 },
505  *         { .nm = 680, .value = 0.766 },
506  *         { .nm = 700, .value = 0.705 },
507  *         { .nm = 720, .value = 0.599 },
508  *         { .nm = 740, .value = 0.850 },
509  *         { .nm = 760, .value = 0.699 },
510  *         { .nm = 780, .value = 0.898 }
511  *     }
512  * };
513  * @endcode
514  */
515 struct zsl_clr_spd {
516 	/** The number of elements in the component array. */
517 	size_t size;
518 	struct {
519 		/** The wavelength in nm for this specific sample. */
520 		unsigned int nm;
521 		/** The relative value of this specific sample. */
522 		zsl_real_t value;
523 	} comps[];  /**< The spectral component data that makes up the spd. */
524 };
525 
526 /** @} */ /* End of STRUCT group */
527 
528 /**
529  * @addtogroup CONV Conversion Functions
530  *
531  * Helper functions to convert between color systems and coordinates.
532  *
533  * @ingroup COLORIMETRY
534  *  @{ */
535 
536 /**
537  * @brief Converts the supplied spectral power distribution data into it's
538  * equivalent XYZ tristimulus using the specified standard observer model.
539  *
540  * @param spd   Pointer to the spectral power distribution data to use.
541  * @param obs   The CIE standard observer model to use for the conversion.
542  * @param xyz   Pointer to the placeholder for the output XYZ tristimulus.
543  *
544  * @returns 0 on normal execution, otherwise an appropriate error code.
545  */
546 int zsl_clr_conv_spd_xyz(const struct zsl_clr_spd *spd, enum zsl_clr_obs obs,
547 			 struct zsl_clr_xyz *xyz);
548 
549 /**
550  * @brief Converts a CIE 1931 xyY chromaticity to its XYZ tristimulus
551  *        equivalent.
552  *
553  * @param xyy		Pointer to the input xyY triplet.
554  * @param xyz       Pointer to the output XYZ triplet.
555  *
556  * @return 0 on success, error code on failure.
557  */
558 int zsl_clr_conv_xyy_xyz(struct zsl_clr_xyy *xyy, struct zsl_clr_xyz *xyz);
559 
560 /**
561  * @brief Converts CIE 1931 XYZ tristimulus values to the xyY chromaticity
562  *        equivalent.
563  *
564  * @param xyz       Pointer to the input XYZ triplet.
565  * @param xyy		Pointer to the output xyY triplet.
566  *
567  * @return 0 on success, error code on failure.
568  */
569 int zsl_clr_conv_xyz_xyy(struct zsl_clr_xyz *xyz, struct zsl_clr_xyy *xyy);
570 
571 /**
572  * @brief Converts a CIE 1931 xyY chromaticity to its CIE 1960 uv equivalent.
573  *
574  * @param xyy       Pointer to the input xyY triplet.
575  * @param uv        Pointer to the output CIE 1960 u,v pair.
576  *
577  * @return 0 on success, error code on failure.
578  */
579 int zsl_clr_conv_xyy_uv60(struct zsl_clr_xyy *xyy, struct zsl_clr_uv60 *uv);
580 
581 /**
582  * @brief Converts CIE 1931 XYZ tristimulus values to its CIE 1960 uv
583  *        equivalent.
584  *
585  * @param xyz       Pointer to the input zsl_clr_xyz triplet.
586  * @param uv        Pointer to the output CIE 1960 u,v pair.
587  *
588  * @return 0 on success, error code on failure.
589  */
590 int zsl_clr_conv_xyz_uv60(struct zsl_clr_xyz *xyz, struct zsl_clr_uv60 *uv);
591 
592 /**
593  * @brief Converts a CIE 1960 uv value to its CIE 1931 XYZ tristimulus
594  *        equivalent.
595  *
596  * @param uv        Pointer to the input CIE 1960 u,v pair.
597  * @param xyz       Pointer to the output XYZ tristimulus.
598  *
599  * @return 0 on success, error code on failure.
600  */
601 int zsl_clr_conv_uv60_xyz(struct zsl_clr_uv60 *uv, struct zsl_clr_xyz *xyz);
602 
603 /**
604  * @brief Converts a CIE 1960 uv value to its CIE 1931 xyY chromaticity
605  *        equivalent.
606  *
607  * @param uv        Pointer to the input CIE 1960 u,v pair.
608  * @param xyy       Pointer to the output xyY triplet.
609  *
610  * @return 0 on success, error code on failure.
611  */
612 int zsl_clr_conv_uv60_xyy(struct zsl_clr_uv60 *uv, struct zsl_clr_xyy *xyy);
613 
614 /**
615  * @brief Converts a CIE 1960 uv value to its CIE 1976 u'v' equivalent.
616  *
617  * @param uv60	Pointer to the input CIE 1960 u,v pair.
618  * @param uv76  Pointer to the input CIE 1976 u',v' pair.
619  *
620  * @return 0 on success, error code on failure.
621  */
622 int zsl_clr_conv_uv60_uv76(struct zsl_clr_uv60 *uv60,
623 			   struct zsl_clr_uv76 *uv76);
624 
625 /**
626  * @brief Converts a CIE 1976 u'v' value to its CIE 1960 uv equivalent.
627  *
628  * @param uv76  Pointer to the input CIE 1976 u',v' pair.
629  * @param uv60	Pointer to the input CIE 1960 u,v pair.
630  *
631  * @return 0 on success, error code on failure.
632  */
633 int zsl_clr_conv_uv76_uv60(struct zsl_clr_uv76 *uv76,
634 			   struct zsl_clr_uv60 *uv60);
635 
636 /**
637  * Convert the specified color temperature to a (u,v) chromaticity.
638  *
639  * @param ct    The color temperature to use.
640  * @param obs   The CIE standard observer model to use for the conversion.
641  * @param uv    Pointer to the output (u,v) chromaticity.
642  *
643  * @return 0 on success, error code on failure.
644  */
645 int zsl_clr_conv_ct_uv60(zsl_real_t ct, enum zsl_clr_obs obs,
646 			 struct zsl_clr_uv60 *uv);
647 
648 /**
649  * @brief Converts an exact CIE 1960 CCT (Duv = 0.0) to a CIE 1931 XYZ
650  *        tristimulus.
651  *
652  * @param ct    The color temperature to use.
653  * @param obs   The CIE standard observer model to use for the conversion.
654  * @param xyz   Pointer to the output CIE 1931 XYZ tristimulus.
655  *
656  * @return 0 on success, error code on failure.
657  */
658 int zsl_clr_conv_ct_xyz(zsl_real_t ct, enum zsl_clr_obs obs,
659 			struct zsl_clr_xyz *xyz);
660 
661 /**
662  * @brief Converts an exact CIE 1960 CCT (Duv = 0.0) to an 8-bit RGBA value
663  *        using the supplied XYZ to RGB color space correlation matrix.
664  *
665  * @param ct    The color temperature to use.
666  * @param obs   The CIE standard observer model to use for the conversion.
667  * @param mtx   Pointer to the 3x3 XYZ to RGB color space correlation matrix.
668  * @param rgb   Pointer to the output zsl_clr_rgb8 value.
669  *
670  * @return 0 on success, error code on failure.
671  */
672 int zsl_clr_conv_ct_rgb8(zsl_real_t ct, enum zsl_clr_obs obs,
673 			 struct zsl_mtx *mtx, struct zsl_clr_rgb8 *rgb);
674 
675 /**
676  * @brief Converts an exact CIE 1960 CCT (Duv = 0.0) to an floating point RGBA
677  *        value using the supplied XYZ to RGB color space correlation matrix.
678  *
679  * @param ct    The color temperature to use.
680  * @param obs   The CIE standard observer model to use for the conversion.
681  * @param mtx   Pointer to the 3x3 XYZ to RGB color space correlation matrix.
682  * @param rgb   Pointer to the output zsl_clr_rgbf value.
683  *
684  * @return 0 on success, error code on failure.
685  */
686 int zsl_clr_conv_ct_rgbf(zsl_real_t ct, enum zsl_clr_obs obs,
687 			 struct zsl_mtx *mtx, struct zsl_clr_rgbf *rgb);
688 
689 /**
690  * @brief Converts a CIE 1960 CCT and Duv pair to a CIE 1931 xyY chromaticity.
691  *
692  * @param cct   Pointer to CIE 1960 correlated color temperature and Duv.
693  * @param obs   The CIE standard observer model to use for the conversion.
694  * @param xyy   Pointer to the output CIE 1931 xyY chromaticity.
695  *
696  * @return 0 on success, error code on failure.
697  */
698 int zsl_clr_conv_cct_xyy(struct zsl_clr_cct *cct, enum zsl_clr_obs obs,
699 			 struct zsl_clr_xyy *xyy);
700 
701 /**
702  * @brief Converts a CIE 1960 CCT and Duv pair to a CIE 1931 XYZ tristimulus.
703  *
704  * @param cct   Pointer to CIE 1960 correlated color temperature and Duv.
705  * @param obs   The CIE standard observer model to use for the conversion.
706  * @param xyz   Pointer to the output CIE 1931 XYZ tristimulus.
707  *
708  * @return 0 on success, error code on failure.
709  */
710 int zsl_clr_conv_cct_xyz(struct zsl_clr_cct *cct, enum zsl_clr_obs obs,
711 			 struct zsl_clr_xyz *xyz);
712 
713 /**
714  * @brief Converts a CIE 1960 (u, v) pair to a CIE 1960 CCT and Duv
715  *        pair using the specified conversion algorithm.
716  *
717  * @param method    The algoorithm to use for the conversion.
718  * @param uv        Pointer to input CIE 1960 (u, v) pair.
719  * @param cct       Pointer to output zsl_clr_cct.
720  *
721  * @return 0 on success, error code on failure.
722  */
723 int zsl_clr_conv_uv60_cct(enum zsl_clr_uv_cct_method method,
724 			  struct zsl_clr_uv60 *uv, struct zsl_clr_cct *cct);
725 
726 /**
727  * @brief Converts a CIE 1931 XYZ tristimulus to an 8-bit RGBA value
728  *        using the supplied XYZ to RGB color space correlation matrix.
729  *
730  * @param xyz   The input CIE 1931 XYZ tristimulus value to convert to RGB.
731  * @param mtx   Pointer to the 3x3 XYZ to RGB color space correlation matrix.
732  * @param rgb   Pointer to the output zsl_clr_rgb8 value.
733  *
734  * @return 0 on success, error code on failure.
735  */
736 int zsl_clr_conv_xyz_rgb8(struct zsl_clr_xyz *xyz, struct zsl_mtx *mtx,
737 			  struct zsl_clr_rgb8 *rgb);
738 
739 /**
740  * @brief Converts a CIE 1931 XYZ tristimulus to an floating point RGBA value
741  *        using the supplied XYZ to RGB color space correlation matrix.
742  *
743  * Depending on the value of CONFIG_ZSL_CLR_RGBF_BOUND_CAP, the output values
744  * may be outside of the 0.0..1.0 range if the resulting value is out of
745  * gamut for the specified RGB color space.
746  *
747  * @param xyz   The input CIE 1931 XYZ tristimulus value to convert to RGB.
748  * @param mtx   Pointer to the 3x3 XYZ to RGB color space correlation matrix.
749  * @param rgb   Pointer to the output zsl_clr_rgbf value.
750  *
751  * @return 0 on success, error code on failure.
752  */
753 int zsl_clr_conv_xyz_rgbf(struct zsl_clr_xyz *xyz, struct zsl_mtx *mtx,
754 			  struct zsl_clr_rgbf *rgb);
755 
756 /** @} */ /* End of CONV group */
757 
758 /**
759  * @addtogroup NORM Normalisation Functions
760  *
761  * Helper functions to normalise data sets.
762  *
763  * @ingroup COLORIMETRY
764  *  @{ */
765 
766 /**
767  * @brief Normalises the supplied spectral power distribution data to a
768  * 1.0 range. This function call is destructive to the input zsl_clr_spd data.
769  *
770  * @param spd   Pointer to the spectral power distribution data to normalise.
771  *
772  * @returns 0 on normal execution, otherwise an appropriate error code.
773  */
774 int zsl_clr_norm_spd(struct zsl_clr_spd *spd);
775 
776 /** @} */ /* End of NORM group */
777 
778 /**
779  * @addtogroup COLOR_DATA Data Access Functions
780  *
781  * Function to access various colorimetry datasets.
782  *
783  * @ingroup COLORIMETRY
784  *  @{ */
785 
786 /**
787  * @brief   Retrieves a pointer to the zsl_clr_illum_data for the specified
788  *          illuminant.
789  *
790  * @param obs   The standard observer associated with this #illum.
791  * @param illum The illuminant whose data should be retrieved.
792  * @param data  Pointer to the pointer where the const zsl_clr_illum_data
793  *              should be made accessible.
794  *
795  * @returns 0 on normal execution, otherwise an appropriate error code.
796  *
797  * @b Example
798  *
799  * The following example shows how to use the pointer to a pointer
800  * mechnaism to access illuminant A data in an resource efficient manner.
801  *
802  * @code
803  * void
804  * get_illum(void)
805  * {
806  *     int rc;
807  *     const struct zsl_clr_illum_data *illum;
808  *
809  *     rc = zsl_clr_illum_get(ZSL_CLR_OBS_2_DEG, ZSL_CLR_ILLUM_A, &illum);
810  *     if (rc) {
811  *             // No matching illuminant found!
812  *             return;
813  *     }
814  *
815  *     printf("Illum %s - x = %f\n", illum->name, illum->data.xyz_z);
816  * }
817  *
818  * @endcode
819  */
820 int zsl_clr_illum_get(enum zsl_clr_obs obs, enum zsl_clr_illum illum,
821 		      const struct zsl_clr_illum_data **data);
822 
823 /**
824  * @brief   Retrieves a pointer to the zsl_clr_obs_data for the specified
825  *          CIE standard observer model.
826  *
827  * @param obs   The standard observer whose data should be retrieved.
828  * @param data  Pointer to the pointer where the const zsl_clr_obs_data should
829  *              be made accessible.
830  *
831  * @returns 0 on normal execution, otherwise an appropriate error code.
832  *
833  * @b Example
834  *
835  * The following example shows how to use the pointer to a pointer
836  * mechnaism to access standard 2 degree observer data in an resource
837  * efficient manner.
838  *
839  * @code
840  * void
841  * get_stdobs(void)
842  * {
843  *     const struct zsl_clr_obs_data *obs;
844  *
845  *     zsl_clr_obs_get(ZSL_CLR_OBS_2DEG, &obs);
846  *     printf("obs: %s\n", obs->name);
847  * }
848  * @endcode
849  */
850 void zsl_clr_obs_get(enum zsl_clr_obs obs,
851 		     const struct zsl_clr_obs_data **data);
852 
853 /**
854  * @brief   Retrieves a pointer to the zsl_clr_spd data for the specified
855  *          CIE luminous efficiency function.
856  *
857  * @param lef   The luminous efficiency func. whose data should be retrieved.
858  * @param data  Pointer to the pointer where the const zsl_clr_spd data should
859  *              be made accessible.
860  */
861 void zsl_clr_lef_get(enum zsl_clr_lef lef, const struct zsl_clr_spd **data);
862 
863 /**
864  * @brief   Interpolates a single value from the specified CIE luminous
865  *          efficiency function using linear interpolation.
866  *
867  * @param lef   The luminous efficiency function to use.
868  * @param nm    The wavelength to interpolate.
869  * @param val   Pointer to the interpolated value's placeholder.
870  *
871  * @returns 0 on normal execution, otherwise an appropriate error code.
872  */
873 int zsl_clr_lef_lerp(enum zsl_clr_lef lef, unsigned int nm, zsl_real_t *val);
874 
875 /**
876  * @brief   Retrieves a pointer to a standard 3x3 XYZ to RGB color space
877  *          correlation matrix.
878  *
879  * @param ccm   The XYZ to RGB color space correlation matrix to retrieve.
880  * @param mtx   Pointer to the pointer where the const zsl_mtx data should
881  *              be made accessible.
882  *
883  * @returns 0 on normal execution, otherwise an appropriate error code.
884  */
885 void zsl_clr_rgbccm_get(enum zsl_clr_rgb_ccm ccm, struct zsl_mtx **mtx);
886 
887 /** @} */ /* End of COLOR_DATA group */
888 
889 #ifdef __cplusplus
890 }
891 #endif
892 
893 #endif /* ZEPHYR_INCLUDE_ZSL_COLORIMETRY_H_ */
894 
895 /** @} */ /* End of colorimetry group */
896