Colour SpacesIn what follows are various notes dealing with colour spaces and conversion between them.
RGB colour spaceLists of RGB values for named colours
Written by Paul Bourke This table is the "standard" set as used by the SGI X windows server. The values are in the range of 0 to 255 inclusive. Contribution by Robert Rapplean, C++ program that creates an image that can be folded together to form the RGB colour cube. A colour space is a means of uniquely specifying a colour. There are a number of colour spaces in common usage depending on the particular industry and/or application involved. For example as humans we normally determine colour by parameters such as brightness, hue, and colourfulness. On computers it is more common to describe colour by three components, normally red, green, and blue. These are related to the excitation of red, green, and blue phosphors on a computer monitor. Another similar system geared more towards the printing industry uses cyan, magenta, and yellow to specify colour, they are related to the reflectance and absorbance of inks on paper. Some other major colour spaces are:
There are generally ways of converting (transforming) between different colour spaces although in most cases the transformation is nonlinear. Some colour spaces for example can represent colours which cannot be represented in others. RGB colour cubeThe colour space for computer based applications is often visualised by a unit cube. Each colour (red, green, blue) is assigned to one of the three orthogonal coordinate axes in 3D space. An example of such a cube is shown below along with some key colours and their coordinates.
The first set below was originally compiled by Steve Hollasch and is organised as follows: the first column is the descriptive name of the colour; the next three columns are the RGB coordinates in the 0 to 255 range as if the components were being stored in one unsigned byte; the last three columns are the RGB colour coordinates in the range of 0 to 1 inclusive. Whites antique_white 250 235 215 0.9804 0.9216 0.8431 azure 240 255 255 0.9412 1.0000 1.0000 bisque 255 228 196 1.0000 0.8941 0.7686 blanched_almond 255 235 205 1.0000 0.9216 0.8039 cornsilk 255 248 220 1.0000 0.9725 0.8627 eggshell 252 230 201 0.9900 0.9000 0.7900 floral_white 255 250 240 1.0000 0.9804 0.9412 gainsboro 220 220 220 0.8627 0.8627 0.8627 ghost_white 248 248 255 0.9725 0.9725 1.0000 honeydew 240 255 240 0.9412 1.0000 0.9412 ivory 255 255 240 1.0000 1.0000 0.9412 lavender 230 230 250 0.9020 0.9020 0.9804 lavender_blush 255 240 245 1.0000 0.9412 0.9608 lemon_chiffon 255 250 205 1.0000 0.9804 0.8039 linen 250 240 230 0.9804 0.9412 0.9020 mint_cream 245 255 250 0.9608 1.0000 0.9804 misty_rose 255 228 225 1.0000 0.8941 0.8824 moccasin 255 228 181 1.0000 0.8941 0.7098 navajo_white 255 222 173 1.0000 0.8706 0.6784 old_lace 253 245 230 0.9922 0.9608 0.9020 papaya_whip 255 239 213 1.0000 0.9373 0.8353 peach_puff 255 218 185 1.0000 0.8549 0.7255 seashell 255 245 238 1.0000 0.9608 0.9333 snow 255 250 250 1.0000 0.9804 0.9804 thistle 216 191 216 0.8471 0.7490 0.8471 titanium_white 252 255 240 0.9900 1.0000 0.9400 wheat 245 222 179 0.9608 0.8706 0.7020 white 255 255 255 1.0000 1.0000 1.0000 white_smoke 245 245 245 0.9608 0.9608 0.9608 zinc_white 253 248 255 0.9900 0.9700 1.0000 Greys cold_grey 128 138 135 0.5000 0.5400 0.5300 dim_grey 105 105 105 0.4118 0.4118 0.4118 grey 192 192 192 0.7529 0.7529 0.7529 light_grey 211 211 211 0.8275 0.8275 0.8275 slate_grey 112 128 144 0.4392 0.5020 0.5647 slate_grey_dark 47 79 79 0.1843 0.3098 0.3098 slate_grey_light 119 136 153 0.4667 0.5333 0.6000 warm_grey 128 128 105 0.5000 0.5000 0.4100 Blacks black 0 0 0 0.0000 0.0000 0.0000 ivory_black 41 36 33 0.1600 0.1400 0.1300 lamp_black 46 71 59 0.1800 0.2800 0.2300 Reds alizarin_crimson 227 38 54 0.8900 0.1500 0.2100 brick 156 102 31 0.6100 0.4000 0.1200 cadmium_red_deep 227 23 13 0.8900 0.0900 0.0500 coral 255 127 80 1.0000 0.4980 0.3137 coral_light 240 128 128 0.9412 0.5020 0.5020 deep_pink 255 20 147 1.0000 0.0784 0.5765 english_red 212 61 26 0.8300 0.2400 0.1000 firebrick 178 34 34 0.6980 0.1333 0.1333 geranium_lake 227 18 48 0.8900 0.0700 0.1900 hot_pink 255 105 180 1.0000 0.4118 0.7059 indian_red 176 23 31 0.6900 0.0900 0.1200 light_salmon 255 160 122 1.0000 0.6275 0.4784 madder_lake_deep 227 46 48 0.8900 0.1800 0.1900 maroon 176 48 96 0.6902 0.1882 0.3765 pink 255 192 203 1.0000 0.7529 0.7961 pink_light 255 182 193 1.0000 0.7137 0.7569 raspberry 135 38 87 0.5300 0.1500 0.3400 red 255 0 0 1.0000 0.0000 0.0000 rose_madder 227 54 56 0.8900 0.2100 0.2200 salmon 250 128 114 0.9804 0.5020 0.4471 tomato 255 99 71 1.0000 0.3882 0.2784 venetian_red 212 26 31 0.8300 0.1000 0.1200 Browns beige 163 148 128 0.6400 0.5800 0.5000 brown 128 42 42 0.5000 0.1647 0.1647 brown_madder 219 41 41 0.8600 0.1600 0.1600 brown_ochre 135 66 31 0.5300 0.2600 0.1200 burlywood 222 184 135 0.8706 0.7216 0.5294 burnt_sienna 138 54 15 0.5400 0.2100 0.0600 burnt_umber 138 51 36 0.5400 0.2000 0.1400 chocolate 210 105 30 0.8235 0.4118 0.1176 deep_ochre 115 61 26 0.4500 0.2400 0.1000 flesh 255 125 64 1.0000 0.4900 0.2500 flesh_ochre 255 87 33 1.0000 0.3400 0.1300 gold_ochre 199 120 38 0.7800 0.4700 0.1500 greenish_umber 255 61 13 1.0000 0.2400 0.0500 khaki 240 230 140 0.9412 0.9020 0.5490 khaki_dark 189 183 107 0.7412 0.7176 0.4196 light_beige 245 245 220 0.9608 0.9608 0.8627 peru 205 133 63 0.8039 0.5216 0.2471 rosy_brown 188 143 143 0.7373 0.5608 0.5608 raw_sienna 199 97 20 0.7800 0.3800 0.0800 raw_umber 115 74 18 0.4500 0.2900 0.0700 sepia 94 38 18 0.3700 0.1500 0.0700 sienna 160 82 45 0.6275 0.3216 0.1765 saddle_brown 139 69 19 0.5451 0.2706 0.0745 sandy_brown 244 164 96 0.9569 0.6431 0.3765 tan 210 180 140 0.8235 0.7059 0.5490 van_dyke_brown 94 38 5 0.3700 0.1500 0.0200 Oranges cadmium_orange 255 97 3 1.0000 0.3800 0.0100 cadmium_red_light 255 3 13 1.0000 0.0100 0.0500 carrot 237 145 33 0.9300 0.5700 0.1300 dark_orange 255 140 0 1.0000 0.5490 0.0000 mars_orange 150 69 20 0.5900 0.2700 0.0800 mars_yellow 227 112 26 0.8900 0.4400 0.1000 orange 255 128 0 1.0000 0.5000 0.0000 orange_red 255 69 0 1.0000 0.2706 0.0000 yellow_ochre 227 130 23 0.8900 0.5100 0.0900 Yellows aureoline_yellow 255 168 36 1.0000 0.6600 0.1400 banana 227 207 87 0.8900 0.8100 0.3400 cadmium_lemon 255 227 3 1.0000 0.8900 0.0100 cadmium_yellow 255 153 18 1.0000 0.6000 0.0700 gold 255 215 0 1.0000 0.8431 0.0000 goldenrod 218 165 32 0.8549 0.6471 0.1255 goldenrod_dark 184 134 11 0.7216 0.5255 0.0431 goldenrod_light 250 250 210 0.9804 0.9804 0.8235 goldenrod_pale 238 232 170 0.9333 0.9098 0.6667 light_goldenrod 238 221 130 0.9333 0.8667 0.5098 melon 227 168 105 0.8900 0.6600 0.4100 naplesyellowdeep 255 168 18 1.0000 0.6600 0.0700 yellow 255 255 0 1.0000 1.0000 0.0000 yellow_light 255 255 224 1.0000 1.0000 0.8784 Greens chartreuse 127 255 0 0.4980 1.0000 0.0000 chromeoxidegreen 102 128 20 0.4000 0.5000 0.0800 cinnabar_green 97 179 41 0.3800 0.7000 0.1600 cobalt_green 61 145 64 0.2400 0.5700 0.2500 emerald_green 0 201 87 0.0000 0.7900 0.3400 forest_green 34 139 34 0.1333 0.5451 0.1333 green 0 255 0 0.0000 1.0000 0.0000 green_dark 0 100 0 0.0000 0.3922 0.0000 green_pale 152 251 152 0.5961 0.9843 0.5961 green_yellow 173 255 47 0.6784 1.0000 0.1843 lawn_green 124 252 0 0.4863 0.9882 0.0000 lime_green 50 205 50 0.1961 0.8039 0.1961 mint 189 252 201 0.7400 0.9900 0.7900 olive 59 94 43 0.2300 0.3700 0.1700 olive_drab 107 142 35 0.4196 0.5569 0.1373 olive_green_dark 85 107 47 0.3333 0.4196 0.1843 permanent_green 10 201 43 0.0400 0.7900 0.1700 sap_green 48 128 20 0.1900 0.5000 0.0800 sea_green 46 139 87 0.1804 0.5451 0.3412 sea_green_dark 143 188 143 0.5608 0.7373 0.5608 sea_green_medium 60 179 113 0.2353 0.7020 0.4431 sea_green_light 32 178 170 0.1255 0.6980 0.6667 spring_green 0 255 127 0.0000 1.0000 0.4980 spring_greenmedium 0 250 154 0.0000 0.9804 0.6039 terre_verte 56 94 15 0.2200 0.3700 0.0600 viridian_light 110 255 112 0.4300 1.0000 0.4400 yellow_green 154 205 50 0.6039 0.8039 0.1961 Cyans aquamarine 127 255 212 0.4980 1.0000 0.8314 aquamarinemedium 102 205 170 0.4000 0.8039 0.6667 cyan 0 255 255 0.0000 1.0000 1.0000 cyan_white 224 255 255 0.8784 1.0000 1.0000 turquoise 64 224 208 0.2510 0.8784 0.8157 turquoise_dark 0 206 209 0.0000 0.8078 0.8196 turquoise_medium 72 209 204 0.2824 0.8196 0.8000 turquoise_pale 175 238 238 0.6863 0.9333 0.9333 Blues alice_blue 240 248 255 0.9412 0.9725 1.0000 blue 0 0 255 0.0000 0.0000 1.0000 blue_light 173 216 230 0.6784 0.8471 0.9020 blue_medium 0 0 205 0.0000 0.0000 0.8039 cadet 95 158 160 0.3725 0.6196 0.6275 cobalt 61 89 171 0.2400 0.3500 0.6700 cornflower 100 149 237 0.3922 0.5843 0.9294 cerulean 5 184 204 0.0200 0.7200 0.8000 dodger_blue 30 144 255 0.1176 0.5647 1.0000 indigo 8 46 84 0.0300 0.1800 0.3300 manganese_blue 3 168 158 0.0100 0.6600 0.6200 midnight_blue 25 25 112 0.0980 0.0980 0.4392 navy 0 0 128 0.0000 0.0000 0.5020 peacock 51 161 201 0.2000 0.6300 0.7900 powder_blue 176 224 230 0.6902 0.8784 0.9020 royal_blue 65 105 225 0.2549 0.4118 0.8824 slate_blue 106 90 205 0.4157 0.3529 0.8039 slate_blue_dark 72 61 139 0.2824 0.2392 0.5451 slate_blue_light 132 112 255 0.5176 0.4392 1.0000 slate_blue_medium 123 104 238 0.4824 0.4078 0.9333 sky_blue 135 206 235 0.5294 0.8078 0.9216 sky_blue_deep 0 191 255 0.0000 0.7490 1.0000 sky_blue_light 135 206 250 0.5294 0.8078 0.9804 steel_blue 70 130 180 0.2745 0.5098 0.7059 steel_blue_light 176 196 222 0.6902 0.7686 0.8706 turquoise_blue 0 199 140 0.0000 0.7800 0.5500 ultramarine 18 10 143 0.0700 0.0400 0.5600 Magentas blue_violet 138 43 226 0.5412 0.1686 0.8863 cobalt_violetdeep 145 33 158 0.5700 0.1300 0.6200 magenta 255 0 255 1.0000 0.0000 1.0000 orchid 218 112 214 0.8549 0.4392 0.8392 orchid_dark 153 50 204 0.6000 0.1961 0.8000 orchid_medium 186 85 211 0.7294 0.3333 0.8275 permanent_violet 219 38 69 0.8600 0.1500 0.2700 plum 221 160 221 0.8667 0.6275 0.8667 purple 160 32 240 0.6275 0.1255 0.9412 purple_medium 147 112 219 0.5765 0.4392 0.8588 ultramarine_violet 92 36 110 0.3600 0.1400 0.4300 violet 143 94 153 0.5600 0.3700 0.6000 violet_dark 148 0 211 0.5804 0.0000 0.8275 violet_red 208 32 144 0.8157 0.1255 0.5647 violet_redmedium 199 21 133 0.7804 0.0824 0.5216 violet_red_pale 219 112 147 0.8588 0.4392 0.5765References An inexpensive scheme for calibration of a color monitor in terms of CIE standard coordinates W.B. Cowan, Computer Graphics, Vol. 17 No. 3, 1983
Calibration of a computer controlled color monitor
Color Monitor Colorimetry
Color Temperature for Color Television Studio Monitors
Color Science in Television and Display Systems
CIE Colorimetry
CRT Colorimetry:Part 1 Theory and Practice, Part 2 Metrology
Effective Color Displays. Theory and Practice
Color and Its Reproduction
Gamma and its disguises: The nonlinear mappings of intensity in perception,
CRT's, Film and Video
Measuring Color (second edition),
On the Gun Independence and Phosphor Consistency of Color Video
Monitors
Precision requirements for digital color reproduction
The colorimetry of self luminous displays - a bibliography
The Reproduction of Color in PhotoGraphy, Printing and Television
Fully Utilizing Photo CD Images, Article No. 4, PhotoYCC Color Encoding and
Compression Schemes
Digital halftoning
WWW Browser coloursWritten by Paul BourkeSeptember 1996 Achieving consistent colour representation within WWW documents between browsers (NetScape, MSIE) and hardware platforms (Macintosh, Windows, UNIX) requires some knowledge of how browsers allocate colours when running in 8 bit mode (256 colours). If 16, 24 or higher colour modes are being used then exact colour representation is achieved without dithering and the following doesn't apply. Colour in HTML is represented by 3 hexadecimal (hex) pairs, representing the red, green, blue components of the final colour. Each RGB component is stored as 1 byte (unsigned) ranging numerically from 0 to 255, in hex this is "00" to "ff". The colour model is the familiar colour cube used in computer graphics. ![]()
Any colour can be requested by a WWW page but the browser will not necessarily use that colour precisely due to hardware limitations. Even if the hardware is capable of 24 bit colour, the actual RGB components are often rounded to multiples of 4, fortunately this is not discernable by humans even if it could be resolved by the monitor. In index colour system such as the most common 256 colour system, the actual colours that can be displayed are quantised into much coarser steps. The operating system generally needs some colours for its own use such as drawing window boundaries, menus, etc. Browsers on Macintosh and MSWindows systems use 216 of the available 256 colours, the remaining 40 are left available for the operating system to allocate as necessary. If colours are used that are not in the palette of 256 colours the browser will either convert the colour to one that is closest in the palette or it will give the bext representation of the requested colour by dithering a number of the available colours. If these colours are being used for backgrounds and/or text it can often mean the difference between a readable and unreadable page.
The set of colours which, if used, will look the same on all 256 palette systems is simply a 6x6x6 (216) partitioning of the colour cube. The discrete steps in each RGB component are
or in hex
or as percentages
This doesn't include any grey scale levels (where r = g = b) but fortunately the 40 system wide colours usually include a good range of grey values.
The above table was generated by slicing along the red axis of the colour cube, that is, each table above is a sampled plane parallel to the green-blue plane. Slices could be generated along the other two axes as well. Laid out as a PhotoShop table, the 256 colour palette for the Macintosh is shown on the left and the 216 palette for MS based machines is shown on the right.
All three slices can be viewed below
Note: The above refers to what colours should be used when creating simple colour diagrams, for example, backgrounds, logos, etc. For photographic or other images with more than 256 colours it is better to use an adaptive colour table when creating the gif rather than dithering to the browser palette. C code to create colour table.
Converting between RGB and CMY, YIQ, YUVCompiled by Paul BourkeFebruary 1994 RGB to/from CMY
Converting from RGB to CMY is simply the following
The reverse mapping is similarly obvious
The two system may also be known as additive for RGB and subtractive for CMY. RGB to/from YIQ
The YIQ system is the colour primary system adopted by NTSC for colour television broadcasting. The YIQ color solid is formed by a linear transformation of the RGB cube. Its purpose is to exploit certain characteristics of the human visual system to maximize the use of a fixed bandwidth. The transform maxtrix is as follows
Note: First line Y = (0.299, 0.587, 0.144) (R,G,B) also gives pure B&W translation for RGB. The inverse transformation matrix that converts YIQ to RGB is
RGB to/from YUV
YUV is like YIQ, except that it is the PAL/European standard. Transformation matrix is
The reverse transform is
Frequency to RGBCompiled by Paul BourkeFebruary 1994
Reference:
Rogers, David F., "Procedural Elements for Computer Graphics," The best way of finding the RGB values of a given wavelength is to use the CIE chromaticity diagram. The spectral locus is on the edge of the wing-shaped curve. You just need to transform the xy coordinate from CIEXYZ space into RGB space. Below I have spectral locus coordinates from 380nm to 780m in steps of 5 nm. It's written as a C array. We'll refer to any particular wavelength's coordinates as xc and yc. To transform into RGB, we need the xy coordinates of the RGB primaries and the alignment white. I'll use a set of typical values.
x y
Red 0.628 0.346 call these xr and yr
Green 0.268 0.588 " " xg and yg
Blue 0.150 0.070 " " xb and yb
White 0.313 0.329 " " xw and yw
From these we can compute the linear transformation from CIEXYZ to RGB.It is:
[R] = [ 2.739 -1.145 -0.424 ] [X]
[G] = [ -1.119 2.029 0.033 ] [Y]
[B] = [ 0.138 -0.333 1.105 ] [Z]
However, if the xy coordinate of the spectral color isn't inside the triangle formed by the RGB xy coordinates given above (and none of them are), then we must first find a closest match that is inside the triangle. Otherwise our RGB values will go outside the range [0,1], i.e. some values will be less than zero or greater than one. One common way of moving the color inside the triangle is to make the color whiter (i.e. desaturate it). Mathematically we do this by intersecting the line joining the color and the alignment white with the edges of the triangle. First define the line that goes through white and your color implicitly:
Lc: [-(yw - yc)] * P + [-(yw - yc)] * [xc]
[ xw - wc ] [ xw - xc ] [yc]
For every pair of red, green, and blue, define an explicit (parametric line). For example, the line between the red and green primaries is:
Lrg: P = [xr] + t * [xg - xr]
[yr] [yg - yr]
Substitute Lrg for P into Lc and solve for the parameter t. If 0 <= t <= 1, then you've got the answer and you don't need to try the other lines. Otherwise, substitute Lgb, and if necessary Lbr. If t is not in the range [0,1] then the intersection occurred outside the triangle. Once you have t, plug it into the original equation for Lrg (or whatever line gave a good solution) and you get the xy coordinate. Plug this into the linear transformation above (using z = 1 - x - y) to get the RGB values. At least one of R, G, or B should be exactly one (ie fully saturated in the RGB color space). Since this is an involved procedure, I would suggest precomputing RGB's for all the wavelengths you'll need (or enough to interpolate) once for each display device you'll be using. If you know the chromaticity coordinates of your display's primaries and its white you can compute the linear transformation easily.
/* CIE 1931 chromaticity coordinates of spectral stimuli (only xy, z = 1 - x - y) */
float spectrum_xy[][2] = {
{0.1741, 0.0050},
{0.1740, 0.0050},
{0.1738, 0.0049},
{0.1736, 0.0049},
{0.1733, 0.0048},
{0.1730, 0.0048},
{0.1726, 0.0048},
{0.1721, 0.0048},
{0.1714, 0.0051},
{0.1703, 0.0058},
{0.1689, 0.0069},
{0.1669, 0.0086},
{0.1644, 0.0109},
{0.1611, 0.0138},
{0.1566, 0.0177},
{0.1510, 0.0227},
{0.1440, 0.0297},
{0.1355, 0.0399},
{0.1241, 0.0578},
{0.1096, 0.0868},
{0.0913, 0.1327},
{0.0687, 0.2007},
{0.0454, 0.2950},
{0.0235, 0.4127},
{0.0082, 0.5384},
{0.0039, 0.6548},
{0.0139, 0.7502},
{0.0389, 0.8120},
{0.0743, 0.8338},
{0.1142, 0.8262},
{0.1547, 0.8059},
{0.1929, 0.7816},
{0.2296, 0.7543},
{0.2658, 0.7243},
{0.3016, 0.6923},
{0.3373, 0.6589},
{0.3731, 0.6245},
{0.4087, 0.5896},
{0.4441, 0.5547},
{0.4788, 0.5202},
{0.5125, 0.4866},
{0.5448, 0.4544},
{0.5752, 0.4242},
{0.6029, 0.3965},
{0.6270, 0.3725},
{0.6482, 0.3514},
{0.6658, 0.3340},
{0.6801, 0.3197},
{0.6915, 0.3083},
{0.7006, 0.2993},
{0.7079, 0.2920},
{0.7140, 0.2859},
{0.7190, 0.2809},
{0.7230, 0.2770},
{0.7260, 0.2740},
{0.7283, 0.2717},
{0.7300, 0.2700},
{0.7311, 0.2689},
{0.7320, 0.2680},
{0.7327, 0.2673},
{0.7334, 0.2666},
{0.7340, 0.2660},
{0.7344, 0.2656},
{0.7346, 0.2654},
{0.7347, 0.2653},
{0.7347, 0.2653},
{0.7347, 0.2653},
{0.7347, 0.2653},
{0.7347, 0.2653},
{0.7347, 0.2653},
{0.7347, 0.2653},
{0.7347, 0.2653},
{0.7347, 0.2653},
{0.7347, 0.2653},
{0.7347, 0.2653},
{0.7347, 0.2653},
{0.7347, 0.2653},
{0.7347, 0.2653},
{0.7347, 0.2653},
{0.7347, 0.2653},
{0.7347, 0.2653}};
YCC colour space and image compressionWritten by Paul BourkeApril 2000
There are an infinite number of possible colour spaces instead of the common RGB (Red, Green, Blue) system most commonly used in computer graphics. Many of these other colour spaces are derived by applying linear functions of r, g, b. So for example, a colour space based upon 3 coordinates v1, v2, and v3 can be written as: v1 = Ar1 R + Ag1 G + Ab1 B v2 = Ar2 R + Ag2 G + Ab2 B v3 = Ar3 R + Ag3 G + Ab3 B Where the Ar, Ag, Ab are constants for a particular colour space. Similarly for any such system there are linear functions to go back to RGB space. The coefficients Dr, Dg, Dc can be derived by solving the above equations for r,g,b. For example: R = Dr1 v1 + Dg1 v2 + Db1 v3 G = Dr2 v1 + Dg2 v2 + Db2 v3 B = Dr3 v1 + Dg3 v2 + Db3 v3 The human visual system has much less dynamic range (acuity) for spatial variation in colour than for brightness (luminance), in other words, we are acutely aware of changes in the brightness of details than of small changes in hue. So rather than saving as RGB it can be more efficient to encode luminance in one channel and colour information (that has had the luminance contribution removed) in two other channels. The two colour channels can be encoded with less bandwidth by using a number of techniques, predominantly by reducing the precision, or as will be discussed here, reducing the spatial resolution. Since green dominates the luminance channel it makes sense to base the other two chrominance channels on luminance subtracted red and blue. Such luminance, red chrominance and blue chrominance systems are generally referred to as Y, Cr, and Cb. In what follows they will generally be referred this way or simply as YCC. Example: Kodak PhotoCD YCC
The Kodak PhotoYCC colour space was designed for encoding images with the PhotoCD system. It is based on both CCIR Recommendations 709 and 601-1, having a colour gamut defined by the CCIR 709 primaries and a luminance - chrominance representation of colour like CCIR 601-1's YCbCr. To convert from RGB to PhotoCD YCC, the following matrix operation is used (after appropriate gamma correction has been applied). Notice the major contribution to the Cr value is red and the main contribution to the Cb value is blue. The unbalanced scale difference between Chroma1 and Chroma2 is designed, according to Kodak, to follow the typical distribution of colours in real scenes. Y = 0.299 R + 0.587 G + 0.114 B Cr = 0.701 R - 0.587 G - 0.114 B Cb = -0.299 R - 0.587 G + 0.886 B The rationale behind these coefficients can be found by considering that the luminance subtracted blue (B-Y) signal reaches its extreme values at blue (R=0, G=0, B=1, Y=0.114, B-Y=0.886) and at yellow (R=1, G=1, B=0, Y=0.886, B-Y=-0.886). Similarly, the extrema of the luminance subtracted red (R-Y), +-0.701, occur at red and cyan. In a similar way there is a matrix for creating RGB colour values from any colour space created as discussed above. Note that in many cases and this applies to YCC colour spaces, it is possible to represent colours that cannot be represented in RGB space. For the Kodak system the reverse mapping from YCC into RGB is:
Given the human visual systems "preference" for luminance information, one can design an image compression system around YCC colour space. Consider an RGB image with Nx horizontal pixels and Ny vertical pixels. If each pixel is repreented as one byte the the image size in bytes is Nx Ny 3. Consider storing the image in YCC space where the luminance channel Y is stored as one byte for each pixel but the two chrominance channels are only stored for each block of say 4x4 pixels. The resulting image would be Nx Ny + 2 (Nx/4 + Ny/4), this is an image 2 and 2/3rds smaller. Put another way, instead of using on average 3 bytes (24 bits) per pixel we would only be using 9 bits per pixel. ![]()
Note the chrominance is averaged over each 4x4 block. There is nothing particularly special about a 4x4 block instead of a 3x3 or 5x5 or other sizes. A 2x2 by two results in a factor 2 saving, a 3x3 grid results in a saving of 2.45. Larger grids give ever decreasing rates of return and soon impact on the image quality. The YCC colour space used follows that used by TIFF and JPEG (Rec 601-1)Y = 0.2989 R + 0.5866 G + 0.1145 B Cb = -0.1687 R - 0.3312 G + 0.5000 B Cr = 0.5000 R - 0.4183 G - 0.0816 B RGB values are normally on the scale of 0 to 1, or since they are stored as unsigned single bytes, 0 to 255. The resulting luminance value is also on the scale of 0 to 255, the chrominance values need 127.5 added to them so they can saved in an unsigned byte. Of course when the YCC values are turned back into RGB, then 127.5 must be first subtracted from the two chrominance values. The reverse transform is R = Y + 1.4022 Cr G = Y - 0.3456 Cb - 0.7145 Cr B = Y + 1.7710 Cb The full chrominance range of +-0.5 maps into a larger colour space than supported by RGB. The above equations can yield RGB values outside the 0 to 255 (or 0 to 1) range, these typically relate to very light or dark colours. The RGB values should be clipped so they lie within the allowed range after the transform from YCC to RGB is calculated. An image compressed this way is obviously degraded but could one tell the difference? Below are two images, the one on the left uses 24 bits per pixel and the one on the right uses 9 bits per pixel as described above.
The compression scheme above is most noticeable when there are rapid changes in hue but little change in luminance, in this case the 4x4 subsampling of the Cr and Cb channels is most noticeable. For images of real world scenes this happens surprisingly rarely, in the before and after example above it is virtually impossible to zoom in and find examples of the 4x4 subsampling. Similarly one would not generally use this sort of compression for low colour images, in that case other compression techniques are available. Appendix: Other standard colour space conversions
PAL television standard
NTSC television standard
References
Color Monitor Colorimetry
CIE Colorimetry
Effective Color Displays. Theory and Practice
Measuring Colour (Second edition)
Precision requirements for digital color reproduction
The Reproduction of Colour in Photography, Printing and Television
Colour Ramping for Data VisualisationWritten by Paul BourkeJuly 1996 Contribution: Ramp.cs by Russell Plume in DotNet C#. This note introduces the most commonly used colour ramps for mapping colours onto a range of scalar values as is often required in data visualisation. The colour space will be based upon the RGB system. Grey Scale
The most basic mapping of some scalar value to a colour ramp is to use either an intensity ramp from black to a single colour or use the greyscale ramp from black to white. Black normally being the low end of the range of values, and white the high end. On the colour cube this is a diagonal line between the two opposite corners, the red, green, blue components are all the same. ![]()
The map from black to white is usually just a linear ramp, for a
value (v) which varies from vmin to vmax, the colour is ![]()
The most commonly used colour ramp is often refer to as the "hot- to-cold" colour ramp. Blue is chosen for the low values, green for middle values, and red for the high as these seem "intuitive" bounds. One could ramp between these points on the colour cube but this involves moving diagonally across the faces of the cube. Instead we add the colours cyan and yellow so that the colour ramp only moves along the edges of the colour cube from blue to red. This not only makes the mapping easier and faster but introduces more colour variation. The following illustrates the path on the colour cube. ![]() The colour ramp is shown below along with the transition values. ![]() Again there is a linear relationship of the scalar value with colour within each of the 4 colour bands. In some applications the variable being represented with the colour map is circular in nature in which case a cyclic colour map is desirable. The above can be simply modified to pass through magenta to yield one of many possible circular colour maps. ![]()
A more general case ramps between N colours, each colour has a corresponding value within the range of values of the variable being mapped. The points within the colour cube can be linearly ramped between the points or the transition can be smoothed by some interpolation function such a bezier curve. For example a 3 colour ramp for terrain visualisation might choose 3 heights and three corresponding colours. ![]() Displayed as a colour ramp
![]() The resulting terrain map
![]() C Source for the "standard" hot-to-cold colour ramp.
/*
Return a RGB colour value given a scalar v in the range [vmin,vmax]
In this case each colour component ranges from 0 (no contribution) to
1 (fully saturated), modifications for other ranges is trivial.
The colour is clipped at the end of the scales if v is outside
the range [vmin,vmax]
typedef struct {
double r,g,b;
} COLOUR;
*/
COLOUR GetColour(double v,double vmin,double vmax)
{
COLOUR c = {1.0,1.0,1.0}; // white
double dv;
if (v < vmin)
v = vmin;
if (v > vmax)
v = vmax;
dv = vmax - vmin;
if (v < (vmin + 0.25 * dv)) {
c.r = 0;
c.g = 4 * (v - vmin) / dv;
} else if (v < (vmin + 0.5 * dv)) {
c.r = 0;
c.b = 1 + 4 * (vmin + 0.25 * dv - v) / dv;
} else if (v < (vmin + 0.75 * dv)) {
c.r = 4 * (v - vmin - 0.5 * dv) / dv;
c.b = 0;
} else {
c.g = 1 + 4 * (vmin + 0.75 * dv - v) / dv;
c.b = 0;
}
return(c);
}
Note about gamma
Please note that the above are not corrected for the gamma of the display device. As such the colours may indeed appear different on different diaplays. The gamma of displays can be adjusted and typically have a power relationship, that is, if (r,g,b) is the colour being displayed, it will appear as (rG,gG,bG). In order to achieve a display colour or (r,g,b) the inverse of the gamma function needs to be created, namely (r1/G,g1/G,b1/G). Note also that the gamma value G is not necessarily the same for each (r,g,b) component.
Simple method of storing colour rampsAdapted from OGLE (By Dr. Michael J. Gourlay)
Written By Paul Bourke Many applications in computer graphics use colour and/or opacity ramps, in particular, visualisation using volume rendering. In this and other cases one often just requires colour and opacity index tables for 256 states. The following is a straightforward approach to storing such index colour maps, it has been adopted from the OGLE volume rendering software, at least this means there is one other piece of software that uses the format rather than dreaming up an entirely new format. Example (ramp1.dat)
This is the standard blue to green to red colour map. The columns are the index value follwed by the red, green, blue values ranging from 0 (no contribution) to 255 (full contribution). 0 0 0 255 64 0 255 254 128 1 255 0 192 255 252 0 1 0 3 255 65 0 255 249 129 5 255 0 193 255 247 0 2 0 7 255 66 0 255 246 130 9 255 0 194 255 244 0 3 0 11 255 67 0 255 241 131 13 255 0 195 255 239 0 4 0 15 255 68 0 255 238 132 17 255 0 196 255 236 0 5 0 19 255 69 0 255 233 133 21 255 0 197 255 231 0 6 0 23 255 70 0 255 230 134 25 255 0 198 255 228 0 7 0 27 255 71 0 255 225 135 29 255 0 199 255 223 0 8 0 31 255 72 0 255 222 136 33 255 0 200 255 220 0 9 0 35 255 73 0 255 217 137 37 255 0 201 255 215 0 10 0 39 255 74 0 255 214 138 41 255 0 202 255 212 0 11 0 43 255 75 0 255 209 139 45 255 0 203 255 207 0 12 0 47 255 76 0 255 206 140 49 255 0 204 255 204 0 13 0 51 255 77 0 255 201 141 53 255 0 205 255 199 0 14 0 55 255 78 0 255 198 142 57 255 0 206 255 196 0 15 0 59 255 79 0 255 193 143 61 255 0 207 255 191 0 16 0 63 255 80 0 255 190 144 66 255 0 208 255 188 0 17 0 67 255 81 0 255 185 145 70 255 0 209 255 183 0 18 0 71 255 82 0 255 182 146 74 255 0 210 255 180 0 19 0 75 255 83 0 255 177 147 78 255 0 211 255 175 0 20 0 79 255 84 0 255 174 148 82 255 0 212 255 172 0 21 0 83 255 85 0 255 169 149 86 255 0 213 255 167 0 22 0 87 255 86 0 255 166 150 90 255 0 214 255 164 0 23 0 91 255 87 0 255 161 151 94 255 0 215 255 159 0 24 0 95 255 88 0 255 158 152 98 255 0 216 255 156 0 25 0 99 255 89 0 255 153 153 102 255 0 217 255 151 0 26 0 103 255 90 0 255 150 154 106 255 0 218 255 148 0 27 0 107 255 91 0 255 145 155 110 255 0 219 255 143 0 28 0 111 255 92 0 255 142 156 114 255 0 220 255 140 0 29 0 115 255 93 0 255 137 157 118 255 0 221 255 135 0 30 0 119 255 94 0 255 134 158 122 255 0 222 255 132 0 31 0 123 255 95 0 255 129 159 126 255 0 223 255 127 0 32 0 127 255 96 0 255 126 160 129 255 0 224 255 123 0 33 0 132 255 97 0 255 122 161 134 255 0 225 255 119 0 34 0 135 255 98 0 255 118 162 137 255 0 226 255 115 0 35 0 140 255 99 0 255 114 163 142 255 0 227 255 111 0 36 0 143 255 100 0 255 110 164 145 255 0 228 255 107 0 37 0 148 255 101 0 255 106 165 150 255 0 229 255 103 0 38 0 151 255 102 0 255 102 166 153 255 0 230 255 99 0 39 0 156 255 103 0 255 98 167 158 255 0 231 255 95 0 40 0 159 255 104 0 255 94 168 161 255 0 232 255 91 0 41 0 164 255 105 0 255 90 169 166 255 0 233 255 87 0 42 0 167 255 106 0 255 86 170 169 255 0 234 255 83 0 43 0 172 255 107 0 255 82 171 174 255 0 235 255 79 0 44 0 175 255 108 0 255 78 172 177 255 0 236 255 75 0 45 0 180 255 109 0 255 74 173 182 255 0 237 255 71 0 46 0 183 255 110 0 255 70 174 185 255 0 238 255 67 0 47 0 188 255 111 0 255 66 175 190 255 0 239 255 63 0 48 0 191 255 112 0 255 61 176 193 255 0 240 255 59 0 49 0 196 255 113 0 255 57 177 198 255 0 241 255 55 0 50 0 199 255 114 0 255 53 178 201 255 0 242 255 51 0 51 0 204 255 115 0 255 49 179 206 255 0 243 255 47 0 52 0 207 255 116 0 255 45 180 209 255 0 244 255 43 0 53 0 212 255 117 0 255 41 181 214 255 0 245 255 39 0 54 0 215 255 118 0 255 37 182 217 255 0 246 255 35 0 55 0 220 255 119 0 255 33 183 222 255 0 247 255 31 0 56 0 223 255 120 0 255 29 184 225 255 0 248 255 27 0 57 0 228 255 121 0 255 25 185 230 255 0 249 255 23 0 58 0 231 255 122 0 255 21 186 233 255 0 250 255 19 0 59 0 236 255 123 0 255 17 187 238 255 0 251 255 15 0 60 0 239 255 124 0 255 13 188 241 255 0 252 255 11 0 61 0 244 255 125 0 255 9 189 246 255 0 253 255 7 0 62 0 247 255 126 0 255 5 190 249 255 0 254 255 3 0 63 0 252 255 127 0 255 1 191 254 255 0 255 255 0 0 Opacity maps are stored in the same way even though the rgb colour information is usually redundant (r == g == b). Having the opacity map separate from the colour map allows one to use them interchangably, if the rgb values of a map used as an opacity map are not equal then the application can choose how to derive the single opacity value (eg: use the red channel, use the magnitude of the colour....). Collection of colour ramps and associated data file
HSV colour ramp/selectorWritten by Paul BourkeJuly 2005 A useful colour picker interface is often based upon the HSV colour system, sometimes the HSL. The layout of the colour table is often as follows although there is some variation in the functions used for saturation and value. All the colours in rgb space lie on the surface of the colour cube. ![]() Example As a web based paint selection interface, note the extra bar for grey scale selection.
![]()
Index ColourMacintosh palette -- PhotoShop colour tables
Written by Paul Bourke Index colour systems are still prevalent in many graphical computer systems. An index colour system is one in which colour is specified by an integer normally from 0 up to the number of colours in the colour table. Each entry in the colour table gives the red, green, blue components for that particular index. In such colour systems the colour table is sometimes fixed. In these cases you can only use the preset colours. When a particular colour is required which isn't in the table the closest may be used or a number of colours that are in the table may be dithered in order to approximate the desired colour. A more common situation is when the colour table is of a fixed size but the actual RGB values at each position in the table can be changed. Therefore, if you require a wide range of a particular hue you can load up the colour table accordingly. It also leads to situations where one might want to optimise the colour table to best represent a particular image. For example if an image only contains 100 different colours then irrespective of what these colours are, a colour table containing these colours will allow the image to be represented exactly. A much more common situation is when the colour table isn't large enough to hold all the different colours desired, in these cases one might engage in a process called "colour table optimisation" where one attempts to load the colour table with colours so that the image can be best represented. In yet other systems the colour table can be made as large as desired. One often then wants to create a colour table for a particular task. The remained of this document will describe the most unbiased method of creating a colour table in cases where you don't know what colours will be required and thus want an equal sampling of the RGB colour space ![]()
There are two processes involved. The first is creating the entries in the colour table, the second is given an RGB value determining the index of its closest representation in the table. In what follows, an RGB triple will be floating point numbers in the inclusive range [0,1]. If your colour space uses different ranges then simple scaling converts one range to the [0,1] range used here. To create a n sampling along each r,g,b axis will result in n3 colour values. Converting from (r,g,b) triples into the colour index is Some examples of colour tables are illustrated below. The index ranges from 0 top left, increasing left to right - top to bottom. The index in the bottom right cell is n3-1. 3x3x3 sampling![]()
4x4x4 sampling ![]()
5x5x5 sampling ![]()
6x6x6 sampling ![]()
Finding the index of the colour closest to a particular (r,g,b) triple is accomplished as follows where nint(x) is the nearest integer to x. Note
The table
The following is the C code that created the above colour table.
Source code Performing colour remapping with indexed colour images in PhotoShop is particularly straightforward mainly because the colour table files are so easy to generate. The colour table files (which can be loaded into PhotoShop) consist of 256 RGB colour entries, each RGB colour component is stored as 1 byte. Each colour component ranges from 0 to 255. As such they are straightforward to generate mathematically with a programming language.
Address Hexadecimal data, 16 bytes per line ------- --------------------------------------- 0000000 ff00 00ff 0600 ff0c 00ff 1200 ff18 00ff 0000020 1e00 ff24 00ff 2a00 ff30 00ff 3600 ff3c 0000040 00ff 4200 ff48 00ff 4e00 ff54 00ff 5a00 0000060 ff60 00ff 6600 ff6c 00ff 7200 ff78 00ff 0000100 7e00 ff84 00ff 8a00 ff90 00ff 9600 ff9c 0000120 00ff a200 ffa8 00ff ae00 ffb4 00ff ba00 0000140 ffc0 00ff c600 ffcc 00ff d200 ffd8 00ff 0000160 de00 ffe4 00ff ea00 fff0 00ff f600 fffc 0000200 00fc ff00 f6ff 00f0 ff00 eaff 00e4 ff00 0000220 deff 00d8 ff00 d2ff 00cc ff00 c6ff 00c0 0000240 ff00 baff 00b3 ff00 aeff 00a8 ff00 a2ff 0000260 009c ff00 96ff 0090 ff00 8aff 0083 ff00 0000300 7eff 0078 ff00 71ff 006c ff00 66ff 0060 0000320 ff00 59ff 0054 ff00 4eff 0048 ff00 41ff 0000340 003c ff00 36ff 0030 ff00 29ff 0024 ff00 0000360 1eff 0018 ff00 11ff 000c ff00 06ff 0000 0000400 ff00 00ff 0600 ff0c 00ff 1200 ff18 00ff 0000420 1e00 ff24 00ff 2a00 ff30 00ff 3600 ff3c 0000440 00ff 4200 ff48 00ff 4e00 ff54 00ff 5a00 0000460 ff60 00ff 6600 ff6c 00ff 7200 ff78 00ff 0000500 7e00 ff84 00ff 8a00 ff90 00ff 9600 ff9c 0000520 00ff a200 ffa8 00ff ae00 ffb4 00ff ba00 0000540 ffc0 00ff c600 ffcc 00ff d200 ffd8 00ff 0000560 de00 ffe4 00ff ea00 fff0 00ff f600 fffc 0000600 00fc ff00 f6ff 00f0 ff00 eaff 00e4 ff00 0000620 deff 00d8 ff00 d2ff 00cc ff00 c6ff 00c0 0000640 ff00 baff 00b3 ff00 aeff 00a8 ff00 a2ff 0000660 009c ff00 96ff 0090 ff00 8aff 0083 ff00 0000700 7eff 0078 ff00 71ff 006c ff00 66ff 0060 0000720 ff00 59ff 0054 ff00 4eff 0048 ff00 41ff 0000740 003c ff00 36ff 0030 ff00 29ff 0024 ff00 0000760 1eff 0018 ff00 11ff 000c ff00 06ff 0000 0001000 ff06 00ff 0c00 ff12 00ff 1800 ff1e 00ff 0001020 2400 ff2a 00ff 3000 ff36 00ff 3c00 ff42 0001040 00ff 4800 ff4e 00ff 5400 ff5a 00ff 6000 0001060 ff66 00ff 6c00 ff72 00ff 7800 ff7e 00ff 0001100 8400 ff8a 00ff 9000 ff96 00ff 9c00 ffa2 0001120 00ff a800 ffae 00ff b400 ffba 00ff c000 0001140 ffc6 00ff cc00 ffd2 00ff d800 ffde 00ff 0001160 e400 ffea 00ff f000 fff6 00ff fc00 ffff 0001200 00fc ff00 f6ff 00f0 ff00 eaff 00e4 ff00 0001220 deff 00d8 ff00 d2ff 00cc ff00 c6ff 00c0 0001240 ff00 baff 00b3 ff00 aeff 00a8 ff00 a2ff 0001260 009c ff00 96ff 0090 ff00 8aff 0083 ff00 0001300 7eff 0078 ff00 71ff 006c ff00 66ff 0060 0001320 ff00 59ff 0054 ff00 4eff 0048 ff00 41ff 0001340 003c ff00 36ff 0030 ff00 29ff 0024 ff00 0001360 1eff 0018 ff00 11ff 000c ff00 06ff 0000
What is Gamma Correction?orWhy do some pictures appear dark on some displaysWritten by Paul BourkeOriginal: February 1994. Updated Jan 1998. The phosphors on the face of the monitor tube luminesce (or some other computer projection device) when struck by the beam generated by the electron gun sweeping out the scanlines. By increasing the intensity of the beam, the phosphor dot luminesces more brightly, and by reducing the intensity of the beam, the phosphor glows less brightly. The output of the phosphor is not directly proportional to electron beam strength. The response of the phosphors usually looks something like this: ![]()
where the dotted line shows ideal linear response, and the solid line approximates the observed response of a normal phosphor. This response characteristic is due to physical phenomena and can be described via a function of the form Typically monitors have a gamma from anything between 1.5 and 2.8 Subjectively, this causes the colors on the screen to appear darker than expected. Based on this behaviour, an inverse gamma correction function can be applied to compensate for this non-linear response: ![]()
Here, the solid line again represents the uncorrected phosphor response, the large dotted line is the inverse gamma function, and the fine dotted line is the resultant, linearized color response. Determining the gamma valueMost computer systems now days have standard interfaces/utilities for determining and setting the gamma value. For example the Macintosh has a control panel with the OS, SGI machines come with a utility called "gamma" which both reports and sets the gamma value. The following chart can be used to determine the combined gamma value for your system. ![]() Setting the gamma value To adjust the gamma value "roughly", set the contrast and brightness of your monitor to your preferred/comfortable level and use whatever gamma software comes with your hardware. In the absence of other information it is usual to set the effective gamma to 2.2, this is the standard employed for PhotoCD's. On SGI machines this normally means setting a "gamma" value of around 1.2, this is because SGI's are normally configured with a natural gamma of 2.6, the combined gamma value is 2.6 divided by this number. All well written image viewers should provide options for controlling the gamma or they should get the value from the system being used. For example on UNIX machine, the xv viewer can be called with the option -gamma 2.2. Unfortunately at the time of writing none of the two main WEB browsers support gamma correction for images in WWW pages, as a result the images tend to look dark on uncorrected monitors. This is a major problem when it comes to distributing images on a wide variety of systems. Fortunately the PNG format does support the specification of a colourmetric model and will go a long way to providing consistent image appearance across monitor hardware.
|