Skip to main content

Notes on Color #8: Idealized Gamut Mask

Continuing with the previous post, in this one I'll try to identify the goal of gamut mapping, and to create an idealized model. 

The Color "Wheel"

A quick word with color wheel before we can proceed.

The color wheel arranges all paint (or device) colors (or more accurately, chromacity) in a hue-chroma system. The modern version is the uniform color system (UCS). I'll use CAM16UCS as an example. Here is the full visible gamut under D65, projected into CAM16UCS.
"top view" of the D65 visible gamut in CAM16UCS.
The color at (0, 0) is white.
The colors have been mapped to sRGB.

"Side view" of the D65 visible gamut in CAM16UCS.
Note the chroma is 0 at the topmost and the bottom-most.
The colors have been mapped to sRGB.


Observe that the top view resembles the the color wheel, but it is nothing like a perfect circle. We could say this is our modern version of the color "wheel", which presents chromacity uniformly on a 2d plane.

I also included a side view here. We can see that the volume of is a irregular cylinder-alike shape. The volumne is not regular in any direction, because our eyes are more sensitive to some wavelengths (green/yellow) than others (blue).

The Idealized Model

James once mentioned that the gamut mask could be used to simulate/achieve color grading. While color grading in general invovles multiple aspects such as contract, black level, details etc., I believe the focus here is color balance/correction.

Look at the following image:



After Figure 6.10 from Dale Purves and R. Beau Lotto's book Why We See What We Do; An Empirical Theory of Vision (2003, revised 2011)
Source: http://www.huevaluechroma.com/111.php

The blue tiles in A and the yellow tiles in B are actually both neutral gray without the context, which can be verified by sampling the RGB value of the pixels. This demonstrates our abilitiy of chromatic adaptation. We have to keep this in mind when paining a scene with tinted light, or "mood".

To simulate this effect, I simply took standard D65 illuminant, then muted ~1/3 visible spectra on the blue end. This resulting test illuminant would appear strongly yellow.
Under this illuminant, S cells won't receive any (reflected) light, while L and M cells are not affected much. We will not see any "real" blue (under D65) colors, but grey (under D65) objects may appear as blue-ish.

Cone cell response curves.
Source: Wikipedia


Under such an illuminant, the visible gamut is reduced, as shown below: (we do not consider self-emitting objects here)
"top view" of the visible gamut under the test illuminant.
Note that it is much smaller than the D65 version, especially the blue part.
The colors have been mapped to sRGB.
"Side view" of the visible gamut under the test illuminant.
Note the chroma is 0 at the bottom-most, but large at the topmost.
The colors have been mapped to sRGB.

Observed that almost all blue/purple fractions are missing, comparing with the D65 gamut.

We are not done yet. Definitely it's not the case where blue-purple colors suddenly disappear while all other colors stay the same. We still need to figure out how colors are shifted.

To do so, we study the Munsell colors (at value of 5) under D65 and the test illuminant. 

Munsell Colors (V=5) under D65, in CAM16UCS.
Black dots indicate colors that are outside of sRGB

Munsell Colors (V=5) under the test illuminant, in CAM16UCS.
Black dots indicate colors that are outside of sRGB.
Munsell Colors (V=2) under the test illuminant, in CAM16UCS.
Black dots indicate colors that are outside of sRGB.

Observations and interpretations:
  1. Only the top half of the original gamut is covered by the test version. All the colors are shifted towards the new "white" under the test illuminant, which appears yellow if compared with D65. Some colors are pushed outside sRGB and some are pulled inside.
  2. The yellow (D65) area (black dot on the top) is very crowded, while the blue (D65) area (blue-green dots on the bottom) is sparse. Remember that chroma and hue reflect wavelength and relative strength of the dominanting spectrum, therefore removing blue-ish spectra has much greater impact on blue-ish colors than yellow-ish colors.
  3. Comparing the V=2 version and the V=5 version. As V increases, the center of the Munsell colors is moving from black toward  the illuminant color. This is actually the black/grey/white value scale under the test illuminant. 
Assuming the standard Munsell colors represents a uniform color wheel, the shifted Munsell colors would work as a modern version of the gamut mask.

Comparing with the Orignial Version

Interestingly, the original triangular gamut mask works in a very similar way:
  • The triangle covers the top-center area of color wheel. (More accurately, it is important that the gask is off-center, not necessarily at the top-center).
  • The center of the mask is for white/neurtal grey in the painting
  • At least one primary color is completely out of the mask, we have to use grey or grey-ish color instead.
  • Consider the color at the center of the mask. When we mix the lighter and dark versions, it naturally ( and roughly) follows the path from black to the illuminant color.
I think these may well explain the color science behind the gamut mask method.

Meanwhile, also note that:
  • It is not (always) true that "all colors in the gamut mask may be obtained by mixing the gamut primaries. Paint mixing is not linear, it is somwhere between additive and subtractive.
  • The shape of the gamut should be more like ellipse, if we want to cover the entire chromacity. However that way it'd be difficult to identifiy primaries or to obtain colors inside the mask.
  • We need to pay attention to the white point as well as the distribution/division of hue & chroma inside the mask, which should not be uniform in general.
These a few points might worth some attention when we are dicussing color theories, but they may be far less important when we are painting in practice.

Final Thoughts

In this post I tried to interpret and extend the gamut mapping method with modern color theories. If you agree with my arguments, please stay skeptical and be aware of my shallow knowledge of color science. I would appreciate critiques.

