Color: the 1931 CIE color-matching functions and chromaticity chart


The CIE chromaticy chart is one of the things we are headed for. Here is a black-and-white drawing of its boundary. I’ll show you later how I got it.

CIE bdy

You should be able to find color versions of the CIE chromaticity chart (1931) all over the Internet. Here’s one that shows some curves of constant hue. I’ll point out now that these curves are not straight lines. I will also use that image to decide that something is a greenish-yellow or yellow-green.

Wikipedia seems to have a lot of information, such as this, for example.

What my drawing shows is that I can reproduce the analytical content of it. Black and white, but no color.

How did I do that?

the color-matching functions and chromaticity coordinates

I have four tables of data, from Wyszecki and Stiles, for which see the bibliography; and I will abbreviate them “w&s” in this post.

“rgb” are chromaticity coordinates (row sums = 1), “rgb bar” are color-matching functions. The full heading on the combined “rgb” and “rgb bar” tables is “Chromaticity Coordinates and Color-matching Functions of the CIE 1931 Standard Colorimetric System, with respect to real primary stimuli:
R at \lambda_R = 700.0\ nm;
G at \lambda_G = 546.1\ nm;
B at \lambda_B = 435.8\ nm”

We also have “xyz” chromaticity coordinates (row sums = 1), and “xyz bar” color-matching functions.

All 4 tables are at 5 nm intervals from 380 to 780.

Well, these 4 tables come in a variety of sets. I chose to use the 1931 tables at 5 nm intervals.

They have been interpolated to 1 nm intervals. They have been corrected by several authors in different ways. They were re-done in 1964 by the CIE to use a 10° field instead of the 2° field of the 1931 standard.

My choice of the uncorrected 5 nm 1931 standard is not universal — but it is an extremely common choice, and an awful lot of the work done since 1931 has used it.

At my level of usage, it probably doesn’t matter a whole lot. In fact, a whole lot of other things will turn out to be more important.

Since I’ve had more than a little time to get used to the 4 different tables, and you may not have, let me list them:

  • rgb bar
  • rgb
  • xyz bar
  • xyz

My source for the tables, as I said, was w&s. I am not going to reproduce them — as far as I can see the CIE charges for some of them — but I wouldn’t be surprised if you can find them on the Internet.

In principle, three of the tables are secondary. Their source is the table of rgb bar. First, let me show you what they look like.

Here is a picture of the rbar, gbar, bbar data. The x-axis runs through wavelengths from 380-780, the points are 5 nm apart.

rgb bar plot

It is clear that rbar is significantly negative over part of its range (440-545 nm); it is true, but not clear, that gbar is very slightly negative over 380-435, and bbar is very slightly negative over 550-655 — and it’s shown as 0 for longer wavelengths.

In fact, at any given wavelength, exactly one of the three is negative; nevertheless, only the red rbar gets seriously negative.

What do these negative numbers mean?

I suspect that the simple description of the color matching experiment is too simple experimentally, but I also believe it suffices in principle. Imagine that you are looking at a split screen, at two halves of a colored disk. The left half of the disk is a monochromatic color. (Think of a tunable laser — but of course they didn’t have lasers in the 1920s when the experiments were done!) The right half of the disk is controlled by the viewer, who has three dials and may choose mixtures of red, green, and blue in order to make the two halves of the disk match.

It turns out that we can’t do that. Over most of the range, we have to change the color of the left half of the disk as well as the right half. We can’t match a wavelength of 380 nm (the violet end of the visble spectrum) with red, green, and blue. But if we add a tiny of green to the violet, we can match that combination with red and blue.

We record a negative number for green at that wavelength.

Until the blue goes to zero thru negative values, exactly one of the 3 numbers is negative. At long wavelengths, when blue is zero, we just use red and green.

So much for the negative values.

Oh, having said that I will not reproduce the table, I will present — so you can do these calculations yourself — one quarter of it. Here is the rgb bar table at 20-nm intervals.

rgb bar ~ \left(\begin{array}{cccc} 380 & 0.00003 & -0.00001 & 0.00117 \\ 400 & 0.0003 & -0.00014 & 0.01214 \\ 420 & 0.00211 & -0.0011 & 0.11541 \\ 440 & -0.00261 & 0.00149 & 0.31228 \\ 460 & -0.02608 & 0.01485 & 0.29821 \\ 480 & -0.04939 & 0.03914 & 0.14494 \\ 500 & -0.07173 & 0.08536 & 0.04776 \\ 520 & -0.09264 & 0.17468 & 0.01221 \\ 540 & -0.03152 & 0.21466 & 0.00146 \\ 560 & 0.0906 & 0.19702 & -0.0013 \\ 580 & 0.24526 & 0.1361 & -0.00108 \\ 600 & 0.34429 & 0.06246 & -0.00049 \\ 620 & 0.29708 & 0.01828 & -0.00015 \\ 640 & 0.15968 & 0.00334 & -0.00003 \\ 660 & 0.05932 & 0.00037 & 0 \\ 680 & 0.01687 & 0.00003 & 0 \\ 700 & 0.0041 & 0 & 0 \\ 720 & 0.00105 & 0 & 0 \\ 740 & 0.00025 & 0 & 0 \\ 760 & 0.00006 & 0 & 0 \\ 780 & 0 & 0 & 0\end{array}\right)

