Imagine a typical device gamut on CIE xy diagram:

enter image description here

x and y coordinates for primary colors (red, green and blue) is defined and known, how to calculate secondary colors (cyan, magenta and yellow)?

  • 2
    \$\begingroup\$ This is interesting, and obviously color is relevant to photography in general, but could you spell out the particular photographic application you have in mind here? \$\endgroup\$
    – mattdm
    Mar 1, 2016 at 17:39
  • \$\begingroup\$ @mattdm I working with projectors and color matching between them \$\endgroup\$
    – Jeka
    Mar 2, 2016 at 15:35
  • \$\begingroup\$ What are cyan, magenta, yellow which you are talking about? Are they blue+green, red+blue, red+green respectively? \$\endgroup\$ Aug 2, 2016 at 21:21
  • \$\begingroup\$ @EuriPinhollow As I mentioned before I am working with color matching system with projectors. In each projector menu I have to set real measured CIE xy coordinates for primaries R,G,B. Then I have to calculate common reachable gamut. It's is easy to calculate R,G,B coordinates of it, but projector also require C, M, Y, which I have to calculate somehow. \$\endgroup\$
    – Jeka
    Aug 3, 2016 at 10:07
  • \$\begingroup\$ @jeka: should not they be measured too? If you have a LUT (i.e. not matrix) profile for your projector you can deduce those coordinates from it. \$\endgroup\$ Aug 3, 2016 at 10:14

1 Answer 1


Performing the operation directly using the chromaticity coordinates (ie: taking the midpoint between the two chromaticity coordinates) will yield incorrect results as the chromaticity diagram is highly non uniform.

Assuming you are using linear light values you could perform the following chain of computations:

  • CIE xy to CIE xyY (Optional) for each pair of chromaticity coordinates where the Y Luminance value is retrieved from the sRGB normalised primary matrix. It is important to acknowledge that when you are using chromaticity coordinates alone you don't have any Luminance information which can also produce unexpected results.
  • CIE xy to CIE XYZ for each pair of chromaticity coordinates
  • CIE XYZ to sRGB for each pair of tristimulus values
  • sRGB add of your pair of RGB values
  • sRGB to CIE XYZ of you resulting RGB values
  • CIE XYZ to CIE xy

Now this is likely more dedicated to SO but you could use colour to perform those computations:

% matplotlib inline

import numpy as np
import pylab

import colour
from colour.plotting import *

# Conversion from RGB to chromaticity coordinates.
# Defining RGB values for reference.
RGB_r = np.array([1, 0, 0])
RGB_g = np.array([0, 1, 0])

# We assume they are encoded in *sRGB* colourspace.
XYZ_r = colour.sRGB_to_XYZ(RGB_r, apply_EOCF=False)
XYZ_g = colour.sRGB_to_XYZ(RGB_g, apply_EOCF=False)

# Conversion to chromaticity coordinates.
xy_r = colour.XYZ_to_xy(XYZ_r)
# [ 0.64  0.33]

xy_g = colour.XYZ_to_xy(XYZ_g) 
# [ 0.3  0.6]

# Conversion to CIE xyY in order to maintain Luminance ratios.
# Using sRGB Luminance ratios, second row of the NPM.
xyY_r = [0.64, 0.33, colour.sRGB_COLOURSPACE.RGB_to_XYZ_matrix[1, 0]]
xyY_g = [0.3, 0.6, colour.sRGB_COLOURSPACE.RGB_to_XYZ_matrix[1, 1]]

xy_s = colour.XYZ_to_xy(
        colour.XYZ_to_sRGB(colour.xyY_to_XYZ(xyY_r), apply_OECF=False) +
        colour.XYZ_to_sRGB(colour.xyY_to_XYZ(xyY_g), apply_OECF=False)))
# [ 0.41930366  0.50525886]

# Plotting.
    ('sRGB', ),
    bounding_box=(-0.1, 0.9, -0.1, 0.9), 

pylab.plot(xy_r[0], xy_r[1], 'o', markersize=15, color=RGB_r)
pylab.plot(xy_g[0], xy_g[1], 'o', markersize=15, color=RGB_g)
pylab.plot(xy_s[0], xy_s[1], 'o', markersize=15, color=RGB_s)

Secondary Chromaticity Coordinates

  • \$\begingroup\$ I stand corrected :-). Nice Python package BTW. \$\endgroup\$
    – TFuto
    Mar 2, 2016 at 14:27
  • \$\begingroup\$ Thanks, looks promising, I am going to implement it in C++ but thanks for python code. Could you explain why we should use sRGB. Also I have luminance data (cd/m2 or foot-lambert) can it be helpfull? to de honest I don't understand optional part where you a sugesting to convert xy to xyY \$\endgroup\$
    – Jeka
    Mar 2, 2016 at 16:01
  • \$\begingroup\$ I have troubles running your code: Traceback (most recent call last): File "C:/Users/Жека/PycharmProjects/SecondaryColors/colors.py", line 6, in <module> from colour.models.rgb.derivation import xy_to_z ImportError: No module named 'colour.models.rgb.derivation'; 'colour.models.rgb' is not a package Is xy_to_z is just 1 - x - y? \$\endgroup\$
    – Jeka
    Mar 2, 2016 at 20:16
  • \$\begingroup\$ > Could you explain why we should use sRGB. I choose sRGB because we have convenient wrappers around it but you could have chosen any RGB colourspace really (XYZ_to_RGB, RGB_to_XYZ). > to de honest I don't understand optional part where you a sugesting to convert xy to xyY With using only the chromaticity coordinates, you don't know what the Luminance is. You may want to pick a Luminance value per chromaticity coordinates that preserve the ratios of human visual system sensitivity to brightness. \$\endgroup\$
    – Kel Solaar
    Mar 4, 2016 at 18:54
  • \$\begingroup\$ But this is optional, if you have the Luminance values then it is even better. > I have troubles running your code Ah yeah I'm running that from latest develop branch on Github: github.com/colour-science/colour \$\endgroup\$
    – Kel Solaar
    Mar 4, 2016 at 18:54

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.