The eye is a detector of light whose sensitivity to the quality or wavelength of the light has developed into color perception. Color is the only one of several qualities that go to make up our field of vision. The physical features of the light, the physiological progress in retina and brain, and finally the psychological interpretation of the physiologic response determine the color sensation that we experience. The retina, located in the inner surface of the eye, contains light receptors (specialized photoreceptor cells), called rods and cones. Since rods are unable to distinguish color (being used only under low illumination), we will only concern ourselves with cones.

There are three types of cones, each containing a different pigment with different absorption spectra. (That is, the three types of cones have different spectral sensitivity). Hence response of the three types of cones depend on the spectral distribution of light reaching them.

In optics, Grassmann’s law^{[1]} is an empirical result about human color perception: that chromatic sensation can be described in terms of an effective stimulus consisting of linear combinations of different color lights. That is, human eyes react **linearly** to different colors of light.

If a test color is the combination of two other colors, then in a matching experiment based on mixing primary light colors, an observer’s matching value of each primary will be the sum of the matching values for each of the other test colors when viewed separately. In other words, if **beam 1** and **beam 2** are the initial colors, and the observer chooses\(\left( {{R}_{1}},{{G}_{1}},{{B}_{1}} \right)\)as the strengths of the primaries that match beam 1 and\(\left( {{R}_{2}},{{G}_{2}},{{B}_{2}} \right)\)as the strengths of the primaries that match beam 2, then if the two beams were combined, the matching values will be the sums of the components. Precisely, \(\alpha \)**beam 1** +\(\beta \)**beam 2 =\(\alpha \left( {{R}_{1}},{{G}_{1}},{{B}_{1}} \right)+\beta \left( {{R}_{2}},{{G}_{2}},{{B}_{2}} \right)\)**.

The **CIE 1931 RGB color space** and **CIE 1931 XYZ color space** were created by the International Commission on Illumination (CIE) in 1931. They resulted from a series of experiments done in the late 1920s by William David Wright and John Guild. The experimental results were combined into the specification of the CIE RGB color space, from which the CIE XYZ color space was derived.

We briefly describe the experiment^{[2,3,4]} that gives rise to the color matching functions. The screen is divided by an opaque panel. A source beam, its color\(C\), is casted on the left half part. Then three beams with different colors\(R,G,B\)are casted on the right half part and we adapt the intensity of beams to make the color of the right screen same to the left one. The corresponding intensities of three colors are\(r,g,b\). Because of the linearity of light color, we can get the equation:

\(C=rR+gG+bB\)

A series of experiments were carried out using various primaries at various intensities and all of their results were summarized by the standardized CIE RGB leading to the **color matching functions**, obtained using three monochromatic primaries (\(\overline{r}\left( \lambda \right),\overline{g}\left( \lambda \right),\overline{b}\left( \lambda \right)\)). The color matching functions are the amounts of primaries needed to match the monochromatic test color at the wavelength at the following figure.

Figure 1^{[5]}. The CIE 1931 RGB color matching functions.

In the figure, we can find some negative values on the curve. Why is it? In the above experiment, three light beams of different colors on the right screen are adapted to left one. If there exit one case that no appropriate combination make the color on the right screen same to left when we try anything, we cast a certain amount of light on the left screen to make the equilibrium. The addition on the left is equal to the subtraction on the right. Therefore, we get the negative values on the curve.

Once the RGB tristimulus values were obtained^{[6]}, they were found to be wanting in some regards. Due to gamut restraints, the RGB color model could not reproduce all spectral light without introducing the effect of negative RGB values (this was done by mixing red, green, or blue light with the test lamp as needed). CIE thought a system that used negative values would not be acceptable as an international standard. Accordingly, they translated the RGB tristimulus values into a different set of all positive tristimulus values, called XYZ, which formed the first CIE color model. From this first model, other models were derived in response to various concerns as following figure:

Figure 2^{[5]}. The CIE XYZ color matching functions.

