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.
Colour space
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 absorbency of inks on paper.
Some other major colour spaces are:
HSL, Hue Saturation and Lightness.
HSI, Hue Saturation and Intensity
HSV, Hue Saturation and Value
CIE, a colour standard from the for Commission Internationale
de l'Eclairage based on brightness, hue, and colourfulness.
There are generally ways of converting (transforming) between different colour
spaces although in most cases the transformation is non-linear. Some colour
spaces for example can represent colours which cannot be represented in others.
RGB colour cube
The 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.
Note:
Along each axis of the colour cube the colours range from no contribution of
that component to a fully saturated colour.
The colour cube is solid, any point (colour) within the cube is specified by
three numbers, namely, an r,g,b triple.
The diagonal line of the cube from black (0,0,0) to white (1,1,1) represents
all the greys, that is, all the red, green, and blue components are the same.
In practice different computer hardware/software combinations will use
different ranges for the colours, common ones are 0-256 and 0-65536 for each
component. This is simply a linear scaling of the unit colour cube described
here.
This RGB colour space lies within our perceptual space, that is, the RGB cube
is smaller and represents fewer colours than we can see.
A more "colourful" view of the shell of the colour cube is shown below.
RGB colour values for "familiar" colours.
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.
An inexpensive scheme for calibration of a colour monitor in terms of CIE
standard coordinates. W.B. Cowan, Computer Graphics, Vol. 17 No. 3, 1983
Calibration of a computer controlled colour monitor.
Brainard, D.H,Color Research & Application, 14, 1, pp 23-34 (1989).
Color Monitor Colorimetry. SMPTE Recommended Practice RP 145-1987
Color Temperature for Color Television Studio Monitors.
SMPTE Recommended Practice RP 37
Color Science in Television and Display Systems.
Sproson, W, N, Adam Hilger Ltd, 1983. ISBN 0-85274-413-7
CIE Colorimetry. Official recommendations of the International
Commission on Illumination, Publication 15.2 1986
CRT Colorimetry: Part 1 Theory and Practice, Part 2 Metrology.
Berns, R.S., Motta, R.J. and Gorzynski, M.E., Color Research and
Application, 18, (1993)
Effective Color Displays. Theory and Practice.
Travis, D, Academic Press, 1991. ISBN 0-12-697690-2
Color and Its Reproduction.
Field, G.G., Graphics Arts Technical, Foundation, 1988, pp. 320-9
Gamma and its disguises: The non-linear mappings of intensity in perception,
CRT's, Film and Video. C. A. Poynton, SMPTE Journal, December 1993
Measuring Color (second edition).
R. W. G. Hunt, Ellis Horwood 1991, ISBN 0-13-567686-x
On the Gun Independence and Phosphor Consistency of Color Video Monitors.
W.B. Cowan N. Rowell, Color Research and Application, V.11 Supplement 1986
Precision requirements for digital Color reproduction.
M Stokes MD Fairchild RS Berns, ACM Transactions on graphics, v11 n4 1992
The colorimetry of self luminous displays - a bibliography.
CIE Publication n.87, Central Bureau of the CIE, Vienna 1990
The Reproduction of Color in Photography, Printing and Television.
R. W. G. Hunt, Fountain Press, Tolworth, England, 1987
Fully Utilizing Photo CD Images, Article No. 4, PhotoYCC Color Encoding and
Compression Schemes. Eastman Kodak Company, Rochester NY (USA) (1993).
Digital halftoning.
Robert Ulichney, MIT Press, 1987, ISBN 0-262-21009-6
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 discernible 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 best 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.
Consider the rectangle on the right.
It is created using a colour that is in the standard 216 palette used
by browsers (NetScape and MSIE).
The rectangle on the right however uses a colour not in the standard palette.
It will either look like a solid colour if you have a 16 or 24 bit colour
system or dithered if you have a 256 indexed colour system.
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
000
051
102
153
204
255
or in hex
00
33
66
99
cc
ff
or as percentages
000%
020%
040%
060%
080%
100%
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.
Colour table - red
00 00 00
00 00 33
00 00 66
00 00 99
00 00 CC
00 00 FF
00 33 00
00 33 33
00 33 66
00 33 99
00 33 CC
00 33 FF
00 66 00
00 66 33
00 66 66
00 66 99
00 66 CC
00 66 FF
00 99 00
00 99 33
00 99 66
00 99 99
00 99 CC
00 99 FF
00 CC 00
00 CC 33
00 CC 66
00 CC 99
00 CC CC
00 CC FF
00 FF 00
00 FF 33
00 FF 66
00 FF 99
00 FF CC
00 FF FF
33 00 00
33 00 33
33 00 66
33 00 99
33 00 CC
33 00 FF
33 33 00
33 33 33
33 33 66
33 33 99
33 33 CC
33 33 FF
33 66 00
33 66 33
33 66 66
33 66 99
33 66 CC
33 66 FF
33 99 00
33 99 33
33 99 66
33 99 99
33 99 CC
33 99 FF
33 CC 00
33 CC 33
33 CC 66
33 CC 99
33 CC CC
33 CC FF
33 FF 00
33 FF 33
33 FF 66
33 FF 99
33 FF CC
33 FF FF
66 00 00
66 00 33
66 00 66
66 00 99
66 00 CC
66 00 FF
66 33 00
66 33 33
66 33 66
66 33 99
66 33 CC
66 33 FF
66 66 00
66 66 33
66 66 66
66 66 99
66 66 CC
66 66 FF
66 99 00
66 99 33
66 99 66
66 99 99
66 99 CC
66 99 FF
66 CC 00
66 CC 33
66 CC 66
66 CC 99
66 CC CC
66 CC FF
66 FF 00
66 FF 33
66 FF 66
66 FF 99
66 FF CC
66 FF FF
99 00 00
99 00 33
99 00 66
99 00 99
99 00 CC
99 00 FF
99 33 00
99 33 33
99 33 66
99 33 99
99 33 CC
99 33 FF
99 66 00
99 66 33
99 66 66
99 66 99
99 66 CC
99 66 FF
99 99 00
99 99 33
99 99 66
99 99 99
99 99 CC
99 99 FF
99 CC 00
99 CC 33
99 CC 66
99 CC 99
99 CC CC
99 CC FF
99 FF 00
99 FF 33
99 FF 66
99 FF 99
99 FF CC
99 FF FF
CC 00 00
CC 00 33
CC 00 66
CC 00 99
CC 00 CC
CC 00 FF
CC 33 00
CC 33 33
CC 33 66
CC 33 99
CC 33 CC
CC 33 FF
CC 66 00
CC 66 33
CC 66 66
CC 66 99
CC 66 CC
CC 66 FF
CC 99 00
CC 99 33
CC 99 66
CC 99 99
CC 99 CC
CC 99 FF
CC CC 00
CC CC 33
CC CC 66
CC CC 99
CC CC CC
CC CC FF
CC FF 00
CC FF 33
CC FF 66
CC FF 99
CC FF CC
CC FF FF
FF 00 00
FF 00 33
FF 00 66
FF 00 99
FF 00 CC
FF 00 FF
FF 33 00
FF 33 33
FF 33 66
FF 33 99
FF 33 CC
FF 33 FF
FF 66 00
FF 66 33
FF 66 66
FF 66 99
FF 66 CC
FF 66 FF
FF 99 00
FF 99 33
FF 99 66
FF 99 99
FF 99 CC
FF 99 FF
FF CC 00
FF CC 33
FF CC 66
FF CC 99
FF CC CC
FF CC FF
FF FF 00
FF FF 33
FF FF 66
FF FF 99
FF FF CC
FF FF FF
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.
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.
Converting from RGB to CMY is simply the following
C = M = Y =
1 - R 1 - G 1 - B
The reverse mapping is similarly obvious
R = G = B =
1 - C 1 - M 1 - Y
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 matrix is as follows
Y
I
Q
=
0.299
0.587
0.114
0.596
-0.274
-0.322
0.212
-0.523
0.311
R
G
B
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
R
G
B
=
1.0
0.956
0.621
1.0
-0.272
-0.647
1.0
-1.105
1.702
Y
I
Q
RGB to/from YUV
YUV is like YIQ, except that it is the PAL/European standard.
Transformation matrix is
The HSL colour space has three coordinates: hue, saturation, and lightness
(sometimes luminance)
respectively, it is sometimes referred to as HLS. The hue is an angle from
0 to 360 degrees, typically 0 is red, 60 degrees yellow, 120 degrees
green, 180 degrees cyan, 240 degrees blue, and 300 degrees magenta.
Saturation typically ranges from 0 to 1 (sometimes 0 to 100%) and
defines how grey the colour is, 0 indicates grey and 1 is the pure
primary colour. Lightness is intuitively what it's name indicates,
varying the lightness reduces the values of the primary colours while
keeping them in the same ratio. If the colour space is represented
by disks of varying lightness then the hue and saturation are the
equivalent to polar coordinates (r,theta) of any point in the plane.
These disks are shown on the right for various values of lightness.
C code to transform between RGB and HSL is given below
/*
Calculate HSL from RGB
Hue is in degrees
Lightness is between 0 and 1
Saturation is between 0 and 1
*/
HSL RGB2HSL(COLOUR c1)
{
double themin,themax,delta;
HSL c2;
themin = MIN(c1.r,MIN(c1.g,c1.b));
themax = MAX(c1.r,MAX(c1.g,c1.b));
delta = themax - themin;
c2.l = (themin + themax) / 2;
c2.s = 0;
if (c2.l > 0 && c2.l < 1)
c2.s = delta / (c2.l < 0.5 ? (2*c2.l) : (2-2*c2.l));
c2.h = 0;
if (delta > 0) {
if (themax == c1.r && themax != c1.g)
c2.h += (c1.g - c1.b) / delta;
if (themax == c1.g && themax != c1.b)
c2.h += (2 + (c1.b - c1.r) / delta);
if (themax == c1.b && themax != c1.r)
c2.h += (4 + (c1.r - c1.g) / delta);
c2.h *= 60;
}
return(c2);
}
The HSV colour space has three coordinates: hue, saturation, and value
(sometimes called brightness) respectively.
This colour system is attributed to "Smith" around 1978 and used
to be called the hexcone colour model.
The hue is an angle from
0 to 360 degrees, typically 0 is red, 60 degrees yellow, 120 degrees
green, 180 degrees cyan, 240 degrees blue, and 300 degrees magenta.
Saturation typically ranges from 0 to 1 (sometimes 0 to 100%) and
defines how grey the colour is, 0 indicates grey and 1 is the pure
primary colour.
Value is similar to luminance except it also varies the colour
saturation.
If the colour space is represented
by disks of varying lightness then the hue and saturation are the
equivalent to polar coordinates (r,theta) of any point in the plane.
The disks on the right show this for various values.
C code to transform between RGB and HSV is given below
Reference:
Rogers, David F., "Procedural Elements for Computer Graphics,"
McGraw-Hill Book Company, New York, 1985, pp390-398.
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:
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 colour inside the triangle is to make the colour
whiter (i.e. desaturate it). Mathematically we do this by intersecting the
line joining the colour and the alignment white with the edges of the
triangle.
First define the line that goes through white and your colour implicitly:
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 colour
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
displays primaries and its white you can compute the linear transformation
easily.
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:
Application to image compression
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 represented 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.
Before
The above is the original image that is used as an example in what follows.
It was captured as a single from a digital movie camera.
After
The above is the image that results from a 1 byte Y channel and
4x4 subsampled Cr, Cc channels.
Y channel
First C channel (Cr)
Second C channel (Cb)
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
RGB -> CIE XYZitu (D65)
X = 0.431 R + 0.342 G + 0.178 B
Y = 0.222 R + 0.707 G + 0.071 B
Z = 0.020 R + 0.130 G + 0.939 B
CIE XYZitu (D65) -> RGB
R = 3.063 X - 1.393 Y - 0.476 Z
G = -0.969 X + 1.876 Y + 0.042 Z
B = 0.068 X - 0.229 Y + 1.069 Z
RGB -> CIE XYZrec601-1 (C illuminant)
X = 0.607 R + 0.174 G + 0.200 B
Y = 0.299 R + 0.587 G + 0.114 B
Z = 0.000 R + 0.066 G + 1.116 B
CIE XYZrec601-1 (C illuminant) -> RGB
R = 1.910 X - 0.532 Y - 0.288 Z
G = -0.985 X + 1.999 Y - 0.028 Z
B = 0.058 X - 0.118 Y + 0.898 Z
RGB -> CIE XYZccir709 (D65)
X = 0.412 R + 0.358 G + 0.180 B
Y = 0.213 R + 0.715 G + 0.072 B
Z = 0.019 R + 0.119 G + 0.950 B
CIE XYZccir709 (D65) -> RGB
R = 3.241 X - 1.537 Y - 0.499 Z
G = -0.969 X + 1.876 Y + 0.042 Z
B = 0.056 X - 0.204 Y + 1.057 Z
PAL television standard
RGB -> YUV
Y = 0.299 R + 0.587 G + 0.114 B
U = -0.147 R - 0.289 G + 0.436 B
V = 0.615 R - 0.515 G - 0.100 B
YUV -> RGB
R = Y + 0.000 U + 1.140 V
G = Y - 0.396 U - 0.581 V
B = Y + 2.029 U + 0.000 V
NTSC television standard
RGB -> YIQ
Y = 0.299 R + 0.587 G + 0.114 B
I = 0.596 R - 0.274 G - 0.322 B
Q = 0.212 R - 0.523 G + 0.311 B
YIQ -> RGB
R = Y + 0.956 I + 0.621 Q
G = Y - 0.272 I - 0.647 Q
B = Y - 1.105 I + 1.702 Q
References
Color Monitor Colorimetry.
SMPTE Recommended Practice RP 145-1987
CIE Colorimetry.
Official recommendations of the International Commission
on Illumination, Publication 15.2 1986
Effective Color Displays. Theory and Practice.
D. Travis, Academic Press, 1991. ISBN 0-12-697690-2
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 grey scale 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
red = green = blue = (v - vmin) / (vmax - vmin)
Colour
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.
General map
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 displays. 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.
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.
This is the standard blue to green to red colour map. The columns are the
index value followed by the red, green, blue values ranging from 0 (no
contribution) to 255 (full contribution).
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 interchangeably, 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
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 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
index = b * (n-1) * n * n + g * (n-1) * n + r * (n-1)
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
index = nint(r * (n-1)) + nint(g * (n-1)) * n + nint(b * (n-1)) * n * n
where nint(x) is the nearest integer to x.
Note
If an odd sampling is used then the colour table will have a sampling
of grey values (the diagonal of the colour cube where r = g = b)
Many colour tables are restricted to one byte for the index, that is,
up to 256 entries. It is common in these cases to use a 6x6x6 sampling
and fill in the remaining 40 colour table entries with red, blue, green,
and grey 10 sample ramps.
Strictly speaking the samples generated as above are not all equally
distributed, the 8 vertices of the colour cube are less likely than
colours along the 12 edges which in turn are less likely than points
lying near the 6 planes which are less likely that interior points.
The Macintosh 256 Colour Palette
The following shows the RGB value of each colour in the default
256 Macintosh palette. The first column is the index, column 2 to
4 are the RGB values in the range 0 to 65535, columns 5 to 7 are
the RGB values in the range of 0 to 1.
The palette is arranged as follows: there are 256 colours to allocate,
an even distribution of colours through the colour cube might be
desirable but 256 is not the cube of an integer. 6x6x6 is 216 and so
the first 216 colours are an equal 6x6x6 sampling of the colour cube.
This leaves 40 colours to allocate, this has been done by choosing a
ramp of 10 shades each for red, green, blue and grey.
The table
Index
Red
Green
Blue
Red
Green
Blue
0
65535
65535
65535
1
1
1
1
65535
65535
52428
1
1
0.8
2
65535
65535
39321
1
1
0.6
3
65535
65535
26214
1
1
0.4
4
65535
65535
13107
1
1
0.2
5
65535
65535
0
1
1
0
6
65535
52428
65535
1
0.8
1
7
65535
52428
52428
1
0.8
0.8
8
65535
52428
39321
1
0.8
0.6
9
65535
52428
26214
1
0.8
0.4
10
65535
52428
13107
1
0.8
0.2
11
65535
52428
0
1
0.8
0
12
65535
39321
65535
1
0.6
1
13
65535
39321
52428
1
0.6
0.8
14
65535
39321
39321
1
0.6
0.6
15
65535
39321
26214
1
0.6
0.4
16
65535
39321
13107
1
0.6
0.2
17
65535
39321
0
1
0.6
0
18
65535
26214
65535
1
0.4
1
19
65535
26214
52428
1
0.4
0.8
20
65535
26214
39321
1
0.4
0.6
21
65535
26214
26214
1
0.4
0.4
22
65535
26214
13107
1
0.4
0.2
23
65535
26214
0
1
0.4
0
24
65535
13107
65535
1
0.2
1
25
65535
13107
52428
1
0.2
0.8
26
65535
13107
39321
1
0.2
0.6
27
65535
13107
26214
1
0.2
0.4
28
65535
13107
13107
1
0.2
0.2
29
65535
13107
0
1
0.2
0
30
65535
0
65535
1
0
1
31
65535
0
52428
1
0
0.8
32
65535
0
39321
1
0
0.6
33
65535
0
26214
1
0
0.4
34
65535
0
13107
1
0
0.2
35
65535
0
0
1
0
0
36
52428
65535
65535
0.8
1
1
37
52428
65535
52428
0.8
1
0.8
38
52428
65535
39321
0.8
1
0.6
39
52428
65535
26214
0.8
1
0.4
40
52428
65535
13107
0.8
1
0.2
41
52428
65535
0
0.8
1
0
42
52428
52428
65535
0.8
0.8
1
43
52428
52428
52428
0.8
0.8
0.8
44
52428
52428
39321
0.8
0.8
0.6
45
52428
52428
26214
0.8
0.8
0.4
46
52428
52428
13107
0.8
0.8
0.2
47
52428
52428
0
0.8
0.8
0
48
52428
39321
65535
0.8
0.6
1
49
52428
39321
52428
0.8
0.6
0.8
50
52428
39321
39321
0.8
0.6
0.6
51
52428
39321
26214
0.8
0.6
0.4
52
52428
39321
13107
0.8
0.6
0.2
53
52428
39321
0
0.8
0.6
0
54
52428
26214
65535
0.8
0.4
1
55
52428
26214
52428
0.8
0.4
0.8
56
52428
26214
39321
0.8
0.4
0.6
57
52428
26214
26214
0.8
0.4
0.4
58
52428
26214
13107
0.8
0.4
0.2
59
52428
26214
0
0.8
0.4
0
60
52428
13107
65535
0.8
0.2
1
61
52428
13107
52428
0.8
0.2
0.8
62
52428
13107
39321
0.8
0.2
0.6
63
52428
13107
26214
0.8
0.2
0.4
64
52428
13107
13107
0.8
0.2
0.2
65
52428
13107
0
0.8
0.2
0
66
52428
0
65535
0.8
0
1
67
52428
0
52428
0.8
0
0.8
68
52428
0
39321
0.8
0
0.6
69
52428
0
26214
0.8
0
0.4
70
52428
0
13107
0.8
0
0.2
71
52428
0
0
0.8
0
0
72
39321
65535
65535
0.6
1
1
73
39321
65535
52428
0.6
1
0.8
74
39321
65535
39321
0.6
1
0.6
75
39321
65535
26214
0.6
1
0.4
76
39321
65535
13107
0.6
1
0.2
77
39321
65535
0
0.6
1
0
78
39321
52428
65535
0.6
0.8
1
79
39321
52428
52428
0.6
0.8
0.8
80
39321
52428
39321
0.6
0.8
0.6
81
39321
52428
26214
0.6
0.8
0.4
82
39321
52428
13107
0.6
0.8
0.2
83
39321
52428
0
0.6
0.8
0
84
39321
39321
65535
0.6
0.6
1
85
39321
39321
52428
0.6
0.6
0.8
86
39321
39321
39321
0.6
0.6
0.6
87
39321
39321
26214
0.6
0.6
0.4
88
39321
39321
13107
0.6
0.6
0.2
89
39321
39321
0
0.6
0.6
0
90
39321
26214
65535
0.6
0.4
1
91
39321
26214
52428
0.6
0.4
0.8
92
39321
26214
39321
0.6
0.4
0.6
93
39321
26214
26214
0.6
0.4
0.4
94
39321
26214
13107
0.6
0.4
0.2
95
39321
26214
0
0.6
0.4
0
96
39321
13107
65535
0.6
0.2
1
97
39321
13107
52428
0.6
0.2
0.8
98
39321
13107
39321
0.6
0.2
0.6
99
39321
13107
26214
0.6
0.2
0.4
100
39321
13107
13107
0.6
0.2
0.2
101
39321
13107
0
0.6
0.2
0
102
39321
0
65535
0.6
0
1
103
39321
0
52428
0.6
0
0.8
104
39321
0
39321
0.6
0
0.6
105
39321
0
26214
0.6
0
0.4
106
39321
0
13107
0.6
0
0.2
107
39321
0
0
0.6
0
0
108
26214
65535
65535
0.4
1
1
109
26214
65535
52428
0.4
1
0.8
110
26214
65535
39321
0.4
1
0.6
111
26214
65535
26214
0.4
1
0.4
112
26214
65535
13107
0.4
1
0.2
113
26214
65535
0
0.4
1
0
114
26214
52428
65535
0.4
0.8
1
115
26214
52428
52428
0.4
0.8
0.8
116
26214
52428
39321
0.4
0.8
0.6
117
26214
52428
26214
0.4
0.8
0.4
118
26214
52428
13107
0.4
0.8
0.2
119
26214
52428
0
0.4
0.8
0
120
26214
39321
65535
0.4
0.6
1
121
26214
39321
52428
0.4
0.6
0.8
122
26214
39321
39321
0.4
0.6
0.6
123
26214
39321
26214
0.4
0.6
0.4
124
26214
39321
13107
0.4
0.6
0.2
125
26214
39321
0
0.4
0.6
0
126
26214
26214
65535
0.4
0.4
1
127
26214
26214
52428
0.4
0.4
0.8
128
26214
26214
39321
0.4
0.4
0.6
129
26214
26214
26214
0.4
0.4
0.4
130
26214
26214
13107
0.4
0.4
0.2
131
26214
26214
0
0.4
0.4
0
132
26214
13107
65535
0.4
0.2
1
133
26214
13107
52428
0.4
0.2
0.8
134
26214
13107
39321
0.4
0.2
0.6
135
26214
13107
26214
0.4
0.2
0.4
136
26214
13107
13107
0.4
0.2
0.2
137
26214
13107
0
0.4
0.2
0
138
26214
0
65535
0.4
0
1
139
26214
0
52428
0.4
0
0.8
140
26214
0
39321
0.4
0
0.6
141
26214
0
26214
0.4
0
0.4
142
26214
0
13107
0.4
0
0.2
143
26300
4265
486
0.401312
0.0650797
0.00741588
144
13107
65535
65535
0.2
1
1
145
13107
65535
52428
0.2
1
0.8
146
13107
65535
39321
0.2
1
0.6
147
13107
65535
26214
0.2
1
0.4
148
13107
65535
13107
0.2
1
0.2
149
13107
65535
0
0.2
1
0
150
13107
52428
65535
0.2
0.8
1
151
13107
52428
52428
0.2
0.8
0.8
152
13107
52428
39321
0.2
0.8
0.6
153
13107
52428
26214
0.2
0.8
0.4
154
13107
52428
13107
0.2
0.8
0.2
155
13107
52428
0
0.2
0.8
0
156
13107
39321
65535
0.2
0.6
1
157
13107
39321
52428
0.2
0.6
0.8
158
13107
39321
39321
0.2
0.6
0.6
159
13107
39321
26214
0.2
0.6
0.4
160
13107
39321
13107
0.2
0.6
0.2
161
13107
39321
0
0.2
0.6
0
162
13107
26214
65535
0.2
0.4
1
163
13107
26214
52428
0.2
0.4
0.8
164
13107
26214
39321
0.2
0.4
0.6
165
13107
26214
26214
0.2
0.4
0.4
166
13107
26214
13107
0.2
0.4
0.2
167
13107
26214
0
0.2
0.4
0
168
13107
13107
65535
0.2
0.2
1
169
13107
13107
52428
0.2
0.2
0.8
170
13107
13107
39321
0.2
0.2
0.6
171
13107
13107
26214
0.2
0.2
0.4
172
13107
13107
13107
0.2
0.2
0.2
173
15976
14457
2622
0.243778
0.2206
0.0400092
174
13107
0
65535
0.2
0
1
175
13107
0
52428
0.2
0
0.8
176
13107
0
39321
0.2
0
0.6
177
13107
0
26214
0.2
0
0.4
178
13107
0
13107
0.2
0
0.2
179
13107
0
0
0.2
0
0
180
0
65535
65535
0
1
1
181
0
65535
52428
0
1
0.8
182
0
65535
39321
0
1
0.6
183
0
65535
26214
0
1
0.4
184
0
65535
13107
0
1
0.2
185
0
65535
0
0
1
0
186
0
52428
65535
0
0.8
1
187
0
52428
52428
0
0.8
0.8
188
0
52428
39321
0
0.8
0.6
189
0
52428
26214
0
0.8
0.4
190
0
52428
13107
0
0.8
0.2
191
0
52428
0
0
0.8
0
192
0
40000
65535
0
0.610361
1
193
0
39321
52428
0
0.6
0.8
194
0
39321
39321
0
0.6
0.6
195
0
39321
26214
0
0.6
0.4
196
0
39321
13107
0
0.6
0.2
197
0
39321
0
0
0.6
0
198
0
26214
65535
0
0.4
1
199
0
26214
52428
0
0.4
0.8
200
0
26214
39321
0
0.4
0.6
201
0
26214
26214
0
0.4
0.4
202
0
26214
13107
0
0.4
0.2
203
0
26214
0
0
0.4
0
204
0
13107
65535
0
0.2
1
205
0
13107
52428
0
0.2
0.8
206
0
13107
39321
0
0.2
0.6
207
0
13107
26214
0
0.2
0.4
208
0
13107
13107
0
0.2
0.2
209
0
13107
0
0
0.2
0
210
0
0
65535
0
0
1
211
0
0
52428
0
0
0.8
212
0
0
39321
0
0
0.6
213
0
0
26214
0
0
0.4
214
0
0
13107
0
0
0.2
215
61183
2079
4938
0.933593
0.0317235
0.0753491
216
56797
0
0
0.866667
0
0
217
48059
0
0
0.733333
0
0
218
43690
0
0
0.666667
0
0
219
34952
0
0
0.533333
0
0
220
30583
0
0
0.466667
0
0
221
21845
0
0
0.333333
0
0
222
17476
0
0
0.266667
0
0
223
8738
0
0
0.133333
0
0
224
4369
0
0
0.0666667
0
0
225
0
61166
0
0
0.933333
0
226
0
56797
0
0
0.866667
0
227
0
48059
0
0
0.733333
0
228
0
43690
0
0
0.666667
0
229
0
34952
0
0
0.533333
0
230
0
30583
0
0
0.466667
0
231
0
21845
0
0
0.333333
0
232
0
17476
0
0
0.266667
0
233
0
8738
0
0
0.133333
0
234
0
4369
0
0
0.0666667
0
235
0
0
61166
0
0
0.933333
236
0
0
56797
0
0
0.866667
237
0
0
48059
0
0
0.733333
238
0
0
43690
0
0
0.666667
239
0
0
34952
0
0
0.533333
240
0
0
30583
0
0
0.466667
241
0
0
21845
0
0
0.333333
242
0
0
17476
0
0
0.266667
243
0
0
8738
0
0
0.133333
244
0
0
4369
0
0
0.0666667
245
61166
61166
61166
0.933333
0.933333
0.933333
246
56797
56797
56797
0.866667
0.866667
0.866667
247
48059
48059
48059
0.733333
0.733333
0.733333
248
43690
43690
43690
0.666667
0.666667
0.666667
249
34952
34952
34952
0.533333
0.533333
0.533333
250
30583
30583
30583
0.466667
0.466667
0.466667
251
21845
21845
21845
0.333333
0.333333
0.333333
252
17476
17476
17476
0.266667
0.266667
0.266667
253
8738
8738
8738
0.133333
0.133333
0.133333
254
4369
4369
4369
0.0666667
0.0666667
0.0666667
255
0
0
0
0
0
0
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.
Example 1
The following short piece of C will generate a blue to red ramp.
Of course this can be created manually in PhotoShop itself but this
example illustrates
the principle by which more complicated colour tables could be
automatically generated.
On the Macintosh the file creator will need to be set to 8BIM
and the file type to 8BCT
int main(int argc,char **argv)
{
int i;
for (i=0;i<256;i++) {
putchar(i);
putchar(0);
putchar(255-i);
}
}
Example 2
A circular red -> yellow -> green -> cyan -> blue -> magenta -> red
colour table file in hexadecimal and the map shown
visually in PhotoShop are illustrated below
Written by Paul Bourke
Original: February 1994. Updated Jan 1998.
Introduction
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
output luminance = beamstrength gamma
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 value
Most 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.
Converts to/from sRGB and LAB space
Presented as JavaScript, originally for Quartz Composer
Written by Paul Bourke
November 2018
The following present functions to convert to and from sRGB and LAB colour,
in both cases going through XYZ as an intermediate stage. While presented as
JavaScript, it does still uniquely define the transformations and should be
easy to transcribe into other languages. Note the XYZ mappings require a
reference illuminate white point, for example D65.
sRGB to XYZ
function (__structure xyzcolour) main(__number rgbcolour[4])
{
var result = new Object();
result.xyzcolour = new Array();
var R = new Object();
var g = new Object();
var B = new Object();
if (rgbcolour[0] > 0.04045 )
R = Math.pow( ( (rgbcolour[0] + 0.055 ) / 1.055 ),2.4);
else
R = rgbcolour[0] / 12.92;
if (rgbcolour[1] > 0.04045 )
G = Math.pow( ( (rgbcolour[1] + 0.055 ) / 1.055 ),2.4);
else
G = rgbcolour[1] / 12.92;
if (rgbcolour[2] > 0.04045 )
B = Math.pow( ( (rgbcolour[2] + 0.055 ) / 1.055 ),2.4);
else
B = rgbcolour[2] / 12.92;
R = R * 100;
G = G * 100;
B = B * 100;
result.xyzcolour[0] = R * 0.4124 + G * 0.3576 + B * 0.1805;
result.xyzcolour[1] = R * 0.2126 + G * 0.7152 + B * 0.0722;
result.xyzcolour[2] = R * 0.0193 + G * 0.1192 + B * 0.9505;
result.xyzcolour[3] = rgbcolour[3];
return result;
}
XYZ to LAB
function (__structure labcolour) main(__number xyzcolour[4],__number xyzref[3])
{
var result = new Object();
result.labcolour = new Array();
var X = new Object();
var Y = new Object();
var Z = new Object();
X = xyzcolour[0] / xyzref[0];
Y = xyzcolour[1] / xyzref[1];
Z = xyzcolour[2] / xyzref[2];
if ( X > 0.008856 )
X = Math.pow( X , 1/3.0 );
else
X = ( 903.3 * X + 16.0 ) / 116.0;
if ( Y > 0.008856 )
Y = Math.pow( Y, 1/3.0 );
else
Y = ( 903.3 * Y + 16.0) / 116.0;
if ( Z > 0.008856 )
Z = Math.pow( Z, 1/3.0 );
else
Z = ( 903.3 * Z + 16.0) / 116.0;
result.labcolour[0] = ( 116 * Y ) - 16;
result.labcolour[1] = 500 * ( X - Y );
result.labcolour[2] = 200 * ( Y - Z );
result.labcolour[3] = xyzcolour[3];
return result;
}
LAB to XYZ
function (__structure xyzcolour) main(__number labcolour[4],__number xyzref[3])
{
var result = new Object();
result.xyzcolour = new Array();
var X = new Object();
var Y = new Object();
var Z = new Object();
Y = (labcolour[0] + 16.0) / 116.0;
X = labcolour[1] / 500.0 + Y;
Z = Y - labcolour[2] / 200.0;
Y = Adjust(Y);
X = Adjust(X);
Z = Adjust(Z);
result.xyzcolour[0] = X * xyzref[0];
result.xyzcolour[1] = Y * xyzref[1];
result.xyzcolour[2] = Z * xyzref[2];
result.xyzcolour[3] = labcolour[3];
return result;
}
function Adjust(a) {
if (Math.pow(a,3.0) > 0.008856)
return(Math.pow(a,3.0));
else
return((a - 16.0/116.0) / 7.787);
}
XYZ to sRGB
function (__structure rgbcolour) main(__number xyzcolour[4])
{
var result = new Object();
result.rgbcolour = new Array();
var R = new Object();
var G = new Object();
var B = new Object();
var X = new Object();
var Y = new Object();
var Z = new Object();
X = xyzcolour[0] / 100.0;
Y = xyzcolour[1] / 100.0;
Z = xyzcolour[2] / 100.0;
R = X * 3.2406 + Y * (-1.5372) + Z * (-0.4986);
G = X * (-0.9689) + Y * 1.8758 + Z * 0.0415;
B = X * 0.0557 + Y * (-0.2040) + Z * 1.0570;
R = Adjust(R);
G = Adjust(G);
B = Adjust(B);
R = Clip(R);
G = Clip(G);
B = Clip(B);
result.rgbcolour[0] = R * 255.0;
result.rgbcolour[1] = G * 255.0;
result.rgbcolour[2] = B * 255.0;
result.rgbcolour[3] = xyzcolour[3];
return result;
}
function Adjust(a) {
if (a > 0.0031308)
return(1.055*Math.pow(a,1.0/2.4)-0.055);
else
return(12.92*a);
}
function Clip(a) {
if (a > 1)
return(1);
else if (a < 0)
return(0);
else
return(a);
}