diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/libclut.c | 80 | ||||
-rw-r--r-- | src/libclut.h | 175 |
2 files changed, 185 insertions, 70 deletions
diff --git a/src/libclut.c b/src/libclut.c index 0a1b2f4..8963a4d 100644 --- a/src/libclut.c +++ b/src/libclut.c @@ -24,9 +24,9 @@ * @param c The linear RGB value. * @return Corresponding sRGB value. */ -double libclut_model_linear_to_standard1(double c) +double (libclut_model_linear_to_standard1)(double c) { - return (c <= 0.0031308) ? (12.92 * c) : ((1.0 + 0.055) * pow(c, 1.0 / 2.4)); + return libclut_model_linear_to_standard1(c); } @@ -40,11 +40,9 @@ double libclut_model_linear_to_standard1(double c) * @param b Pointer to the linear blue component, * and output parameter for the blue component. */ -void libclut_model_linear_to_standard(double* r, double* g, double* b) +void (libclut_model_linear_to_standard)(double* r, double* g, double* b) { - *r = libclut_model_linear_to_standard1(*r); - *g = libclut_model_linear_to_standard1(*g); - *b = libclut_model_linear_to_standard1(*b); + libclut_model_linear_to_standard(r, g, b); } @@ -54,9 +52,9 @@ void libclut_model_linear_to_standard(double* r, double* g, double* b) * @param c The sRGB value. * @return Corresponding linear RGB value. */ -double libclut_model_standard_to_linear1(double c) +double (libclut_model_standard_to_linear1)(double c) { - return (c <= 0.04045) ? (c / 12.92) : pow((c + 0.055) / (1.0 + 0.055), 2.4); + return libclut_model_standard_to_linear1(c); } @@ -70,11 +68,9 @@ double libclut_model_standard_to_linear1(double c) * @param b Pointer to the blue component, and output * parameter for the linear blue component. */ -void libclut_model_standard_to_linear(double* r, double* g, double* b) +void (libclut_model_standard_to_linear)(double* r, double* g, double* b) { - *r = libclut_model_standard_to_linear1(*r); - *g = libclut_model_standard_to_linear1(*g); - *b = libclut_model_standard_to_linear1(*b); + libclut_model_standard_to_linear(r, g, b); } @@ -87,10 +83,9 @@ void libclut_model_standard_to_linear(double* r, double* g, double* b) * @param X Output parameter for the X parameter. * @param Z Output parameter for the Z parameter. */ -void libclut_model_ciexyy_to_ciexyz(double x, double y, double Y, double* X, double* Z) +void (libclut_model_ciexyy_to_ciexyz)(double x, double y, double Y, double* X, double* Z) { - *X = (y == 0.0) ? Y : (Y * x / y); - *Z = (y == 0.0) ? Y : (Y * (1 - x - y) / y); + libclut_model_ciexyy_to_ciexyz(x, y, Y, X, Z); } @@ -103,13 +98,9 @@ void libclut_model_ciexyy_to_ciexyz(double x, double y, double Y, double* X, dou * @param x Output parameter for the x parameter. * @param y Output parameter for the y parameter. */ -void libclut_model_ciexyz_to_ciexyy(double X, double Y, double Z, double* x, double* y) +void (libclut_model_ciexyz_to_ciexyy)(double X, double Y, double Z, double* x, double* y) { - double s = X + Y + Z; - if (s == 0.0) - *x = *y = 0.0; - else - *x = X / s, *y = Y / s; + libclut_model_ciexyz_to_ciexyy(X, Y, Z, x, y); } @@ -123,11 +114,9 @@ void libclut_model_ciexyz_to_ciexyy(double X, double Y, double Z, double* x, dou * @param g Output parameter for the green component. * @param b Output parameter for the blue component. */ -void libclut_model_ciexyz_to_linear(double X, double Y, double Z, double* r, double* g, double* b) +void (libclut_model_ciexyz_to_linear)(double X, double Y, double Z, double* r, double* g, double* b) { - *r = ( 3.2404500 * X) + (-1.537140 * Y) + (-0.4985320 * Z); - *g = (-0.9692660 * X) + ( 1.876010 * Y) + ( 0.0415561 * Z); - *b = ( 0.0556434 * X) + (-0.204026 * Y) + ( 1.0572300 * Z); + libclut_model_ciexyz_to_linear(X, Y, Z, r, g, b); } @@ -141,11 +130,9 @@ void libclut_model_ciexyz_to_linear(double X, double Y, double Z, double* r, dou * @param Y Output parameter for the Y parameter. * @param Z Output parameter for the Z parameter. */ -void libclut_model_linear_to_ciexyz(double r, double g, double b, double* X, double* Y, double* Z) +void (libclut_model_linear_to_ciexyz)(double r, double g, double b, double* X, double* Y, double* Z) { - *X = (0.4124564 * r) + (0.3575761 * g) + (0.1804375 * b); - *Y = (0.2126729 * r) + (0.7151522 * g) + (0.0721750 * b); - *Z = (0.0193339 * r) + (0.1191920 * g) + (0.9503041 * b); + libclut_model_linear_to_ciexyz(r, g, b, X, Y, Z); } @@ -159,12 +146,9 @@ void libclut_model_linear_to_ciexyz(double r, double g, double b, double* X, dou * @param y Output parameter for the y parameter. * @param Y Output parameter for the Y parameter. */ -void libclut_model_srgb_to_ciexyy(double r, double g, double b, double* x, double* y, double* Y) +void (libclut_model_srgb_to_ciexyy)(double r, double g, double b, double* x, double* y, double* Y) { - double X, Z; - libclut_model_standard_to_linear(&r, &g, &b); - libclut_model_linear_to_ciexyz(r, g, b, &X, Y, &Z); - libclut_model_ciexyz_to_ciexyy(X, *Y, Z, x, y); + libclut_model_srgb_to_ciexyy(r, g, b, x, y, Y); } @@ -178,12 +162,9 @@ void libclut_model_srgb_to_ciexyy(double r, double g, double b, double* x, doubl * @param g Output parameter for the green component. * @param b Output parameter for the blue component. */ -void libclut_model_ciexyy_to_srgb(double x, double y, double Y, double* r, double* g, double* b) +void (libclut_model_ciexyy_to_srgb)(double x, double y, double Y, double* r, double* g, double* b) { - double X, Z; - libclut_model_ciexyy_to_ciexyz(x, y, Y, &X, &Z); - libclut_model_ciexyz_to_linear(X, Y, Z, r, g, b); - libclut_model_linear_to_standard(r, g, b); + libclut_model_ciexyy_to_srgb(x, y, Y, r, g, b); } @@ -197,15 +178,9 @@ void libclut_model_ciexyy_to_srgb(double x, double y, double Y, double* r, doubl * @param a Output parameter for the a* component. * @param b Output parameter for the b* component. */ -void libclut_model_ciexyz_to_cielab(double X, double Y, double Z, double* L, double* a, double* b) +void (libclut_model_ciexyz_to_cielab)(double X, double Y, double Z, double* L, double* a, double* b) { -#define F(C) ((C) > 0.00885642) ? pow((C), 1.0 / 3.0) : ((7.78 + 703.0 / 99900.0) * (C) + 0.1379310) - X /= 0.95047, Z /= 1.08883; - X = F(X), Y = F(Y), Z = F(Z); - *L = 116.0 * Y - 16.0; - *a = 500.0 * (X - Y); - *b = 200.0 * (Y - Z); -#undef F + libclut_model_ciexyz_to_cielab(X, Y, Z, L, a, b); } @@ -219,15 +194,8 @@ void libclut_model_ciexyz_to_cielab(double X, double Y, double Z, double* L, dou * @param Y Output parameter for the Y parameter. * @param Z Output parameter for the Z parameter. */ -void libclut_model_cielab_to_xiexyz(double L, double a, double b, double* X, double* Y, double* Z) +void (libclut_model_cielab_to_ciexyz)(double L, double a, double b, double* X, double* Y, double* Z) { -#define F(C) (((C)*(C)*(C) > 0.00885642) ? ((C)*(C)*(C)) : (((C) - 0.1379310) / (7.78 + 703.0 / 99900.0))) - *Y = (L + 16.0) / 116.0; - *X = a / 500.0 + *Y; - *Z = *Y - b / 200.0; - *X = F(*X) * 0.95047; - *Y = F(*Y); - *Z = F(*Z) * 1.08883; -#undef F + libclut_model_cielab_to_ciexyz(L, a, b, X, Y, Z); } diff --git a/src/libclut.h b/src/libclut.h index e2feb50..c2f31de 100644 --- a/src/libclut.h +++ b/src/libclut.h @@ -134,7 +134,8 @@ * * None of the parameter may have side-effects. * - * Requires linking with '-lclut'. + * Requires linking with '-lclut', or '-lm' if + * `libclut_model_standard_to_linear1` is not undefined. * * @param clut Pointer to the gamma ramps, must have the arrays * `red`, `green`, and `blue`, and the scalars @@ -165,7 +166,8 @@ * * None of the parameter may have side-effects. * - * Requires linking with '-lclut'. + * Requires linking with '-lclut', or '-lm' if + * `libclut_model_linear_to_standard1` is not undefined. * * @param clut Pointer to the gamma ramps, must have the arrays * `red`, `green`, and `blue`, and the scalars @@ -930,15 +932,25 @@ /** * Convert one component from [0, 1] linear RGB 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. * @return Corresponding sRGB value. */ LIBCLUT_GCC_ONLY__(__attribute__((__const__, __leaf__))) -double libclut_model_linear_to_standard1(double); +double (libclut_model_linear_to_standard1)(double); +#define libclut_model_linear_to_standard1(c) \ + (((double)(c) <= 0.0031308) ? (12.92 * (double)(c)) : ((1.0 + 0.055) * pow((double)(c), 1.0 / 2.4))) /** * Convert [0, 1] linear RGB to [0, 1] sRGB. * + * The macro variant requires linking with '-lm', + * if the 'libclut_model_linear_to_standard1' is defined, + * otherwise it requires linking with '-lclut'. + * * @param r Pointer to the linear red component, * and output parameter for the red component. * @param g Pointer to the linear green component, @@ -946,20 +958,39 @@ double libclut_model_linear_to_standard1(double); * @param b Pointer to the linear blue component, * and output parameter for the blue component. */ -void libclut_model_linear_to_standard(double*, double*, double*); +void (libclut_model_linear_to_standard)(double*, double*, double*); +#define libclut_model_linear_to_standard(r, g, b) \ + do \ + { \ + double *r__ = (r), *g__ = (g), *b__ = (b); \ + *r__ = libclut_model_linear_to_standard1(*r__); \ + *g__ = libclut_model_linear_to_standard1(*g__); \ + *b__ = libclut_model_linear_to_standard1(*b__); \ + } \ + while (0) /** * Convert one component from [0, 1] sRGB to [0, 1] linear RGB. * + * 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. */ LIBCLUT_GCC_ONLY__(__attribute__((__const__, __leaf__))) -double libclut_model_standard_to_linear1(double); +double (libclut_model_standard_to_linear1)(double); +#define libclut_model_standard_to_linear1(c) \ + (((double)(c) <= 0.04045) ? ((double)(c) / 12.92) : pow(((double)(c) + 0.055) / (1.0 + 0.055), 2.4)) /** * Convert [0, 1] sRGB to [0, 1] linear RGB. * + * The macro variant requires linking with '-lm', + * if the 'libclut_model_standard_to_linear1' is defined, + * otherwise it requires linking with '-lclut'. + * * @param r Pointer to the red component, and output * parameter for the linear red component. * @param g Pointer to the green component, and output @@ -967,7 +998,16 @@ double libclut_model_standard_to_linear1(double); * @param b Pointer to the blue component, and output * parameter for the linear blue component. */ -void libclut_model_standard_to_linear(double*, double*, double*); +void (libclut_model_standard_to_linear)(double*, double*, double*); +#define libclut_model_standard_to_linear(r, g, b) \ + do \ + { \ + double *r__ = (r), *g__ = (g), *b__ = (b); \ + *r__ = libclut_model_standard_to_linear1(*r__); \ + *g__ = libclut_model_standard_to_linear1(*g__); \ + *b__ = libclut_model_standard_to_linear1(*b__); \ + } \ + while (0) /** * Convert CIE xyY to CIE XYZ. @@ -979,7 +1019,15 @@ void libclut_model_standard_to_linear(double*, double*, double*); * @param Z Output parameter for the Z parameter. */ LIBCLUT_GCC_ONLY__(__attribute__((__leaf__))) -void libclut_model_ciexyy_to_ciexyz(double, double, double, double*, double*); +void (libclut_model_ciexyy_to_ciexyz)(double, double, double, double*, double*); +#define libclut_model_ciexyy_to_ciexyz(x, y, Y, X, Z) \ + do \ + { \ + double x__ = (x), y__ = (y), Y__ = (Y), *X__ = (X), *Z__ = (Z); \ + *X__ = (y__ == 0.0) ? Y__ : (Y__ * x__ / y__); \ + *Z__ = (y__ == 0.0) ? Y__ : (Y__ * (1.0 - x__ - y__) / y__); \ + } \ + while (0) /** * Convert CIE XYZ to CIE xyY. @@ -991,7 +1039,18 @@ void libclut_model_ciexyy_to_ciexyz(double, double, double, double*, double*); * @param y Output parameter for the y parameter. */ LIBCLUT_GCC_ONLY__(__attribute__((__leaf__))) -void libclut_model_ciexyz_to_ciexyy(double, double, double, double*, double*); +void (libclut_model_ciexyz_to_ciexyy)(double, double, double, double*, double*); +#define libclut_model_ciexyz_to_ciexyy(X, Y, Z, x, y) \ + do \ + { \ + double X__ = (X), Y__ = (Y), Z__ = (Z), *x__ = (x), *y__ = (y); \ + double s__ = X__ + Y__ + Z__; \ + if (s__ == 0.0) \ + *x__ = *y__ = 0.0; \ + else \ + *x__ = X__ / s__, *y__ = Y__ / s__; \ + } \ + while (0) /** * Convert CIE XYZ to [0, 1] linear RGB. @@ -1004,7 +1063,16 @@ void libclut_model_ciexyz_to_ciexyy(double, double, double, double*, double*); * @param b Output parameter for the blue component. */ LIBCLUT_GCC_ONLY__(__attribute__((__leaf__))) -void libclut_model_ciexyz_to_linear(double, double, double, double*, double*, double*); +void (libclut_model_ciexyz_to_linear)(double, double, double, double*, double*, double*); +#define libclut_model_ciexyz_to_linear(X, Y, Z, r, g, b) \ + do \ + { \ + double X__ = (X), Y__ = (Y), Z__ = (Z); \ + *(r) = ( 3.2404500 * X__) + (-1.537140 * Y__) + (-0.4985320 * Z__); \ + *(g) = (-0.9692660 * X__) + ( 1.876010 * Y__) + ( 0.0415561 * Z__); \ + *(b) = ( 0.0556434 * X__) + (-0.204026 * Y__) + ( 1.0572300 * Z__); \ + } \ + while (0) /** * Convert [0, 1] linear RGB to CIE XYZ. @@ -1017,11 +1085,28 @@ void libclut_model_ciexyz_to_linear(double, double, double, double*, double*, do * @param Z Output parameter for the Z parameter. */ LIBCLUT_GCC_ONLY__(__attribute__((__leaf__))) -void libclut_model_linear_to_ciexyz(double, double, double, double*, double*, double*); +void (libclut_model_linear_to_ciexyz)(double, double, double, double*, double*, double*); +#define libclut_model_linear_to_ciexyz(r, g, b, X, Y, Z) \ + do \ + { \ + double r__ = (r), g__ = (g), b__ = (b); \ + *(X) = (0.4124564 * r__) + (0.3575761 * g__) + (0.1804375 * b__); \ + *(Y) = (0.2126729 * r__) + (0.7151522 * g__) + (0.0721750 * b__); \ + *(Z) = (0.0193339 * r__) + (0.1191920 * g__) + (0.9503041 * b__); \ + } \ + while (0) /** * Convert [0, 1] linear RGB to CIE xyY. * + * The macro variant requires linking with '-lclut' + * if any of `libclut_model_ciexyz_to_ciexyy`, + * `libclut_model_linear_to_ciexyz`, and + * `libclut_model_standard_to_linear` are undefined. + * The macro variant requires linking with '-lm' if + * neither `libclut_model_standard_to_linear` nor + * `libclut_model_standard_to_linear1` are undefined. + * * @param r The red component. * @param g The green component. * @param b The blue component. @@ -1029,11 +1114,30 @@ void libclut_model_linear_to_ciexyz(double, double, double, double*, double*, do * @param y Output parameter for the y parameter. * @param Y Output parameter for the Y parameter. */ -void libclut_model_srgb_to_ciexyy(double, double, double, double*, double*, double*); +void (libclut_model_srgb_to_ciexyy)(double, double, double, double*, double*, double*); +#define libclut_model_srgb_to_ciexyy(r, g, b, x, y, Y) \ + do \ + { \ + double r___ = (r), g___ = (g), b___ = (b); \ + double *x___ = (x), *y___ = (y), *Y___ = (Y); \ + double X___, Z___; \ + libclut_model_standard_to_linear(&r___, &g___, &b___); \ + libclut_model_linear_to_ciexyz(r___, g___, b___, &X___, Y___, &Z___); \ + libclut_model_ciexyz_to_ciexyy(X___, *Y___, Z___, x___, y___); \ + } \ + while (0) /** * Convert CIE xyY to [0, 1] sRGB. * + * The macro variant requires linking with '-lclut' + * if any of `libclut_model_ciexyy_to_ciexyz`, + * `libclut_model_ciexyz_to_linear`, and + * `libclut_model_linear_to_standard` are undefined. + * The macro variant requires linking with '-lm' if + * neither `libclut_model_linear_to_standard` nor + * `libclut_model_linear_to_standard1` are undefined. + * * @param x The x parameter. * @param y The y parameter. * @param Y The Y parameter. @@ -1041,11 +1145,24 @@ void libclut_model_srgb_to_ciexyy(double, double, double, double*, double*, doub * @param g Output parameter for the green component. * @param b Output parameter for the blue component. */ -void libclut_model_ciexyy_to_srgb(double, double, double, double*, double*, double*); +void (libclut_model_ciexyy_to_srgb)(double, double, double, double*, double*, double*); +#define libclut_model_ciexyy_to_srgb(x, y, Y, r, g, b) \ + do \ + { \ + double x___ = (x), y___ = (y), Y___ = (Y); \ + double *r___ = (r), *g___ = (g), *b___ = (b); \ + double X___, Z___; \ + libclut_model_ciexyy_to_ciexyz(x___, y___, Y___, &X___, &Z___); \ + libclut_model_ciexyz_to_linear(X___, Y___, Z___, r___, g___, b___); \ + libclut_model_linear_to_standard(r___, g___, b___); \ + } \ + while(0) /** * Convert from CIE XYZ to CIE L*a*b*. * + * The macro variant requires linking with '-lm'. + * * @param X The X parameter. * @param Y The Y parameter. * @param Z The Z parameter. @@ -1054,7 +1171,22 @@ void libclut_model_ciexyy_to_srgb(double, double, double, double*, double*, doub * @param b Output parameter for the b* component. */ LIBCLUT_GCC_ONLY__(__attribute__((__leaf__))) -void libclut_model_ciexyz_to_cielab(double, double, double, double*, double*, double*); +void (libclut_model_ciexyz_to_cielab)(double, double, double, double*, double*, double*); +#define libclut_model_ciexyz_to_cielab(X, Y, Z, L, a, b) \ + do \ + { \ + double X__ = (X), Y__ = (Y), Z__ = (Z); \ + X__ /= 0.95047, Z__ /= 1.08883; \ + X__ = LIBCLUT_MODEL_CIEXYZ_TO_CIELAB__(X__); \ + Y__ = LIBCLUT_MODEL_CIEXYZ_TO_CIELAB__(Y__); \ + Z__ = LIBCLUT_MODEL_CIEXYZ_TO_CIELAB__(Z__); \ + *(L) = 116.0 * Y__ - 16.0; \ + *(a) = 500.0 * (X__ - Y__); \ + *(b) = 200.0 * (Y__ - Z__); \ + } \ + while (0) +#define LIBCLUT_MODEL_CIEXYZ_TO_CIELAB__(C) \ + (((C) > 0.00885642) ? pow((C), 1.0 / 3.0) : ((7.78 + 703.0 / 99900.0) * (C) + 0.1379310)) /** * Convert from CIE L*a*b* to CIE XYZ. @@ -1067,7 +1199,22 @@ void libclut_model_ciexyz_to_cielab(double, double, double, double*, double*, do * @param Z Output parameter for the Z parameter. */ LIBCLUT_GCC_ONLY__(__attribute__((__leaf__))) -void libclut_model_cielab_to_xiexyz(double, double, double, double*, double*, double*); +void (libclut_model_cielab_to_ciexyz)(double, double, double, double*, double*, double*); +#define libclut_model_cielab_to_ciexyz(L, a, b, X, Y, Z) \ + do \ + { \ + double L__ = (L), a__ = (a), b__ = (b); \ + double *X__ = (X), *Y__ = (Y), *Z__ = (Z); \ + *Y__ = (L__ + 16.0) / 116.0; \ + *X__ = a__ / 500.0 + *Y__; \ + *Z__ = *Y__ - b__ / 200.0; \ + *X__ = LIBCLUT_MODEL_CIELAB_TO_CIEXYZ__(*X__) * 0.95047; \ + *Y__ = LIBCLUT_MODEL_CIELAB_TO_CIEXYZ__(*Y__); \ + *Z__ = LIBCLUT_MODEL_CIELAB_TO_CIEXYZ__(*Z__) * 1.08883; \ + } \ + while (0) +#define LIBCLUT_MODEL_CIELAB_TO_CIEXYZ__(C) \ + (((C)*(C)*(C) > 0.00885642) ? ((C)*(C)*(C)) : (((C) - 0.1379310) / (7.78 + 703.0 / 99900.0))) |