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

libclut has a number of functions for converting between colour space models. The supported colour space models are [0, 1] sRGB, [0, 1] linear RGB, CIE xyY, CIE XYZ, and CIE Lab. These functions are implemented as macros, but regular functions are available either by putting the name in the function is brackets, taking the address of the function, or by undefining the macro with the name of the function.

libclut has two functions intended for internal use. If the macro verions are used, their parameter must not have any side-effets. Additionally their macro versions require linking with -lm.

double libclut_model_linear_to_standard1(double c)
     Convert one component from [0, 1] linear RGB to [0, 1] sRGB.

double libclut_model_standard_to_linear1(double c)
     Convert one component from [0, 1] sRGB to [0, 1] linear RGB.

libclut has ten functions that are intended for the user to use, but some are used internally too. These functions' parameters may have side-effects. All parameters are of the type double, and they do not have a return value.

libclut_model_linear_to_standard(*r. *g, *b)
     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.

     Parameters:

     r
          Pointer to the linear red component, and output parameter for the red component.

     g
          Pointer to the linear green component, and output parameter for the green component.

     b
          Pointer to the linear blue component, and output parameter for the blue component.

libclut_model_standard_to_linear(*r, *g, *b)
     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.

     Parameters:

     r
          Pointer to the red component, and output parameter for the linear red component.

     g
          Pointer to the green component, and output parameter for the linear green component.

     b
          Pointer to the blue component, and output parameter for the linear blue component.

libclut_model_ciexyy_to_ciexyz(x, y, Y, *X, *Z)
     Convert CIE xyY to CIE XYZ.

     Parameters:

     x
          The x parameter.

     y
          The y parameter.

     Y
          The Y parameter. This is also the Y (middle) parameter for the CIE XYZ colour.

     X
          Output parameter for the X parameter.

     Z
          Output parameter for the Z parameter.

libclut_model_ciexyz_to_ciexyy(X, Y, Z, *x, *y)
     Convert CIE XYZ to CIE xyY.

     Parameters:

     X
          The X parameter.

     Y
          The Y parameter. This is also the Y (last) parameter for the CIE xyY colour.

     Z
          The Z parameter.

     x
          Output parameter for the x parameter.

     y
          Output parameter for the y parameter.

libclut_model_ciexyz_to_linear(X, Y, Z, *r, *g, *b)
     Convert CIE XYZ to [0, 1] linear RGB.

     Parameters:

     X
          The X parameter.

     Y
          The Y parameter.

     Z
          The Z parameter.

     r
          Output parameter for the red component.

     g
          Output parameter for the green component.

     b
          Output parameter for the blue component.

libclut_model_linear_to_ciexyz(r, g, b, *X, *Y, *Z)
     Convert [0, 1] linear RGB to CIE XYZ.

     Parameters:

     r
          The red component.

     g
          The green component.

     b
          The blue component.

     X
          Output parameter for the X parameter.

     Y
          Output parameter for the Y parameter.

     Z
          Output parameter for the Z parameter.

libclut_model_srgb_to_ciexyy(r, g, b, *x, *y, *Y)
     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.

     Parameters:

     r
          The red component.

     g
          The green component.

     b
          The blue component.

     x
          Output parameter for the x parameter.

     y
          Output parameter for the y parameter.

     Y
          Output parameter for the Y parameter.

libclut_model_ciexyy_to_srgb(x, y, Y, *r, *g, *b)
     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.

     Parameters:

     x
          The x parameter.

     y
          The y parameter.

     Y
          The Y parameter.

     r
          Output parameter for the red component.

     g
          Output parameter for the green component.

     b
          Output parameter for the blue component.

libclut_model_ciexyz_to_cielab(X, Y, Z, *L, *a, *b)
     Convert from CIE XYZ to CIE L*a*b*.

     The macro variant requires linking with -lm.

     Parameters:

     X
          The X parameter.

     Y
          The Y parameter.

     Z
          The Z parameter.

     L
          Output parameter for the L* component.

     a
          Output parameter for the a* component.

     b
          Output parameter for the b* component.

libclut_model_cielab_to_ciexyz(L, a, b, *X, *Y, *Z)
     Convert from CIE L*a*b* to CIE XYZ.

     Parameters:

     L
          The L* component.

     a
          The a* component.

     b
          The b* component.

     X
          Output parameter for the X parameter.

     Y
          Output parameter for the Y parameter.

     Z
          Output parameter for the Z parameter.

RGB Conversion
==============

