Convert from linear RGB to XYZ

2.2k views Asked by At

This matrix is supposed to convert from linear RGBA to XYZ, preserving the alpha channel as it is:

vec4 M[4]=
    {
     vec4{0.4124564f,0.3575761f,0.1804375f,0.0f}
    ,vec4{0.2126729f,0.7151522f,0.0721750f,0.0f}
    ,vec4{0.0193339f,0.1191920f,0.9503041f,0.0f}
    ,vec4{0.0,0.0f,0.0f,1.0f}
    };

Is that correct? Where can I find the values in double precision? I am asking, because the second row is very close to the luma formula, which from what I understood is associated with non-linear sRGB values:

vec4 weights{0.2126f,0.7152f,0.0722f,0.0f};
auto temp=m_data*weights; //vectorized multiplication
return temp[0] + temp[1] + temp[2] + temp[3]; //Sum it up to compute the dot product (weighted average)

Other questions: Should the weights discussed actually be identical? Should conversion to Y'CbCr use the same weights? Should it be performed in linear or sRGB space?

1

There are 1 answers

4
Kel Solaar On BEST ANSWER

This matrix converts from a sRGB flavour to CIE XYZ D65. This is however not the official sRGB matrix published in IEC 61966-2-1:1999 which is rounded to 4 digits as follows:

[[ 0.4124  0.3576  0.1805]
 [ 0.2126  0.7152  0.0722]
 [ 0.0193  0.1192  0.9505]]

Depending the context you are performing your conversions, it might be important to use the official IEC 61966-2-1:1999 matrix to get matching results with other third-party datasets as it is likely that they will be using the canonical matrix.

For reference here is a double precision conversion matrix computed with Colour:

[[0.412390799265960 0.357584339383878 0.180480788401834]
 [0.212639005871510 0.715168678767756 0.072192315360734]
 [0.019330818715592 0.119194779794626 0.950532152249661]]

And the code used to generate it:

import numpy as np
import colour

print(colour.models.sRGB_COLOURSPACE.RGB_to_XYZ_matrix)
np.set_printoptions(formatter={'float': '{:0.15f}'.format})
colour.models.sRGB_COLOURSPACE.use_derived_transformation_matrices(True)
print(colour.models.sRGB_COLOURSPACE.RGB_to_XYZ_matrix)

Should the weights discussed actually be identical?

For consistency in your computations you might want to use weights matching your matrix or you will get issues when doing conversions back and forth.

Should conversion to Y'CbCr use the same weights?

Y'CbCr has many variants and nobody will be able to answer properly if you don't know which variant you need.

Should it be performed in linear or sRGB space?

Y'CbCr conversions are pretty much always happening in gamma encoded values, ITU-R BT.2020 YcCbcCrc being a notable exception as it is based on linearly encoded values. It is also important to understand that the sRGB colourspace is also linear, as a matter of fact the matrix central to the discussion here is meant to be applied on linearly encoded sRGB values.

Those two last questions should probably be asked in another new question.