aboutsummaryrefslogtreecommitdiffstats
path: root/src/libclut.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/libclut.h')
-rw-r--r--src/libclut.h570
1 files changed, 558 insertions, 12 deletions
diff --git a/src/libclut.h b/src/libclut.h
index 9bc1876..e1601f1 100644
--- a/src/libclut.h
+++ b/src/libclut.h
@@ -224,6 +224,38 @@
/**
* Initialiser for `struct libclut_rgb_colour_space` with the values
+ * of the ITU-R Recommendation BT.709 (ITU-R BT.709) colour space.
+ *
+ * This gamma colour space's gamma is 2.4. It cannot be used with
+ * RGB colour space conversion unless the values are tranlated into
+ * using the sRGB gamma function.
+ */
+#define LIBCLUT_RGB_COLOUR_SPACE_ITU_R_BT_709_INITIALISER \
+ { \
+ .red_x = 0.6400, .red_y = 0.3300, .red_Y = 0.212656, \
+ .green_x = 0.3000, .green_y = 0.6000, .green_Y = 0.715158, \
+ .blue_x = 0.1500, .blue_y = 0.0600, .blue_Y = 0.072186, \
+ LIBCLUT_ILLUMINANT_D65 \
+ }
+
+/**
+ * Initialiser for `struct libclut_rgb_colour_space` with the values
+ * of the Lightroom RGB colour space.
+ *
+ * This gamma colour space's gamma is 1.0. It cannot be used with
+ * RGB colour space conversion unless the values are tranlated into
+ * using the sRGB gamma function.
+ */
+#define LIBCLUT_RGB_COLOUR_SPACE_LIGHTROOM_RGB_INITIALISER \
+ { \
+ .red_x = 0.7347, .red_y = 0.2653, .red_Y = 0.288040, \
+ .green_x = 0.1596, .green_y = 0.8404, .green_Y = 0.711874, \
+ .blue_x = 0.0366, .blue_y = 0.0001, .blue_Y = 0.000086, \
+ LIBCLUT_ILLUMINANT_D50 \
+ }
+
+/**
+ * Initialiser for `struct libclut_rgb_colour_space` with the values
* of the NTSC RGB colour space.
*
* This gamma colour space's gamma is 2.2. It cannot be used with
@@ -302,6 +334,18 @@
LIBCLUT_ILLUMINANT_D50 \
}
+/*
+ * name gamma xw yw xr yr xg yg xb yb
+ * ITU-R Recommendation BT.2020 (ITU-R BT.2020) *1 { D65 } 0.708 0.292 0.170 0.797 0.131 0.046
+ * ITU-R Recommendation BT.2100 (ITU-R BT.2100) *2 { D65 } 0.708 0.292 0.170 0.797 0.131 0.046
+ * DCI-P3 D65 ? { D65 } 0.680 0.320 0.265 0.690 0.150 0.060
+ * DCI-P3 Theater ? 0.314 0.351 0.680 0.320 0.265 0.690 0.150 0.060
+ * https://en.wikipedia.org/wiki/Rec._601
+ *
+ * *1 https://en.wikipedia.org/wiki/Rec._2020#Transfer_characteristics
+ * *2 http://www.itu.int/dms_pubrec/itu-r/rec/bt/R-REC-BT.2100-0-201607-I!!PDF-E.pdf
+ */
+
/**
@@ -371,6 +415,7 @@ typedef struct libclut_rgb_colour_space
} libclut_rgb_colour_space_t;
+
/**
* Matrix date-type for colour space conversion.
*/
@@ -519,7 +564,7 @@ static inline int libclut_0__(double x) { return libclut_eq__(x, 0); }
/**
- * Convert the curves from formatted in standard RGB to linear RGB.
+ * Convert the curves from formatted in standard RGB to linear sRGB.
*
* None of the parameter may have side-effects.
*
@@ -551,7 +596,7 @@ static inline int libclut_0__(double x) { return libclut_eq__(x, 0); }
/**
- * Convert the curves from formatted in linear RGB to standard RGB.
+ * Convert the curves from formatted in linear sRGB to standard RGB.
*
* None of the parameter may have side-effects.
*
@@ -1651,13 +1696,13 @@ static inline int libclut_0__(double x) { return libclut_eq__(x, 0); }
/**
- * Convert one component from [0, 1] linear RGB to [0, 1] sRGB.
+ * Convert one component from [0, 1] linear sRGB to [0, 1] sRGB.
*
* If the macro variant is used, the argument must not have
* any side-effects. The macro variant requires linking with
* '-lm'.
*
- * @param c The linear RGB value.
+ * @param c The linear sRGB value.
* @return Corresponding sRGB value.
*/
LIBCLUT_GCC_ONLY__(__attribute__((__const__, __leaf__)))
@@ -1667,7 +1712,7 @@ double (libclut_model_linear_to_standard1)(double);
/**
- * Convert [0, 1] linear RGB to [0, 1] sRGB.
+ * Convert [0, 1] linear sRGB to [0, 1] sRGB.
*
* The macro variant requires linking with '-lm',
* if the 'libclut_model_linear_to_standard1' is defined,
@@ -1693,14 +1738,14 @@ void (libclut_model_linear_to_standard)(double*, double*, double*);
/**
- * Convert one component from [0, 1] sRGB to [0, 1] linear RGB.
+ * Convert one component from [0, 1] sRGB to [0, 1] linear sRGB.
*
* If the macro variant is used, the argument must not have
* any side-effects. The macro variant requires linking with
* '-lm'.
*
* @param c The sRGB value.
- * @return Corresponding linear RGB value.
+ * @return Corresponding linear sRGB value.
*/
LIBCLUT_GCC_ONLY__(__attribute__((__const__, __leaf__)))
double (libclut_model_standard_to_linear1)(double);
@@ -1709,7 +1754,7 @@ double (libclut_model_standard_to_linear1)(double);
/**
- * Convert [0, 1] sRGB to [0, 1] linear RGB.
+ * Convert [0, 1] sRGB to [0, 1] linear sRGB.
*
* The macro variant requires linking with '-lm',
* if the 'libclut_model_standard_to_linear1' is defined,
@@ -1780,7 +1825,7 @@ void (libclut_model_ciexyz_to_ciexyy)(double, double, double, double*, double*);
/**
- * Convert CIE XYZ to [0, 1] linear RGB.
+ * Convert CIE XYZ to [0, 1] linear sRGB.
*
* @param X The X parameter.
* @param Y The Y parameter.
@@ -1803,7 +1848,7 @@ void (libclut_model_ciexyz_to_linear)(double, double, double, double*, double*,
/**
- * Convert [0, 1] linear RGB to CIE XYZ.
+ * Convert [0, 1] linear sRGB to CIE XYZ.
*
* @param r The red component.
* @param g The green component.
@@ -1826,7 +1871,7 @@ void (libclut_model_linear_to_ciexyz)(double, double, double, double*, double*,
/**
- * Convert [0, 1] linear RGB to CIE xyY.
+ * Convert [0, 1] linear sRGB to CIE xyY.
*
* The macro variant requires linking with '-lclut'
* if any of `libclut_model_ciexyz_to_ciexyy`,
@@ -1950,6 +1995,507 @@ void (libclut_model_cielab_to_ciexyz)(double, double, double, double*, double*,
/**
+ * Convert from CIE XYZ to CIELUV.
+ *
+ * Requires linking with `-lm`.
+ *
+ * @param X The X component.
+ * @param Y The Y component.
+ * @param Z The Z component.
+ * @param Xn The X component of the specified white object (white point).
+ * @param Yn The Y component of the specified white object (white point).
+ * @param Zn The Z component of the specified white object (white point).
+ * @param L Output parameter for the L* parameter.
+ * @param u Output parameter for the u* parameter.
+ * @param v Output parameter for the v* parameter.
+ */
+LIBCLUT_GCC_ONLY__(__attribute__((__leaf__)))
+void (libclut_model_ciexyz_to_cieluv)(double, double, double, double, double,
+ double, double*, double*, double*);
+#define libclut_model_ciexyz_to_cieluv(X, Y, Z, Xn, Yn, Zn, L, u, v) \
+ do \
+ { \
+ double x__ = (Xn), y__ = (Yn); \
+ double t__ = x__ + 15 * y__ + 3 * (Zn); \
+ double u__ = 4 * x__ / t__; \
+ double v__ = 9 * y__ / t__; \
+ x__ = (X), y__ = (Y); \
+ t__ = x__ + 15 * y__ + 3 * (Z); \
+ u__ = 4 * x__ / t__ - u__; \
+ v__ = 9 * y__ / t__ - v__; \
+ y__ = (Y) / y__; \
+ if (y__ * 24389 <= (double)216) \
+ y__ *= 24389, y__ /= 27; \
+ else \
+ y__ = cbrt(y__) * 116 - 16; \
+ *(L) = y__; \
+ y__ *= 13; \
+ *(u) = y__ * u__; \
+ *(v) = y__ * v__; \
+ } \
+ while (0)
+
+
+/**
+ * Convert from CIELUV to CIE XYZ.
+ *
+ * @param L The L* component.
+ * @param u The u* component.
+ * @param v The v* component.
+ * @param Xn The X component of the specified white object (white point).
+ * @param Yn The Y component of the specified white object (white point).
+ * @param Zn The Z component of the specified white object (white point).
+ * @param X Output parameter for the X parameter.
+ * @param Y Output parameter for the Y parameter.
+ * @param Z Output parameter for the Z parameter.
+ */
+LIBCLUT_GCC_ONLY__(__attribute__((__leaf__)))
+void (libclut_model_cieluv_to_ciexyz)(double, double, double, double, double,
+ double, double*, double*, double*);
+#define libclut_model_cieluv_to_ciexyz(L, u, v, Xn, Yn, Zn, X, Y, Z) \
+ do \
+ { \
+ double x__ = (Xn), y__ = (Yn), l__ = (L), l13__ = l__ * 13; \
+ double t__ = x__ + 15 * y__ + 3 * (Zn); \
+ double u__ = 4 * x__ / t__; \
+ double v__ = 9 * y__ / t__; \
+ u__ = (u) / l13__ + u__; \
+ v__ = (v) / l13__ + v__; \
+ if (l__ <= (double)8) \
+ y__ *= l__ * 27 / 24389; \
+ else \
+ { \
+ l__ += 16, l__ /= 116; \
+ y__ *= l__ *= l__ * l__; \
+ } \
+ *(Y) = y__; \
+ *(X) = y__ * 9 * u__ / (4 * v__); \
+ *(Z) = y__ * (12 - 3 * u__ - 20 * v__) / (4 * v__); \
+ } \
+ while (0)
+
+
+/**
+ * Convert from CIELCh to CIE L*u*v*.
+ *
+ * Requires linking with `-lm`.
+ *
+ * @param C The C*_uv component.
+ * @param h The h_uv component.
+ * @param u Output parameter for the u* parameter.
+ * @param v Output parameter for the v* parameter.
+ */
+LIBCLUT_GCC_ONLY__(__attribute__((__leaf__)))
+void (libclut_model_cielch_to_cieluv)(double, double, double*, double*);
+#define libclut_model_cielch_to_cieluv(C, h, u, v) \
+ do \
+ { \
+ double h__ = (h), C__ = (C); \
+ *(u) = sin(h__) * C__; \
+ *(v) = cos(h__) * C__; \
+ } \
+ while (0)
+
+
+/**
+ * Convert from CIE L*u*v* to CIELCh.
+ *
+ * Requires linking with `-lm`.
+ *
+ * @param u The u* component.
+ * @param v The v* component.
+ * @param C Output parameter for the C*_uv parameter.
+ * @param h Output parameter for the h_uv parameter.
+ */
+LIBCLUT_GCC_ONLY__(__attribute__((__leaf__)))
+void (libclut_model_cieluv_to_cielch)(double, double, double*, double*);
+#define libclut_model_cieluv_to_cielch(u, v, C, h) \
+ do \
+ { \
+ double u__ = (u), v__ = (v__); \
+ *(C) = sqrt(u__ * u__ + v__ * v__); \
+ *(h) = atan2(u__, v__); \
+ } \
+ while (0)
+
+
+/**
+ * Convert from sRGB to YIQ.
+ *
+ * Requires linking with '-lclut', or '-lm' if
+ * `libclut_model_standard_to_linear1` is not undefined.
+ *
+ * @param r The R component.
+ * @param g The G component.
+ * @param b The B component.
+ * @param y Output parameter for the Y parameter.
+ * @param i Output parameter for the I parameter.
+ * @param q Output parameter for the Q parameter.
+ */
+LIBCLUT_GCC_ONLY__(__attribute__((__leaf__)))
+void (libclut_model_srgb_to_yiq)(double, double, double, double*, double*, double*);
+#define libclut_model_srgb_to_yiq(r, g, b, y, i, q) \
+ do \
+ { \
+ double r__ = libclut_model_standard_to_linear1(r); \
+ double g__ = libclut_model_standard_to_linear1(g); \
+ double b__ = libclut_model_standard_to_linear1(b); \
+ *(y) = r__ * 299 / 1000 + g__ * 587 / 1000 + b__ * 114 / 1000; \
+ *(i) = r__ * 596 / 1000 - g__ * 247 / 1000 - b__ * 322 / 1000; \
+ *(q) = r__ * 211 / 1000 - g__ * 523 / 1000 + b__ * 312 / 1000; \
+ } \
+ while (0)
+
+
+/**
+ * Convert from YIQ to sRGB.
+ *
+ * Requires linking with '-lclut', or '-lm' if
+ * `libclut_model_linear_to_standard1` is not undefined.
+ *
+ * @param y The Y component.
+ * @param i The I component.
+ * @param q The Q component.
+ * @param r Output parameter for the R parameter.
+ * @param g Output parameter for the G parameter.
+ * @param b Output parameter for the B parameter.
+ */
+LIBCLUT_GCC_ONLY__(__attribute__((__leaf__)))
+void (libclut_model_yiq_to_srgb)(double, double, double, double*, double*, double*);
+#define libclut_model_yiq_to_srgb(y, i, q, r, g, b) \
+ do \
+ { \
+ double y__ = (y), i__ = (i), q__ = (q), r__, g__, b__; \
+ r__ = y__ + i__ * 596 / 1000 + q__ * 621 / 1000; \
+ g__ = y__ - i__ * 272 / 1000 - q__ * 647 / 1000; \
+ b__ = y__ - i__ * 1106 / 1000 + q__ * 1703 / 1000; \
+ *(r) = libclut_model_linear_to_standard1(r__); \
+ *(g) = libclut_model_linear_to_standard1(g__); \
+ *(b) = libclut_model_linear_to_standard1(b__); \
+ } \
+ while (0)
+
+
+/**
+ * Convert from sRGB to YDbDr.
+ *
+ * Requires linking with '-lclut', or '-lm' if
+ * `libclut_model_standard_to_linear1` is not undefined.
+ *
+ * @param r The R component.
+ * @param g The G component.
+ * @param b The B component.
+ * @param y Output parameter for the Y parameter.
+ * @param db Output parameter for the Db parameter.
+ * @param dr Output parameter for the Dr parameter.
+ */
+LIBCLUT_GCC_ONLY__(__attribute__((__leaf__)))
+void (libclut_model_srgb_to_ydbdr)(double, double, double, double*, double*, double*);
+#define libclut_model_srgb_to_ydbdr(r, g, b, y, db, dr) \
+ do \
+ { \
+ double r__ = libclut_model_standard_to_linear1(r); \
+ double g__ = libclut_model_standard_to_linear1(g); \
+ double b__ = libclut_model_standard_to_linear1(b); \
+ *(y) = r__ * 299 / 1000 + g__ * 587 / 1000 + b__ * 114 / 1000; \
+ *(db) = -r__ * 450 / 1000 - g__ * 883 / 1000 + b__ * 1333 / 1000; \
+ *(dr) = -r__ * 1333 / 1000 + g__ * 1116 / 1000 + b__ * 217 / 1000; \
+ } \
+ while (0)
+
+
+/**
+ * Convert from YDbDr to sRGB.
+ *
+ * Requires linking with '-lclut', or '-lm' if
+ * `libclut_model_linear_to_standard1` is not undefined.
+ *
+ * @param y The Y component.
+ * @param db The Db component.
+ * @param dr The Dr component.
+ * @param r Output parameter for the R parameter.
+ * @param g Output parameter for the G parameter.
+ * @param b Output parameter for the B parameter.
+ */
+LIBCLUT_GCC_ONLY__(__attribute__((__leaf__)))
+void (libclut_model_ydbdr_to_srgb)(double, double, double, double*, double*, double*);
+#define libclut_model_ydbdr_to_srgb(y, db, dr, r, g, b) \
+ do \
+ { \
+ double y__ = (y), db__ = (db), dr__ = (dr), r__, g__, b__; \
+ db__ /= 1000000000000000ULL; \
+ dr__ /= 1000000000000000ULL; \
+ r__ = y__ + db__ * 92303716148ULL - dr__ * 525912630661865ULL; \
+ g__ = y__ - db__ * 129132898890509ULL + dr__ * 267899328207599ULL; \
+ b__ = y__ + db__ * 664679059978955ULL - dr__ * 79202543533ULL; \
+ *(r) = libclut_model_linear_to_standard1(r__); \
+ *(g) = libclut_model_linear_to_standard1(g__); \
+ *(b) = libclut_model_linear_to_standard1(b__); \
+ } \
+ while (0)
+
+
+/**
+ * Convert from YUV to YDbDr.
+ *
+ * @param u The U component.
+ * @param v The V component.
+ * @param db Output parameter for the Db parameter.
+ * @param dr Output parameter for the Dr parameter.
+ */
+LIBCLUT_GCC_ONLY__(__attribute__((__leaf__)))
+void (libclut_model_yuv_to_ydbdr)(double, double, double*, double*);
+#define libclut_model_yuv_to_ydbdr(u, v, db, dr) \
+ do \
+ { \
+ *(db) = 3069 * (u) / 1000; \
+ *(dr) = -2169 * (v) / 1000; \
+ } \
+ while (0)
+
+
+/**
+ * Convert from YDbDr to YUV.
+ *
+ * @param db The Db component.
+ * @param dr The Dr component.
+ * @param u Output parameter for the U parameter.
+ * @param v Output parameter for the V parameter.
+ */
+LIBCLUT_GCC_ONLY__(__attribute__((__leaf__)))
+void (libclut_model_ydbdr_to_yuv)(double, double, double*, double*);
+#define libclut_model_ydbdr_to_yuv(db, dr, u, v) \
+ do \
+ { \
+ *(u) = (db) * 1000 / 3069; \
+ *(v) = (dr) * 1000 / -2169; \
+ } \
+ while (0)
+
+
+/**
+ * Convert from sRGB to YPbPr.
+ *
+ * Requires linking with '-lclut', or '-lm' if
+ * `libclut_model_standard_to_linear1` is not undefined.
+ *
+ * @param r The R component.
+ * @param g The G component.
+ * @param b The B component.
+ * @param y Output parameter for the Y parameter.
+ * @param pb Output parameter for the Pb parameter.
+ * @param pr Output parameter for the Pr parameter.
+ */
+LIBCLUT_GCC_ONLY__(__attribute__((__leaf__)))
+void (libclut_model_srgb_to_ypbpr)(double, double, double, double*, double*, double*);
+#define libclut_model_srgb_to_ypbpr(r, g, b, y, pb, pr) \
+ do \
+ { \
+ double r__ = libclut_model_standard_to_linear1(r); \
+ double g__ = libclut_model_standard_to_linear1(g); \
+ double b__ = libclut_model_standard_to_linear1(b); \
+ double y__; \
+ y__ = r__ * 2126 / 10000; \
+ y__ += g__ * 7152 / 10000; \
+ y__ += b__ * 722 / 10000; \
+ *(y) = y__; \
+ *(pb) = b__ - y__; \
+ *(pr) = r__ - y__; \
+ ; \
+ } \
+ while (0)
+
+
+/**
+ * Convert from YPbPr to sRGB.
+ *
+ * Requires linking with '-lclut', or '-lm' if
+ * `libclut_model_linear_to_standard1` is not undefined.
+ *
+ * @param y The Y component.
+ * @param pb The Pb component.
+ * @param pr The Pr component.
+ * @param r Output parameter for the R parameter.
+ * @param g Output parameter for the G parameter.
+ * @param b Output parameter for the B parameter.
+ */
+LIBCLUT_GCC_ONLY__(__attribute__((__leaf__)))
+void (libclut_model_ypbpr_to_srgb)(double, double, double, double*, double*, double*);
+#define libclut_model_ypbpr_to_srgb(y, pb, pr, r, g, b) \
+ do \
+ { \
+ double y__ = (y), r__ = (pr) + y__, g__, b__ = (pb) + y__; \
+ y__ -= r__ * 2126 / 10000; \
+ y__ -= b__ * 722 / 10000; \
+ g__ = y__ * 10000 / 7152; \
+ *(r) = libclut_model_linear_to_standard1(r__); \
+ *(g) = libclut_model_linear_to_standard1(g__); \
+ *(b) = libclut_model_linear_to_standard1(b__); \
+ } \
+ while (0)
+
+
+/**
+ * Convert from sRGB to YCgCo.
+ *
+ * Requires linking with '-lclut', or '-lm' if
+ * `libclut_model_standard_to_linear1` is not undefined.
+ *
+ * @param r The R component.
+ * @param g The G component.
+ * @param b The B component.
+ * @param y Output parameter for the Y parameter.
+ * @param cg Output parameter for the Cg parameter.
+ * @param co Output parameter for the Co parameter.
+ */
+LIBCLUT_GCC_ONLY__(__attribute__((__leaf__)))
+void (libclut_model_srgb_to_ycgco)(double, double, double, double*, double*, double*);
+#define libclut_model_srgb_to_ycgco(r, g, b, y, cg, co) \
+ do \
+ { \
+ double r__ = libclut_model_standard_to_linear1(r); \
+ double g__ = libclut_model_standard_to_linear1(g); \
+ double b__ = libclut_model_standard_to_linear1(b); \
+ *(y) = r__ / 4 + g__ / 2 + b__ / 4; \
+ *(cg) = r__ / -4 + g__ / 2 - b__ / 4; \
+ *(co) = r__ / 2 - b__ / 2; \
+ } \
+ while (0)
+
+
+/**
+ * Convert from YCgCo to sRGB.
+ *
+ * Requires linking with '-lclut', or '-lm' if
+ * `libclut_model_linear_to_standard1` is not undefined.
+ *
+ * @param y The Y component.
+ * @param cg The Cg component.
+ * @param co The Co component.
+ * @param r Output parameter for the R parameter.
+ * @param g Output parameter for the G parameter.
+ * @param b Output parameter for the B parameter.
+ */
+LIBCLUT_GCC_ONLY__(__attribute__((__leaf__)))
+void (libclut_model_ycgco_to_srgb)(double, double, double, double*, double*, double*);
+#define libclut_model_ycgco_to_srgb(y, cg, co, r, g, b) \
+ do \
+ { \
+ double y__ = (y), cg__ = (cg), co__ = (co); \
+ double r__ = y__ - cg__ + co__; \
+ double g__ = y__ + cg__; \
+ double b__ = y__ - cg__ - co__; \
+ *(r) = libclut_model_linear_to_standard1(r__); \
+ *(g) = libclut_model_linear_to_standard1(g__); \
+ *(b) = libclut_model_linear_to_standard1(b__); \
+ } \
+ while (0)
+
+
+/**
+ * Convert from CIE 1960 UCS to CIE XYZ.
+ *
+ * @param u The u component.
+ * @param v The v component.
+ * @param Y The Y component.
+ * @param x Output parameter for the X parameter.
+ * @param y Output parameter for the Y parameter.
+ * @param z Output parameter for the Z parameter.
+ */
+LIBCLUT_GCC_ONLY__(__attribute__((__leaf__)))
+void (libclut_model_cie_1960_ucs_to_ciexyz)(double, double, double, double*, double*, double*);
+#define libclut_model_cie_1960_ucs_to_ciexyz(u, v, Y, x, y, z) \
+ do \
+ { \
+ double u__ = (u), v__ = (v), y__ = (Y); \
+ *(y) = y__; \
+ *(x) = 3 * y__ * u__ / (2 * v__); \
+ *(z) = y__ * ((4 - u__) / (2 * v__) - 1) / 5; \
+ } \
+ while (0)
+
+
+/**
+ * Convert from CIE XYZ to CIE 1960 UCS.
+ *
+ * @param x The X component.
+ * @param y The Y component.
+ * @param z The Z component.
+ * @param u Output parameter for the u parameter.
+ * @param v Output parameter for the v parameter.
+ * @param Y Output parameter for the Y parameter.
+ */
+LIBCLUT_GCC_ONLY__(__attribute__((__leaf__)))
+void (libclut_model_ciexyz_to_cie_1960_ucs)(double, double, double, double*, double*, double*);
+#define libclut_model_ciexyz_to_cie_1960_ucs(x, y, z, u, v, Y) \
+ do \
+ { \
+ double x__ = (x), y__ = (y); \
+ double d__ = x__ + 15 * y__ + 3 * (z); \
+ *(u) = 4 * x__ / d__; \
+ *(v) = 6 * y__ / d__; \
+ *(Y) = y__; \
+ } \
+ while (0)
+
+
+/**
+ * Convert from CIEUVW to CIE 1960 UCS.
+ *
+ * @param U:double The U* component.
+ * @param V:double The V* component.
+ * @param W:double The W* component.
+ * @param u0:double The u parameter for the white point.
+ * @param v0:double The v parameter for the white point.
+ * @param u:double* Output parameter for the u parameter.
+ * @param v:double* Output parameter for the v parameter.
+ * @param Y:double* Output parameter for the Y parameter.
+ */
+LIBCLUT_GCC_ONLY__(__attribute__((__leaf__)))
+void (libclut_model_cieuvw_to_cie_1960_ucs)(double, double, double, double, double,
+ double*, double*, double*);
+#define libclut_model_cieuvw_to_cie_1960_ucs(U, V, W, u0, v0, u, v, Y) \
+ do \
+ { \
+ double w__ = (W), y__ = (w__ + 17) / 25; \
+ *(Y) = y__ *= y__ * y__; \
+ w__ *= 13; \
+ *(u) = (U) / w__ + (u0); \
+ *(v) = (V) / w__ + (v0); \
+ } \
+ while (0)
+
+
+/**
+ * Convert from CIE 1960 UCS to CIEUVW.
+ *
+ * Requires linking with `-lm`.
+ *
+ * @param u:double The u component.
+ * @param v:double The v component.
+ * @param Y:double The Y component.
+ * @param u0:double The u parameter for the white point.
+ * @param v0:double The v parameter for the white point.
+ * @param U:double* Output parameter for the U* parameter.
+ * @param V:double* Output parameter for the V* parameter.
+ * @param W:double* Output parameter for the W* parameter.
+ */
+LIBCLUT_GCC_ONLY__(__attribute__((__leaf__)))
+void (libclut_model_cie_1960_ucs_to_cieuvw)(double, double, double, double, double,
+ double*, double*, double*);
+#define libclut_model_cie_1960_ucs_to_cieuvw(u, v, Y, u0, v0, U, V, W) \
+ do \
+ { \
+ double w__ = 25 * cbrt(Y) - 17; \
+ *(W) = w__; \
+ w__ *= 13; \
+ *(U) = w__ * ((u) - (u0)); \
+ *(V) = w__ * ((v) - (v0)); \
+ } \
+ while (0)
+
+
+/**
* Create a matrix for converting values between
* two RGB colour spaces.
*
@@ -1988,7 +2534,7 @@ int libclut_model_get_rgb_conversion_matrix(const libclut_rgb_colour_space_t*,
*/
LIBCLUT_GCC_ONLY__(__attribute__((__leaf__)))
void (libclut_model_convert_rgb)(double, double, double, libclut_colour_space_conversion_matrix_t,
- double *, double *, double *);
+ double*, double*, double*);
#define libclut_model_convert_rgb(r, g, b, M, out_r, out_g, out_b) \
do \
{ \