CIE considered the tristimulus values for red, green, and blue to be undesirable for creating a standardized color model^{[6]}. Instead, they used a mathematical formula to convert the RGB data to a system that uses only positive integers as values. The reformulated tristimulus values were indicated as XYZ. These values do not directly correspond to red, green, and blue, but are approximately so. The curve for the Y tristimulus value is equal to the curve that indicates the human eye's response to the total power of a light source.

Conversion from XYZ to RGB space is linear and can be done with a matrix^{[7]}:

\[\left( {\begin{array}{*{20}{c}}R\\G\\B\end{array}} \right) = \left( {\begin{array}{*{20}{c}}{3.240479}&{ - 1.537150}&{ - 0.498535}\\{ - 0.969256}&{1.875992}&{0.041556}\\{0.055648}&{ - 0.204043}&{1.057311}\end{array}} \right) \cdot \left( {\begin{array}{*{20}{c}}X\\Y\\Z\end{array}} \right)\]

This conversion matrix is for a monitor with a D65 white point, a particular definition of the “full on” white color produced by the monitor. Some XYZ values can transform to RGB values that are negative or greater than one. The inverse RGB to XYZ conversion is:

\[\left( {\begin{array}{*{20}{c}}X\\Y\\Z\end{array}} \right) = \left( {\begin{array}{*{20}{c}}{0.412453}&{0.357580}&{0.180423}\\{0.212671}&{0.715160}&{0.072169}\\{0.019334}&{0.119193}&{0.950227}\end{array}} \right) \cdot \left( {\begin{array}{*{20}{c}}R\\G\\B\end{array}} \right)\]

A common conversion is to transform an RGB color to a grayscale luminance value, which is simply the middle row of the previous equation:

\[Y = 0.212671R + 0.715160G + 0.072169B\]

We will introduce other color model, **HSL** and **HSV**. HSL and HSV are the two most common cylindrical-coordinate representations of points in an RGB color model. The two representations rearrange the geometry of RGB in an attempt to be more intuitive and perceptually relevant than the cartesian (cube) representation. Developed in the 1970s for computer graphics applications, HSL and HSV are used today in color pickers, in image editing software, and less commonly in image analysis and computer vision. HSL stands for hue, saturation, and lightness (or luminosity), and is also often called HLS. HSV stands for hue, saturation, and value, and is also often called HSB (B for brightness).

In HSL, the saturation component always goes from fully saturated color to the equivalent gray. The lightness in HSL always spans the entire range from black through the chosen hue to white. HSL conceptually represents a double-cone or sphere (with white at the top, black at the bottom, and the fully-saturated colors around the edge of a horizontal cross-section with middle gray at its center) as the following figure^{[8]}:

Figure 3^{[8]}. Graphical depiction of HSL

In HSV, with value at maximum, it goes from saturated color to white, which may be considered counterintuitive. The Value component only goes half that way, from black to the chosen hue as the following figure:

Figure 4^{[8]}. Graphical depiction of HSV

**Converting to RGB from HSL**

Given a color with hue\(H\in \left[ 0,360 \right]\), saturation\(S\in \left[ 0,1 \right]\), and lightness\(L\in \left[ 0,1 \right]\).The equation is as following:

\(C=\left( 1-\left| 2L-1 \right| \right)\cdot S,H'=H/60,X=C\left( 1-\left| H'\bmod 2-1 \right| \right)\).

\begin{eqnarray*}

