From 96a7efc1df64b23697f9d5ae398604bf1471a56f Mon Sep 17 00:00:00 2001 From: Mattias Andrée Date: Fri, 9 Jun 2017 23:08:39 +0200 Subject: Reduce size of RGB struct, and add LIBCOLOUR_CIELCHUV.7 and LIBCOLOUR_RGB.7 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Mattias Andrée --- LIBCOLOUR_CIELCHUV.7 | 95 ++++++++++++++++++++++++ LIBCOLOUR_RGB.7 | 202 +++++++++++++++++++++++++++++++++++++++++++++++++++ LIBCOLOUR_SRGB.7 | 2 +- convert-template.c | 64 +++++++++------- libcolour-template.c | 139 +++++++++++++++++++---------------- libcolour.h | 31 +++++--- test.c | 43 +++++++---- 7 files changed, 463 insertions(+), 113 deletions(-) create mode 100644 LIBCOLOUR_CIELCHUV.7 create mode 100644 LIBCOLOUR_RGB.7 diff --git a/LIBCOLOUR_CIELCHUV.7 b/LIBCOLOUR_CIELCHUV.7 new file mode 100644 index 0000000..1b551c7 --- /dev/null +++ b/LIBCOLOUR_CIELCHUV.7 @@ -0,0 +1,95 @@ +.TH LIBCOLOUR_CIELCHUV 7 libcolour +.SH NAME +LIBCOLOUR_CIELCHUV - CIE LChuv +.SH DESCRIPTION +CIE LCh_uv [\(aq_\(aq denotes subscript of +subsequent characters] (also known as CIE HLC_uv) +colours are presented with either of +.nf + + \fBtypedef struct libcolour_cielchuv_f libcolour_cielchuv_f_t;\fP + \fBtypedef struct libcolour_cielchuv_lf libcolour_cielchuv_lf_t;\fP + \fBtypedef struct libcolour_cielchuv_llf libcolour_cielchuv_llf_t;\fP + +.fi +These +.BR struct s +use +.BR float , +.BR double , +and +.BR long\ double , +respecitively, for the values stored in them, +and are otherwise identical. +.B struct libcolour_cielchuv_f +is defined as +.nf + + \fBstruct libcolour_cielchuv_f {\fP + \fBenum libcolour_model\fP \fImodel\fP\fB;\fP + \fBfloat\fP \fIL\fP\fB;\fP + \fBfloat\fP \fIC\fP\fB;\fP + \fBfloat\fP \fIh\fP\fB;\fP + \fBstruct libcolour_ciexyz\fP \fIwhite\fP\fB;\fP + \fBdouble\fP \fIone_revolution\fP\fB;\fP + \fB};\fP + +.fi +.I .model +shall be set to +.BR LIBCOLOUR_CIELCHUV . +In +.BR union\ libcolour_colour_f , +.BR union\ libcolour_colour_lf , +and +.BR union\ libcolour_colour_llf , +.I .cielchuv +is used for CIE LChuv colours. +.P +.IR .L , +.IR .C , +and +.I .h +hold the L* (luma), C*_uv (chroma), and +h_uv (hue) values, respectively, +.I .white +is the white point, and +.I .one_revolution +the The value lowest positive values of +.I .h +that is equivalent to 0. 360 if the hue is measured +in degrees, 400 if the hue is measured in gon, and +2 pi if the hue is measured radian. Any value can +be used. +.I .white +and +.I .one_revolution +are not part of the colour, but rather part of +the colour space. +.P +L* is 0 in black and 100 in white. +.P +The call +.BI libcolour_proper(& c ) +on a +.B struct libcolour_cielchuv_t +.I c +sets +.I c.white.model +to +.BR LIBCOLOUR_CIEXYZ , +and if +.I c.one_revolution +is 0, it is set to 360. +Zero is always returned in this case. +.P +CIE LCh_uv approximates uniform human colour +perception using cylindrical representation. +.P +CIE LCh_uv is not additive. It is a cylindrical +representation of CIE 1976 (L*, u*, v*). +.SH SEE ALSO +.BR libcolour (7) +.SH AUTHORS +Mattias Andrée +.RI < maandree@kth.se > diff --git a/LIBCOLOUR_RGB.7 b/LIBCOLOUR_RGB.7 new file mode 100644 index 0000000..af49fe2 --- /dev/null +++ b/LIBCOLOUR_RGB.7 @@ -0,0 +1,202 @@ +.TH LIBCOLOUR_RGB 7 libcolour +.SH NAME +LIBCOLOUR_RGB - Generic RGB +.SH DESCRIPTION +Generic RGB colours are presented with either of +.nf + + \fBtypedef struct libcolour_rgb_f libcolour_rgb_f_t;\fP + \fBtypedef struct libcolour_rgb_lf libcolour_rgb_lf_t;\fP + \fBtypedef struct libcolour_rgb_llf libcolour_rgb_llf_t;\fP + +.fi +These +.BR struct s +use +.BR float , +.BR double , +and +.BR long\ double , +respecitively, for the values stored in them, +and are otherwise identical. +.B struct libcolour_rgb_f +is defined as +.nf + + \fBstruct libcolour_rgb_f {\fP + \fBenum libcolour_model\fP \fImodel\fP\fB;\fP + \fBfloat\fP \fIR\fP\fB;\fP + \fBfloat\fP \fIG\fP\fB;\fP + \fBfloat\fP \fIB\fP\fB;\fP + \fBint\fP \fIwith_transfer\fP\fB;\fP + \fBenum libcolour_encoding_type\fP \fIencoding_type\fP\fB;\fP + \fBunion {\fP + \fBstruct {\fP + \fBfloat\fP \fIgamma\fP\fB;\fP + \fB}\fP \fIsimple\fB;\fP + \fBstruct {\fP + \fBfloat\fP \fIgamma\fP\fB;\fP + \fBfloat\fP \fIoffset\fP\fB;\fP + \fBfloat\fP \fIslope\fP\fB;\fP + \fBfloat\fP \fItransition\fP\fB;\fP + \fBfloat\fP \fItransitioninv\fP\fB;\fP + \fB}\fP \fIregular\fB;\fP + \fBstruct {\fP + \fBfloat (*\fP\fIto_encoded_red\fP\fB)(float);\fP + \fBfloat (*\fP\fIto_decoded_red\fP\fB)(float);\fP + \fBfloat (*\fP\fIto_encoded_green\fP\fB)(float);\fP + \fBfloat (*\fP\fIto_decoded_green\fP\fB)(float);\fP + \fBfloat (*\fP\fIto_encoded_blue\fP\fB)(float);\fP + \fBfloat (*\fP\fIto_decoded_blue\fP\fB)(float);\fP + \fB}\fP \fIcustom\fB;\fP + \fB}\fP \fItransfer\fB;\fP + \fBstruct libcolour_ciexyy\fP \fIred\fP\fB;\fP + \fBstruct libcolour_ciexyy\fP \fIgreen\fP\fB;\fP + \fBstruct libcolour_ciexyy\fP \fIblue\fP\fB;\fP + \fBstruct libcolour_ciexyy\fP \fIwhite\fP\fB;\fP + \fBfloat\fP \fIwhite_r\fP\fB;\fP + \fBfloat\fP \fIwhite_g\fP\fB;\fP + \fBfloat\fP \fIwhite_b\fP\fB;\fP + \fBfloat\fP \fIM\fP\fB[3][3];\fP + \fBfloat\fP \fIMinv\fP\fB[3][3];\fP + \fBenum libcolour_rgb_colour_space\fP \fIcolour_space\fP\fB;\fP + \fB};\fP + +.fi +.I .model +shall be set to +.BR LIBCOLOUR_RGB . +In +.BR union\ libcolour_colour_f , +.BR union\ libcolour_colour_lf , +and +.BR union\ libcolour_colour_llf , +.I .rgb +is used for generic RGB colours. +.P +.IR .R , +.IR .G , +and +.I .B +hold the red, green, and blue values, respectively, +and shall have a value between 0 and 1, inclusively, +for the colour to be in gamut. +.I .with_transfer +shall be set to a non-zero value if the specified transfer +function (\(dqgamma function\(dq) is applied, and zero +otherwise, meaning colours are linearly encoded. +.P +.I .encoding_type +shall be set to one of the following values: +.TP +.B LIBCOLOUR_ENCODING_TYPE_LINEAR +The colour space does not have a transfer function. +.TP +.B LIBCOLOUR_ENCODING_TYPE_SIMPLE +The colour space uses a simple gamma transfer function +that only uses the +.I .transfer.simple.gamma +parameter. +.TP +.B LIBCOLOUR_ENCODING_TYPE_REGULAR +The colour space uses a linear-gamma hybrid transfer +function that uses the +.IR .transfer.simple.gamma , +.IR .transfer.simple.offset , +.IR .transfer.simple.slope , +and +.I .transfer.simple.transition +parameters as well as +.IR .transfer.simple.transitioninv , +the inverse value of the +.I .transfer.simple.transition parameter of the transfer +function, that is, where the transition takes place in +the encoded, rather than linear, values. This value is +set automatically. +.TP +.B LIBCOLOUR_ENCODING_TYPE_CUSTOM +The colour space uses a custom transfer function. When +this value is used, +.IR .transfer.custom.to_encoded_red , +.IR .transfer.custom.to_encoded_green , +and +.IR .transfer.custom.to_encoded_blue +shall be set to the function used to apply the red, +green, and blue channels' transfer functions to a value, +respectively, and +.IR .transfer.custom.to_decoded_red , +.IR .transfer.custom.to_decoded_green , +and +.IR .transfer.custom.to_decoded_blue +shall be set to the inverse of those functions. +.P +The colour space is defined by +.I .red +(the red primary), +.I .green +(the green primary), +.I .blue +(the blue primary), +.I .white +(the white point), and the RGB value of for the white +point, which is specified by +.I .white_r +(the red value for the white point), +.I .white_g +(the green value for the white point), +and +.IR .white_b +(the blue value for the white point). +.IR .white.Y , +.IR .white_r , +.IR .white_g , +and +.IR .white_b +should usually be 1. +.I .M +is derived from these values, it is the matrix that is +to convert a colour from the specified RGB colour space +to CIE 1931 YXZ. +.I .Minv +is derived from +.I .M +is used to convert in the opposite direction. +.IR .colour_space , +which is set automatically, is the colour space. +.P +.BR libcolour_get_rgb_colour_space (3) +is used to set the transfer function and colour space +parameters. +.P +The RGB colour model is an additive colour model, that is, +without a transfer function applied, linearily isomorphic +to CIE 1931 XYZ. +.P +The call +.BI libcolour_proper(& c ) +on a +.B struct libcolour_rgb_t +.I c +(done automatically for predefined colour spaces) sets +.IR c.red.model , +.IR c.green.model , +and +.I c.blue.model +to +.BR LIBCOLOUR_CIEXYY , +and calculate and sets the Y values for +.IR c.red , +.IR c.green , +and +.IR c.blue . +Zero is always normally returned, but of there is something +wrong with with the values of the primaries, −1 is returned +and +.I errno +is set to +.BR EDOM . +.SH SEE ALSO +.BR libcolour (7) +.SH AUTHORS +Mattias Andrée +.RI < maandree@kth.se > diff --git a/LIBCOLOUR_SRGB.7 b/LIBCOLOUR_SRGB.7 index fd6f819..f5bff7b 100644 --- a/LIBCOLOUR_SRGB.7 +++ b/LIBCOLOUR_SRGB.7 @@ -55,7 +55,7 @@ shall be set to a non-zero value if the sRGB transfer function (\(dqgamma function\(dq) is applied, and zero otherwise, meaning colours are linearly encoded. .P -The RGB color model, of which sRGB is a specific colour +The RGB colour model, of which sRGB is a specific colour space, is an additive colour model, that is, without a transfer function applied, linearily isomorphic to CIE 1931 XYZ. diff --git a/convert-template.c b/convert-template.c index d06ccc0..223f840 100644 --- a/convert-template.c +++ b/convert-template.c @@ -20,8 +20,8 @@ #define PI2 (2 * D(3.14159265358979323846)) #define WASDIV0(X) (xisinf(X) || xisnan(X)) -#define REGULAR(S, T) ((T) <= (S)->transition ? (S)->slope * (T) : (1 + (S)->offset) * xpow((T), 1 / (S)->gamma) - (S)->offset) -#define INVREGULAR(S, T) ((T) <= (S)->transitioninv ? (T) / (S)->slope : xpow(((T) + (S)->offset) / (1 + (S)->offset), (S)->gamma)) +#define REGULAR(S, T) ((T) <= (S)->TRANSITION ? (S)->SLOPE * (T) : (1 + (S)->OFFSET) * xpow((T), 1 / (S)->GAMMA) - (S)->OFFSET) +#define INVREGULAR(S, T) ((T) <= (S)->TRANSITIONINV ? (T) / (S)->SLOPE : xpow(((T) + (S)->OFFSET) / (1 + (S)->OFFSET), (S)->GAMMA)) #define TRANSFORM(X, Y, Z, A, B, C, R1C1, R1C2, R1C3, R2C1, R2C2, R2C3, R3C1, R3C2, R3C3)\ do {\ @@ -33,6 +33,20 @@ +#define SLOPE transfer.regular.slope +#define TRANSITIONINV transfer.regular.transitioninv +#define TRANSITION transfer.regular.transition +#define GAMMA transfer.regular.gamma +#define OFFSET transfer.regular.offset +#define TO_ENCODED_RED transfer.custom.to_encoded_red +#define TO_DECODED_RED transfer.custom.to_decoded_red +#define TO_ENCODED_GREEN transfer.custom.to_encoded_green +#define TO_DECODED_GREEN transfer.custom.to_decoded_green +#define TO_ENCODED_BLUE transfer.custom.to_encoded_blue +#define TO_DECODED_BLUE transfer.custom.to_decoded_blue + + + static void to_rgb(const libcolour_colour_t *restrict from, libcolour_rgb_t *restrict to); static void to_srgb(const libcolour_colour_t *restrict from, libcolour_srgb_t *restrict to); static void to_ciexyy(const libcolour_colour_t *restrict from, libcolour_ciexyy_t *restrict to); @@ -73,9 +87,9 @@ rgb_encode(libcolour_rgb_t *restrict colour, const libcolour_rgb_t *restrict spa if (colour->G < 0) g_sign = -1, colour->G = -colour->G; if (colour->B < 0) b_sign = -1, colour->B = -colour->B; if (space->encoding_type == LIBCOLOUR_ENCODING_TYPE_SIMPLE) { - colour->R = xpow(colour->R, 1 / space->gamma); - colour->G = xpow(colour->G, 1 / space->gamma); - colour->B = xpow(colour->B, 1 / space->gamma); + colour->R = xpow(colour->R, 1 / space->GAMMA); + colour->G = xpow(colour->G, 1 / space->GAMMA); + colour->B = xpow(colour->B, 1 / space->GAMMA); } else { colour->R = REGULAR(space, colour->R); colour->G = REGULAR(space, colour->G); @@ -86,9 +100,9 @@ rgb_encode(libcolour_rgb_t *restrict colour, const libcolour_rgb_t *restrict spa colour->B *= b_sign; break; case LIBCOLOUR_ENCODING_TYPE_CUSTOM: - colour->R = (space->to_encoded_red)(colour->R); - colour->G = (space->to_encoded_green)(colour->G); - colour->B = (space->to_encoded_blue)(colour->B); + colour->R = (space->TO_ENCODED_RED)(colour->R); + colour->G = (space->TO_ENCODED_GREEN)(colour->G); + colour->B = (space->TO_ENCODED_BLUE)(colour->B); break; default: fprintf(stderr, "libcolour: invalid encoding type\n"); @@ -109,9 +123,9 @@ rgb_decode(libcolour_rgb_t *restrict colour, const libcolour_rgb_t *restrict spa if (colour->G < 0) g_sign = -1, colour->G = -colour->G; if (colour->B < 0) b_sign = -1, colour->B = -colour->B; if (space->encoding_type == LIBCOLOUR_ENCODING_TYPE_SIMPLE) { - colour->R = xpow(colour->R, space->gamma); - colour->G = xpow(colour->G, space->gamma); - colour->B = xpow(colour->B, space->gamma); + colour->R = xpow(colour->R, space->GAMMA); + colour->G = xpow(colour->G, space->GAMMA); + colour->B = xpow(colour->B, space->GAMMA); } else { colour->R = INVREGULAR(space, colour->R); colour->G = INVREGULAR(space, colour->G); @@ -122,9 +136,9 @@ rgb_decode(libcolour_rgb_t *restrict colour, const libcolour_rgb_t *restrict spa colour->B *= b_sign; break; case LIBCOLOUR_ENCODING_TYPE_CUSTOM: - colour->R = (space->to_decoded_red)(colour->R); - colour->G = (space->to_decoded_green)(colour->G); - colour->B = (space->to_decoded_blue)(colour->B); + colour->R = (space->TO_DECODED_RED)(colour->R); + colour->G = (space->TO_DECODED_GREEN)(colour->G); + colour->B = (space->TO_DECODED_BLUE)(colour->B); break; default: fprintf(stderr, "libcolour: invalid encoding type\n"); @@ -139,19 +153,19 @@ rgb_same_transfer(const libcolour_rgb_t *restrict a, const libcolour_rgb_t *rest return 0; switch (a->encoding_type) { case LIBCOLOUR_ENCODING_TYPE_SIMPLE: - return a->gamma == b->gamma; + return a->GAMMA == b->GAMMA; case LIBCOLOUR_ENCODING_TYPE_REGULAR: - return a->gamma == b->gamma && - a->offset == b->offset && - a->slope == b->slope && - a->transition == b->transition; + return a->GAMMA == b->GAMMA && + a->OFFSET == b->OFFSET && + a->SLOPE == b->SLOPE && + a->TRANSITION == b->TRANSITION; case LIBCOLOUR_ENCODING_TYPE_CUSTOM: - return a->to_encoded_red == b->to_encoded_red && - a->to_encoded_green == b->to_encoded_green && - a->to_encoded_blue == b->to_encoded_blue && - a->to_decoded_red == b->to_decoded_red && - a->to_decoded_green == b->to_decoded_green && - a->to_decoded_blue == b->to_decoded_blue; + return a->TO_ENCODED_RED == b->TO_ENCODED_RED && + a->TO_ENCODED_GREEN == b->TO_ENCODED_GREEN && + a->TO_ENCODED_BLUE == b->TO_ENCODED_BLUE && + a->TO_DECODED_RED == b->TO_DECODED_RED && + a->TO_DECODED_GREEN == b->TO_DECODED_GREEN && + a->TO_DECODED_BLUE == b->TO_DECODED_BLUE; default: return 1; } diff --git a/libcolour-template.c b/libcolour-template.c index 3862fce..80568de 100644 --- a/libcolour-template.c +++ b/libcolour-template.c @@ -16,7 +16,22 @@ #endif -#define MARSHAL_VERSION 0 +#define MARSHAL_VERSION 0 + + + +#define SLOPE transfer.regular.slope +#define TRANSITIONINV transfer.regular.transitioninv +#define TRANSITION transfer.regular.transition +#define GAMMA transfer.regular.gamma +#define OFFSET transfer.regular.offset +#define TO_ENCODED_RED transfer.custom.to_encoded_red +#define TO_DECODED_RED transfer.custom.to_decoded_red +#define TO_ENCODED_GREEN transfer.custom.to_encoded_green +#define TO_DECODED_GREEN transfer.custom.to_decoded_green +#define TO_ENCODED_BLUE transfer.custom.to_encoded_blue +#define TO_DECODED_BLUE transfer.custom.to_decoded_blue + TYPE @@ -338,8 +353,8 @@ get_transfer_function(libcolour_colour_t *cs) if (cs->model == LIBCOLOUR_RGB) { switch (cs->rgb.colour_space) { case LIBCOLOUR_RGB_COLOUR_SPACE_ECI_RGB_V2: - cs->rgb.to_encoded_red = cs->rgb.to_encoded_green = cs->rgb.to_encoded_blue = transfer_function_l_star; - cs->rgb.to_decoded_red = cs->rgb.to_decoded_green = cs->rgb.to_decoded_blue = invtransfer_function_l_star; + cs->rgb.TO_ENCODED_RED = cs->rgb.TO_ENCODED_GREEN = cs->rgb.TO_ENCODED_BLUE = transfer_function_l_star; + cs->rgb.TO_DECODED_RED = cs->rgb.TO_DECODED_GREEN = cs->rgb.TO_DECODED_BLUE = invtransfer_function_l_star; break; case LIBCOLOUR_RGB_COLOUR_SPACE_ITU_R_BT_2100_EOTF_PQ: case LIBCOLOUR_RGB_COLOUR_SPACE_ITU_R_BT_2100_OOTF_PQ: @@ -349,8 +364,8 @@ get_transfer_function(libcolour_colour_t *cs) /* TODO http://www.itu.int/dms_pubrec/itu-r/rec/bt/R-REC-BT.2100-0-201607-I!!PDF-E.pdf */ break; case LIBCOLOUR_RGB_COLOUR_SPACE_ITU_R_BT_2100_OETF_HLG: - cs->rgb.to_encoded_red = cs->rgb.to_encoded_green = cs->rgb.to_encoded_blue = transfer_function_oetf_hlg; - cs->rgb.to_decoded_red = cs->rgb.to_decoded_green = cs->rgb.to_decoded_blue = invtransfer_function_oetf_hlg; + cs->rgb.TO_ENCODED_RED = cs->rgb.TO_ENCODED_GREEN = cs->rgb.TO_ENCODED_BLUE = transfer_function_oetf_hlg; + cs->rgb.TO_DECODED_RED = cs->rgb.TO_DECODED_GREEN = cs->rgb.TO_DECODED_BLUE = invtransfer_function_oetf_hlg; break; default: break; @@ -369,21 +384,21 @@ libcolour_get_rgb_colour_space(libcolour_rgb_t *cs, libcolour_rgb_colour_space_t if (get_matrices(cs)) return -1; if (cs->encoding_type == LIBCOLOUR_ENCODING_TYPE_REGULAR) - cs->transitioninv = cs->transition * cs->slope; + cs->TRANSITIONINV = cs->TRANSITION * cs->SLOPE; return 0; case LIBCOLOUR_RGB_COLOUR_SPACE_CUSTOM_FROM_MATRIX: if (invert(cs->Minv, cs->M, 3) || get_primaries(cs)) return -1; if (cs->encoding_type == LIBCOLOUR_ENCODING_TYPE_REGULAR) - cs->transitioninv = cs->transition * cs->slope; + cs->TRANSITIONINV = cs->TRANSITION * cs->SLOPE; return 0; case LIBCOLOUR_RGB_COLOUR_SPACE_CUSTOM_FROM_INV_MATRIX: if (invert(cs->M, cs->Minv, 3) || get_primaries(cs)) return -1; if (cs->encoding_type == LIBCOLOUR_ENCODING_TYPE_REGULAR) - cs->transitioninv = cs->transition * cs->slope; + cs->TRANSITIONINV = cs->TRANSITION * cs->SLOPE; return 0; case LIBCOLOUR_RGB_COLOUR_SPACE_SRGB: @@ -392,10 +407,10 @@ libcolour_get_rgb_colour_space(libcolour_rgb_t *cs, libcolour_rgb_colour_space_t cs->blue = XYY(0.1500, 0.0600); cs->white = LIBCOLOUR_ILLUMINANT_D65; cs->encoding_type = LIBCOLOUR_ENCODING_TYPE_REGULAR; - cs->offset = D(0.055); - cs->gamma = D(2.4); - cs->slope = D(12.92); - cs->transition = D(0.0031306684425217108); + cs->OFFSET = D(0.055); + cs->GAMMA = D(2.4); + cs->SLOPE = D(12.92); + cs->TRANSITION = D(0.0031306684425217108); break; case LIBCOLOUR_RGB_COLOUR_SPACE_ADOBE_RGB: @@ -404,7 +419,7 @@ libcolour_get_rgb_colour_space(libcolour_rgb_t *cs, libcolour_rgb_colour_space_t cs->blue = XYY(0.1500, 0.0600); cs->white = LIBCOLOUR_ILLUMINANT_D65; cs->encoding_type = LIBCOLOUR_ENCODING_TYPE_SIMPLE; - cs->gamma = D(2.2); + cs->GAMMA = D(2.2); break; case LIBCOLOUR_RGB_COLOUR_SPACE_APPLE_RGB: @@ -413,7 +428,7 @@ libcolour_get_rgb_colour_space(libcolour_rgb_t *cs, libcolour_rgb_colour_space_t cs->blue = XYY(0.1550, 0.0700); cs->white = LIBCOLOUR_ILLUMINANT_D65; cs->encoding_type = LIBCOLOUR_ENCODING_TYPE_SIMPLE; - cs->gamma = D(1.8); + cs->GAMMA = D(1.8); break; case LIBCOLOUR_RGB_COLOUR_SPACE_BEST_RGB: @@ -422,7 +437,7 @@ libcolour_get_rgb_colour_space(libcolour_rgb_t *cs, libcolour_rgb_colour_space_t cs->blue = XYY(0.1300, 0.0350); cs->white = LIBCOLOUR_ILLUMINANT_D50; cs->encoding_type = LIBCOLOUR_ENCODING_TYPE_SIMPLE; - cs->gamma = D(2.2); + cs->GAMMA = D(2.2); break; case LIBCOLOUR_RGB_COLOUR_SPACE_BETA_RGB: @@ -431,7 +446,7 @@ libcolour_get_rgb_colour_space(libcolour_rgb_t *cs, libcolour_rgb_colour_space_t cs->blue = XYY(0.1265, 0.0352); cs->white = LIBCOLOUR_ILLUMINANT_D50; cs->encoding_type = LIBCOLOUR_ENCODING_TYPE_SIMPLE; - cs->gamma = D(2.2); + cs->GAMMA = D(2.2); break; case LIBCOLOUR_RGB_COLOUR_SPACE_BRUCE_RGB: @@ -440,7 +455,7 @@ libcolour_get_rgb_colour_space(libcolour_rgb_t *cs, libcolour_rgb_colour_space_t cs->blue = XYY(0.1500, 0.0600); cs->white = LIBCOLOUR_ILLUMINANT_D65; cs->encoding_type = LIBCOLOUR_ENCODING_TYPE_SIMPLE; - cs->gamma = D(2.2); + cs->GAMMA = D(2.2); break; case LIBCOLOUR_RGB_COLOUR_SPACE_CIE_RGB: @@ -449,7 +464,7 @@ libcolour_get_rgb_colour_space(libcolour_rgb_t *cs, libcolour_rgb_colour_space_t cs->blue = XYY(0.1670, 0.0090); cs->white = LIBCOLOUR_ILLUMINANT_E; cs->encoding_type = LIBCOLOUR_ENCODING_TYPE_SIMPLE; - cs->gamma = D(2.2); + cs->GAMMA = D(2.2); break; case LIBCOLOUR_RGB_COLOUR_SPACE_COLORMATCH_RGB: @@ -458,7 +473,7 @@ libcolour_get_rgb_colour_space(libcolour_rgb_t *cs, libcolour_rgb_colour_space_t cs->blue = XYY(0.1500, 0.0750); cs->white = LIBCOLOUR_ILLUMINANT_D50; cs->encoding_type = LIBCOLOUR_ENCODING_TYPE_SIMPLE; - cs->gamma = D(1.8); + cs->GAMMA = D(1.8); break; case LIBCOLOUR_RGB_COLOUR_SPACE_DCI_P3_D65: @@ -467,7 +482,7 @@ libcolour_get_rgb_colour_space(libcolour_rgb_t *cs, libcolour_rgb_colour_space_t cs->blue = XYY(0.1500, 0.0600); cs->white = LIBCOLOUR_ILLUMINANT_D65; cs->encoding_type = LIBCOLOUR_ENCODING_TYPE_SIMPLE; - cs->gamma = D(2.6); + cs->GAMMA = D(2.6); break; case LIBCOLOUR_RGB_COLOUR_SPACE_DCI_P3_THEATER: @@ -476,7 +491,7 @@ libcolour_get_rgb_colour_space(libcolour_rgb_t *cs, libcolour_rgb_colour_space_t cs->blue = XYY(0.1500, 0.0600); cs->white = XYY(0.314, 0.351); cs->encoding_type = LIBCOLOUR_ENCODING_TYPE_SIMPLE; - cs->gamma = D(2.6); + cs->GAMMA = D(2.6); break; case LIBCOLOUR_RGB_COLOUR_SPACE_DON_RGB_4: @@ -485,7 +500,7 @@ libcolour_get_rgb_colour_space(libcolour_rgb_t *cs, libcolour_rgb_colour_space_t cs->blue = XYY(0.1300, 0.0350); cs->white = LIBCOLOUR_ILLUMINANT_D50; cs->encoding_type = LIBCOLOUR_ENCODING_TYPE_SIMPLE; - cs->gamma = D(2.2); + cs->GAMMA = D(2.2); break; case LIBCOLOUR_RGB_COLOUR_SPACE_ECI_RGB: @@ -494,7 +509,7 @@ libcolour_get_rgb_colour_space(libcolour_rgb_t *cs, libcolour_rgb_colour_space_t cs->blue = XYY(0.1400, 0.0800); cs->white = LIBCOLOUR_ILLUMINANT_D50; cs->encoding_type = LIBCOLOUR_ENCODING_TYPE_SIMPLE; - cs->gamma = D(1.8); + cs->GAMMA = D(1.8); break; case LIBCOLOUR_RGB_COLOUR_SPACE_ECI_RGB_V2: @@ -511,7 +526,7 @@ libcolour_get_rgb_colour_space(libcolour_rgb_t *cs, libcolour_rgb_colour_space_t cs->blue = XYY(0.1100, 0.0050); cs->white = LIBCOLOUR_ILLUMINANT_D50; cs->encoding_type = LIBCOLOUR_ENCODING_TYPE_SIMPLE; - cs->gamma = D(2.2); + cs->GAMMA = D(2.2); break; case LIBCOLOUR_RGB_COLOUR_SPACE_ITU_R_BT_601_625_LINE: @@ -520,10 +535,10 @@ libcolour_get_rgb_colour_space(libcolour_rgb_t *cs, libcolour_rgb_colour_space_t cs->blue = XYY(0.1500, 0.0060); cs->white = LIBCOLOUR_ILLUMINANT_D65; cs->encoding_type = LIBCOLOUR_ENCODING_TYPE_REGULAR; - cs->gamma = 1 / D(0.45); - cs->offset = D(0.09929682680944); - cs->slope = D(4.5); - cs->transition = D(0.018053968510807); + cs->GAMMA = 1 / D(0.45); + cs->OFFSET = D(0.09929682680944); + cs->SLOPE = D(4.5); + cs->TRANSITION = D(0.018053968510807); break; case LIBCOLOUR_RGB_COLOUR_SPACE_ITU_R_BT_601_525_LINE: @@ -532,10 +547,10 @@ libcolour_get_rgb_colour_space(libcolour_rgb_t *cs, libcolour_rgb_colour_space_t cs->blue = XYY(0.1550, 0.0700); cs->white = LIBCOLOUR_ILLUMINANT_D65; cs->encoding_type = LIBCOLOUR_ENCODING_TYPE_REGULAR; - cs->gamma = 1 / D(0.45); - cs->offset = D(0.09929682680944); - cs->slope = D(4.5); - cs->transition = D(0.018053968510807); + cs->GAMMA = 1 / D(0.45); + cs->OFFSET = D(0.09929682680944); + cs->SLOPE = D(4.5); + cs->TRANSITION = D(0.018053968510807); break; case LIBCOLOUR_RGB_COLOUR_SPACE_ITU_R_BT_709: @@ -544,10 +559,10 @@ libcolour_get_rgb_colour_space(libcolour_rgb_t *cs, libcolour_rgb_colour_space_t cs->blue = XYY(0.1500, 0.0600); cs->white = LIBCOLOUR_ILLUMINANT_D65; cs->encoding_type = LIBCOLOUR_ENCODING_TYPE_REGULAR; - cs->gamma = 1 / D(0.45); - cs->offset = D(0.09929682680944); - cs->slope = D(4.5); - cs->transition = D(0.018053968510807); + cs->GAMMA = 1 / D(0.45); + cs->OFFSET = D(0.09929682680944); + cs->SLOPE = D(4.5); + cs->TRANSITION = D(0.018053968510807); break; case LIBCOLOUR_RGB_COLOUR_SPACE_ITU_R_BT_2020: @@ -556,10 +571,10 @@ libcolour_get_rgb_colour_space(libcolour_rgb_t *cs, libcolour_rgb_colour_space_t cs->blue = XYY(0.1310, 0.0460); cs->white = LIBCOLOUR_ILLUMINANT_D65; cs->encoding_type = LIBCOLOUR_ENCODING_TYPE_REGULAR; - cs->gamma = 1 / D(0.45); - cs->offset = D(0.09929682680944); - cs->slope = D(4.5); - cs->transition = D(0.018053968510807); + cs->GAMMA = 1 / D(0.45); + cs->OFFSET = D(0.09929682680944); + cs->SLOPE = D(4.5); + cs->TRANSITION = D(0.018053968510807); break; case LIBCOLOUR_RGB_COLOUR_SPACE_ITU_R_BT_2100_EOTF_PQ: @@ -589,10 +604,10 @@ libcolour_get_rgb_colour_space(libcolour_rgb_t *cs, libcolour_rgb_colour_space_t cs->blue = XYY(0.1400, 0.0800); cs->white = LIBCOLOUR_ILLUMINANT_C; cs->encoding_type = LIBCOLOUR_ENCODING_TYPE_REGULAR; - cs->gamma = 1 / D(0.45); - cs->offset = D(0.09929682680944); - cs->slope = D(4.5); - cs->transition = D(0.018053968510807); + cs->GAMMA = 1 / D(0.45); + cs->OFFSET = D(0.09929682680944); + cs->SLOPE = D(4.5); + cs->TRANSITION = D(0.018053968510807); break; case LIBCOLOUR_RGB_COLOUR_SPACE_PAL_SECAM_RGB: @@ -601,10 +616,10 @@ libcolour_get_rgb_colour_space(libcolour_rgb_t *cs, libcolour_rgb_colour_space_t cs->blue = XYY(0.1500, 0.0600); cs->white = LIBCOLOUR_ILLUMINANT_D65; cs->encoding_type = LIBCOLOUR_ENCODING_TYPE_REGULAR; - cs->gamma = 1 / D(0.45); - cs->offset = D(0.09929682680944); - cs->slope = D(4.5); - cs->transition = D(0.018053968510807); + cs->GAMMA = 1 / D(0.45); + cs->OFFSET = D(0.09929682680944); + cs->SLOPE = D(4.5); + cs->TRANSITION = D(0.018053968510807); break; case LIBCOLOUR_RGB_COLOUR_SPACE_PROPHOTO_RGB: @@ -613,7 +628,7 @@ libcolour_get_rgb_colour_space(libcolour_rgb_t *cs, libcolour_rgb_colour_space_t cs->blue = XYY(0.0366, 0.0001); cs->white = LIBCOLOUR_ILLUMINANT_D50; cs->encoding_type = LIBCOLOUR_ENCODING_TYPE_SIMPLE; - cs->gamma = D(1.8); + cs->GAMMA = D(1.8); break; case LIBCOLOUR_RGB_COLOUR_SPACE_SGI_RGB: @@ -622,7 +637,7 @@ libcolour_get_rgb_colour_space(libcolour_rgb_t *cs, libcolour_rgb_colour_space_t cs->blue = XYY(0.1550, 0.0700); cs->white = LIBCOLOUR_ILLUMINANT_D50; cs->encoding_type = LIBCOLOUR_ENCODING_TYPE_SIMPLE; - cs->gamma = D(1.47); + cs->GAMMA = D(1.47); break; case LIBCOLOUR_RGB_COLOUR_SPACE_SMPTE_240M_RGB: @@ -631,10 +646,10 @@ libcolour_get_rgb_colour_space(libcolour_rgb_t *cs, libcolour_rgb_colour_space_t cs->blue = XYY(0.1550, 0.0700); cs->white = LIBCOLOUR_ILLUMINANT_D65; cs->encoding_type = LIBCOLOUR_ENCODING_TYPE_REGULAR; - cs->gamma = 1 / D(0.45); - cs->offset = D(0.1115721957735072); - cs->slope = D(4.0); - cs->transition = D(0.022821585552393633); + cs->GAMMA = 1 / D(0.45); + cs->OFFSET = D(0.1115721957735072); + cs->SLOPE = D(4.0); + cs->TRANSITION = D(0.022821585552393633); break; case LIBCOLOUR_RGB_COLOUR_SPACE_SMPTE_C_RGB: @@ -643,10 +658,10 @@ libcolour_get_rgb_colour_space(libcolour_rgb_t *cs, libcolour_rgb_colour_space_t cs->blue = XYY(0.1550, 0.0700); cs->white = LIBCOLOUR_ILLUMINANT_D65; cs->encoding_type = LIBCOLOUR_ENCODING_TYPE_REGULAR; - cs->gamma = 1 / D(0.45); - cs->offset = D(0.09929682680944); - cs->slope = D(4.5); - cs->transition = D(0.018053968510807); + cs->GAMMA = 1 / D(0.45); + cs->OFFSET = D(0.09929682680944); + cs->SLOPE = D(4.5); + cs->TRANSITION = D(0.018053968510807); break; case LIBCOLOUR_RGB_COLOUR_SPACE_WIDE_GAMUT_RGB: @@ -655,7 +670,7 @@ libcolour_get_rgb_colour_space(libcolour_rgb_t *cs, libcolour_rgb_colour_space_t cs->blue = XYY(0.1570, 0.0180); cs->white = LIBCOLOUR_ILLUMINANT_D50; cs->encoding_type = LIBCOLOUR_ENCODING_TYPE_SIMPLE; - cs->gamma = D(2.19921875); + cs->GAMMA = D(2.19921875); break; default: @@ -663,7 +678,7 @@ libcolour_get_rgb_colour_space(libcolour_rgb_t *cs, libcolour_rgb_colour_space_t return -1; } if (cs->encoding_type == LIBCOLOUR_ENCODING_TYPE_REGULAR) - cs->transitioninv = cs->transition * cs->slope; + cs->TRANSITIONINV = cs->TRANSITION * cs->SLOPE; cs->colour_space = space; cs->white_r = cs->white_g = cs->white_b = 1; if (get_matrices(cs) || libcolour_proper((libcolour_colour_t *)cs)) @@ -722,8 +737,8 @@ libcolour_unmarshal(libcolour_colour_t *colour, const void *buf) } if (colour) { if (colour->model == LIBCOLOUR_RGB) { - colour->rgb.to_encoded_red = colour->rgb.to_encoded_green = colour->rgb.to_encoded_blue = NULL; - colour->rgb.to_decoded_red = colour->rgb.to_decoded_green = colour->rgb.to_decoded_blue = NULL; + colour->rgb.TO_ENCODED_RED = colour->rgb.TO_ENCODED_GREEN = colour->rgb.TO_ENCODED_BLUE = NULL; + colour->rgb.TO_DECODED_RED = colour->rgb.TO_DECODED_GREEN = colour->rgb.TO_DECODED_BLUE = NULL; } get_transfer_function(colour); } diff --git a/libcolour.h b/libcolour.h index 63d37a1..e685d8f 100644 --- a/libcolour.h +++ b/libcolour.h @@ -396,17 +396,26 @@ typedef struct libcolour_rgb_##RES {\ TYPE B;\ int with_transfer;\ enum libcolour_encoding_type encoding_type;\ - TYPE gamma;\ - TYPE offset;\ - TYPE slope;\ - TYPE transition;\ - TYPE transitioninv;\ - TYPE (*to_encoded_red)(TYPE);\ - TYPE (*to_decoded_red)(TYPE);\ - TYPE (*to_encoded_green)(TYPE);\ - TYPE (*to_decoded_green)(TYPE);\ - TYPE (*to_encoded_blue)(TYPE);\ - TYPE (*to_decoded_blue)(TYPE);\ + union {\ + struct {\ + TYPE gamma;\ + } simple;\ + struct {\ + TYPE gamma;\ + TYPE offset;\ + TYPE slope;\ + TYPE transition;\ + TYPE transitioninv;\ + } regular;\ + struct {\ + TYPE (*to_encoded_red)(TYPE);\ + TYPE (*to_decoded_red)(TYPE);\ + TYPE (*to_encoded_green)(TYPE);\ + TYPE (*to_decoded_green)(TYPE);\ + TYPE (*to_encoded_blue)(TYPE);\ + TYPE (*to_decoded_blue)(TYPE);\ + } custom;\ + } transfer;\ struct libcolour_ciexyy_##RES red;\ struct libcolour_ciexyy_##RES green;\ struct libcolour_ciexyy_##RES blue;\ diff --git a/test.c b/test.c index f6fb2e1..5264694 100644 --- a/test.c +++ b/test.c @@ -13,6 +13,21 @@ #define libcolour_unmarshal libcolour_unmarshal_lf + +#define SLOPE transfer.regular.slope +#define TRANSITIONINV transfer.regular.transitioninv +#define TRANSITION transfer.regular.transition +#define GAMMA transfer.regular.gamma +#define OFFSET transfer.regular.offset +#define TO_ENCODED_RED transfer.custom.to_encoded_red +#define TO_DECODED_RED transfer.custom.to_decoded_red +#define TO_ENCODED_GREEN transfer.custom.to_encoded_green +#define TO_DECODED_GREEN transfer.custom.to_decoded_green +#define TO_ENCODED_BLUE transfer.custom.to_encoded_blue +#define TO_DECODED_BLUE transfer.custom.to_decoded_blue + + + #ifndef SKIP_2CONVERT static int test_2convert(libcolour_colour_t *c1, libcolour_colour_t *c2, libcolour_colour_t *c3) @@ -391,15 +406,15 @@ main(int argc, char *argv[]) if (c2.rgb.white_r != 1 || c2.rgb.white_g != 1 || c2.rgb.white_b != 1 || c2.rgb.red.model != LIBCOLOUR_CIEXYY || c2.rgb.green.model != LIBCOLOUR_CIEXYY || c2.rgb.blue.model != LIBCOLOUR_CIEXYY || c2.rgb.white.model != LIBCOLOUR_CIEXYY || - c2.rgb.colour_space != LIBCOLOUR_RGB_COLOUR_SPACE_SRGB || c2.rgb.gamma != 2.4 || - c2.rgb.encoding_type != LIBCOLOUR_ENCODING_TYPE_REGULAR || c2.rgb.slope != 12.92 - || c2.rgb.offset != 0.055 || c2.rgb.transitioninv != c2.rgb.transition * c2.rgb.slope || - !ftest(c2.rgb.transition, 0.00313067, 0.00000001)) { + c2.rgb.colour_space != LIBCOLOUR_RGB_COLOUR_SPACE_SRGB || c2.rgb.GAMMA != 2.4 || + c2.rgb.encoding_type != LIBCOLOUR_ENCODING_TYPE_REGULAR || c2.rgb.SLOPE != 12.92 + || c2.rgb.OFFSET != 0.055 || c2.rgb.TRANSITIONINV != c2.rgb.TRANSITION * c2.rgb.SLOPE || + !ftest(c2.rgb.TRANSITION, 0.00313067, 0.00000001)) { printf("LIBCOLOUR_RGB_COLOUR_SPACE_SRGB failed\n"), rc = 0; goto colour_spaces_done; } - t1 = c2.rgb.transition * c2.rgb.slope; - t2 = (1 + c2.rgb.offset) * pow(c2.rgb.transition, 1 / c2.rgb.gamma) - c2.rgb.offset; + t1 = c2.rgb.TRANSITION * c2.rgb.SLOPE; + t2 = (1 + c2.rgb.OFFSET) * pow(c2.rgb.TRANSITION, 1 / c2.rgb.GAMMA) - c2.rgb.OFFSET; if (!ftest(t1, t2, 0.0000001) || c2.rgb.white.Y != 1 || c2.rgb.red.x != 0.64 || c2.rgb.red.y != 0.33 || !ftest(c2.rgb.red.Y, 0.21265, 0.00005) || c2.rgb.green.x != 0.30 || c2.rgb.green.y != 0.60 || !ftest(c2.rgb.green.Y, 0.71515, 0.00005) || @@ -546,14 +561,14 @@ main(int argc, char *argv[]) } c1.rgb.encoding_type = LIBCOLOUR_ENCODING_TYPE_SIMPLE; - c1.rgb.gamma = 2.2; + c1.rgb.GAMMA = 2.2; c1.rgb.with_transfer = 0; c1.rgb.R = 0.25; c1.rgb.G = 0.5; c1.rgb.B = 0.75; c4 = c3 = c2 = c1; c2.rgb.with_transfer = c3.srgb.with_transfer = 1; - c3.rgb.gamma = c4.rgb.gamma = 1.8; + c3.rgb.GAMMA = c4.rgb.GAMMA = 1.8; if (libcolour_convert(&c1, &c2)) goto fail; if (libcolour_convert(&c2, &c3)) @@ -621,12 +636,12 @@ colour_spaces_done: if (libcolour_get_rgb_colour_space(&c1.rgb, LIBCOLOUR_RGB_COLOUR_SPACE_ECI_RGB_V2)) goto fail; c3 = c1; - c1.rgb.to_encoded_red = NULL; - c1.rgb.to_encoded_green = NULL; - c1.rgb.to_encoded_blue = NULL; - c1.rgb.to_decoded_red = NULL; - c1.rgb.to_decoded_green = NULL; - c1.rgb.to_decoded_blue = NULL; + c1.rgb.TO_ENCODED_RED = NULL; + c1.rgb.TO_ENCODED_GREEN = NULL; + c1.rgb.TO_ENCODED_BLUE = NULL; + c1.rgb.TO_DECODED_RED = NULL; + c1.rgb.TO_DECODED_GREEN = NULL; + c1.rgb.TO_DECODED_BLUE = NULL; if (libcolour_marshal(&c1, NULL) > sizeof(buf)) { printf("libcolour_marshal failed\n"), rc = 0; goto marshal_done; -- cgit v1.2.3-70-g09d2