The second table, rgb, is derived from the first in principle — but not in practice!

In principle, take the rgb bar table and recsale it by setting every row sum to 1.

In parctice, we don’t have enough digits to do that. They provide a table. It is called the rgb (chromaticity coordinates).

Here is what the rgb table looks like at 5 nm intervals.
rgb plot

And here is a subset of the rgb table, at 20-nm intervals.

rgb ~ \left(\begin{array}{cccc} 380 & 0.0272 & -0.0115 & 0.9843 \\ 400 & 0.0247 & -0.0112 & 0.9865 \\ 420 & 0.0181 & -0.0094 & 0.9913 \\ 440 & -0.0084 & 0.0048 & 1.0036 \\ 460 & -0.0909 & 0.0517 & 1.0392 \\ 480 & -0.3667 & 0.2906 & 1.0761 \\ 500 & -1.1685 & 1.3905 & 0.778 \\ 520 & -0.983 & 1.8534 & 0.1296 \\ 540 & -0.1707 & 1.1628 & 0.0079 \\ 560 & 0.3164 & 0.6881 & -0.0045 \\ 580 & 0.6449 & 0.3579 & -0.0028 \\ 600 & 0.8475 & 0.1537 & -0.0012 \\ 620 & 0.9425 & 0.058 & -0.0005 \\ 640 & 0.9797 & 0.0205 & -0.0002 \\ 660 & 0.994 & 0.0061 & -0.0001 \\ 680 & 0.9984 & 0.0016 & 0. \\ 700 & 1. & 0. & 0. \\ 720 & 1. & 0. & 0. \\ 740 & 1. & 0. & 0. \\ 760 & 1. & 0. & 0. \\ 780 & 1. & 0. & 0.\end{array}\right)

Let me show you an example of why we need their table, instead of trying to generate it ourselves. At 380 nm, the rgb bar table has values…


which sum to 0.00119 .

If I divide that row by its sum, and round, I get…


but the corresponding row of the rgb table is…

\{0.0272,-0.0115,0.9843\}\ .

Close, but not the same.

That’s two of the four tables. As it happens, they’re the two we may be able to dispense with in practice — but in principle, rgb bar is the starting point.

Let me emphasize that these values depend on a specific choice of red, green, and blue.

We can fix that.

The CIE defined a specific change-of-basis. The tri-stimulus coordinates (rbar, gbar, bbar) or (R,G,B) are a vector in R^3; they defined a vector denoted either (xbar, ybar, zbar) or (X,Y,Z).

Oh, although the table is denoted rgb bar, specific coordinates wrt it are usually denoted RGB; similarly, specific coordinates wrt the xyz bar table are usually denoted upper-case XYZ.

Bear in mind that these RGB are not the same as coordinates in RGB-color space. (The latter is bounded by 0 and 1; the former is not!) We’ll see more about this down the road.

Let me show it to you:

xyz bar

And let me show you the cut-down data, every 20-nm; this is a subset of the “xyz bar” table:

xyz bar ~ \left(\begin{array}{cccc} 380 & 0.0014 & 0. & 0.0065 \\ 400 & 0.0143 & 0.0004 & 0.0679 \\ 420 & 0.1344 & 0.004 & 0.6456 \\ 440 & 0.3483 & 0.023 & 1.7471 \\ 460 & 0.2908 & 0.06 & 1.6692 \\ 480 & 0.0956 & 0.139 & 0.813 \\ 500 & 0.0049 & 0.323 & 0.272 \\ 520 & 0.0633 & 0.71 & 0.0782 \\ 540 & 0.2904 & 0.954 & 0.0203 \\ 560 & 0.5945 & 0.995 & 0.0039 \\ 580 & 0.9163 & 0.87 & 0.0017 \\ 600 & 1.0622 & 0.631 & 0.0008 \\ 620 & 0.8544 & 0.381 & 0.0002 \\ 640 & 0.4479 & 0.175 & 0. \\ 660 & 0.1649 & 0.061 & 0. \\ 680 & 0.0468 & 0.017 & 0. \\ 700 & 0.0114 & 0.0041 & 0. \\ 720 & 0.0029 & 0.001 & 0. \\ 740 & 0.0007 & 0.0003 & 0. \\ 760 & 0.0002 & 0.0001 & 0. \\ 780 & 0. & 0. & 0.\end{array}\right)

Here is the change-of-basis matrix:

T = \left(\begin{array}{ccc} 2.76888 & 1.75175 & 1.13016 \\ 1 & 4.5907 & 0.0601 \\ 0 & 0.05651 & 5.59427\end{array}\right)

They tell us we can check it, for example, by applying their matrix T to RGB coordinates, such as for example at 500 nm…


Apply T, and round off, getting


… and compare that to the XYZ coordinates at 500 nm:

\{0.0049,0.323,0.272\}\ .

The same.

Still… raise your hands and step away from the keyboard.

What we just did was apply their matrix T to RGB components to get XYZ components. Perfectly natural. But we know that the transition matrix delivers old components when it is applied to new ones. If we want to call that given matrix T the transition matrix, then we must think of XYZ as the old components.

In practice, this really just means that we better know which way the transformation goes. They gave us the transition matrix for old components XYZ and new components RGB — even though they derived the XYZ basis from the RGB basis.

OK? If not, please be patient.