libclut provides a functions for converting RGB values between RGB colour spaces. An RGB colour space is described using struct libclut_rgb_colour_space (also known as libclut_rgb_colour_space_t). It describes the colour of the red, green, and blue, stimuli as well as the white point, in CIE xyY. It does however not describe the colour space's gamma function, because sRGB uses a irregular gamma function, and ECI RGB v2 uses L*. The structure contains the following double:s:

red_x
     The CIE xyY x-value of the red stimulus.

red_y
     The CIE xyY y-value of the red stimulus.

red_Y
     The CIE xyY Y-value of the red stimulus.

green_x
     The CIE xyY x-value of the green stimulus.

green_y
     The CIE xyY y-value of the green stimulus.

green_Y
     The CIE xyY Y-value of the green stimulus.

blue_x
     The CIE xyY x-value of the blue stimulus.

blue_y
     The CIE xyY y-value of the blue stimulus.

blue_Y
     The CIE xyY Y-value of the blue stimulus.

white_x
     The CIE xyY x-value of the white point.

white_y
     The CIE xyY y-value of the white point.

white_Y
     The CIE xyY Y-value of the white point.

libclut provides macros used to initialise a struct libclut_rgb_colour_space with values for a number of RGB colour spaces. These are listed below, along with the gamma each colour space uses.

Model

Gamma

Initialiser

sRGB

sRGB

LIBCLUT_RGB_COLOUR_SPACE_SRGB_INITIALISER

Adobe RGB (1998)

2.2

LIBCLUT_RGB_COLOUR_SPACE_ADOBE_RGB_INITIALISER

Apple RGB

1.8

LIBCLUT_RGB_COLOUR_SPACE_APPLE_RGB_INITIALISER

Best RGB

2.2

LIBCLUT_RGB_COLOUR_SPACE_BEST_RGB_INITIALISER

Beta RGB

2.2

LIBCLUT_RGB_COLOUR_SPACE_BETA_RGB_INITIALISER

Bruce RGB

2.2

LIBCLUT_RGB_COLOUR_SPACE_BRUCE_RGB_INITIALISER

CIE RGB

2.2

LIBCLUT_RGB_COLOUR_SPACE_CIE_RGB_INITIALISER

ColorMatch RGB

1.8

LIBCLUT_RGB_COLOUR_SPACE_COLORMATCH_RGB_INITIALISER

Don RGB 4

2.2

LIBCLUT_RGB_COLOUR_SPACE_DON_RGB_4_INITIALISER

ECI RGB v2

L*

LIBCLUT_RGB_COLOUR_SPACE_ECI_RGB_V2_INITIALISER

Ekta Space PS5

2.2

LIBCLUT_RGB_COLOUR_SPACE_EKTA_SPACE_PS5_INITIALISER

NTSC RGB

2.2

LIBCLUT_RGB_COLOUR_SPACE_NTSC_RGB_INITIALISER

PAL/SECAM RGB

2.2

LIBCLUT_RGB_COLOUR_SPACE_PAL_SECAM_RGB_INITIALISER

ProPhoto RGB

1.8

LIBCLUT_RGB_COLOUR_SPACE_PROPHOTO_RGB_INITIALISER

SMPTE-C RGB

2.2

LIBCLUT_RGB_COLOUR_SPACE_SMPTE_C_RGB_INITIALISER

Wide Gamut RGB

2.2

LIBCLUT_RGB_COLOUR_SPACE_WIDE_GAMUT_RGB_INITIALISER

To create a description for the sRGB colour space write:

     struct libclut_rgb_colour_space srgb = \
             LIBCLUT_RGB_COLOUR_SPACE_SRGB_INITIALISER;

libgamma and libcoopgamma can be used to get the x and y values of the user's monitors' red, green, and blue stimuli. Otherwise, all values specified by LIBCLUT_RGB_COLOUR_SPACE_SRGB_INITIALISER can be used, and the sRGB gamma function can be used. However, the Y values of the stimuli may be off, however, this does not affect conversion.

sRGB uses an irregular gamma function. libclut assumes that the colour spaces uses this gamma function when converting between RGB colour spaces. If you want to convert from a colour space with another gamma function, you must first convert the gamma function. This can be done by linearising the values and then use libclut_model_linear_to_standard1, libclut_model_linear_to_standard, or libclut_standardise. If you want to convert to a colour spce with another gamma function, you must after the conversion also convert the gamma function. This can be done by using libclut_model_standard_to_linear1, libclut_model_standard_to_linear, or libclut_linearise, and then converting from linear to the proper gamma function. Note that even if you are converting between two colour spaces with the same gamma function, gamma function conversion must be done (before and after) unless they use the sRGB gamma function.

Before RGB colour space conversion can be done, you need to create a conversion matrix. It has the type

     typedef double libclut_colour_space_conversion_matrix_t[3][3];

