Colour Spaces
*************

A colour in libcolour is represented using

     typedef union libcolour_colour {
         enum libcolour_model model;
         struct libcolour_rgb rgb;
         struct libcolour_srgb srgb;
         struct libcolour_ciexyy ciexyy;
         struct libcolour_ciexyz ciexyz;
         struct libcolour_cielab cielab;
         struct libcolour_cieluv cieluv;
         struct libcolour_cielch cielch;
         struct libcolour_yiq yiq;
         struct libcolour_ydbdr ydbdr;
         struct libcolour_yuv yuv;
         struct libcolour_ypbpr ypbpr;
         struct libcolour_ycgco ycgco;
         struct libcolour_cie1960ucs cie1960ucs;
         struct libcolour_cieuvw cieuvw;
     } libcolour_colour_t;

where .model is used to select colour model. Each enum and struct is also typedef:ed to the same name but with an _t suffix.

The macro LIBCOLOUR_LIST_MODELS can be used to list all available colour models. It expands to a list of calls to X with the appropriate value for .model as the first argument and the struct, using the typedef name with the _t suffix, which is used to represent colours in that colour model as the second argument. It can used like this:

     void print_libcolour_srgb_t(libcolour_srgb* colour)
     {
         printf("sRGB(%lf, %lf, %lf, with_gamma = %i)\n",
                colour->R, colour->G, colour->B, colour->with_gamma);
     }

     /* ... */

     void print_colour(libcolour_colour_t* colour)
     {
     #define X(MODEL, TYPE)\
         case MODEL:\
             print_##TYPE((TYPE*)colour);\
             break;
     #undef X
         switch (colour->model) {
         LIBCOLOUR_LIST_MODELS
         default:
             printf("Unknown colour model!\n");
             break;
         }
     }

To convert between a colour into another colour space, the function libcolour_convert is used. It takes two arguments, both if the type libcolour_colour_t*. The first parameter is const, it shall be the colour you want to convert. The second parameter shall be a different pointer, and it shall have it's .model set to the wanted colour model, and any colour space specific parameter for that model shall also be set. It can be used like this:

     int to_srgb(const libcolour_colour* from, libcolour_srgb_t* to)
     {
         to->model = LIBCOLOUR_SRGB;
         to->with_gamma = 1;
         return libcolour_convert(from, to);
     }

libcolour_convert return 0 on success, on error -1 is returned and errno is to indicate the error. Possible errors are:

EINVAL
     Invalid colour model.

Colours obtained by conversion can be out of gamut. In RGB colour spaces, including sRGB, this means that at least one of the values (.R, .G, or .B) is less than 0 or greater than 1. libcolour does not provide any colour-matching functions for finding an in-gamut colour.

Generic RGB
===========

RGB colours, of any RGB colour space, are presented with struct libcolour_rgb (libcolour_rgb_t), and the .model member shall be set to LIBCOLOUR_RGB. In union libcolour_colour, .rgb are used for RGB colours. RGB colours are additive.

struct libcolour_rgb has the following members

enum libcolour_model model
     Shall be set to LIBCOLOUR_RGB.

double R
     The red value. In-gamut values are between 0 and 1, inclusively.

double G
     The green value. In-gamut values are between 0 and 1, inclusively.

double B
     The blue value. In-gamut values are between 0 and 1, inclusively.

int with_gamma
     Whether the the transfer function is applied to the values of .R, .G, and .B, which makes them non-linear.

enum libcolour_encoding_type encoding_type
     One of the following:

     LIBCOLOUR_ENCODING_TYPE_LINEAR
          The colour space does not have a transfer function.

     LIBCOLOUR_ENCODING_TYPE_SIMPLE
          The colour space uses a simple gamma transfer function that only uses the gamma parameter.

     LIBCOLOUR_ENCODING_TYPE_REGULAR
          The colour space uses a linear–gamma hybrid transfer function that uses the gamma, offset, slope, and transition parameters.

     LIBCOLOUR_ENCODING_TYPE_CUSTOM
          The colour space uses a custom transfer function.

double gamma
     The gamma parameter of the transfer function. Ignored unless .encoding_type is LIBCOLOUR_ENCODING_TYPE_SIMPLE or LIBCOLOUR_ENCODING_TYPE_REGULAR.

double offset
     The offset parameter of the transfer function. Ignored unless .encoding_type is LIBCOLOUR_ENCODING_TYPE_REGULAR.

double slope
     The slope parameter of the transfer function. Ignored unless .encoding_type is LIBCOLOUR_ENCODING_TYPE_REGULAR.

double transition
     The transition parameter of the transfer function. Ignored unless .encoding_type is LIBCOLOUR_ENCODING_TYPE_REGULAR.

double transitioninv
     The inverse value of the 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. Ignored unless .encoding_type is LIBCOLOUR_ENCODING_TYPE_REGULAR.

double (*to_encoded_red)(double)
     Function used to apply the red channels transfer function to a value. Ignored unless .encoding_type is LIBCOLOUR_ENCODING_TYPE_CUSTOM.

double (*to_decoded_red)(double)
     Function used to unapply the red channels transfer function from a value. Ignored unless .encoding_type is LIBCOLOUR_ENCODING_TYPE_CUSTOM.

double (*to_encoded_green)(double)
     Function used to apply the green channels transfer function to a value. Ignored unless .encoding_type is LIBCOLOUR_ENCODING_TYPE_CUSTOM.

double (*to_decoded_green)(double)
     Function used to unapply the green channels transfer function from a value. Ignored unless .encoding_type is LIBCOLOUR_ENCODING_TYPE_CUSTOM.

double (*to_encoded_blue)(double)
     Function used to apply the blue channels transfer function to a value. Ignored unless .encoding_type is LIBCOLOUR_ENCODING_TYPE_CUSTOM.

double (*to_decoded_blue)(double)
     Function used to unapply the blue channels transfer function from a value. Ignored unless .encoding_type is LIBCOLOUR_ENCODING_TYPE_CUSTOM.

struct libcolour_ciexyy red
     The CIE xyY value of the red primarily.

struct libcolour_ciexyy green
     The CIE xyY value of the green primarily.

struct libcolour_ciexyy blue
     The CIE xyY value of the blue primarily.

struct libcolour_ciexyy white
     The CIE xyY value of the white point, the Y value should usually be 1.

double white_r
     The red value of the white point, should usually by 1.

double white_g
     The green value of the white point, should usually by 1.

double white_b
     The blue value of the white point, should usually by 1.

double M[3][3]
     Matrix used to convert a colour to CIE 1931 XYZ.

double Minv[3][3]
     Matrix used to convert a colour from CIE 1931 XYZ.

enum libcolour_rgb_colour_space colour_space
     The colour space. Set automatically.

libcolour_get_rgb_colour_space is set the values in a libcolour_rgb_t to the those used to represent a specified RGB colour space. libcolour_get_rgb_colour_space has two arguments:

libcolour_rgb_t*
     The struct whose members shall be set to represent to selected colour space.

enum libcolour_rgb_colour_space
     The selected colour space.

libcolour_get_rgb_colour_space return 0 on success, on error -1 is returned and errno is to indicate the error. Possible errors are:

EINVAL
     Invalid colour space.

EDOM
     The specified colour space parameters cannot be used as it results in matematical errors.

The following values are available for enum libcolour_rgb_colour_space (libcolour_rgb_colour_space_t):

LIBCOLOUR_RGB_COLOUR_SPACE_CUSTOM_FROM_MEASUREMENTS
     A custom colour space. .red, .green, .blue, .white, .white_r, .white_g and .white_b must be set. The transfer functions, and parameters, must be set manually. .colour_space must be set to any negative value, LIBCOLOUR_RGB_COLOUR_SPACE_CUSTOM_FROM_MEASUREMENTS (zero), LIBCOLOUR_RGB_COLOUR_SPACE_CUSTOM_FROM_MATRIX, or LIBCOLOUR_RGB_COLOUR_SPACE_CUSTOM_FROM_INV_MATRIX. .red.Y, .green.Y, .blue.Y can be any value.

LIBCOLOUR_RGB_COLOUR_SPACE_CUSTOM_FROM_MATRIX
     A custom colour space. .M, .white_r, .white_g and .white_b must be set. The transfer functions, and parameters, must be set manually. .colour_space must be set to any negative value, LIBCOLOUR_RGB_COLOUR_SPACE_CUSTOM_FROM_MEASUREMENTS (zero), LIBCOLOUR_RGB_COLOUR_SPACE_CUSTOM_FROM_MATRIX, or LIBCOLOUR_RGB_COLOUR_SPACE_CUSTOM_FROM_INV_MATRIX.