Now just where did that change-of-basis transformation come from? Malacara has a readable discussion. The most important point, to my mind, is that the Y column vector, the second column, is chosen to be the “phototopic response” (1924) of the human eye, that is, daylight vision, that is, color vision. There’s not much point in my digging out that data and plotting it: it is exactly the green curve in the drawing of the xyz bar table.

Second, all the values X,Y,Z are non-negative. Third, they also set the column sums almost equal to the value for the Y column. There was another criterion, but I’ll show it to you after I show you the fourth table.

Table 4 comes from table 3 as table 2 comes from table 1: get table 4 by setting the row sums of table 3 to 1, just as we got table 2 by setting row sums of table 1 to 1. All in principle, of course, or having more digits available than were printed.

Here is what the xyz table looks like:

xyz plot

and here is the cut-down data:

xyz ~ \left(\begin{array}{cccc} 380 & 0.1741 & 0.005 & 0.8209 \\ 400 & 0.1733 & 0.0048 & 0.8219 \\ 420 & 0.1714 & 0.0051 & 0.8235 \\ 440 & 0.1644 & 0.0109 & 0.8247 \\ 460 & 0.144 & 0.0297 & 0.8263 \\ 480 & 0.0913 & 0.1327 & 0.776 \\ 500 & 0.0082 & 0.5384 & 0.4534 \\ 520 & 0.0743 & 0.8338 & 0.0919 \\ 540 & 0.2296 & 0.7543 & 0.0161 \\ 560 & 0.3731 & 0.6245 & 0.0024 \\ 580 & 0.5125 & 0.4866 & 0.0009 \\ 600 & 0.627 & 0.3725 & 0.0005 \\ 620 & 0.6915 & 0.3083 & 0.0002 \\ 640 & 0.719 & 0.2809 & 0.0001 \\ 660 & 0.73 & 0.27 & 0. \\ 680 & 0.7334 & 0.2666 & 0. \\ 700 & 0.7347 & 0.2653 & 0. \\ 720 & 0.7347 & 0.2653 & 0. \\ 740 & 0.7347 & 0.2653 & 0. \\ 760 & 0.7347 & 0.2653 & 0. \\ 780 & 0.7347 & 0.2653 & 0.\end{array}\right)

Just for the fun of it, check the column sums of XYZ. I said they were almost equal. I get

\{21.3713,21.3714,21.3715\}\ .

I do not know if that is deliberate, or whether its round-off and the real tables have more digits. (I don’t really care. But I couldn’t very well say they were equal….)

The CIE chromaticity chart

Ok, here’s the next major idea. Since x+y+z = 1, this table is essentially 2D, and we can plot y vs x.

That is exactly the picture I started this post with, the boundary of the chromaticity chart.

That’s all it is: take the first two columns of the xyz table, read each row as (x,y) coordinates, and plot each row.

The fourth criterion was to make the line x+y = 1 tangent to the curve. (In fact, the earlier criterion about X,Y,Z being non-negative was implemented by setting the y-axis tangent to the boundary.

Let me show you:

CIE with tangent

So, 4 tables, one 2D chart. We could also draw a 2D chart of g vs r, or b vs r, from the rgb table, since its rows each sum to 1.

What we have lost, in that chart, is the intensity. To recover XYZ from xy, we would need, for example, xyY; x,y and any one of X, Y, or Z would suffice.

Let me start using that chart right now. We have RGB basis vectors (1,0,0), (0,1,0), and (0,0,1}. What are their (x,y) coordinates?

There are a few ways to do this. Given the scale at which we are working, the easiest is to interpolate the x,y coordinates from the xyz table at wavelengths 435.8, 546.1, and 700 (that last one is a table value).

I get x,y coordinates of

R = {0.7347,0.2653}

G = {0.2737,0.717411}

B = {0.166541,0.00892768}

Let’ s plot them on the chromaticity chart… and let’s draw lines connecting them.

CIE with orig RGB

Think back to simplices. All of the points inside (and on) that triangle can be written as linear combinations of the coordinates of the 3 vertices; most importantly, the coefficients of those linear combinations are between 0 and 1, inclusive. That is, when the coefficients are in the closed interval [0,1], the combination is inside or on the triangle.

That restriction to [0,1] is what restricts us to the inside (and on) the triangle. That triangle is said to describe the gamut of these three R,G,B vertices.

The points outside the triangle have either negative coefficients (or perhaps coefficients larger than 1; I’m not sure). This is why we have negative values inside the primary table, rgb bar: all the points on the curved boundary are outside, or just on, the rgb bar triangle.

That triangle is said to to show the gamut of those choices for R,G,B primaries. One of the most common uses of the chromaticity chart is to compare gamuts.

From Foley, van Dam et al., I get the following x,y coordinates for the “standard NTSC RGB phosphor” (the color TV standard):

R = {0.67,0.33},

G = {0.21,0.71},

B = {0.14,0.08}

Let’s add them to the CIE, triangle in red:

A TV with these phosphors can reproduce colors in the red triangle.

Another set of coordinates from Foley & van Dam et al., for “short-persistence phosphors” are:

R = {0.61,0.35},

G = {0.29,0.59},

B = {0.15,0.063}

Let’s add them to the drawing, with their triangle in green:

CIE with short

Whatever these are, they can only produce the comparatively limited set of colors bounded by the green triangle.

To reproduce the entire CIE chart, within a triangle — i.e. with linear combinations having components in [0,1], we would need to have B at x,y = (0,0), R at x,y = (1,0), and G at x,y = (1,0).

Easy enough to draw, but don’t ask me how to get such sources physically.
CIE with biggest

A different form of the same principle — linear combinations of vectors — leads to the idea of mixing two colors. That is, instead of looking at all that can be produced by a particular set of RGB phosphors, we take two points and consider the line joining them.

A particularly useful choice is when one of the points is defined as “white”. Here are the x,y coordinates of a white known as D65, a standard form of “daylight”; here also are x,y coordinates of a form of green (from Andrew Glassner’s “Principles of Digital Image Synthesis”, volume 2, Appendix G; Morgan kaufmann, 1995), known as “foliage” on the MacBeth Color Checker.

p65 = {0.31271,0.32902}

pf = {0.4002,0.3504}

I want the equation of the line thru those points, and considering triangles, I’m going to write the equation as

line[t_] := t pf + (1 – t) p65.

Like our discussion of triangles, if t is restricted to [0,1], then we get the line segment bounded by the two points. Only if we let t range outside [0,1] do we get line segments that extend beyond the two points.

For what it’s worth, the numerical equation of the line is

line[t] = \{0.08749 t+0.31271,0.02138 t+0.32902\}\ .

Here are the two points and the line segment joining them:
CIE with 2 pts

But I’d rather do something else: extend the line to the boundary, and consider the green point to be a combination of the white point and the boundary point.
CIE with 3 pts

According to my poster of the 1931 CIE, a wavelength of 570 is on the border between greenish-yellow and yellowish-green. Go to the first link in this post. So our “foliage” at the red point is a mixture of white and a wavelength very close to 570 nm. (Or, Malacara has a version of this drawing.)

(I meant to show the two points as black and red in both drawings, but I forgot. I didn’t want to imply that the dot was the “right” color.)

One final point. We could go from HSB to RGB (for some standard set of RGB) and compute curves of constant hue. They are not straight lines. Rather than prove this by computation, let me just point you at the very first link again: the boundaries which it shows are not straight lines, and those boundaries certainly ought to be curves of constant hue, namely the boundary hue. (It ought to be easy enough to show this, but not now.)

It is crucial that the XYZ values are independent of any particular RGB values. Of course, they originally came from the spectrallly pure ones — but once we have the XYZ basis, we can go to any other RGB basis we choose.

Having seen other gamuts, we should expect that people get XYZ values from a spectrum. I’ll show you that next.

46 Responses to “Color: the 1931 CIE color-matching functions and chromaticity chart”

  1. vaibhav Says:

    How can i get RGB values (0-255 ; as in MS Word) from CIE (x,y) values.

    For eg;
    x=.31 and y=.32
    Then how will i get RGB values
    p.s.- I understand that two values are given and we need three values .

  2. rip Says:

    Thanks for asking, …. There are three parts to this answer.

    First, you must be given 3 values, not 2. The most customary set is xyY, but x,y and any one of X, Y, or Z would suffice. In your case, with x and y so close to 1/3, the color is a neutral, but without Y (or X or Z) you can’t tell whether it’s white, black, or any gray in between.

    Second, assuming you have xyY, you get XYZ by reversing the calculation that transforms XYZ to xy. That original calculation says:

    given X,Y,Z, compute their sum = X+Y+Z;

    divide each of X,Y,Z by the sum, to get x,y,z respectively; that implies that x+y+z = 1, so we may plot (x,y), and we may recover z from x and y as

    z = 1 – x – y.

    To reverse this calculation, assuming we have xyY, write

    y = Y/sum


    sum = Y/y,

    and then we compute X and Z from

    X = x sum = x Y / y

    Z = z sum = z Y / y.

    At this point we have a device-independent specification: X, Y, Z for the standard observer.

    Third, because RGB is device-dependent, you must specify what RGB basis you are using. Let me illustrate this using the RGB basis for the 1931 standard observer. This is just one choice out of many other possible choices. In this case, the published transition matrix from RGB to XYZ is:

    \left( \begin{array}{ccc}  2.76888 & 1.75175 & 1.13016 \\  1 & 4.5907 & 0.0601 \\  0 & 0.05651 & 5.59427 \end{array} \right)

    As we saw here (, that is not exact — and it can’t be, because the RGB and XYZ spaces are not exactly the same 3D subpsaces of R^81 (81 wavelengths from 380 to 780 at 5 nm intervals), but it’s what we are given.

    Because the transition matrix T31 is from RGB to XYZ, we convert from XYZ to RGB by using the inverse of T31.

    Let me illustrate that. At 500 nm, the 1931 xyz bar tables tell us

    X,Y,Z = \{0.0049,0.323,0.272\}

    To convert that to RGB, we apply the inverse of T31 (and round for comparison):

    R,G,B = \{-0.07173,0.08536,0.04776\}

    and that is what the rgb bar tables show at 500 nm.

    We may not like the negative value of R, but what it says is that this color is out of gamut for the three primaries they used – that what was matched was not this color, but this color plus red. In other words, the three CIE primaries cannot produce this color.

    I have not yet played with device RGB, so this is about all I can say confidently, at this time.

  3. rip Says:

    My comment is not wrong, but I feel like I’m standing at the edge of the Grand Canyon, looking down. I was right at the edge of my understanding. (Not a bad place to be, but I’m glad I stopped where I did.)

    Okay, I said I was working it out for one of many possibilities, and that I was ignorant of device RGB — what I didn’t say was that I was working it out for the only possibility which I knew to be linear.

    There may be other linear cases, but I don’t know of any yet. More to the point, it appears that — despite all the linear transformations I’ve seen — some if not all device transformations are nonlinear to some extent.

    The general answer is that the purpose of an ICC device profile is precisely that: to translate between the device RGB and CIE XYZ (or between the device RGB and CIE Lab). And that ICC profile (or profiles) is what you need to use, for whatever device (or devices) you’re focusing on.

    (That’s my understanding from “Real World Color Management” by Fraser, Murphy, and Bunting; Peachpit Press, 2003. There is a 2nd edition dated 2004.)

    I find that answer less than satisfying for two reasons.

    First, the translation is nonlinear — and I do not know why. Yes, I can see the calculations… but I have not yet isolated the nonlinearities. (Is it only the intensity Y?)

    Second, I am shocked — shocked and embarrassed — to discover, after all the linear algebra I’ve seen people using, that there are significant fundamental nonlinearities in color. Where I expected to find a simple change-of-basis transformation for my monitor, I seem to have found a nonlinear transformation. And I now wonder if the triangles everyone draws on the CIE chromaticity chart — to show device gamut, what we can produce from the primaries at the vertices — are approximations, not the full truth.

    What i want to know is exactly where those nonlinearities arise.

    While I continue to investigate these nonlinearities, I will confine myself — as I hope I have — to CIE XYZ, and perhaps its change-of-basis CIE RGB. By ignoring device RGB, I stay on the high ground instead of plunging into the canyon of ignorance.

    But, of course, I do need to explore the canyon.

    While drafting this, I have found a calculation for the change-of-basis for the NTSC phosphors and a particular white point — and it raises some very intriguing possibilities. When I understand it, I should show it to you.

    But the key point of this comment can be summarized as: I’m not at all sure that the linear transformation I have seen for NTSC is the full truth.

  4. Color: Glassner’s transformation XYZ to RGB « Rip’s Applied Mathematics Blog Says:

    […] There’s nothing sacred about that choice, but without somehing like it, we can’t get from xy to XYZ. […]

  5. Bo Says:

    Can you tell me how exactly you get rgb table for rgbbar table, as you told they are close but not the same?

  6. rip Says:

    Hi Bo,

    Thanks for asking.

    If I understand your question, you want to know why I said the rgb table is derived differently in practice than in principle. That’s an excellent question, and I must revise my statement.

    My post shows that the published 5 nm rgb table cannot be computed exactly by setting each row sum in the rgb bar table to 1. My counterexample is for the 380 nm row.

    My statement is correct for the 5 nm tables: if you start from the 5 nm rgb bar tables and normalize the rows to 1, you will be close to but not exactly match the published rgb table.

    But a quick check – the corresponding numbers for the 1 nm tables at 380 nm – is off by only .00001 for the blue column., and exact to 5 places for red and green.

    Now, confirming one line doesn’t prove that the entire tables are consistent – but I no longer have any reason to doubt them.

    For the 1 nm tables. This is crucial. The 5 nm tables – at least in Wyszecki & Stiles – show fewer places than the 1 nm tables.

    Since I never use the 1 nm tables, I don’t have any easy way, nor any reason, to check them all.

    In summary: until I have reason to believe otherwise, I will take it that, yes, we can compute the rgb table from the rgb bar table at 1 nm intervals – but not at 5 nm intervals.

    If this wasn’t your question (!), please ask again. But in any case, it was a good question for me.

    Thank you.


  7. ram Says:

    Can you tell me how to prove that the gamut of colors generated by three primaries is a triangle formed by those primaries in the CIE chromaticity diagram.

    • rip Says:

      Hi again,

      Well, I can think of a couple of ways to show it.

      One uses “barycentric coordinates” …


      at least implicitly. Basically, geometry yells us that any weighted combination of the 3 points r, g, b — with weights between 0 and 1 — is the coordinates of a point inside or on the triangle whose vertices are those 3 points. The weights are limited because we assume we cannot take more that 1 times any phosphor.

      On the other hand, we haven’t really justified taking weighted sums of the xy coordinates. The chromaticity chart in NOT constant intensity, so maybe we should go back to the XYZ values for each phosphor, take a weighted sum of them, and show that the resulting xy must lie in or on the triangle.

      I haven’t worked that out, so you might let me know if it doesn’t work.

      Good luck,

  8. ram Says:

    If the incident light is monochrome,f(u)= impulse at T=0.4 , what are the RGB tristimulus values generated? What are the CIE XYZ tristimulus values?

    where R(u) is given such that it starts from .25 to .75 on u (amplitude 0 at .25 and raises to amplitude 1 at .75)and then from amplitude 1 at .75 it drops to 0 at 1, therefore forming a triangle with base from .25 to 1 on u.

  9. daniel Says:

    Thanks in advance to take your time to read this post

    I have in high esteem your opinions in the colour field since I could learnt a lot through the extremely well presented information at your blog
    I will appreciate your point of view in the problem I am trying to solve :


    Painters are accustomed to use colour laws and pseudo-colour-laws as rigid tools. One that ever intrigued many of us is about predicting Hue Shifting in Shadow Series (SS)

    I tried the following way to solve it …

    Used the following Colour Spaces and Models :

    • Munsell Colour Space as THE Perceptual Model
    • CIE Tristimulus Model to Predict the Shadow Series as THE Mathematical Model
    • RGB Colour Space to show the Series Colour Steps as THE Representational Model

    Then I proceeded :

    1. Took the middle colour Munsell Main Hues : 5R, 5YR, 5Y, … 5RP having a valid representation in the RGB Colour Space, at maximum Chroma
    2. Converted HVC coordinates to XYZ CIE Tristimulus with a software conversion program
    3. Adopted a Decayment Factor in Light Intensity : 1.0, 0.9, 0.8, … 0.1 to get the SS.
    4. As the Decayment Factor affects proportionally to each XYZ coordinate (i.e. X0.7 = 0.7 x X1.0), I used it to predict the SS steps
    5. Converted the XYZ of each SS step to HVC Munsell
    6. Finally I analyzed Hue Shifting in the Munsell Perceptual Model and obtained conclusions

    My conclusions were :

    As illumination is increased Colours tend to shift in hue toward purple
    As illumination is decreased Colours tend to shift toward yellow

    These are in contradiction with Faber Birren observations he enunciates as a law (Principles of Colour, Pg 36) :

    As illumination is increased Colours tend to shift in hue toward yellow
    As illumination is decreased Colours tend to shift toward violet

    He says exactly the opposite !

    Then I corroborated the same tendency I found with those colours in Adobe Photoshop, converting RGB to HSB and reducing B while H&S remain constants and then returning from RGB to HVC world

    What I’m doing wrong to get exactly the opposite?
    Is the Faber Birren’s Law erroneous?

    Again, Thanks a lot for your attention


  10. rip Says:

    Hi Daniel,

    I appreciate your confidence in me, but I know very little about the perception of color. On the other hand, hue shift effects sound fascinating. (Among other things, I guess it’s the lack of hue shifting that lets us tell that a movie was colorized rather than shot in color.)

    I do note, however, that according to wikipedia–Brücke_shift

    the shift is either to blue or yellow depending on whether you are already closer to blue or yellow (below or above 500 nm).

    That effect, the Bezold-Brucke effect, may not be quite the same as part of an object being in shadow. And it’s quite different from an object being viewed at borderline illumination, when the rods are starting to work.

    There are two things I do not understand in your calculations. One, why did you reduce all of X,Y,Z instead of just Y? (I know, changing just Y leaves x,y fixed — but I don’t believe that x,y determine a unique hue.) Two, how are you modeling the human eye? I don’t see how the hue-shift effect can be captured by XYZ at all: XYZ defines a stimulus, not a perception, i.e. not a color. (Not that I knew that when I started this exploration.)

    Somewhere, I’ve got a book on optical illusions….

    • daniel Says:


      Thanks a lot for your answer!

      Yes, Bezold-Brücke is the effect to consider when light intensity varies
      I could take Munsell Main Hues and build (following Bezold-Brücke) this progression as light increases :

      P->PB->B->BG->G->GY-> (Y) <-YR<-R<-RP

      But my dilemma is WHY I arrive to the opposite secuence? What I’m doing wrong?

      I’m modeling the human eye responsiveness with the CIE 1931 Colour Matching Functions (CMF)

      I started defining the Illuminant to use in the analysis : CIE D65, so I got the Illuminant Spectrum : S(lamba)
      Then I defined the Object Reflectance Curve for a typical blue pigment colour, so I got R(lamba)
      To simulate the Shadow Series, I affected the Reflectance Curve by a “m” Decayment Factor, that multiplies the “original” reflectance Curve : R’(lambda) = m . R(lambda) adopting a sequence (for m) like this : 1.0, 0.9, 0.8, …, 0.1
      Then I obtained the Reflected Spectrum doing : SR(lambda) = S(lambda) . R’(lambda)
      Then I obtained the Perceived Spectrum doing : SP = SR(lambda) . CMF(lambda)
      Then integrating … I got the XYZ Tristimulus Values
      Then I converted XYZ Tristimulus Values to HVC Munsell Values
      Then I repeated the analysis for each 10 Munsell Main Hues
      Finally analyzed the obtained Hue Shiftings, arriving to the opposite and wrong conclusions

      “m” Factor affects directly to each XYZ variable, doing X’ = m . X and so on …
      “m” affects not only to the Y (luminance coordinate), it also affects X and Z

      As you say : XYZ defines a stimulus, not a perception … but to convert Colour Stimulus to Colour Perception I used the XYZ to HVC conversion (through GretagMacbeth software)


  11. rip Says:

    Hi Daniel,

    Thank you for elaborating.

    As I said, I do not understand human visual response; you could easily understand it better than I do.

    But given that you do not get the right answer, I would say three things.

    One, let me quote from the Giorgianni & Madden book (see my bibliography). “A given color perception can be elicited by a stimulus represented by just about any point on the chromaticity diagram, depending on the nature of the visual field and the viewer’s state of adaptation.”

    Perhaps I misunderstand them, but they seem to be saying that XYZ cannot be associated to a unique color, that the 1931 CIE does not model the human visual response to a stimulus.

    Two, you might look at

    Click to access Hue-Shift%20Modeling%20and%20Correction%20Method%20for%20High%20Luminance%20Display.pdf

    to see how they did it. In particular, they did their own color matching experiments to study this effect. That is, they did not use the CIE.

    Three, you might go to the newsgroup sci.engr.color where there are real experts.

    Thank you again for posting the question. I’m sorry I don’t know enough to answer it.

  12. daniel Says:


    Thanks a lot for the links!

  13. rip Says:

    You’re welcome.

    I do read the color newsgroup, so I’ll see whatever you get out there.

    Good luck!

  14. ram Says:

    How to implement the block-DCT compression algorithm and how to investigate the relation between the quantization scale factor and image quality (using mean square error and structural similarity “ssim” measures).

  15. rip Says:

    I have no idea.


  16. Faraz Says:

    Dear RIP,

    You have done a fantastic job by posting this article and by reading this article I think I have finally found a veteran of color technology. During last few months I had been struggling with different concepts in color systems. Actually I am designing a color sensor for liquids for my project and being an engineer I have lots of difficulties tackling some mathematical issues.
    Lately I have encountered a problem. For calibration of my sensor on different industrial regulations I read the regulation on Rosin color scale D509 and wanted to implement it. Now the point is that you know the path length of fluid affects the color in general. The longer the path length containing solution the darker would be the appearance. Now I have the values of xyY (chromaticity coordinates) for 22.6mm path length. If I want to get the values for 10mm path length by doing some maths I know that the values of spectral reflectance Y would change as per Beers law and should look like Y^(10/22.6). But the question is that how do I get to the new xy values after calculating the new Y under 10mm path length. Is there a mathematical way. I know that x=(X)/X+Y+Z, but could we solve this equation to get corrected xy. And secondly am I even right about the fact that changing path length should change xy and not only Y.
    Please help me, I am screwed by this.

  17. rip Says:

    Hi Faraz,

    I hate to say it, but the problem you’re describing is utterly new to me. I can’t help you.

    You might post the question to the USENET newsgroup sci.engr.color . And you might search other newsgroups to discover if people have talked about this kind of problem.

    Good luck.


    • Faraz Says:

      Hey RIP,

      No problem, lets keep it simple. If I have a value of xyY, and then due to some reasons I change the value of Y. Is there a mathematical relation to get the new values of xy depending on the updated value of Y. Can you tell me mathematically.


  18. rip Says:

    hi faraz,

    no, there’s no way. x,y,Y are independent. In particular, you can hold xy constant while changing only Y. For example, a published set of 1931 CIE xyY for the bottom line of the Macbeth Color Checker have

    xy = .3101, .3163

    Y = 3.13, 9.00, 19.77, 36.2, 59.1, 90.01 .

    they are black, 4 grays, and white.

    the only plausible prediction from that data is “xy = constant, independent of Y”. No, i’m not saying that “the” function is xy = constant — i’m saying they’re independent of Y.

    Now, if you change something else, maybe xy depend on that.


    • Faraz Says:

      Thanks RIP,

      That was it. I got the point. But I guess thats the beauty of trichromaticity representation that changing Y doesnt affects xy. I think its the denominator factor that nullifies the effect when changing from XYZ to xyY. This would really help me to proceed.


  19. rip Says:

    Hi Faraz,

    Although you didn’t ask a question, I thought of one. Did you mean to hold X and Z constant?

    If so, start from initial values xo, yo, Yo = 1… get constants

    Xo = xo Yo / yo

    zo = 1 – xo – yo

    Zo = zo Yo / yo

    and then let Y vary from 0 to 2 (2 looks good, if Yo = 1), computing

    x = Xo / (Xo + Y + Zo)

    y = Y / (Xo + Y + Zo).

    I can’t say that the resulting curves look very useful to me, since they all run in a NNW to SSE direction, but maybe you see something.


  20. John Peterson Says:

    OK, this discussion is far from my expertice, so I not only approached the edge but willingly flung myself into the Grand Canyon. I have unravled 50% of my challenge which is to extract xy from RGB but I am stuck on the other half. I also need to extract luminance (in cd/m2) from RGB and have found plenty of information but nothing definitive. Is it possible? If so, how? Any help would be appreciated.

  21. rip Says:

    Hi John,

    I don’t think you can recover an absolute intensity from RGB or XYZ, but I’d be happy to be shown wrong.

    Here’s why I think we can’t. I have shown how to get from a spectrum (actually two, source and reflectance spectra) to XYZ and xy. The first post doing that was

    That calculation shows that if we took a half-intensity source (or a half-intensity reflectance spectrum) then we would get exactly the same XYZ. If different intensities lead to the same XYZ, we can’t very well recover the intensity from XYZ.

    You could, I suppose, be asking a simpler question: given xy, how do I recover XYZ? The answer is that you must know one of X, Y, Z… it is customary to supply Y, and then we can get from xyY to XYZ.


    • John Peterson Says:

      Thank you for your reply. My project is to measure a light source and the prefered instrument (due to $$$) is a camera that can extract RGB measurements. I need to report color (in xy) and luminance (in cd/m2). From what I’ve read it does not seem to be possible with any accuracy and repeatability.

  22. rip Says:

    Hi John,

    If you can look at a copy of Giorgianni and Madden “Digital Color Management, Encoding Solutions”, 2nd ed, 978-0-470-51244-9, chapter 5 discusses going from a camera to a monitor. I don’t believe it will solve your problem, but it might give you some ideas.


  23. roshanak Says:

    For conversion form CIE xyY to XYZ. how much should the value of Y be considered? or better to say what are the possible values, do you know any references for this?
    one more question : if we compute the center of the rgb triangles for different rgb , whould it be the reference white for that specified rgb triangle?


  24. rip Says:


    These are good questions. I’d have answered sooner if I had had easy answers.

    First, plausible values for Y can easily vary by a factor of 100: we might set Y = 1 or Y = 100 for the white point. That is, for some purposes, Y has no physical significant, but is a scale factor.

    If we go the other way, from an illuminant and a reflectance spectrum to XYZ, Y may have physical significance – but I’m not sure. For me, much of this is just linear algebra.

    I will point out that I have examples of Z > Y, so any interpretation of Y is more complicated than “Y is maximum brightness.” This post, for example:

    As for the center of the triangle… well, we can use any white point we want with the given phosphors. That’s what the two “color primary conversion” posts show. That is, given the xyz for 3 phosphors and the white point (and setting Y = 1 or 100, usually), we can get the transformation matrices between XYZ and RGB. This post actually does the computations for two different white points but one set of phosphors:

  25. roshanak Says:

    Thanks Rip
    the book was great.

  26. roshanak Says:

    Dear Rip
    I need the CIE color matching function with 1nm intervals, but the only think I can find on the net is the matrix with 5nm.
    May I ask you to help me and guide me to a website or a book where I can find it.
    thank you very much

  27. rip Says:


    The 1-nm tables can be found in Wyszecki & Stiles “Color Science” pp.725-735 (see the bilbliographies page).

  28. Teeba Says:

    Hi RIP,
    I’m doing optical testing on colorful LEDs. I noticed that the Cx and Cy for blue LED goes beyond the gamut. The values are 0.136,0.0216.. I have repeated my measurements few times..But I’m getting the same results.. I’m not sure whether it caused by the LED or the testing software problem?..Is it possible to have coordinates beyond the gamut??..Please advice me on this..
    thank you very much.

    • rip Says:

      Hi Teeba,

      I’m sorry for the delay, but if I’d known an answer for you, I would have put it out quite a while ago. By now I hope you’ve gotten help elsewhere.

      I can find an assertion (Giorgianni & Madden, p 15; see my bibliography) that the x,y chromaticity coordinates of all physically realizable color stimuli must lie within the boundaries of the chromaticity chart, I find it plausible but I have never proved it.

      That said, we’re talking about “the standard observer”, so I have to wonder how your measuring device was calibrated. And exactly what computations does it do to get x,y from what it actually measures?

      I suggest is that you talk to the manufacturer of the measuring device.

      • Teeba Says:

        thank you for your reply.. I also have doubt on the calibration of the blue reference LED in the measuring equipment. Anyways I just want to confirm whether it is possible to have the color coordinates beyond the gamut..thank you very much. I’ll contact the vendor as soon as possible..
        God Bless…

  29. bercier Says:

    la première ligne de différences provient de la non précision des valeurs du tableau rbar
    il faut partir du tableau xbar qui est donné avec une grande précision
    on applique rbar,gbar,bbar=xbar,ybazr,bar)*Mt-1)n1
    n1=normalisation à 1

    .49 .31 .2
    M .17697 .8124 .01063
    0 .01 .99

  30. swapna Says:

    i want to draw CIE Color Coordinates by using orginpro8. can you help me

  31. rip Says:


    I can’t help you with originpro8, but to draw the CIE chart itself, “take the first two columns of the xyz table, read each row as (x,y) coordinates, and plot [them].”


  32. bercierbercier Says:


    MATRIX CIE 1931 =M

    0.49 0.31 0.2
    0.17697 0.8124 0.01063
    0 0.01 0.99

    t=transpose -> Mt

    Mt-1 inverse




    So n1 normalisation to 1


    CIE1931 -2° CMF

    Pour380nm qui est la valeur pour laquelle RIP trouve une grosse différence
    entre le calcul et les valeurs tabuléées :




    now to have rbar,gbar,bbar


    They are « biunivoque » relations between all this CMF

    xbarybarzbar gives xyz,XYZ who gives rbargbarbbar,rgb,(r1g1b1) Wright colorimetric fonctions,who gives lms and LMS relative luminous efficiency who gives now also r1g1b1 (WRIGHT) or all another colorimetric fonctions with others primaries like 460nm,513nm and 650 nm who gives a Maxwell approximated triangle
    and even polaried coordonnées rho and théta always >0

  33. bercier Says:

    on retrouve bien les valeurs tabulées données par RIP
    et non
    comme calculées par RIP
    La précision sur rbar,, est insuffisante pour pouvoir calculer r,, par normalisation à l’unité

    b e r c i e r

  34. rip Says:


    I do not understand the purpose of either of these comments. Unfortunately, I do not read French.

  35. Radu Says:

    Hey! I have a little problem.. I use the RGB spectrum, at work, to identify the colour my client want’s for his compound ( I have PVC compounding factory) and I have to make the PVC compound and the specific colour. Can you help me, with an ideea, at least, of hou to combine the pigments that I have into the right colour he wants? I have the RGB translated into Lab system and then I try combining the pigments until I find the right combination. But it takes time.. I am working on simplifying the process, but I lack the mathematic thinking. Any help would be apreciated! 😀

Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

%d bloggers like this: