From 5796370cc9df515a5c0b37ac0444af262247af66 Mon Sep 17 00:00:00 2001 From: Mattias Andrée Date: Fri, 2 Dec 2016 22:09:08 +0100 Subject: Add new colour spaces MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Mattias Andrée --- src/libclut.c | 317 ++++++++++++++++++++++++++++++-- src/libclut.h | 570 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++-- src/test.c | 26 ++- 3 files changed, 887 insertions(+), 26 deletions(-) (limited to 'src') diff --git a/src/libclut.c b/src/libclut.c index c783e31..9395c71 100644 --- a/src/libclut.c +++ b/src/libclut.c @@ -21,9 +21,9 @@ /** - * Convert one component from [0, 1] linear RGB to [0, 1] sRGB. + * Convert one component from [0, 1] linear sRGB to [0, 1] sRGB. * - * @param c The linear RGB value. + * @param c The linear sRGB value. * @return Corresponding sRGB value. */ double (libclut_model_linear_to_standard1)(double c) @@ -33,7 +33,7 @@ double (libclut_model_linear_to_standard1)(double c) /** - * Convert [0, 1] linear RGB to [0, 1] sRGB. + * Convert [0, 1] linear sRGB to [0, 1] sRGB. * * @param r Pointer to the linear red component, * and output parameter for the red component. @@ -49,10 +49,10 @@ void (libclut_model_linear_to_standard)(double* r, double* g, double* b) /** - * Convert one component from [0, 1] sRGB to [0, 1] linear RGB. + * Convert one component from [0, 1] sRGB to [0, 1] linear sRGB. * * @param c The sRGB value. - * @return Corresponding linear RGB value. + * @return Corresponding linear sRGB value. */ double (libclut_model_standard_to_linear1)(double c) { @@ -61,7 +61,7 @@ double (libclut_model_standard_to_linear1)(double c) /** - * Convert [0, 1] sRGB to [0, 1] linear RGB. + * Convert [0, 1] sRGB to [0, 1] linear sRGB. * * @param r Pointer to the red component, and output * parameter for the linear red component. @@ -107,7 +107,7 @@ void (libclut_model_ciexyz_to_ciexyy)(double X, double Y, double Z, double* x, d /** - * 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. @@ -123,7 +123,7 @@ void (libclut_model_ciexyz_to_linear)(double X, double Y, double Z, double* r, d /** - * 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. @@ -139,7 +139,7 @@ void (libclut_model_linear_to_ciexyz)(double r, double g, double b, double* X, d /** - * Convert [0, 1] linear RGB to CIE xyY. + * Convert [0, 1] linear sRGB to CIE xyY. * * @param r The red component. * @param g The green component. @@ -202,6 +202,303 @@ void (libclut_model_cielab_to_ciexyz)(double L, double a, double b, double* X, d } +/** + * Convert from CIE XYZ to CIE L*u*v*. + * + * @param X The X parameter. + * @param Y The Y parameter. + * @param Z The Z parameter. + * @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* component. + * @param u Output parameter for the u* component. + * @param v Output parameter for the v* component. + */ +void (libclut_model_ciexyz_to_cieluv)(double X, double Y, double Z, double Xn, double Yn, double Zn, + double* L, double* u, double* v) +{ + libclut_model_ciexyz_to_cieluv(X, Y, Z, Xn, Yn, Zn, L, u, v); +} + + +/** + * Convert from CIE L*u*v* 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. + */ +void (libclut_model_cieluv_to_ciexyz)(double L, double u, double v, double Xn, double Yn, double Zn, + double* X, double* Y, double* Z) +{ + libclut_model_cieluv_to_ciexyz(L, u, v, Xn, Yn, Zn, X, Y, Z); +} + + +/** + * Convert from CIELCh to CIE L*u*v*. + * + * @param L The L* component. + * @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. + */ +void (libclut_model_cielch_to_cieluv)(double C, double h, double* u, double* v) +{ + libclut_model_cielch_to_cieluv(C, h, u, v); +} + + +/** + * Convert from CIE L*u*v* to CIELCh. + * + * @param L The L* component. + * @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. + */ +void (libclut_model_cieluv_to_cielch)(double u, double v, double* C, double* h) +{ + libclut_model_cieluv_to_cielch(u, v, C, h); +} + + +/** + * Convert from sRGB to YIQ. + * + * @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. + */ +void (libclut_model_srgb_to_yiq)(double r, double g, double b, double* y, double* i, double* q) +{ + libclut_model_srgb_to_yiq(r, g, b, y, i, q); +} + + +/** + * Convert from YIQ to sRGB. + * + * @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. + */ +void (libclut_model_yiq_to_srgb)(double y, double i, double q, double* r, double* g, double* b) +{ + libclut_model_yiq_to_srgb(y, i, q, r, g, b); +} + + +/** + * Convert from sRGB to YDbDr. + * + * @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. + */ +void (libclut_model_srgb_to_ydbdr)(double r, double g, double b, double* y, double* db, double* dr) +{ + libclut_model_srgb_to_ydbdr(r, g, b, y, db, dr); +} + + +/** + * Convert from YDbDr to sRGB. + * + * @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. + */ +void (libclut_model_ydbdr_to_srgb)(double y, double db, double dr, double* r, double* g, double* b) +{ + libclut_model_ydbdr_to_srgb(y, db, dr, r, g, b); +} + +/** + * 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. + */ +void (libclut_model_yuv_to_ydbdr)(double u, double v, double* db, double* dr) +{ + libclut_model_yuv_to_ydbdr(u, v, db, dr); +} + + +/** + * 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. + */ +void (libclut_model_ydbdr_to_yuv)(double db, double dr, double* u, double* v) +{ + libclut_model_ydbdr_to_yuv(db, dr, u, v); +} + + +/** + * Convert from sRGB to YPbPr. + * + * @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. + */ +void (libclut_model_srgb_to_ypbpr)(double r, double g, double b, double* y, double* pb, double* pr) +{ + libclut_model_srgb_to_ypbpr(r, g, b, y, pb, pr); +} + + +/** + * Convert from YPbPr to sRGB. + * + * @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. + */ +void (libclut_model_ypbpr_to_srgb)(double y, double pb, double pr, double* r, double* g, double* b) +{ + libclut_model_ypbpr_to_srgb(y, pb, pr, r, g, b); +} + + +/** + * Convert from sRGB to YCgCo. + * + * @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. + */ +void (libclut_model_srgb_to_ycgco)(double r, double g, double b, double* y, double* cg, double* co) +{ + libclut_model_srgb_to_ycgco(r, g, b, y, cg, co); +} + + +/** + * Convert from YCgCo to sRGB. + * + * @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. + */ +void (libclut_model_ycgco_to_srgb)(double y, double cg, double co, double* r, double* g, double* b) +{ + libclut_model_ycgco_to_srgb(y, cg, co, r, g, b); +} + + +/** + * 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. + */ +void (libclut_model_cie_1960_ucs_to_ciexyz)(double u, double v, double Y, double* x, double* y, double* z) +{ + libclut_model_cie_1960_ucs_to_ciexyz(u, v, Y, x, y, z); +} + + +/** + * 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. + */ +void (libclut_model_ciexyz_to_cie_1960_ucs)(double x, double y, double z, double* u, double* v, double* Y) +{ + libclut_model_ciexyz_to_cie_1960_ucs(x, y, z, u, v, Y); +} + + +/** + * Convert from CIEUVW to CIE 1960 UCS. + * + * @param U The U* component. + * @param V The V* component. + * @param W The W* component. + * @param u0 The u parameter for the white point. + * @param v0 The v parameter for the white point. + * @param u Output parameter for the u parameter. + * @param v Output parameter for the v parameter. + * @param Y Output parameter for the Y parameter. + */ +void (libclut_model_cieuvw_to_cie_1960_ucs)(double U, double V, double W, double u0, double v0, + double* u, double* v, double* Y) +{ + libclut_model_cieuvw_to_cie_1960_ucs(U, V, W, u0, v0, u, v, Y); +} + + +/** + * Convert from CIE 1960 UCS to CIEUVW. + * + * Requires linking with `-lm`. + * + * @param u The u component. + * @param v The v component. + * @param Y The Y component. + * @param u0 The u parameter for the white point. + * @param v0 The v parameter for the white point. + * @param U Output parameter for the U* parameter. + * @param V Output parameter for the V* parameter. + * @param W Output parameter for the W* parameter. + */ +void (libclut_model_cie_1960_ucs_to_cieuvw)(double u, double v, double Y, double u0, double v0, + double* U, double* V, double* W) +{ + libclut_model_cie_1960_ucs_to_cieuvw(u, v, Y, u0, v0, U, V, W); +} + + /** * Divide all values in a row by a divisor. @@ -410,7 +707,7 @@ int libclut_model_get_rgb_conversion_matrix(const libclut_rgb_colour_space_t* fr * @param out_b Output parameter for the new blue component. */ void (libclut_model_convert_rgb)(double r, double g, double b, libclut_colour_space_conversion_matrix_t M, - double *out_r, double *out_g, double *out_b) + double* out_r, double* out_g, double* out_b) { libclut_model_convert_rgb(r, g, b, M, out_r, out_g, out_b); } diff --git a/src/libclut.h b/src/libclut.h index 9bc1876..e1601f1 100644 --- a/src/libclut.h +++ b/src/libclut.h @@ -222,6 +222,38 @@ LIBCLUT_ILLUMINANT_D50 \ } +/** + * 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. @@ -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`, @@ -1949,6 +1994,507 @@ void (libclut_model_cielab_to_ciexyz)(double, double, double, double*, double*, (((C)*(C)*(C) > 0.00885642) ? ((C)*(C)*(C)) : (((C) - 0.1379310) / (7.78 + 703.0 / 99900))) +/** + * 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 \ { \ diff --git a/src/test.c b/src/test.c index d7ee130..b4491a8 100644 --- a/src/test.c +++ b/src/test.c @@ -358,11 +358,31 @@ int main(int argc, char *argv[]) } - libclut_convert_rgb_inplace(&t1, 1, double, M, trunc); - libclut_convert_rgb(&t1, 1, double, M, trunc, &t2); + libclut_convert_rgb_inplace(&t1, 1, double, M, trunc); /* TODO test */ + libclut_convert_rgb(&t1, 1, double, M, trunc, &t2); /* TODO test */ rgb_conversion_done: + + + libclut_model_ciexyz_to_cieluv(1, 1, 1, 1, 1, 1, &r, &g, &b); /* TODO test */ + libclut_model_cieluv_to_ciexyz(1, 1, 1, 1, 1, 1, &r, &g, &b); /* TODO test */ + libclut_model_cielch_to_cieluv(1, 1, &r, &g); /* TODO test */ + libclut_model_cieluv_to_cielch(1, 1, &r, &g); /* TODO test */ + libclut_model_srgb_to_yiq(1, 1, 1, &r, &g, &b); /* TODO test */ + libclut_model_yiq_to_srgb(1, 1, 1, &r, &g, &b); /* TODO test */ + libclut_model_srgb_to_ydbdr(1, 1, 1, &r, &g, &b); /* TODO test */ + libclut_model_ydbdr_to_srgb(1, 1, 1, &r, &g, &b); /* TODO test */ + libclut_model_yuv_to_ydbdr(1, 1, &r, &g); /* TODO test */ + libclut_model_ydbdr_to_yuv(1, 1, &r, &g); /* TODO test */ + libclut_model_srgb_to_ypbpr(1, 1, 1, &r, &g, &b); /* TODO test */ + libclut_model_ypbpr_to_srgb(1, 1, 1, &r, &g, &b); /* TODO test */ + libclut_model_srgb_to_ycgco(1, 1, 1, &r, &g, &b); /* TODO test */ + libclut_model_ycgco_to_srgb(1, 1, 1, &r, &g, &b); /* TODO test */ + libclut_model_cie_1960_ucs_to_ciexyz(1, 1, 1, &r, &g, &b); /* TODO test */ + libclut_model_ciexyz_to_cie_1960_ucs(1, 1, 1, &r, &g, &b); /* TODO test */ + libclut_model_cieuvw_to_cie_1960_ucs(1, 1, 1, 1, 1, &r, &g, &b); /* TODO test */ + libclut_model_cie_1960_ucs_to_cieuvw(1, 1, 1, 1, 1, &r, &g, &b); /* TODO test */ if (!rc) @@ -393,7 +413,5 @@ int main(int argc, char *argv[]) libclut_cie_limits libclut_cie_manipulate libclut_cie_apply - libclut_convert_rgb_inplace - libclut_convert_rgb */ -- cgit v1.2.3-70-g09d2