LIBCOLOUR_RGB_COLOUR_SPACE_CUSTOM_FROM_INV_MATRIX
     A custom colour space. .Minv, .white_r, .white_g and .white_b must be set. The transfer functions, and parameters, must be set manually. .colour_space must be set to any negative value, LIBCOLOUR_RGB_COLOUR_SPACE_CUSTOM_FROM_MEASUREMENTS (zero), LIBCOLOUR_RGB_COLOUR_SPACE_CUSTOM_FROM_MATRIX, or LIBCOLOUR_RGB_COLOUR_SPACE_CUSTOM_FROM_INV_MATRIX.

LIBCOLOUR_RGB_COLOUR_SPACE_SRGB
     The sRGB colour space.

LIBCOLOUR_RGB_COLOUR_SPACE_ADOBE_RGB
     The Adobe RGB colour space.

LIBCOLOUR_RGB_COLOUR_SPACE_APPLE_RGB
     The Apple RGB (1998) colour space.

LIBCOLOUR_RGB_COLOUR_SPACE_BEST_RGB
     The Best RGB colour space.

LIBCOLOUR_RGB_COLOUR_SPACE_BETA_RGB
     The Beta RGB colour space.

LIBCOLOUR_RGB_COLOUR_SPACE_BRUCE_RGB
     The Bruce RGB colour space.

LIBCOLOUR_RGB_COLOUR_SPACE_CIE_RGB
     The CIE 1931 RGB colour space.

LIBCOLOUR_RGB_COLOUR_SPACE_COLORMATCH_RGB
     The ColorMatch RGB colour space.

LIBCOLOUR_RGB_COLOUR_SPACE_DCI_P3_D65
     The DCI-P3 D65 colour space.

LIBCOLOUR_RGB_COLOUR_SPACE_DCI_P3_THEATER
     The DCI-P3 Theater colour space.

LIBCOLOUR_RGB_COLOUR_SPACE_DON_RGB_4
     The Don RGB 4 colour space.

LIBCOLOUR_RGB_COLOUR_SPACE_ECI_RGB_V2
     The ECI RGB v2 colour space.

LIBCOLOUR_RGB_COLOUR_SPACE_EKTA_SPACE_PS5
     The Ekta Space PS5 colour space.

LIBCOLOUR_RGB_COLOUR_SPACE_ITU_R_BT_601_625_LINE
     The ITU-R Recommendation BT.601, 625 line colour space.

LIBCOLOUR_RGB_COLOUR_SPACE_ITU_R_BT_601_525_LINE
     The ITU-R Recommendation BT.601, 525 line colour space.

LIBCOLOUR_RGB_COLOUR_SPACE_ITU_R_BT_709
     The ITU-R Recommendation BT.709 colour space.

LIBCOLOUR_RGB_COLOUR_SPACE_ITU_R_BT_2020
     The ITU-R Recommendation BT.2020 colour space.

LIBCOLOUR_RGB_COLOUR_SPACE_ITU_R_BT_2100_EOTF_PQ
     The ITU-R Recommendation BT.2100 colour space, using the perceptual quantization (PQ) elctro-optical transfer function (EOTF).

LIBCOLOUR_RGB_COLOUR_SPACE_ITU_R_BT_2100_OOTF_PQ
     The ITU-R Recommendation BT.2100 colour space, using the perceptual quantization (PQ) opto-optical transfer function (OOTF).

LIBCOLOUR_RGB_COLOUR_SPACE_ITU_R_BT_2100_OETF_PQ
     The ITU-R Recommendation BT.2100 colour space, using the perceptual quantization (PQ) opto-electronic transfer function (OETF).

LIBCOLOUR_RGB_COLOUR_SPACE_ITU_R_BT_2100_EOTF_HLG
     The ITU-R Recommendation BT.2100 colour space, using the Hybrid Log-Gamma (HLG) elctro-optical transfer function (EOTF).

LIBCOLOUR_RGB_COLOUR_SPACE_ITU_R_BT_2100_OOTF_HLG
     The ITU-R Recommendation BT.2100 colour space, using the Hybrid Log-Gamma (HLG) opto-optical transfer function (OOTF).

