Mike Stark

Homework #2

Excursions in Color Theory

Overview

For this assignment we were asked to render the visible spectrum, over a range of luminances. The problem is that modern computer monitors cannot, in general, faithfully produce any pure "spectral" color, simply because the small light-producing elements, or phosphors, do not produce a purely monochromatic color. The following is a rough illustration of the fundamental plane in the CIE XYZ color space.

The pure colors in the visible spectrum at a fixed luminance are found along the white horseshoe-shaped curve, the interior of which contains all the colors visible to the human eye (at least approximately) at a fixed luminance. The colored triangle is the roughly "gamut" of the Sony monitor on the SGI workstation I used for this assignment. The grayish point at the center is the "white point" of the monitor, and should correspond roughly with the white point of the color space. Lines radiating outward from the white point have the same hue, and become more saturated as they approach the horseshoe. The corners of the triangle are, approximately, the colors of the phosphors of the monitor. Notice they are not actually on the spectrum (as noted above) but they are partially saturated spectral colors. There is a standard, if somewhat imperfect method of converting visible colors in CIE XYZ coordinates, as described in the homework assignment

The image above actually is something of an over-simplification, because the actual gamut of a monitor is a three-dimensional parallelepiped; the triangle above is this solid projected onto the fundamental CIE XYZ plane X + Y + Z = 1. True spectral colors must therefore be mapped somehow into the space of the gamut of the monitor, in a manner that preserves the hue of the color.

Methods

I've tried a huge number of ideas to find a good way of doing this, and I've most of them weren't any good. But I did have some success; although I must admit most of the ideas that worked weren't really my own.

Clipping and Scaling

In general the RGB values of a spectral color are outside the RGB color cube in all directions. That is, values above 1 and below zero appear in all three coordinates. So an obvious reduction method is to simply "clip" RGB values outside the interval [0, 1]:

This works better than one might expect, although the image above has the RGB values implicitly scaled to a "nice" range which I found easier to work with. The most serious problem with the clipping method is that is the absence of the so-called "secondary colors", yellow, cyan, and violet. In fact, there is a significant dark space where the cyan, or indigo, range should be. Also, there are "Mach" bands in the primary color regions.

An alternative but similar approach is to scale the components into the cube, rather than clipping them. In this method, the minimum RGB component is scaled to zero, and the maximum to one.

Desaturation

The boundary of the monitor gamut consists essentially of spectral hues with less saturation, so perhaps the most natural reduction method is to simply "desaturate", or add white, to each spectral color until it reaches the monitor gamut, as shown below:

For this figure, the desaturation was done in RGB space; enough white was added so that the largest negative component was raised to zero, and the result was then clipped. Is this an improvement? Well, there is more violet on the left side, which appeals to me, because I like that color! Also, the primary colors aren't as dominant, and there is less of a "flame" effect which is desirable, as scan-lines should ideally only differ in brightness, or luminance. However, some of the colors are under-saturated, as is particularly noticeable in the cyan region which is too large anyway. The curved Mach bands are not as prevalent, but now the primary colors themselves appear in Mach bands, albeit vertical bands, but now instead of being over-emphasized, the primary colors are reduced to these narrow bands.

A Hybrid Approach

There appear to be definite advantages to both clipping and desaturization, so a hybrid approach seems the natural next step. The method is to desaturate only most of the way to the monitor gamut, then clip as usual. I found that about 70% works pretty well, and this value was used to create to following image.

Notice the Mach bands in the primary colors have been reduces, as has the under-saturated cyan band.

Exactly how much desaturation we should do isn't so clear. For fun, I put together an animation of the result of 0 through 100% desaturation.

Fudging

The hybrid image above leaves much to be desired aesthetically, so perhaps it is worth some effort to "fudge" the image. One approach is to apply a gamma correction on the desaturated and clipped RGB values. Such an image, using an exponent of 0.8 is shown below:

Is this an improvement? Well, the primary color Mach bands are more noticeable, but the image "fadeout" is improved somewhat. I put together another animation of gamma exponents 0.5 through about 2, although this really only shows the effect of gamma corrections. Of course, the monitor is supposedly already gamma corrected, but it never hurts to experiment.

If one really wanted to work on the general appearance of the spectrum, more general corrections need to be used. The following image has been adjusted in a variety of ways, mostly based on localized gamma corrections. I don't claim this image is the best we can do, but it does show how local corrections can be included to make overall improvements.

In particular, the pinkish area to at the right of the image has been reduced, as has the blue Mach band. They cyan area has been contracted somewhat; however, we have lost some of the dimmer yellow and violet. But with more work, these could probably be brought out.

Final Comments

These images were produced using the data Brian Smits provided for the SGI Sony monitors.

As a point of possible interest, the X Window System, beginning with Release 5, provides an extensive mechanism for device-independent color, including functions for converting between various color spaces. Here is how X11 handled the conversion: