RGB to/from CMY
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 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
 = 


HSL colour spaceHue  Saturation  LightnessWritten by Paul BourkeJune 2000
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) : (22*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); } /* Calculate RGB from HSL, reverse of RGB2HSL() Hue is in degrees Lightness is between 0 and 1 Saturation is between 0 and 1 */ COLOUR HSL2RGB(HSL c1) { COLOUR c2,sat,ctmp; while (c1.h < 0) c1.h += 360; while (c1.h > 360) c1.h = 360; if (c1.h < 120) { sat.r = (120  c1.h) / 60.0; sat.g = c1.h / 60.0; sat.b = 0; } else if (c1.h < 240) { sat.r = 0; sat.g = (240  c1.h) / 60.0; sat.b = (c1.h  120) / 60.0; } else { sat.r = (c1.h  240) / 60.0; sat.g = 0; sat.b = (360  c1.h) / 60.0; } sat.r = MIN(sat.r,1); sat.g = MIN(sat.g,1); sat.b = MIN(sat.b,1); ctmp.r = 2 * c1.s * sat.r + (1  c1.s); ctmp.g = 2 * c1.s * sat.g + (1  c1.s); ctmp.b = 2 * c1.s * sat.b + (1  c1.s); if (c1.l < 0.5) { c2.r = c1.l * ctmp.r; c2.g = c1.l * ctmp.g; c2.b = c1.l * ctmp.b; } else { c2.r = (1  c1.l) * ctmp.r + 2 * c1.l  1; c2.g = (1  c1.l) * ctmp.g + 2 * c1.l  1; c2.b = (1  c1.l) * ctmp.b + 2 * c1.l  1; } return(c2); }  Lightness=0.0

HSV colour spaceHue  Saturation  ValueWritten by Paul BourkeJune 2000
The HSV colour space has three coordinates: hue, saturation, and value (sometimes called brighness) 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 luninance 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 /* Calculate RGB from HSV, reverse of RGB2HSV() Hue is in degrees Lightness is between 0 and 1 Saturation is between 0 and 1 */ COLOUR HSV2RGB(HSV c1) { COLOUR c2,sat; while (c1.h < 0) c1.h += 360; while (c1.h > 360) c1.h = 360; if (c1.h < 120) { sat.r = (120  c1.h) / 60.0; sat.g = c1.h / 60.0; sat.b = 0; } else if (c1.h < 240) { sat.r = 0; sat.g = (240  c1.h) / 60.0; sat.b = (c1.h  120) / 60.0; } else { sat.r = (c1.h  240) / 60.0; sat.g = 0; sat.b = (360  c1.h) / 60.0; } sat.r = MIN(sat.r,1); sat.g = MIN(sat.g,1); sat.b = MIN(sat.b,1); c2.r = (1  c1.s + c1.s * sat.r) * c1.v; c2.g = (1  c1.s + c1.s * sat.g) * c1.v; c2.b = (1  c1.s + c1.s * sat.b) * c1.v; return(c2); } /* Calculate HSV from RGB Hue is in degrees Lightness is betweeen 0 and 1 Saturation is between 0 and 1 */ HSV RGB2HSV(COLOUR c1) { double themin,themax,delta; HSV c2; themin = MIN(c1.r,MIN(c1.g,c1.b)); themax = MAX(c1.r,MAX(c1.g,c1.b)); delta = themax  themin; c2.v = themax; c2.s = 0; if (themax > 0) c2.s = delta / themax; 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); }  Value=0.0

Reference: Rogers, David F., "Procedural Elements for Computer Graphics,"
McGrawHill Book Company, New York, 1985, pp390398.
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 wingshaped 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}};
评论