LIBCOLOUR_RGB_COLOUR_SPACE_ITU_R_BT_2100_OETF_HLG
     The ITU-R Recommendation BT.2100 colour space, using the Hybrid Log-Gamma (HLG) opto-electronic transfer function (OETF).

LIBCOLOUR_RGB_COLOUR_SPACE_LIGHTROOM_RGB
     The Lightroom RGB colour space.

LIBCOLOUR_RGB_COLOUR_SPACE_NTSC_RGB
     The NTSC RGB colour space.

LIBCOLOUR_RGB_COLOUR_SPACE_PAL_SECAM_RGB
     The PAL/SECAM RGB colour space.

LIBCOLOUR_RGB_COLOUR_SPACE_PROPHOTO_RGB
     The ProPhoto RGB colour space.

LIBCOLOUR_RGB_COLOUR_SPACE_SGI_RGB
     The SGI RGB colour space.

LIBCOLOUR_RGB_COLOUR_SPACE_SMPTE_240M_RGB
     The SMPTE 240M RGB colour space.

LIBCOLOUR_RGB_COLOUR_SPACE_SMPTE_C_RGB
     The SMPTE C RGB colour space.

LIBCOLOUR_RGB_COLOUR_SPACE_WIDE_GAMUT_RGB
     The wide-gamut RGB colour space, also known as Adobe Wide Gamut RGB.

Call libcolour_proper(&c) on a struct libcolour_rgb_t c (done automatically for predefined colour spaces) sets c.red.model, c.green.model, and c.blue.model to LIBCOLOUR_CIEXYY, and calculate and sets the Y values for c.red, c.green, and c.blue. Zero is always normally returned, but of there is something wrong with with the values of the primaries, -1 is returned and errno is set to EDOM.

Standard RGB
============

sRGB colours are presented with struct libcolour_srgb (libcolour_srgb_t), and the .model member shall be set to LIBCOLOUR_SRGB. In union libcolour_colour, .srgb are used for sRGB colours. This is the colour model and colour space normally used on computers, it is however not the colour space your monitor have, although it is close to it. sRGB is designed after the human eye, but fails to take into account how the brain process the input to figure out which colour it actually receives.

struct libcolour_srgb has the following members

enum libcolour_model model
     Shall be set to LIBCOLOUR_SRGB.

double R
     The red value. In-gamut values are between 0 and 1, inclusively.

double G
     The green value. In-gamut values are between 0 and 1, inclusively.

double B
     The blue value. In-gamut values are between 0 and 1, inclusively.

int with_gamma
     Whether the the transfer function is applied to the values of .R, .G, and .B, which makes them non-linear.

The RGB color model, of which sRGB is a specific colour space, is an additive colour model.

For your convenience, the sRGB transfer function and its inverse function is available for your use:

double libcolour_srgb_encode(double x)
     Applies the sRGB transfer function. It's full code is

          return x <= 0.0031306684425217108
                 ? 12.92 * x
                 : 1.055 * pow(x, 1 / 2.4) - 0.055;

double libcolour_srgb_decode(double x)
     Unapplies the sRGB transfer function. It's full code is

          return x <= 0.040448236277380506
                 ? x / 12.92
                 : pow((x + 0.055) / 1.055, 2.4);

CIE xyY
=======

CIE xyY colours are presented with struct libcolour_ciexyy (libcolour_ciexyy_t), and the .model member shall be set to LIBCOLOUR_CIEXYY. In union libcolour_colour, .ciexyy are used for CIE xyY colours. This colour space is derived from CIE 1931 XYZ and is primarily used for representing chromaticities.

struct libcolour_ciexyy has the following members

enum libcolour_model model
     Shall be set to LIBCOLOUR_CIEXYY.

double x
     The x value.

double y
     The y value.

double Y
     The Y value.

CIE xyY is not additive. CIE xyY is defined by x = X/(X + Y + Z), y = Y/(X + Y + Z) where X, Y, and Z are CIE XYZ values.

CIE 1931 XYZ
============