and can be created with

int libclut_model_get_rgb_conversion_matrix(*from, *to, M, Minv)
     Create a conversion matrix from one RGB colour space to another RGB colour space, and optionally a matrix for an inverse conversion.

     Returns 0 on success, and -1 on error. The only possible error is EINVAL, which indicates that there is something wrong with the colour spaces and a conversion matrix cannot be created.

     This function is not available as a macro, thus, linking with -lclut is required.

     Parameters:

     const libclut_rgb_colour_space_t* from
          Description of the input colour space.

     const libclut_rgb_colour_space_t* to
          Description of the output colour space.

     libclut_colour_space_conversion_matrix_t M
          Matrix to fill with values so it can be used for converting from the input colour space to the output colour space.

     libclut_colour_space_conversion_matrix_t Minv
          Matrix to fill with values so it can be used for converting from the output colour space to the input colour space. (That is, inverse conversion.) This parameter may be NULL.

You can also create the matrix manually. If you for example have a libclut_colour_space_conversion_matrix_t named M, and want to set the cell at row 1 and column 3, to 0.5, you make the assignment M[0][2] = 0.5.

Once you have your conversion matrix, libclut has three macro functions you can used to convert colours between RGB colour space. Remember that they require the sRGB gamma function.

libclut_model_convert_rgb(r, g, b, M, *out_r, *out_g, *out_b)
     Convert a single RGB colour into another RGB colour space. The colour space must have same gamma functions as RGB.

     This macro is also available a function. If the function is used, linking with -lclut is required, otherwise, linking with -lm is required, or -lclut if libclut_model_standard_to_linear1 or libclut_model_linear_to_standard1 is undefined.

     Parameters:

     double r
          The red value of the colour to convert.

     double g
          The green value of the colour to convert.

     double b
          The blue value of the colour to convert.

     libclut_colour_space_conversion_matrix_t M
          The conversion matrix.

     double* out_r
          Output parameter for the red value of the colour after conversion.

     double* out_g
          Output parameter for the green value of the colour after conversion.

     double* out_b
          Output parameter for the blue value of the colour after conversion.

libclut_convert_rgb_inplace(clut, max, type, m, trunc)
     Convert the curves between two RGB colour spaces.

     The red, green, and blue ramps must be of the same size.

     None of the parameter may have side-effects.

     Requires linking with -lm, or -lclut if libclut_model_standard_to_linear1, libclut_model_linear_to_standard1, or libclut_model_convert_rgb  is undefined.

     Parameters:

     clut
          Pointer to the gamma ramps to convert. This must be a pointer to an instance of a struct that must at least have the array members red, green, and blue, whose elements shall be of the type specified by the parameter type. The struct must also have the scalar members red_size, green_size, and blue_size, and shall be of the type size_t; they shall specify the number of stops (elements) in the arrays .red, .green, and .blue, respectively, which shall be the gamma ramp for the red, green, and blue channels respectively. Its values will be modified to the new values.

     max
          The maximum value on each stop in the ramps.

     type
          The data type used for each stop in the ramps.

     libclut_colour_space_conversion_matrix_t m
          Conversion matrix.

     int trunc
          If this is a non-zero value, resulting colours that are out of gamut are truncated. (Not necessarily the best approximation.)

libclut_convert_rgb(clut, max, type, m, trunc, out)
     Convert the curves between two RGB colour spaces.

     This is a slower version of libclut_convert_rgb_inplace that supports clut:s where the red, green, and blue ramps are not of the same size.

     None of the parameter may have side-effects.

     Requires linking with -lm. If libclut_model_linear_to_standard1, libclut_model_standard_to_linear1, or libclut_model_convert_rgb has been undefined, linking with -lclut is also required.

     Parameters:

     clut
          Pointer to the gamma ramps to convert. This must be a pointer to an instance of a struct that must at least have the array members red, green, and blue, whose elements shall be of the type specified by the parameter type. The struct must also have the scalar members red_size, green_size, and blue_size, and shall be of the type size_t; they shall specify the number of stops (elements) in the arrays .red, .green, and .blue, respectively, which shall be the gamma ramp for the red, green, and blue channels respectively. Its values are not modified.

     max
          The maximum value on each stop in the ramps.

     type
          The data type used for each stop in the ramps.

     libclut_colour_space_conversion_matrix_t m
          Conversion matrix.

     int trunc
          If this is a non-zero value, resulting colours that are out of gamut are truncated. (Not necessarily the best approximation.)

     clut
          Pointer to the gamma ramps of the output values. Shall be of the same data type as clut. And have the same values on .red_size, .green_size, and .blue_size as clut.