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:
Related Questions
drjack9650@gmail.com
Navigate
Integrity-first tutoring: explanations and feedback only — we do not complete graded work. Learn more.