What are the LCh and JCh values for the sRGB blue primary?

Hmm, @KelSolaar - that just outputs the xy values for D65, yes?

@briend - If you put the xy values for D50 in the same place, the resulting LCh values match xicclu when asking for absolute colorimetric intent:

>>> colour.Lab_to_LCHab(colour.XYZ_to_Lab(colour.sRGB_to_XYZ([0, 0, 1]), [ 0.345703,0.358538]))
array([  32.30258667,  148.43329613,  301.62213623])

Which is puzzling. I would have thought that using the xy values for D65 would match ArgyllCMS absolute colorimetric intent.

@KelSolaar - what xy values would you use to match ArgyllCMS relative colorimetric intent, where the LCh values are for sRGB adapted to D50 to make an ICC profile? Or am I completely missing something here?

You’re right. It seems like quite a few of the XYZ->Lab converters are using D65. Does this also explain the results of xicclu and CIECAM02? The manpage makes it sound like the defaults are also D50.

Yes, this will use D65 as the illuminant for the CIE XYZ to CIE Lab transformation, (default is currently D50 but will very likely change to D65 in the future).

There is no gamut mapping in Colour (yet), so you are a bit in uncharted territory here and I don’t know how Argyll works under the hood, so I cannot really comment on that. If the output of Argyll is gamut mapped with Relative Colorimetric Rendering Intent, I’m then not surprised at all that you get discrepancies as it involves projecting colours on the gamut boundaries.

There is no gamut mapping in the xicclu output when converting from a matrix sRGB ICC profile to Lab/LCh/etc. It just does the requested conversion using either relative or absolute colorimetric intent.

@KelSolaar What’s the colour equation for doing a Bradford chromatic adaptation of an XYZ color from one white point to another white point?

@briend - I don’t understand how the colour code deals with D50 vs D65. I also don’t know how to interpret the idea that in the colour-science code sRGB blue when somehow associated with a D65 white point (instead of colour’s default D50 white point), somehow moves to a JCh hue angle of 258 instead of the JCh hue angle of 272 that ArgyllCMS xicclu calculates, such that the line connecting sRGB yellow and blue in the colour-science JCH calculations, does cross through nice green colors.

Maybe this result that in colour’s CIECAM02 “sRGB yellow and blue make green when you use D65 as the color of white” has something to do with the various parameters fed to colour’s CIECAM02 module, which is what I sort of thought might be the source of this result.

But failing to get agreement with xicclu LAB/LCh values without somehow mixing D65 XYZ values for sRGB with colour’s D50 assumed white point, I’m not sure I have the stamina to keep slogging through all the reasons why sRGB yellow and blue are making green in colour’s JCh calculations.

I might be completely missing something here regarding dealing with white points, but I don’t have a clue what that “something” might be (hence “completely missing” :slight_smile: ).

@jdc or @gwgill - can either of you cast light on how a line connecteing sRGB yellow and blue in JCh can cross over greens?

The same it is in every instance? LMS domain via Bradford and scale?

In case it’s not clear from how I worded the question, I’m not asking for theory. I have spreadsheets for calculating Bradford adaptation. I know the equations.

My question is what, exactly, is the syntax - the actual stuff to type at the python prompt - for asking colour to do the calculations to adapt an XYZ color from one white point to another.

I thought intents were the gamut mapping strategy?

Maybe CIECAM02 is just wrong? CAM16 puts sRGB yellow and sRGB blue ~172 degrees apart on the color wheel. That’s much more reasonably close to visual complements, don’t you think?

A couple of notes:

ICC profiles store the basic data in D50 white point relative form (Profile Connection Space). The ICC specified transform from Absolute form (D65 white point in the case of standard Display spaces) into Relative form uses an XYZ chromatic transform (So called “wrong” Von Kries matrix). But historically there was a deal of disagreement about how display D65 absolute space should be transformed into D50 relative space for display profiles. Some very widely distributed profiles (i.e. the Microsoft/HP sRGB and AdobeRGB profiles) used the preferred Bradford chromatic transform matrix. A CMM (Color Management Module) that uses a Wrong Von Kries chromatic matrix to convert standard sRGB values into absolute coorrdinates will give results that do not agree with the sRGB specifications. So this type of thing is a potential explanation for disagreements amongst different programs and/or profiles.

[ I’m moderately confident that ArgyllCMS will be getting it right with the ArgyllCMS supplied sRGB profile. ]

The ArgyllCMS CIECAM Jab and JCh will not agree with the published CIECAM02 space values. This is because I have tweaked the ArgyllCMS CIECAM space space rather extensively in an attempt to avoid some very bad behavior near and beyond the expected gamut that CIECAM02 was developed for. Some notes on these changes are in the source file xicc/cam02.c

The intention of your question wasn’t clear.

https://colour.readthedocs.io/en/latest/colour.adaptation.html

I did indeed consult the documentation:

Despite my best efforts and a lot of tries, I haven’t been able to figure out exactly what to type at the python prompt.

So again, could some kind soul actually provide the syntax, the actual command for doing a chromatic adaptation of an XYZ color using the colour-science code.

What I’m looking for is an example to follow, as in “type exactly this” at the python prompt and “this result will be printed to the screen”

@briend - your cam16 result of h~272 is very close to xicclu result of h~273, so maybe cam16 incorporated a lot of the sort of stuff that @gwgill 's JCh code is doing - reading through the xicc/cam02.c file, there’s a lot of tweaking mentioned in there. Regarding the discussion we were having that prompted this whole thread (“How can the straight line between sRGB blue and yellow cross through green on the JCh color wheel”) it would be interesting to see how close other sRGB colors would be using your cam16 output vs xicclu JCh output. I have the correct python colour syntax from examples you provided, so I’ll try to check some values later today.

Cam16 is giving me 282 hue for sRGB blue 0,0,1

I think on a CAM16 wheel this wouldn’t happen, being 172 degrees opposed

Oh, my apologies! Well, that’s still a lot better than 258 - at least it puts sRGB blue on the positive a-axis side of the JCh color wheel.

Regarding the topic of blue and yellow mixing to create green…

https://www.handprint.com/HP/WCL/vismixmap.html

“Contrary to traditional color theory dogma… light to medium yellows have no true mixing complements, but mix very dull greens with violet blues and tans with purple.”

I think last few sections of that url clear up a lot of the issues with using a visual color wheel to make mixing predictions:

“The fact that the mixing hue circle arranges paints according to their colors is the source of mischief. Mixing complements are always imprecise because (1) all paints of a given hue (“color”) are not effective mixing complements for all the paints of the complementary hue, (2) the mixing complements for a single paint may differ widely in hue (paints obliquely opposite each other on a mixing color wheel can also mix grays or neutral colors), and (3) chroma is as important as hue in defining mixing complement pairs”

So, if we use higher chroma colors than what is natural this is a lot like using an artificial sweetener that might be sweeter than any natural sugar. Might not want to put that in your cake but doesn’t mean you can’t. . .

Well, I did use the words “mix green”. But what I really mean and should have been more careful to always say is “cross through more or less colorful greens when drawing a direct line between sRGB yellow and blue on an LCh or JCh (of various flavors) color wheel”.

Minimally, the various cams are an attempt to capture how we perceive colors, including, I hope - someone please correct me if I’m wrong - how we conceive colors as progressing from one color to the next.

Do we expect a perceptually uniform visual (not talking about mixing actual paints) progression from sRGB yellow to sRGB blue to cross into greens? I can believe “Maybe, but the greens will be very unsaturated”. But I can’t believe “Yes, and the greens will be bright and cheerful”.

I also can’t believe “No, instead the colors cross over oranges and magentas” as seems to be the case with plotting these colors on the LCh color wheel. My conception of “how colors progress” would require a more orange shade of yellow than sRGB yellow, to get oranges and magentas in a progression from yellow to sRGB blue.

Here’s a plot of xicclu JCh (to the left, crossing almost through gray) and xicclu LCh crossing the positive a-axis through orange-yellow) to show what I mean by drawing lines on a color wheel and having the traversed colors look like a believable progression. Please keep in mind I created the progression rather quickly using a spreadsheet, xicclu, and GIMP, so there’s plenty of room for error on my part:

Well, according to that nice “Golden” paint website that @Claes and @paperdigits linked to, sRGB blue isn’t a paint they can mix, and neither is sRGB yellow, though I’m fairly sure sRGB yellow is an actual surface color that paint pigments can produce. But I think sRGB blue isn’t an actual surface color at all.

My understanding of how real world paint pigments mix - multiplying spectral reflectance curves and such - is minimal, practically non-existent. Hopefully other people in this thread might be qualified to predict what might happen when mathematically mixing imaginary paint pigments.

Drawing a straight line on a visual color wheel between visual complements should result in grey colors. So CAM16 seems to agree that blue and yellow pass nearly through the middle.

But ask a child to draw the colors between yellow and blue and they might put green there. Visually interpolating between these colors should, I think, be most similar to LERPing between the JMh values of both colors.

So that’s two models already without including mixing paints. Mixing paint is practically guesswork, which is what MacEvoy is trying convey.

I’m working on a script that takes two colors, does the Meng recovery, and outputs a gradient based on various mixing ratios. I haven’t scaled the illuminant properly yet but it does return valid results I believe. I’ll post that script a bit later.

Your “again” here wasn’t clear. The first time it looked like you were wondering what particular equation Colour was using. Hopefully you can see that it wasn’t terribly clear that you wanted Python syntax.

colour.adaptation.chromatic_adaptation_VonKries(what_to_adaptXYZ, illuminant_XYZ, reference_illuminant_XYZ, transform="Bradford")

As an example of something possible, where colour defines illuminants of course, but for demonstration purposes I’ve put some values in:

  illE = numpy.array([1./3., 1./3., 1.])
  ill65 = numpy.array([0.3127, 0.3290, 1.])

  # Illuminants can be specified from the constants, for example
  # colour.ILLUMINANTS['CIE 1931 2 Degree Standard Observer']['D50']
  # The full constants are at:
  # https://github.com/colour-science/colour/blob/develop/colour/colorimetry/dataset/illuminants/chromaticity_coordinates.py
  illEXYZ = colour.xyY_to_XYZ(illE)
  ill65XYZ = colour.xyY_to_XYZ(ill65)

  sRGBvalue= numpy.array([0.77, 0.66, 0.55])

  # The "False" in the following tells Colour to not apply the transfer function
  sRGBvalueXYZ = colour.sRGB_to_XYZ(sRGBlow, apply_decoding_cctf=False)

  adaptedsRGBXYZ = colour.adaptation.chromatic_adaptation_VonKries(sRGBvalueXYZ, ill65XYZ, illEXYZ, transform="Bradford")

https://colour.readthedocs.io/en/latest/generated/colour.adaptation.chromatic_adaptation_VonKries.html#colour.adaptation.chromatic_adaptation_VonKries

Colour has some excellent plotting tools as well. Hopefully this example helps in some way.

If anyone has some examples for plotting colors on wheel please share :sunglasses:

I am pretty sure you would be able to follow Tutorial | Colour Science and automatically generate the plots required in this thread.

1 Like