As I mentioned in the last section, while there are a few issues, the gamut mask method works quite well in practice, as it is indeed supported by the color science. I find it fascinating that someone was able to come up with it in the 1920s, which is even earlier than the first modern CIE color space (in 1931).

I also believe that these "issues" won't affect much in traditional painting. Nothing is really mathematically accurate anyways, artists are indeed free to adjust chrome/hue/value, or to decide the shape of the mask. Besides, in real life we rarely see the whole visible gamut. In fact, I believe color harmony implies bias/limiting the palette/gamut.

Regarding digital versions, it is also true that most of the issues may be overcome with decent art skills. Yet I think it is important to be aware and conscious the issues when using the tool. 

On the other hand, maybe I can improve it by apply the method for my Zorn palette. We'll see.


Appendix: More on Munsell Colors

I'd like to discuss a few experiments on the Munsell colors. These do not conflict with the points above, but they are less interesting, so I'll just briefly talk about them here in the end.

When calculating Munsell colors under a specific illuminant, it is incorrect to simply apply chromatic adaption on the Munsell colors. That would affect models "self-emitting LEDs under the test illuminant". But we want "reflecting objects under the test illuminant". 

To simulate real reflecting objects we have to start with the spectral reflectance. I ended up using colour.XYZ_to_sd. But keep in mind that this can never be perfect. Information is lost when we convert a spectral distribution into a XYZ value. Also different two sets of  spectral distribution may correspond to the same XYZ value, which means they look exactly the same (by the idealized observer).

One interesting question, at first I expected blue colors would appear much darker under the test illuminant, because I removed all blue-ish wavelengths. However it did not turn out like that. I briefly examined the output of XYZ_to_sd, it seems keep a fraction of reflection of red-ish spectra, even for pure blue in sRGB.

It might be interesting to test a spectral distribution database of paints or real life objects.

In the experiment above, I removed the ~1/3 visible spectra on the blue end from D65. Actually I did the same for 1/3 spectra on the red end or in the middle.

Removed ~1/3 visible spectra on the red end.
Reduced the intensity of ~1/3 visible spectra in the middle to 30%

The results are in general similar, but the impact is quite different. The lost of the red-ish spectra did not have much impact, while the middle spectra had huge impact. In fact I only reduced the intensity or middle spectra to 30%, otherwise all the colors will be pushed out of sRGB.

This effect can be easily understood if we examine the cone cell response curves. The right-most 1/3 span has moderate effects on L cells, but not much on M cells. Meanwhile, the middle 1/3 span covers a large fraction of visible & high sensitive ranges of both L and M. 

Comments

Popular posts from this blog

[转] UTF-8 and Unicode FAQ for Unix/Linux

这几天,这个东西把我搞得很头疼 而且这篇文章好像太大了,blogger自己的发布系统不能发 只好用mail了 //原文 http://www.cl.cam.ac.uk/~mgk25/unicode.html UTF-8 and Unicode FAQ for Unix/Linux by Markus Kuhn This text is a very comprehensive one-stop information resource on how you can use Unicode/UTF-8 on POSIX systems (Linux, Unix). You will find here both introductory information for every user, as well as detailed references for the experienced developer. Unicode has started to replace ASCII, ISO 8859 and EUC at all levels. It enables users to handle not only practically any script and language used on this planet, it also supports a comprehensive set of mathematical and technical symbols to simplify scientific information exchange. With the UTF-8 encoding, Unicode can be used in a convenient and backwards compatible way in environments that were designed entirely around ASCII, like Unix. UTF-8 is the way in which Unicode is used under Unix, Linux, and similar systems. It is now time to make sure that you are well familiar ...

Determine Perspective Lines With Off-page Vanishing Point

In perspective drawing, a vanishing point represents a group of parallel lines, in other words, a direction. For any point on the paper, if we want a line towards the same direction (in the 3d space), we simply draw a line through it and the vanishing point. But sometimes the vanishing point is too far away, such that it is outside the paper/canvas. In this example, we have a point P and two perspective lines L1 and L2. The vanishing point VP is naturally the intersection of L1 and L2. The task is to draw a line through P and VP, without having VP on the paper. I am aware of a few traditional solutions: 1. Use extra pieces of paper such that we can extend L1 and L2 until we see VP. 2. Draw everything in a smaller scale, such that we can see both P and VP on the paper. Draw the line and scale everything back. 3. Draw a perspective grid using the Brewer Method. #1 and #2 might be quite practical. #3 may not guarantee a solution, unless we can measure distances/p...

Moving Items Along Bezier Curves with CSS Animation (Part 2: Time Warp)

This is a follow-up of my earlier article.  I realized that there is another way of achieving the same effect. This article has lots of nice examples and explanations, the basic idea is to make very simple @keyframe rules, usually just a linear movement, then use timing function to distort the time, such that the motion path becomes the desired curve. I'd like to call it the "time warp" hack. Demo See the Pen Interactive cubic Bezier curve + CSS animation by Lu Wang ( @coolwanglu ) on CodePen . How does it work? Recall that a cubic Bezier curve is defined by this formula : \[B(t) = (1-t)^3P_0+3(1-t)^2tP_1+3(1-t)t^2P_2+t^3P_3,\ 0 \le t \le 1.\] In the 2D case, \(B(t)\) has two coordinates, \(x(t)\) and \(y(t)\). Define \(x_i\) to the be x coordinate of \(P_i\), then we have: \[x(t) = (1-t)^3x_0+3(1-t)^2tx_1+3(1-t)t^2x_2+t^3x_3,\ 0 \le t \le 1.\] So, for our animated element, we want to make sure that the x coordiante (i.e. the "left" CSS property) is \(...