diff options
Diffstat (limited to '')
| -rw-r--r-- | LIBCOLOUR_CIELCHUV.7 | 95 | ||||
| -rw-r--r-- | LIBCOLOUR_RGB.7 | 202 | ||||
| -rw-r--r-- | LIBCOLOUR_SRGB.7 | 2 | ||||
| -rw-r--r-- | convert-template.c | 64 | ||||
| -rw-r--r-- | libcolour-template.c | 139 | ||||
| -rw-r--r-- | libcolour.h | 31 | ||||
| -rw-r--r-- | test.c | 43 | 
7 files changed, 463 insertions, 113 deletions
| 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;\ @@ -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; | 