CIE 1931 XYZ colours are presented with struct libcolour_ciexyz (libcolour_ciexyz_t), and the .model member shall be set to LIBCOLOUR_CIEXYZ. In union libcolour_colour, .ciexyz are used for CIE 1931 XYZ colours. This colour space is derived from CIE 1931 RGB and is used as an intermediary representation when converting between many colour spaces and colour models, making it very useful for device independent colour representation.

struct libcolour_ciexyz has the following members

enum libcolour_model model
     Shall be set to LIBCOLOUR_CIEXYZ.

double X
     The X value.

double Y
     The Y value.

double Z
     The Z value.

CIE 1931 XYZ is additive, since it is defined by matrix multiplication with CIE 1932 RGB which is additive because it is an RGB colour space.

CIE L*a*b*
==========

CIE L*a*b* colours are presented with struct libcolour_cielab (libcolour_cielab_t), and the .model member shall be set to LIBCOLOUR_CIELAB. In union libcolour_colour, .cielab are used for CIE L*a*b* colours. CIE L*a*b* approximates human colour perception with a lightness parameter (L*) and two chromaticity parameters (a* and b*), it is therefore useful in image manipulation applications.

struct libcolour_cielab has the following members

enum libcolour_model model
     Shall be set to LIBCOLOUR_CIELAB.

double L
     The L* value. 0 is black, 100 is white.

double a
     The a* value. Negative values are green, positive values are red.

double b
     The b* value. Negative values are blue, positive values are yellow.

CIE L*a*b* is not additive, since conversion from CIE 1931 XYZ is non-linear. It's white point is the CIE Standard Illuminant D50.

CIE 1976 (L*, u*, v*)
=====================

CIE 1976 (L*, u*, v*) colours are presented with struct libcolour_cieluv (libcolour_cieluv_t), and the .model member shall be set to LIBCOLOUR_CIELUV. In union libcolour_colour, .cieluv are used for CIE 1976 (L*, u*, v*) colours. CIE 1976 (L*, u*, v*) approximates uniform human colour perception.

struct libcolour_cieluv has the following members

enum libcolour_model model
     Shall be set to LIBCOLOUR_CIELUV.

double L
     The L* value. 0 is black, 100 is white.

double u
     The u* value.

double v
     The v* value.

struct libcolour_ciexyz white
     The white point.

CIE L*u*v* is not additive, since conversion from CIE 1931 XYZ is non-linear.

Call libcolour_proper(&c) on a struct libcolour_cieluv_t c sets c.white.model to LIBCOLOUR_CIEXYZ. Zero is always returned in this case.

CIE LChuv
=========

CIE LChuv (also known as CIE HLCuv) colours are presented with struct libcolour_cielch (libcolour_cielch_t), and the .model member shall be set to LIBCOLOUR_CIELCH. In union libcolour_colour, .cielch are used for CIE LChuv colours. CIE LChuv approximates uniform human colour perception using cylindrical representation.

struct libcolour_cielch has the following members

enum libcolour_model model
     Shall be set to LIBCOLOUR_CIELCH.

double L
     The L* value. 0 is black, 100 is white.

double C
     The C*uv value, the chroma.

double h
     The huv value, the hue.

struct libcolour_ciexyz white
     The white point.

CIE LChuv is not additive. It is a cylindrical representation of CIE 1976 (L*, u*, v*).

Call libcolour_proper(&c) on a struct libcolour_cielch_t c sets c.white.model to LIBCOLOUR_CIEXYZ. Zero is always returned in this case.

YIQ
===

YIQ colours are presented with struct libcolour_yiq (libcolour_yiq_t), and the .model member shall be set to LIBCOLOUR_YIQ. In union libcolour_colour, .yiq are used for YIQ colours.

struct libcolour_yiq has the following members

enum libcolour_model model
     Shall be set to LIBCOLOUR_YIQ.

double Y
     The Y value, the luma. 0 is black, 1 is white.

double I
     The I (in-phase) value. Negative values are blue, positive values are orange.

double Q
     The Q (quadrature) value. Negative values are green, positive values are purple.

YIQ is additive, since conversion from CIE 1931 XYZ is done with a matrix multiplication. It's white point is the CIE Standard Illuminant D65.

YDbDr
=====

YDbDr colours are presented with struct libcolour_ydbdr (libcolour_ydbdr_t), and the .model member shall be set to LIBCOLOUR_YDBDR. In union libcolour_colour, .ydbdr are used for YDbDr colours.

