C o l o r d e s i g n t u t o r i a l
Ever wondered how to find contrasting colors? A palette of matching pastel colors? Shadow and highlight color variants for one and the same object?
All this type of questions can be answered if you switch your color thinking to HSL - hue, saturation and lightness. It's not difficult and it's far more productive than thinking RGB - red, green and blue.
This article explains how colors work, what a color space is, what the HSL color space is and how to work within this space. The relative nonsense of web safe colors will be explained. There are three pages with 7300 color patches each for you to download. Programmers will find algorithms for converting between RGB, HSL, CIE-XYZ and CIE-L*h*s*.
| 61-153-115 |
For each and every application a different color space has been defined. There is a RGB color space like the one mentioned above, which is very useful for specifying colors for television and computer screens.
If you want to print something onto a medium like paper, it is better to use a CMYK color space, consisting of the colors cyan, magenta, yellow and black. It turns out that if one prints with CMYK colors, many more colors can be simulated than with any other combination of colors.
If you want to transport a color definition from one apparatus to another, for instance from computer screen to a printing press, then it can be useful to convert the colors first to a device independent color space like CIE-XYZ.
If you want to design with colors, the best you can do is to think HSL, which stands for hue, saturation, lightness.
| Go to the index at the top |
| red | |
| red + green = yellow | |
| green | |
| green + blue = cyan | |
| blue | |
| blue + red = magenta | |
| nothing = black | |
| red + green + blue = white |
| 2 parts red + 1 part green light = orange | |
| half red + half green + half blue = grey |
Thinking in terms of additive and subtractive colors seems a bit confusing if you are in the process of finding colors for designs.
It turns out that when we change our color space from red-green-blue to hue-saturation-lightness, colors are much more comprehensible. For humans that is. Computers still need RGB numbers in a special form.
| Go to the index at the top |
| red | primary |
| orange | tertiary |
| yellow | secondary |
| yellow-green | tertiary |
| green | primary |
| blueish green | tertiary |
| cyan | secondary |
| greenish blue | tertiary |
| blue | primary |
| purplish blue | tertiary |
| magenta | secondary |
| purplish red | tertiary |
How do these primary, secondary and tertiary colors influence your design?
Not a bit! For instance, if you are designing sports wear for kids, you should start with the colors vivid red, hard blue and pure white. If you are painting a landscape, you use the colors you'll find in the landscape. The only thing you could do is putting a color cast over the scene, like orange in the case of a near sun set or dark blue for a moonlit landscape. If you are designing products for 50+ aged people in China, you wouldn't use yellow, because the feeling is that yellow is reserved for the emperor. In all these cases: there are many other factors more important than just primary or secondary colors.
| Go to the index at the top |
| Go to the index at the top |
Let's make ourselves acquainted with the HSL space. What is HSL anyhow?
HSL stands for hue, saturation and lightness.
Hue is the color description, expressed as an angle in a sort of color wheel. Zero degrees is red, 120 degrees is green, 240 degrees is blue and with 360 degrees the circle is round again with red. Intermediate angles give intermediate colors. In this strip the hue runs from 0° to 330° in steps of 30°. Saturation (1.0) and lightness (1.0) are kept constant.
| H = 0 | H = 30 | H = 60 | H = 90 | H = 120 | H = 150 | H = 180 | H = 210 | H = 240 | H = 270 | H = 300 | H = 330 |
| S = 1.0 | S = 0.9 | S = 0.8 | S = 0.7 | S = 0.6 | S = 0.5 | S = 0.4 | S = 0.3 | S = 0.2 | S = 0.1 |
| L = 1.0 | L = 0.9 | L = 0.8 | L = 0.7 | L = 0.6 | L = 0.5 | L = 0.4 | L = 0.3 | L = 0.2 | L = 0.1 |
| Go to the index at the top |
| Color | R-G-B | H-S-L | CIE-Lhs | Sample |
|---|---|---|---|---|
| Red | 1-0-0 | 0-1-1 | 54.2-12.2-3.4 | |
| Yellow | 1-1-0 | 60-1-1 | 97.2-85.9-1.1 | |
| Green | 0-1-0 | 120-1-1 | 87.3-129.7-1.6 | |
| Cyan | 0-1-1 | 180-1-1 | 90.7-192.2-0.8 | |
| Blue | 0-0-1 | 240-1-1 | 32.1-265.9-4.1 | |
| Magenta | 1-0-1 | 300-1-1 | 61.1-309.7-2.3 | |
| White | 1-1-1 | 0-0-1 | 100-88.5-0 | |
| Black | 0-0-0 | 0-0-0 | 0-0-0 |
Immediately you can see that the CIE-Lhs color space doesn't give nice and comprehensible numbers. The HSL numbers are more comprehensible for humans and the colors look right too.
By the way, since any CIE color space is device independent, we had to choose a device and an illumination in order to convert the abstract RGB colors to CIE-Lhs. We chose the ITU/EBU 3213 description for PAL television colors and the D65 whitepoint. In a later chapter we give the maths, right now we focus on designing.
What about smooth gradients over a color range? What about complementary colors? Since CIE-Lhs should give better color differences, probably gradients and complementaries are better too. Let's compare RGB-HSL and CIE-Lhs side by side.
The left color strip below follows the RGB-HSL scheme with every 10 degrees of H-value another color and with saturation and lightness the maximum value. The right color strip shows CIE-Lhs colors in steps of 10 degrees of H-value. Since the colors had to be represented in HTML, they had to be converted to RGB.
If CIE-Lhs saturation and lightness are at their maximum values, the RGB values would get out of gamut. Therefore the s-value was optimized in such a way that the lowest of the converted R,G,B values was 0. The L-value was optimized to obtain 1 for the highest of the converted R,G,B values. For the RGB conversion the D65 whitepoint was used and the values of the EuroYu'v' (ITU/EBU PAL TV) RGB-primaries.
The CIE-Lhs strip shows somewhat smoother color transitions, but for non-critical color design work, it probably doesn't worth the trouble to work in the CIE-Lhs color space. With CIE-Lhs colors one can also get more accurate complementary colors, but again, it's hardly worth the effort.
| RGB-HSL | CIE-Lhs | ||
|---|---|---|---|
| 0, 1, 1 | 55.4615, 0, 2.7524 | ||
| 10, 1, 1 | 54.4696, 10, 3.2235 | ||
| 20, 1, 1 | 61.2875, 20, 2.4190 | ||
| 30, 1, 1 | 68.0497, 30, 1.8175 | ||
| 40, 1, 1 | 73.5501, 40, 1.4918 | ||
| 50, 1, 1 | 78.4544, 50, 1.2986 | ||
| 60, 1, 1 | 83.1761, 60, 1.1815 | ||
| 70, 1, 1 | 88.0600, 70, 1.1148 | ||
| 80, 1, 1 | 93.4981, 80, 1.0865 | ||
| 90, 1, 1 | 96.3174, 90, 1.0920 | ||
| 100, 1, 1 | 94.2807, 100, 1.1321 | ||
| 110, 1, 1 | 92.1947, 110, 1.2135 | ||
| 120, 1, 1 | 89.9148, 120, 1.3518 | ||
| 130, 1, 1 | 87.3495, 130, 1.5592 | ||
| 140, 1, 1 | 88.1453, 140, 1.2375 | ||
| 150, 1, 1 | 88.7524, 150, 1.0524 | ||
| 160, 1, 1 | 89.2587, 160, 0.940305 | ||
| 170, 1, 1 | 89.7126, 170, 0.87377 | ||
| 180, 1, 1 | 90.1466, 180, 0.83986 | ||
| 190, 1, 1 | 90.5881, 190, 0.83285 | ||
| 200, 1, 1 | 87.2037, 200, 0.85162 | ||
| 210, 1, 1 | 82.8922, 210, 0.899206 | ||
| 220, 1, 1 | 78.4581, 220, 0.984091 | ||
| 230, 1, 1 | 73.5559, 230, 1.1243 | ||
| 240, 1, 1 | 67.6553, 240, 1.3595 | ||
| 250, 1, 1 | 59.7183, 250, 1.7877 | ||
| 260, 1, 1 | 46.8322, 260, 2.7307 | ||
| 270, 1, 1 | 36.4142, 270, 3.6496 | ||
| 280, 1, 1 | 44.3399, 280, 3.0036 | ||
| 290, 1, 1 | 50.5218, 290, 2.6196 | ||
| 300, 1, 1 | 55.9691, 300, 2.3869 | ||
| 310, 1, 1 | 61.0278, 310, 2.2551 | ||
| 320, 1, 1 | 59.5560, 320, 2.2005 | ||
| 330, 1, 1 | 58.3771, 330, 2.2141 | ||
| 340, 1, 1 | 57.3535, 340, 2.2982 | ||
| 350, 1, 1 | 56.4029, 350, 2.4668 | ||
| 360, 1, 1 | 55.4615, 360, 2.7524 | ||
Arithmetical complementary colors next to each other.
Are the CIE-LHs colors better complementary? Hard to tell.
| RGB-HSL | CIE-Lhs | |||
|---|---|---|---|---|
| Go to the index at the top |
| hsl 30-1-1 rgb 255-128-0 html #FF8000 |
| hsl 30-1-0.3 rgb 76-38-0 html #4C2600 |
Let's try another example.
Violet is a color with a reddish blue hue, a medium saturation and a low lightness, says the dictionary. Reddish blue..., hm, that's in the neighborhood of 275° in hue, let's try 0.8 for saturation and 0.5 for lightness.
| hsl 275-0.8-0.5 rgb 85-25-128 html #551980 |
| hsl 350-0.247-1.0 rgb 255-192-203 html #FFC0CB |
| hsl 252-1-0.51 rgb 27-0-130 html #1B0082 |
| hsl 240-0.7-0.4 rgb 31-31-102 html #1f1f66 |
| olive drab rgb 128-128-0 / 808000 hsl 60-1.0-0.5 | army green rgb 102-153-102 / 669966 hsl 120-0.333-0.6 | FS 34090 rgb 35-130-89 / 238259 hsl 154-0.73-0.51 |
| FS 34095 rgb 89-95-67 / 595F43 hsl 73-0.30-0.37 | FS 34108 rgb 71-110-86 / 476E56 hsl 143-0.36-0.43 | FS 34138 rgb 94-132-80 / 5E8450 hsl 104-0.39-0.52 |
| FS 34151 rgb 113-112-72 / 717048 hsl 59-0.36-0.44 | FS 34230 rgb 89-157-90 / 599D5A hsl 121-0.43-0.62 | FS 34259 rgb 142-131-66 / 8E8342 hsl 51-0.54-0.56 |
| Go to the index at the top |
| 0 0.4 1 FF9999 | 30 0.4 1 FFCC99 | 60 0.4 1 FFFF99 | 90 0.4 1 CCFF99 |
| 120 0.4 1 99FF99 | 150 0.4 1 99FFCC | 180 0.4 1 99FFFF | 210 0.4 1 99CCFF |
| 240 0.4 1 9999FF | 270 0.4 1 CC99FF | 300 0.4 1 FF99FF | 330 0.4 1 FF99CC |
| 0 0.1 1 FFE6E6 | 30 0.1 1 FFF2E6 | 60 0.1 1 FFFFE6 | 90 0.1 1 F2FFE6 |
| 120 0.1 1 E6FFE6 | 150 0.1 1 E6FFF2 | 180 0.1 1 E6FFFF | 210 0.1 1 E6F2FF |
| 240 0.1 1 E6E6FF | 270 0.1 1 F2E6FF | 300 0.1 1 FFE6FF | 330 0.1 1 FFE6F2 |
| 0 0.2 0.3 4C3D3D | 30 0.2 0.3 4C453D | 60 0.2 0.3 4C4C3D | 90 0.2 0.3 454C3D |
| 120 0.2 0.3 3D4C3D | 150 0.2 0.3 3D4C45 | 180 0.2 0.3 3D4C4C | 210 0.2 0.3 3D454C |
| 240 0.2 0.3 3D3D4C | 270 0.2 0.3 453D4C | 300 0.2 0.3 4C3D4C | 330 0.2 0.3 4C3D45 |
| 185 1 1 00EAFF | 185 1 0.8 00BBCC | 185 1 0.6 008C99 | 185 1 0.4 005E66 | 185 1 0.2 002F33 |
| 185 1 1 00EAFF | 185 0.8 1 33EEFF | 185 0.6 1 66F2FF | 185 0.4 1 99F6FF | 185 0.2 1 CCFBFF |
| Highlight versions | ||||||
|---|---|---|---|---|---|---|
| 0 0.1 1 FFE6E6 | 30 0.1 1 FFF2E6 | 60 0.1 1 FFFFE6 | 120 0.1 1 E6FFE6 | 180 0.1 1 E6FFFF | 240 0.1 1 E6E6FF | 300 0.1 1 FFE6FF |
| Light versions | ||||||
| 0 0.4 1 FF9999 | 30 0.4 1 FFCC99 | 60 0.4 1 FFFF99 | 120 0.4 1 99FF99 | 180 0.4 1 99FFFF | 240 0.4 1 9999FF | 300 0.4 1 FF99FF |
| 80% Saturated originals | ||||||
| 0 0.8 1 FF3333 | 30 0.8 1 FF9933 | 60 0.8 1 FFFF33 | 120 0.8 1 33FF33 | 180 0.8 1 33FFFF | 240 0.8 1 3333FF | 300 0.8 1 FF33FF |
| Darker versions | ||||||
| 0 0.8 0.6 991F1F | 30 0.8 0.6 995C1F | 60 0.8 0.6 99991F | 120 0.8 0.6 1F991F | 180 0.8 0.6 1F9999 | 240 0.8 0.6 1F1F99 | 300 0.8 0.6 991F99 |
| Deep shadow versions | ||||||
| 0 0.8 0.2 330A0A | 30 0.8 0.2 331F0A | 60 0.8 0.2 33330A | 120 0.8 0.2 0A330A | 180 0.8 0.2 0A3333 | 240 0.8 0.2 0A0A33 | 300 0.8 0.2 330A33 |
| Go to the index at the top |
We start with a nice orange color with a hue of 40°. The complementary color has a hue of 40° + 180° = 220°. This is a blue color. We show the contrasts with two different values of the lightness.
Another example is a purplish red with a hue of 340°. The complementary color is 340° + 180° = 520° --> 160°, a nice green color.
| color | |||
|---|---|---|---|
| 40 1 1 FFAA00 | 40 1 0.4 664400 | 340 0.8 1 FF3377 | 340 0.8 0.4 661430 |
| complementary color | |||
| 220 1 1 0055FF | 220 1 0.4 002266 | 160 0.8 1 33FFBB | 160 0.8 0.4 14664B |
| color trio | ||
|---|---|---|
| 190 1 1 00D4FF | 310 1 1 FF00D4 | 70 1 1 D4FF00 |
| complementary trio | ||
| 10 1 1 FF2B00 | 130 1 1 00FF2B | 250 1 1 2B00FF |
| two colors | |
|---|---|
| 35 0.8 0.3 4C330F | 75 0.6 0.4 576629 |
| contrasting color | |
| 235 0.7 0.7 3640B2 | |
| Go to the index at the top |
The zip-archive will expand to a folder (directory) with 3 files, each about 640 KB big. Some browsers and some systems, especially with not too many Megabytes in RAM, will have problems displaying such large pages with many table cells. No problem however on a modern computer.
| Go to the index at the top |
Panel with 216 web safe colors
Unfortunately this panel shows the colors in the usual useless manner. Virtually every page of web safe colors has the colors sorted in a mathematically interesting way, which is visually useless. Much more useful to the designer would be a list with colors, sorted by hue. Where can I find such a list? Read on!
An i-mode mobile telephone is a 'colorly deprived' system. This type of telephone is able to display web pages, programmed in cHTML. Colors can be used, but must be chosen from a palette of 256 specific colors. The mathematical construction of these colors is a bit similar to the web safe colors.
On a separate page all web safe colors and all i-mode colors are shown, sorted by hue and including short notes about the construction of the color codes.
|
Go to the index at the top RGB to HSL conversion HSL to RGB RGB to CIE-XYZ and L*h*s* CIE-Lhs to RGB CIE-XYZ and CIE-Lab Equivalent grey Conversion coefficients |
RGB to HSL
When converting from RGB (red green blue) to HSL (hue saturation lightness) one inelegancy arises: the hues have to be divided into sections of 60 degrees. There are some conversion schemes which look more elegant mathematically, but the best linear transform from RGB to HSL divides the hue range into 6 parts.
First you have to make sure that the RGB values are normalized to values between 0 and 1.
The first conversion step is to find the lightness value. It sounds odd, but the best way of doing this is to convert to CMYK (cyan magenta yellow black). After having found the lightness, we set the lightness artificially to 1 so we can find the saturation. The hue can be found by setting both lightness and saturation to 1.
Input: values between 0-1 for red (R), green (G) and blue (B).
Output: values for hue (H, 0-360°), saturation (S, 0-1), lightness (L, 0-1).
C = 1-R; M = 1-G; Y = 1-B; K = min(C,M,Y)
--Normalization
C = min(1,max(0,C-K)); M = min(1,max(0,M-K)); Y = min(1,max(0,Y-K)); K = min(1,max(0,K))
L = 1-K --lightness
if L=0 then return "0,0,0" --pure black
--Find CMY/RGB at K=0/L=1 in order to get S
C = min(1,C/(1-K)); M = min(1,M/(1-K)); Y = min(1,Y/(1-K))
R = 1-C; G = 1-M; B = 1-Y
lowest = min(R,G,B)
highest = max(R,G,B)
S = 1-lowest --saturation
if S=0 then
H=0 --C,M,Y were 0, but K > 0, so a grey; let's set H=0
else
--Set L=1, S=1 in order to find the hue
--We do this by putting 1 into the lowest value, 0 into the highest value
--and an S-corrected value into the middle value.
if R = lowest then
RR = 0
if G = highest then GG = 1; BB = B/S+1-1/S else BB = 1; GG = G/S+1-1/S
else
if G = lowest then
GG = 0
if R = highest then RR = 1; BB = B/S+1-1/S else BB = 1; RR = R/S+1-1/S
else
BB = 0
if R = highest then RR = 1; GG = G/S+1-1/S else GG = 1; RR = R/S+1-1/S
end if
end if
--Now we're ready for the hue
--Hue will be a fraction [0-1]
if RR=1 then
if BB=0 then --H: 0-60°
H = GG/6
else --H: 300-360°
H = 1-BB/6
end if
else
if RR=0 then
if GG=1 then --H: 120-180°
H = 1/3+BB/6
else --H: 180-240°
H = 2/3-GG/6
end if
else
if BB=0 then --H: 60-120°
H = 1/3-RR/6
else --H: 240-300°
H = 2/3+RR/6
end if
end if
end if
end if
return H,S,L
|
Go to the index at the top RGB to HSL conversion HSL to RGB RGB to CIE-XYZ and L*h*s* CIE-Lhs to RGB CIE-XYZ and CIE-Lab Equivalent grey Conversion coefficients |
Input: values between 0-1 for hue (H), saturation (S) and lightness (L).
Output: values between 0-1 for red (R), green (G) and blue (B).
--H [0-1] is divided into 6 equal sectors.
--From within each sector the proper conversion function is called.
if H < 1/6 then
return H1(H,S,L)
else
if H < 1/3 then
return H2(H,S,L)
else
if H < 1/2 then
return H3(H,S,L)
else
if H < 2/3 then
return H4(H,S,L)
else
if H < 5/6 then
return H5(H,S,L)
else
return H6(H,S,L)
end if
end if
end if
end if
end if
--Here are the 6 conversion functions.
--First H,1,1 is converted to R,G,B.
--Then a correction for the actual S.
--At last a correction for the actual L.
function H1 H,S,L
R = 1; G = 6*H; B = 0
G = G*S + 1 - S; B = B*S + 1 - S
R = R*L; G = G*L; B = B*L
return R,G,B
end H1
function H2 H,S,L
R = 1-6*(H - 1/6); G = 1; B = 0
R = R*S + 1 - S; B = B*S + 1 - S
R = R*L; G = G*L; B = B*L
return R,G,B
end H2
function H3 H,S,L
R = 0; G = 1; B = 6*(H - 1/3)
R = R*S + 1 - S; B = B*S + 1 - S
R = R*L; G = G*L; B = B*L
return R,G,B
end H3
function H4 H,S,L
R = 0; G = 1-6*(H - 1/2); B = 1
R = R*S + 1 - S; G = G*S + 1 - S
R = R*L; G = G*L; B = B*L
return R,G,B
end H4
function H5 H,S,L
R = 6*(H - 2/3); G = 0; B = 1
R = R*S + 1 - S; G = G*S + 1 - S
R = R*L; G = G*L; B = B*L
return R,G,B
end H5
function H6 H,S,L
R = 1; G = 0; B = 1-6*(H - 5/6)
G = G*S + 1 - S; B = B*S + 1 - S
R = R*L; G = G*L; B = B*L
return R,G,B
end H6
|
Go to the index at the top RGB to HSL conversion HSL to RGB RGB to CIE-XYZ and L*h*s* CIE-Lhs to RGB CIE-XYZ and CIE-Lab Equivalent grey Conversion coefficients |
Input: values between 0-1 for red (R), green (G) and blue (B).
Output: values for CIE-XYZ coordinates >= 0.
X = 0.430574*R + 0.341550*G + 0.178325*B Y = 0.222015*R + 0.706655*G + 0.071330*B Z = 0.020183*R + 0.129553*G + 0.939180*BThe other way around, if one has XYZ and wants to compute the ITU/EBU 3213 - D65 RGBs:
Input: values for CIE-XYZ coordinates.
Output: values for red (R), green (G) and blue (B), scaled to the range 0-1, but might go past these limits for some XYZ values.
R = 3.063219*X -1.393326*Y -0.475801*Z G = -0.969245*X +1.875968*Y +0.041555*Z B = 0.067872*X -0.228833*Y +1.069251*ZLater we will explain how the coefficients are calculated.
Please don't make the mistake to drop decimals in the conversion process. The coefficients in above conversion matrices vary wildly (between 0.020183 and 0.939180 for the first matrix) which means that you quickly loose accuracy in the back conversion.
After converting RGB to CIE-XYZ one has to convert to CIE-Lhs. This can be done via CIE-Lab or via CIE-Luv, which is followed here.
First we convert the XYZ to Luv values. The CIE-L*u*v* color space has a more even distribution of color differences. We drop the * because this interferes with the multiplication sign.
Input: values for CIE-XYZ coordinates >= 0.
Output: values between 0-100 for CIE lightness (L), and CIE coordinates u, v >= 0.
u' = 4X/(X+15Y+3Z) v' = 9Y/(X+15Y+3Z) if Y > 216/24389 then L = 116*(Y^(1/3)) - 16 else L = Y*24389/27 end if --Now we need the values un, vn of the chosen whitepoint u = 13L(u'-un) v = 13L(v'-vn)At this moment the XYZ values are converted to Luv values.
un = 0.197833 vn = 0.468331Converting from Luv to Lhs is a matter of transforming from cartesian to polar coordinates.
Input: CIE coordinates u, v.
Output: values for CIE lightness (L) 0-100, CIE hue (0-360°) and CIE saturation (>= 0).
h = atan2(v,u) modulo 360° --hue c = sqrt(u*u + v*v) --chroma (colorfulness) s = c/L --saturation; if L=0, take s=0Please don't use the normal arctangent function. With the atan2 function the sign (+/-) is correct. The atan2 function is defined as follows, this in case your math tool has no atan2 function.
Input: scalars v, u (real).
Output: arctangent2 (angle in radians).
function atan2 v,u
if u=0 and v=0 then: not defined, but you might use 0 as answer
if u=0 then
if v > 0 then pi/2 else -pi/2
if u > 0 then atan(v/u) --the normal atan function
if u < 0 then
if v >= 0 then atan(v/u) + pi else atan(v/u) - pi
The production of atan2 is an angle in radians. Probably you want to convert this to an angle in degrees. Do this by multiplying with 180/pi. If the answer is less than 0°, add 360°.
|
Go to the index at the top RGB to HSL conversion HSL to RGB RGB to CIE-XYZ and L*h*s* CIE-Lhs to RGB CIE-XYZ and CIE-Lab Equivalent grey Conversion coefficients |
Input: values for CIE lightness (L, 0-100), CIE hue (H, radians 0-2*pi), and CIE saturation (S, >= 0).
Output: values between 0-1 for red (R), green (G) and blue (B).
c = s*L u = c*cos(h) v = c*sin(h) u' = un + u/(13*L) v' = vn + v/(13*L) --See above for the values of un, vn (whitepoint) if L > 8 then Y = ((L+16)/116)^3 else Y = L*27/24389 end if X = 9*Y*u'/(4*v') Z = Y*(12-3*u'-20*v')/(4*v')Right now we have the XYZ values. Earlier we saw how to convert to RGB:
R = 3.063219*X -1.393326*Y -0.475801*Z G = -0.969245*X +1.875968*Y +0.041555*Z B = 0.067872*X -0.228833*Y +1.069251*ZTake note that this is only valid for the chosen RGB primary colors (ITU/EBU 3213 PAL TV) and the chosen whitepoint (D65).
|
Go to the index at the top RGB to HSL conversion HSL to RGB RGB to CIE-XYZ and L*h*s* CIE-Lhs to RGB CIE-XYZ and CIE-Lab Equivalent grey Conversion coefficients |
From XYZ to Lab
Input: CIE-XYZ values.
Output: CIE-Lab values. L stands for the psychometric lightness and is usually a value between 0 and 100; a and b are reals that can be negative.
The coordinates of the chosen whitepoint are Xw, Yw, Zw.
if Y/Yw >= 216/24389 then L = 116(Y/Yw)^(1/3) - 16 else L = (Y/Yw)*24389/27 end if LF = (L+16)/116 if X/Xw >= 216/24389 then a = 500((X/Xw)^(1/3) - LF) else a = 500((841/108)(X/Xw) - LF + 4/29) end if if Z/Zw >= 216/24389 then b = 200(LF - (Z/Zw)^(1/3)) else b = 200(LF - 4/29 - (841/108)(Z/Zw)) end ifIf needed, it is possible to convert the CIE-Lab coordinates to polar coordinates, expressing hue and chroma.
hab = atan2(b, a) -- hue angle cab = sqrt(a*a + b*b) -- chromaThe atan2 function is defined above. Note that the CIE-Lhc values obtained here, are not the same as the CIE-Lhs values obtained earlier, through the conversion via CIE-Luv.
From Lab to XYZ
Input: CIE-Lab values. L stands for the psychometric lightness and is usually a value between 0 and 100.
Output: CIE-XYZ values.
The coordinates of the chosen whitepoint are Xw, Yw, Zw.
LF = (L+16)/116 if L >= 29b/50 + 8 then Z/Zw = (LF - b/200)^3 else Z/Zw = (108/841)(LF - 4/29 - b/200) end if if L >= 8 - 29a/125 then X/Xw = (a/500 + LF)^3 else X/Xw = (108/841)(a/500 + LF - 4/29) end if if L >= 8 then Y/Yw = LF^3 else Y/Yw = 27L/24389 --yes, 27*L end if
Y = 1; X = x*Y/y; Z = (1-x-y)*Y/y
From Lab to Luv
First, convert Lab to XYZ as shown above.
Then convert XYZ to xy:
x = X/(X+Y+Z); y = Y/(X+Y+Z)Then convert xy to uv:
factor = -2x + 12y + 3 u = 4x/factor v = 6y/factorWhat about the L? The L in Lab is not the same as the L in Luv.
if L >= 8 then Lluv = (Llab + 16)*Yw^(1/3) - 16 else Lluv = Llab*Yw end ifYw is the Y-coordinate of the whitepoint. This is usually taken as 1, so in the end in most cases Lluv = Llab anyhow.
From Luv to Lab
First, convert from uv to xy:
factor = u - 4v + 2 x = 6u/(4*factor) y = v/factorThen convert xy to XYZ. Usually the Y has to be taken arbitrarily as 1 because CIE-xy gives no lightness information, but here we do have information about the lightness, so we can compute Y.
if L >= 8 then Y = ((Lluv + 16)/116)^3 else Y = Lluv*27/24389 end ifNow we have the Y; the X and Y are obtained as follows:
X = Y*x/y; Z = Y*(1-x-y)/yFrom XYZ we can convert to Lab as shown above.
if L >= 8 then Llab = (Lluv + 16)*Yw^(-1/3) - 16 else Llab = Lluv/Yw end if
|
Go to the index at the top RGB to HSL conversion HSL to RGB RGB to CIE-XYZ and L*h*s* CIE-Lhs to RGB CIE-XYZ and CIE-Lab Equivalent grey Conversion coefficients |
grey = (R + G + B)/3An even simpler one is:
grey = the value of GThe most used definition is the ITU-601-1 definition:
grey = 0.299*R + 0.587*G + 0.114*BFor instance Kodak Photo CD and PostScript/PDF use this definition.
grey = 0.298954*R + 0.586434*G + 0.114612*BThis is the equivalent grey definition used in the downloadable color patches.
grey = 0.213*R + 0.715*G + 0.072*BThe definition used for European PAL television systems is an ITU/EBU 3213 standard:
grey = 0.222*R + 0.707*G + 0.071*BInput for al grey functions: values between 0-1 for red (R), green (G) and blue (B).
|
Go to the index at the top RGB to HSL conversion HSL to RGB RGB to CIE-XYZ and L*h*s* CIE-Lhs to RGB CIE-XYZ and CIE-Lab Equivalent grey Conversion coefficients |
X = 0.430574*R + 0.341550*G + 0.178325*B Y = 0.222015*R + 0.706655*G + 0.071330*B Z = 0.020183*R + 0.129553*G + 0.939180*BThe 'certain circumstances' are determined by the color coordinates of the whitepoint of the illuminant and the color coordinates of the red, green and blue producing substances, the primaries. That's where those numbers come from. But how are they computed?
Let's use matrix algebra. The equation set can be rewritten as a matrix multiplication.
|X| = |0.430574 0.341550 0.178325| |R| |Y| = |0.222015 0.706655 0.071330| x |G| |Z| = |0.020183 0.129553 0.939180| |B|By the way, the brown equations are formed with a <pre> instruction, so your browser has to use a monospace font in order to display the matrices readable, i.e. with aligning vertical lines.
Now we are going to derive this coefficients matrix.
First we start with what we know or should know, the color coordinates of the whitepoint and the primaries. Let's say that the xy-coordinates of the RGB-primaries and the whitepoint are:
xr=0.64; yr=0.33 xg=0.29; yg=0.60 xb=0.15; yb=0.06 xw=0.312713; yw=0.329016The xy-coordinates have to be converted to XYZ coordinates. Since the xy-coordinates contain no explicit luminance information, the Y-coordinates of the whitepoint and the primaries are usually set to 1. The XYZ-coordinates can be computed as follows.
Y = 1; X = x*Y/y; Z = (1-x-y)*Y/yLet's name the RGB coefficients matrix
RGB, constructed as:
|Xr Xg Xb|
RGB = |Yr Yg Yb|
|Zr Zg Zb|
Now we have to invert this matrix. Usually this is done with the aid of a programming environment including a library of matrix calculations. If you would like to write your own routine, a 3x3 matrix can be inverted in the following manner.
|a b c|
M = |d e f|
|g h i|
det(M) = a(ei-hf) - b(di-gf) + c(dh-ge) --determinant
if det(M) is not 0 then the inverted matrix exists
-1 1 | (ei-hf) -(bi-hc) (bf-ec)|
M = ------ |-(di-gf) (ai-gc) -(af-dc)|
det(M) | (dh-ge) -(ah-gb) (ae-db)|
Right now we should have obtained RGB-1, the inverse of the RGB coefficients matrix.
|Xw|
W = |Yw|
|Zw|
and then we matrix-multiply the whitepoint matrix by the inverse of the RGB coefficients matrix:
A = RGB-1 x WMatrix A is a matrix with 3 rows and 1 column, representing the achromatic correction. In order to obtain the conversion matrix, we have to scalar-multiply the RGB-matrix with the transpose of the correction matrix:
RGBtoXYZ = RGB * ATThe transpose of the matrix A is a 1-row matrix:
AT = |Ar Ag Ab|To be more clearly: if we scalar-multiply this with matrix RGB, we get:
|Xr*Ar Xg*Ag Xb*Ab|
RGBtoXYZ = |Yr*Ar Yg*Ag Yb*Ab|
|Zr*Ar Zg*Ag Zb*Ab|
So the conversion from RGB to XYZ is in matrix terms:
|X| |R| |Y| = RGBtoXYZ x |G| |Z| |B|The inverse of the matrix RGBtoXYZ is the coefficients matrix, needed to convert from XYZ to RGB.
Let's give a numerical example, so you can check your programming.
xr=0.64; yr=0.33
xg=0.29; yg=0.60
xb=0.15; yb=0.06
xw=0.312713; yw=0.329016
|1.93939 0.48333 2.50000|
RGB = |1.00000 1.00000 1.00000|
|0.09091 0.18333 13.16667|
-1 | 0.68008 -0.30934 -0.10563|
RGB = |-0.68492 1.32566 0.02937|
| 0.00484 -0.01632 0.07627|
|0.95045|
W = |1.00000|
|1.08892|
AT = |0.22201 0.70666 0.07133|
|0.43057 0.34155 0.17833|
RGBtoXYZ = |0.22201 0.70666 0.07133|
|0.02018 0.12955 0.93918|
-1 | 3.06322 -1.39333 -0.47580|
XYZtoRGB = RGBtoXYZ = |-0.96924 1.87597 0.04156|
| 0.06787 -0.22883 1.06925|
We have seen the coefficients matrices RGBtoXYZ and XYZtoRGB before, see the algorithms for converting from RGB to CIE-XYZ.The definition used for European PAL television systems is an ITU/EBU 3213 standard:
grey = 0.222*R + 0.707*G + 0.071*B
Primaries and whitepoints
A table with the xy-coordinates of the most used primaries and whitepoints.
The gamma-correction is usually defined as 1/0.45 = 2.2222, so use for very critical work this value instead of the 2.2 from the table. Gamma-correction is not dealt with in this tutorial at the moment.
| Primaries | Whitepoint | Gamma | RGB (x,y) coordinates |
|---|---|---|---|
| PAL, SECAM, EBU/ITU | D65 | 2.2 | r: (0.64,0.33) g: (0.29,0.60) b: (0.15,0.06) |
| NTSC (1953) | CIE C | 2.2 | r: (0.67,0.33) g: (0.21,0.71) b: (0.14,0.08) |
| NTSC (modern) | D65 | 2.2 | r: (0.630,0.340) g: (0.310,0.595) b: (0.155,0.070) |
| SMPTE-C, CCIR 601-1 | D65 | 2.2 | r: (0.630,0.340) g: (0.310,0.595) b: (0.155,0.070) |
| Apple RGB, Trinitron | D65 | 1.8 | r: (0.625,0.34) g: (0.28,0.595) b: (0.155,0.07) |
| sRGB, HDTV, CCIR 709 | D65 | 2.2 | r: (0.64,0.33) g: (0.30,0.60) b: (0.15,0.06) |
| CIE RGB | CIE E | 2.2 | r: (0.735,0.265) g: (0.274,0.717) b: (0.167, 0.009) |
| Adobe RGB (1998) | D65 | 2.2 | r: (0.64,0.33) g: (0.21,0.71) b: (0.15,0.06) |
The CIE whitepoints are defined for some standard illuminants.
The D-series are supposed to represent black body radiators with a temperature of 100 times the given number, in Kelvin.
| Whitepoint | xy-coordinates |
|---|---|
| CIE A (tungsten lamp) | (0.4476,0.4074) |
| CIE B (direct sunlight) | (0.3484,0.3516) |
| CIE C (average daylight with sun) | (0.310063,0.316158) |
| CIE E (standard reference) | (1/3,1/3) |
| D50 | (0.3457,0.3585) |
| D55 (photography, cloudy daylight) | (0.3324,0.3474) |
| D65 (standard daylight) | (0.312713,0.329016) |
| D75 | (0.299,0.3149) |
| D93 (old CRT monitors) | (0.2848,0.2932) |
Well now, this concludes the maths section of this tutorial. Remain a couple of questions one could ask.
| Go to the index at the top |
Why did you write color instead of colour?
Many more people looking for pages on the internet know the American spelling color better than the British spelling colour. But in the meta-tags of this document also a 'colour' keyword has been incorporated.
With what advanced web development environment has this story been put together?
Sounds silly, but the answer is: a text editor - Macintosh BBEdit. Not even the HTML-tools were used. All HTML-code was written by hand.
That's not too difficult, so it can be done by anyone with a bit of knowledge of programming HTML. One of the major advances is that the code is slim. Even simple HTML-editors tend to produce very bulky code with lots of superfluous spaces, unnecessary end-tags, far too many font-tags, etcetera.
The downloadable pages with color patches were programmed. The code produced by the program was augmented manually with for instance the explaining text.
How was the document title with the color gradient made?
By hand, with font-tags and a color designation in each tag. The colors were found on the page with constant saturations. The grey background is a background color definition in the style attribute of a paragraph tag.
And why didn't you use sophisticated CSS style instructions all over? Well, especially Netscape Navigator hardly supports any CSS, so for this browser we have to use the kiss-principle (keep it simple, silly!).
Hmm, a grey background? Not seen! Then your browser doesn't support style sheets or you have inactivated style sheets. Check the preferences or properties of your browser.
Why do I see here and there strange characters?
Because your browser is too old or not configured too well. It could be that your font is a CJK/Unicode font.
What do you see on the next line?
If it's nothing, then everything is fine. But if you see something, then it is possible that you have a foreign font with a character defined on the location where a non breaking and non visible space should be defined.
And what do you see on the next line?
120°
If you can't make 120 degrees out of this, then your browser is too old or ill configured. Try another display font if you think your browser is OK. This document has a meta-instruction that tells your browser that the page should be displayed as ISO-8859-1, i.e. with 'normal' American/West European characters.
Why don't I see the color examples in print?
Internet Explorer and Netscape Navigator have in their Print dialog (Macintosh) or somewhere else (Extra: Internet options: Advanced) a checkbox for printing backgrounds. Click a check in this checkbox. Most color patches in this document are implemented as background colors in table cells.
If you don't see rectangular color patches on your screen, then it is possible that your browser is not suitable.
On a Macintosh this page can best be printed from Internet Explorer. The Mac browsers have very strangely no means of setting the page margins. A style definition in this page adds a left margin for binding, but only Internet Explorer listens to this instruction. Actually this only works if you check 'Fit to page' in the Print dialog.
What's new?
Sometimes this document is updated. See the modification date at the bottom.
Apart from minor language and spelling corrections, the following items were changed or added.
* April 2001. First edition.
* August 2002: added to the web safe colors chapter a link to a page with HSL sorted web safe colors and i-mode colors.
* October 2002: added to the maths section the conversions between CIE-XYZ and CIE-Lab, and between CIE-Lab and CIE-Luv. Also added a section that derives the RGB-XYZ conversion coefficients matrices. Provided a table with coordinates of RGB primaries and whitepoints.
A new chapter: Primary, secondary and tertiary colors.
* September 2005: examples for violet and indigo2 improved. More elaborate comparison of RGB-HSL and CIE-Lhs.
| Go to the index at the top |
© Oscar van Vlijmen, April 2001
Date of last modification: 2005-09-18
URL: http://ovv.club.tip.nl/ColorDesign.html
and if that doesn't work, try the direct URL:
http://home.tiscali.nl/~t876506/ColorDesign.html