\left( {R',G',B'} \right) = \left\{ {\begin{array}{*{20}{l}}

{\left( {0,0,0} \right)}&{{\rm{if }}H{\rm{ is undefined}}}\\

{\left( {C,X,0} \right)}&{if{\rm{ }}0 \le H' \le 1}\\

{\left( {X,C,0} \right)}&{if{\rm{ }}1 \prec H' \le 2}\\

{\left( {0,C,X} \right)}&{if{\rm{ }}2 \prec H' \le 3}\\

{\left( {0,X,C} \right)}&{if{\rm{ }}3 \prec H' \le 4}\\

{\left( {X,0,C} \right)}&{if{\rm{ }}4 \prec H' \le 5}\\

{\left( {C,0,X} \right)}&{if{\rm{ }}5 \prec H' \le 6}

\end{array}} \right.

\end{eqnarray*}

\(m=L-\frac{1}{2}C\),\(\left( R,G,B \right)=\left( R'+m,G'+m,B'+m \right)\), \(R,G,B\in \left[ 0,1 \right]\).

Fast branchless RGB to HSL conversion in GLSL as follow:

vec3 hsl2rgb(vec3 c){ float t = (1.0 - abs(2.0 * c.z - 1.0)) * c.y; vec4 k = vec4(1.0, 2.0 / 3.0, 1.0 / 3.0, 3.0); vec3 p = abs(fract(c.xxx + k.xyz) * 6.0 - k.www); return (clamp(p - k.xxx, 0.0, 1.0) - vec3(0.5)) * t + vec3(c.z); }

**Converting to HSL from RGB**

Given the color\(R,G,B\in \left[ 0,1 \right]\), the equation is as following:

\(M=\max \left( R,G,B \right),m=\min \left( R,G,B \right),C=M-m\)

\begin{eqnarray*}

H = \left\{ {\begin{array}{*{20}{l}}

{undefined}&{if{\rm{ }}C = 0}\\

{60 \cdot \left( {\frac{{G - B}}{C}\bmod 6} \right)}&{if{\rm{ }}M = R}\\

{60 \cdot \left( {\frac{{B - R}}{C} + 2} \right)}&{if{\rm{ }}M = G}\\

{60 \cdot \left( {\frac{{R - G}}{C} + 4} \right)}&{if{\rm{ }}M = B}

\end{array}} \right.

\end{eqnarray*}

\[L = \frac{{M + m}}{2}\]

\begin{eqnarray*}

S = \left\{ {\begin{array}{*{20}{l}}

0&{if{\rm{ }}C = 0}\\

{\frac{C}{{1 - \left| {2L - 1} \right|}}}&{if{\rm{ }}C \ne 0}

\end{array}} \right.

\end{eqnarray*}

Fast branchless RGB to HSL conversion in GLSL as follow:

vec3 rgb2hsl(vec3 c){ vec4 K = vec4(0.0, -1.0 / 3.0, 2.0 / 3.0, -1.0); vec4 p = mix(vec4(c.bg, K.wz), vec4(c.gb, K.xy), step(c.b, c.g)); vec4 q = mix(vec4(p.xyw, c.r), vec4(c.r, p.yzx), step(p.x, c.r)); float m = min(q.w, q.y); float d = q.x - m; float l = (m + q.x) * 0.5; return vec3(abs(q.z + (q.w - q.y) / (6.0 * d + EPS)), d / (1.0 - abs(2.0 * l - 1.0) + EPS), l); }

**Converting to RGB from HSV**

Given a color with hue\(H\in \left[ 0,360 \right]\), saturation\(S\in \left[ 0,1 \right]\), and value\(V\in \left[ 0,1 \right]\).The equation is as following:

\(C=V\cdot S,H'=H/60,X=C\cdot \left( 1-\left| H'\bmod 2-1 \right| \right),m=V-C\)

\begin{eqnarray*}

\left( {R',G',B'} \right) = \left\{ {\begin{array}{*{20}{l}}

{\left( {0,0,0} \right)}&{{\rm{if }}H{\rm{ is undefined}}}\\

{\left( {C,X,0} \right)}&{if{\rm{ }}0 \le H' \le 1}\\

{\left( {X,C,0} \right)}&{if{\rm{ }}1 \prec H' \le 2}\\

{\left( {0,C,X} \right)}&{if{\rm{ }}2 \prec H' \le 3}\\

{\left( {0,X,C} \right)}&{if{\rm{ }}3 \prec H' \le 4}\\

{\left( {X,0,C} \right)}&{if{\rm{ }}4 \prec H' \le 5}\\

{\left( {C,0,X} \right)}&{if{\rm{ }}5 \prec H' \le 6}

\end{array}} \right.

\end{eqnarray*}

\(\left( R,G,B \right)=\left( R'+m,G'+m,B'+m \right)\), \(R,G,B\in \left[ 0,1 \right]\).

Fast branchless HSV to RGB conversion in GLSL as follow^{[10]}:

vec3 hsv2rgb(vec3 c){ vec4 K = vec4(1.0, 2.0 / 3.0, 1.0 / 3.0, 3.0); vec3 p = abs(fract(c.xxx + K.xyz) * 6.0 - K.www); return c.z * mix(K.xxx, clamp(p - K.xxx, 0.0, 1.0), c.y); }

**Converting to HSV from RGB**

Given the color\(R,G,B\in \left[ 0,1 \right]\), the equation is as following:

\(M=\max \left( R,G,B \right),m=\min \left( R,G,B \right),C=M-m\)

\begin{eqnarray*}

H = \left\{ {\begin{array}{*{20}{l}}

{undefined}&{if{\rm{ }}C = 0}\\

{60 \cdot \left( {\frac{{G - B}}{C}\bmod 6} \right)}&{if{\rm{ }}M = R}\\

{60 \cdot \left( {\frac{{B - R}}{C} + 2} \right)}&{if{\rm{ }}M = G}\\

{60 \cdot \left( {\frac{{R - G}}{C} + 4} \right)}&{if{\rm{ }}M = B}

\end{array}} \right.

\end{eqnarray*}

\begin{eqnarray*}

S = \left\{ {\begin{array}{*{20}{l}}

0&{if{\rm{ }}V = 0}\\

{\frac{C}{V}}&{if{\rm{ }}V \ne 0}

\end{array}} \right.

\end{eqnarray*}

\(V=M\)

Fast branchless RGB to HSV conversion in GLSL as follow^{[10]}:

vec3 rgb2hsv(vec3 c){ vec4 K = vec4(0.0, -1.0 / 3.0, 2.0 / 3.0, -1.0); vec4 p = mix(vec4(c.bg, K.wz), vec4(c.gb, K.xy), step(c.b, c.g)); vec4 q = mix(vec4(p.xyw, c.r), vec4(c.r, p.yzx), step(p.x, c.r)); float d = q.x - min(q.w, q.y); return vec3(abs(q.z + (q.w - q.y) / (6.0 * d + EPS)), d / (q.x + EPS), q.x); }

**Reference**

[1] Wikipedia. “Grassmann's law (optics).” https://en.wikipedia.org/wiki/Grassmann%27s_law _(optics) .

[2] Siddhartha Chaudhuri. “Light and color.” http://graphics.stanford.edu/courses/cs148-10-summer/docs/ 02_light_color.pdf.

[3] 光怪陆离. “色彩空间基础.” https://zhuanlan.zhihu.com/p/24214731.

[4] Adobe. “The CIE Color Models.” http://dba.med.sc.edu/price/irf/Adobe_tg/models/ cie.html.

[5] Wikipedea. “CIE 1931 color space.” https://en.wikipedia.org/wiki/CIE_1931_color_space.

[6] Adobe. “CIEXYZ.” http://dba.med.sc.edu/price/irf/Adobe_tg/models/ciexyz.html.

[7] Tomas Akenine-Möller, Eric Haines, and Naty Hoffman. *Real-time rendering*. CRC Press, 2008.

[8] Wikipedia. “HSL and HSV.” http://www.lps.usp.br/hae/apostila/basico/HSI-wikipedia.pdf.

[9] Wikipedia. “HSL and HSV” https://en.wikipedia.org/wiki/HSL_and_HSV.

[10] lolengine. "Fast branchless RGB to HSV conversion in GLSL." http://lolengine.net/blog/2013/07/27/rgb-to-hsv-in-glsl.