struct libcolour_ydbdr has the following members

enum libcolour_model model
     Shall be set to LIBCOLOUR_YDBDR.

double Y
     The Y value, the luma. 0 is black, 1 is white.

double Db
     The Db value. Difference (with a factor) between Y and blue.

double Dr
     The Dr value. Difference (with a factor) between Y and red.

YDbDr is additive, since conversion from CIE 1931 XYZ is done with a matrix multiplication. It's white point is the CIE Standard Illuminant D65.

YUV
===

YUV colours are presented with struct libcolour_yuv (libcolour_yuv_t), and the .model member shall be set to LIBCOLOUR_YUV. In union libcolour_colour, .yuv are used for YUV colours.

struct libcolour_yuv has the following members

enum libcolour_model model
     Shall be set to LIBCOLOUR_YUV.

double Y
     The Y value, the luma. 0 is black, 1 is white.

double U
     The U value. Difference (with a factor) between Y and blue.

double V
     The V value. Difference (with a factor) between Y and red.

YUV is additive, since conversion from YDbDr is done with a diagonal matrix multiplication. It's white point is the CIE Standard Illuminant D65.

YPBPR
=====

YPBPR colours are presented with struct libcolour_ypbpr (libcolour_ypbpr_t), and the .model member shall be set to LIBCOLOUR_YPBPR. In union libcolour_colour, .ypbpr are used for YPBPR colours.

struct libcolour_ypbpr has the following members

enum libcolour_model model
     Shall be set to LIBCOLOUR_YPBPR.

double Y
     The Y value, the luma. 0 is black, 1 is white.

double Pb
     The PB value. Difference between Y and blue.

double Pr
     The PR value. Difference between Y and red.

YPbPr is additive, since conversion from CIE 1931 XYZ is done with a matrix multiplication. It's white point is the CIE Standard Illuminant D65.

YCgCo
=====

YCgCo colours are presented with struct libcolour_ycgco (libcolour_ycgco_t), and the .model member shall be set to LIBCOLOUR_YCGCO. In union libcolour_colour, .ycgco are used for YCgCo colours.

struct libcolour_ycgco has the following members

enum libcolour_model model
     Shall be set to LIBCOLOUR_YCGCO.

double Y
     The Y value, the luminance. 0 is black, 1 is white.

double Cg
     The Cg (chrominance green) value.

double co
     The Co (chrominance orange) value.

YCgCo is additive, since conversion from CIE 1931 XYZ is done with a matrix multiplication. It's white point is the CIE Standard Illuminant D65.

CIE 1960 UCS
============

CIE 1960 UCS colours are presented with struct libcolour_cie1960ucs (libcolour_cie1960ucs_t), and the .model member shall be set to LIBCOLOUR_CIE1960UCS. In union libcolour_colour, .cie1960ucs are used for CIE 1960 UCS colours.

struct libcolour_cie1960ucs has the following members

enum libcolour_model model
     Shall be set to LIBCOLOUR_CIE1960UCS.

double u
     The u value.

double v
     The v value.

double Y
     The Y value, the luminance.

CIE 1960 UCS is not additive. CIE 1960 UCS is defined by u = 4X/(X + 15Y + 3Z), v = 6Y/(X + 15Y + 3Z) where X, Y, and Z are CIE XYZ values.

CIE 1964 (U*, V*, W*)
=====================

CIE 1964 (U*, V*, W*) colours are presented with struct libcolour_cieuvw (libcolour_cieuvw_t), and the .model member shall be set to LIBCOLOUR_CIEUVW. In union libcolour_colour, .cieuvw are used for CIE 1964 (U*, V*, W*) colours.

struct libcolour_cieuvw has the following members

enum libcolour_model model
     Shall be set to LIBCOLOUR_CIEUVW.

double U
     The U* value.

double V
     The V* value.

double W
     The W* value.

double u0
     The u' chromaticity coordinate of a ``specified white object''. u' is defined as 4X/(X + 15Y + 3Z) where X, Y, and Z are CIE 1931 XYZ values.

double v0
     The v' chromaticity coordinate of a ``specified white object''. u' is defined as 9Y/(X + 15Y + 3Z) where X, Y, and Z are CIE 1931 XYZ values.

CIE 1960 UCS is not additive.