Academic Integrity: tutoring, explanations, and feedback — we don’t complete graded work or submit on a student’s behalf.

Starting with xy coordinates I would like to plot a chromaticity diagram display

ID: 1383048 • Letter: S

Question

Starting with xy coordinates I would like to plot a chromaticity diagram displaying just the sRGB gamut portion of the CIE xy chromaticity diagram.

For each xy coordinate of my diagram I need to determine the corresponding Y value to obtain the complete xyY representation, from which XYZ tristimulus values can be calculated and finally sRGB values derived.

By starting with the known sRGB Red, Green, Blue and white values: #FF0000, #00FF00, #0000FF, #FFFFFF respectively I can use the Bradford matrix to deduce their XYZ tristimulus values and thus their xyY representations.

But starting with xy coordinates is there a method for determining the Y component?

ps. If you are able to add new tags, could you possibly add some tags like 'colorimetry', 'chromaticity-diagram' and 'color-models'?

Explanation / Answer

The Y component is for you to choose, because for a given x,y pair, depending on Y, the colour may or may not lie within the sRGB volume.

It is possible to know whether there is at least one sRGB colour that will map to a given x,y pair, though. Note that if linear RGB values (R,G,B) are transformed to (x,y,Y), then (a*R,a*G,a*B) are transformed to (x,y,a*Y). Multiplying each of the RGB triplets with a constant doest not affect x or y.

So one way to take an (x,y) pair and find out whether it can be obtained from an sRGB value is:

set Y = 100
convert (x,y,Y) back to (X,Y,Z)
convert (X,Y,Z) to linear RGB (R,G,B)
if one of R, G or B is negative, we are out of the sRGB space
otherwise, divide each of R, G and B by the largest of the three
optionally, convert linear (R,G,B) to gamma-corrected sRGB values

Here is some GLSL code that does the job:

vec4 color = vec4(0.0, 0.0, 0.0, 1.0);

vec3 xyY = vec3(pass_Position.xy, 100.0);
vec3 XYZ = xyY.z * vec3(xyY.x / xyY.y, 1.0, (1.0 - xyY.x - xyY.y) / xyY.y);

mat3 XYZtoRGB = mat3(vec3( 0.032406f, -0.009689f, 0.000557f),
vec3(-0.015372f, 0.018758f, -0.002040f),
vec3(-0.004986f, 0.000415f, 0.010570f));

vec3 RGB = XYZtoRGB * XYZ;

if (RGB.x >= 0.0 && RGB.y >= 0.0 && RGB.z >= 0.0)
{
RGB /= max(RGB.x, max(RGB.y, RGB.z));
vec3 sRGB = pow(RGB, vec3(1.0 / 2.4));
color.xyz = sRGB;
}

And this is the result:

Hire Me For All Your Tutoring Needs
Integrity-first tutoring: clear explanations, guidance, and feedback.
Drop an Email at
drjack9650@gmail.com
Chat Now And Get Quote