следующий фpагмент (2)  Usenet echoes (21:200/1)  COMP.GRAPHICS.ALGORITHMS 
Msg : 3 of 175
From : hollasch@acm.org 2:5030/315 07 Nov 95 04:51:14
To : All 11 Nov 95 06:23:00
Subj : Re: HELP:to transform RGB triplet to a spectrum

XRealName: Steve Hollasch
bp@labri.ubordeaux.fr (Brigitte Proutiere [Achille]):
( In order to complete my software development, I'm looking for a algorithm
( or a c code to tranform a RGB triplet to an spectrum.
I'm quoting from an article posted 18 Nov 1991, by Chris Schoenenman:

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 occured 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 (i.e. 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. Just check reference [1] or if you can't get it,
just say so and I'll give you the equations. [1] also gives code to
transform RGB to HSV and back.
Rogers, David F., "Procedural Elements for Computer Graphics,"
McGrawHill Book Company, New York, 1985, pp390398.
/*
* 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}};

Steve <hollasch@acm.org>
Всего 1 фpагмент(а/ов) пpедыдущий фpагмент (1)
