ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/common/spec_rgb.c
Revision: 2.7
Committed: Thu Jan 30 19:14:39 1997 UTC (27 years, 3 months ago) by greg
Content type: text/plain
Branch: MAIN
Changes since 2.6: +8 -5 lines
Log Message:
changed colortrans() to optionally allow negative results

File Contents

# Content
1 /* Copyright (c) 1997 Regents of the University of California */
2
3 #ifndef lint
4 static char SCCSid[] = "$SunId$ LBL";
5 #endif
6
7 /*
8 * Convert colors and spectral ranges.
9 */
10
11 #include "color.h"
12
13
14 RGBPRIMS stdprims = STDPRIMS; /* standard primary chromaticities */
15
16 /*
17 * The following table contains the CIE tristimulus integrals
18 * for X, Y, and Z. The table is cumulative, so that
19 * each color coordinate integrates to 1.
20 */
21
22 #define STARTWL 380 /* starting wavelength (nanometers) */
23 #define INCWL 10 /* wavelength increment */
24 #define NINC 40 /* # of values */
25
26 static BYTE chroma[3][NINC] = {
27 { /* X */
28 0, 0, 0, 2, 6, 13, 22, 30, 36, 41,
29 42, 43, 43, 44, 46, 52, 60, 71, 87, 106,
30 128, 153, 178, 200, 219, 233, 243, 249, 252, 254,
31 255, 255, 255, 255, 255, 255, 255, 255, 255, 255
32 }, { /* Y */
33 0, 0, 0, 0, 0, 1, 2, 4, 7, 11,
34 17, 24, 34, 48, 64, 84, 105, 127, 148, 169,
35 188, 205, 220, 232, 240, 246, 250, 253, 254, 255,
36 255, 255, 255, 255, 255, 255, 255, 255, 255, 255
37 }, { /* Z */
38 0, 0, 2, 10, 32, 66, 118, 153, 191, 220,
39 237, 246, 251, 253, 254, 255, 255, 255, 255, 255,
40 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
41 255, 255, 255, 255, 255, 255, 255, 255, 255, 255
42 }
43 };
44
45 COLORMAT xyz2rgbmat = { /* XYZ to RGB */
46 {(CIE_y_g - CIE_y_b - CIE_x_b*CIE_y_g + CIE_y_b*CIE_x_g)/CIE_C_rD,
47 (CIE_x_b - CIE_x_g - CIE_x_b*CIE_y_g + CIE_x_g*CIE_y_b)/CIE_C_rD,
48 (CIE_x_g*CIE_y_b - CIE_x_b*CIE_y_g)/CIE_C_rD},
49 {(CIE_y_b - CIE_y_r - CIE_y_b*CIE_x_r + CIE_y_r*CIE_x_b)/CIE_C_gD,
50 (CIE_x_r - CIE_x_b - CIE_x_r*CIE_y_b + CIE_x_b*CIE_y_r)/CIE_C_gD,
51 (CIE_x_b*CIE_y_r - CIE_x_r*CIE_y_b)/CIE_C_gD},
52 {(CIE_y_r - CIE_y_g - CIE_y_r*CIE_x_g + CIE_y_g*CIE_x_r)/CIE_C_bD,
53 (CIE_x_g - CIE_x_r - CIE_x_g*CIE_y_r + CIE_x_r*CIE_y_g)/CIE_C_bD,
54 (CIE_x_r*CIE_y_g - CIE_x_g*CIE_y_r)/CIE_C_bD}
55 };
56
57 COLORMAT rgb2xyzmat = { /* RGB to XYZ */
58 {CIE_x_r*CIE_C_rD/CIE_D,CIE_x_g*CIE_C_gD/CIE_D,CIE_x_b*CIE_C_bD/CIE_D},
59 {CIE_y_r*CIE_C_rD/CIE_D,CIE_y_g*CIE_C_gD/CIE_D,CIE_y_b*CIE_C_bD/CIE_D},
60 {(1.-CIE_x_r-CIE_y_r)*CIE_C_rD/CIE_D,
61 (1.-CIE_x_g-CIE_y_g)*CIE_C_gD/CIE_D,
62 (1.-CIE_x_b-CIE_y_b)*CIE_C_bD/CIE_D}
63 };
64
65
66
67 spec_rgb(col, s, e) /* compute RGB color from spectral range */
68 COLOR col;
69 int s, e;
70 {
71 COLOR ciecolor;
72
73 spec_cie(ciecolor, s, e);
74 cie_rgb(col, ciecolor);
75 }
76
77
78 spec_cie(col, s, e) /* compute a color from a spectral range */
79 COLOR col; /* returned color */
80 int s, e; /* starting and ending wavelengths */
81 {
82 register int i, d, r;
83
84 s -= STARTWL;
85 if (s < 0)
86 s = 0;
87
88 e -= STARTWL;
89 if (e <= s) {
90 col[CIEX] = col[CIEY] = col[CIEZ] = 0.0;
91 return;
92 }
93 if (e >= INCWL*(NINC - 1))
94 e = INCWL*(NINC - 1) - 1;
95
96 d = e / INCWL; /* interpolate values */
97 r = e % INCWL;
98 for (i = 0; i < 3; i++)
99 col[i] = chroma[i][d]*(INCWL - r) + chroma[i][d + 1]*r;
100
101 d = s / INCWL;
102 r = s % INCWL;
103 for (i = 0; i < 3; i++)
104 col[i] -= chroma[i][d]*(INCWL - r) - chroma[i][d + 1]*r;
105
106 col[CIEX] = (col[CIEX] + 0.5) * (1./(256*INCWL));
107 col[CIEY] = (col[CIEY] + 0.5) * (1./(256*INCWL));
108 col[CIEZ] = (col[CIEZ] + 0.5) * (1./(256*INCWL));
109 }
110
111
112 colortrans(c2, mat, c1, noneg) /* convert c1 by mat and put into c2 */
113 register COLORMAT mat;
114 register COLOR c1, c2;
115 int noneg;
116 {
117 static float cout[3];
118
119 cout[0] = mat[0][0]*c1[0] + mat[0][1]*c1[1] + mat[0][2]*c1[2];
120 cout[1] = mat[1][0]*c1[0] + mat[1][1]*c1[1] + mat[1][2]*c1[2];
121 cout[2] = mat[2][0]*c1[0] + mat[2][1]*c1[1] + mat[2][2]*c1[2];
122 if (!noneg)
123 return;
124 if ((c2[0] = cout[0]) < 0.) c2[0] = 0.;
125 if ((c2[1] = cout[1]) < 0.) c2[1] = 0.;
126 if ((c2[2] = cout[2]) < 0.) c2[2] = 0.;
127 }
128
129
130 multcolormat(m3, m2, m1) /* multiply m1 by m2 and put into m3 */
131 COLORMAT m1, m2, m3; /* m3 can be either m1 or m2 w/o harm */
132 {
133 COLORMAT mt;
134 register int i, j;
135
136 for (i = 0; i < 3; i++)
137 for (j = 0; j < 3; j++)
138 mt[i][j] = m1[i][0]*m2[0][j] +
139 m1[i][1]*m2[1][j] +
140 m1[i][2]*m2[2][j] ;
141 cpcolormat(m3, mt);
142 }
143
144
145 compxyz2rgbmat(mat, pr) /* compute conversion from CIE to RGB space */
146 COLORMAT mat;
147 register RGBPRIMS pr;
148 {
149 double C_rD, C_gD, C_bD;
150
151 if (pr == stdprims) { /* can use xyz2rgbmat */
152 cpcolormat(mat, xyz2rgbmat);
153 return;
154 }
155 C_rD = (1./pr[WHT][CIEY]) *
156 ( pr[WHT][CIEX]*(pr[GRN][CIEY] - pr[BLU][CIEY]) -
157 pr[WHT][CIEY]*(pr[GRN][CIEX] - pr[BLU][CIEX]) +
158 pr[GRN][CIEX]*pr[BLU][CIEY] - pr[BLU][CIEX]*pr[GRN][CIEY] ) ;
159 C_gD = (1./pr[WHT][CIEY]) *
160 ( pr[WHT][CIEX]*(pr[BLU][CIEY] - pr[RED][CIEY]) -
161 pr[WHT][CIEY]*(pr[BLU][CIEX] - pr[RED][CIEX]) -
162 pr[RED][CIEX]*pr[BLU][CIEY] + pr[BLU][CIEX]*pr[RED][CIEY] ) ;
163 C_bD = (1./pr[WHT][CIEY]) *
164 ( pr[WHT][CIEX]*(pr[RED][CIEY] - pr[GRN][CIEY]) -
165 pr[WHT][CIEY]*(pr[RED][CIEX] - pr[GRN][CIEX]) +
166 pr[RED][CIEX]*pr[GRN][CIEY] - pr[GRN][CIEX]*pr[RED][CIEY] ) ;
167
168 mat[0][0] = (pr[GRN][CIEY] - pr[BLU][CIEY] -
169 pr[BLU][CIEX]*pr[GRN][CIEY] +
170 pr[BLU][CIEY]*pr[GRN][CIEX])/C_rD ;
171 mat[0][1] = (pr[BLU][CIEX] - pr[GRN][CIEX] -
172 pr[BLU][CIEX]*pr[GRN][CIEY] +
173 pr[GRN][CIEX]*pr[BLU][CIEY])/C_rD ;
174 mat[0][2] = (pr[GRN][CIEX]*pr[BLU][CIEY] -
175 pr[BLU][CIEX]*pr[GRN][CIEY])/C_rD ;
176 mat[1][0] = (pr[BLU][CIEY] - pr[RED][CIEY] -
177 pr[BLU][CIEY]*pr[RED][CIEX] +
178 pr[RED][CIEY]*pr[BLU][CIEX])/C_gD ;
179 mat[1][1] = (pr[RED][CIEX] - pr[BLU][CIEX] -
180 pr[RED][CIEX]*pr[BLU][CIEY] +
181 pr[BLU][CIEX]*pr[RED][CIEY])/C_gD ;
182 mat[1][2] = (pr[BLU][CIEX]*pr[RED][CIEY] -
183 pr[RED][CIEX]*pr[BLU][CIEY])/C_gD ;
184 mat[2][0] = (pr[RED][CIEY] - pr[GRN][CIEY] -
185 pr[RED][CIEY]*pr[GRN][CIEX] +
186 pr[GRN][CIEY]*pr[RED][CIEX])/C_bD ;
187 mat[2][1] = (pr[GRN][CIEX] - pr[RED][CIEX] -
188 pr[GRN][CIEX]*pr[RED][CIEY] +
189 pr[RED][CIEX]*pr[GRN][CIEY])/C_bD ;
190 mat[2][2] = (pr[RED][CIEX]*pr[GRN][CIEY] -
191 pr[GRN][CIEX]*pr[RED][CIEY])/C_bD ;
192 }
193
194
195 comprgb2xyzmat(mat, pr) /* compute conversion from RGB to CIE space */
196 COLORMAT mat;
197 register RGBPRIMS pr;
198 {
199 double C_rD, C_gD, C_bD, D;
200
201 if (pr == stdprims) { /* can use rgb2xyzmat */
202 cpcolormat(mat, rgb2xyzmat);
203 return;
204 }
205 C_rD = (1./pr[WHT][CIEY]) *
206 ( pr[WHT][CIEX]*(pr[GRN][CIEY] - pr[BLU][CIEY]) -
207 pr[WHT][CIEY]*(pr[GRN][CIEX] - pr[BLU][CIEX]) +
208 pr[GRN][CIEX]*pr[BLU][CIEY] - pr[BLU][CIEX]*pr[GRN][CIEY] ) ;
209 C_gD = (1./pr[WHT][CIEY]) *
210 ( pr[WHT][CIEX]*(pr[BLU][CIEY] - pr[RED][CIEY]) -
211 pr[WHT][CIEY]*(pr[BLU][CIEX] - pr[RED][CIEX]) -
212 pr[RED][CIEX]*pr[BLU][CIEY] + pr[BLU][CIEX]*pr[RED][CIEY] ) ;
213 C_bD = (1./pr[WHT][CIEY]) *
214 ( pr[WHT][CIEX]*(pr[RED][CIEY] - pr[GRN][CIEY]) -
215 pr[WHT][CIEY]*(pr[RED][CIEX] - pr[GRN][CIEX]) +
216 pr[RED][CIEX]*pr[GRN][CIEY] - pr[GRN][CIEX]*pr[RED][CIEY] ) ;
217 D = pr[RED][CIEX]*(pr[GRN][CIEY] - pr[BLU][CIEY]) +
218 pr[GRN][CIEX]*(pr[BLU][CIEY] - pr[RED][CIEY]) +
219 pr[BLU][CIEX]*(pr[RED][CIEY] - pr[GRN][CIEY]) ;
220 mat[0][0] = pr[RED][CIEX]*C_rD/D;
221 mat[0][1] = pr[GRN][CIEX]*C_gD/D;
222 mat[0][2] = pr[BLU][CIEX]*C_bD/D;
223 mat[1][0] = pr[RED][CIEY]*C_rD/D;
224 mat[1][1] = pr[GRN][CIEY]*C_gD/D;
225 mat[1][2] = pr[BLU][CIEY]*C_bD/D;
226 mat[2][0] = (1.-pr[RED][CIEX]-pr[RED][CIEY])*C_rD/D;
227 mat[2][1] = (1.-pr[GRN][CIEX]-pr[GRN][CIEY])*C_gD/D;
228 mat[2][2] = (1.-pr[BLU][CIEX]-pr[BLU][CIEY])*C_bD/D;
229 }
230
231
232 comprgb2rgbmat(mat, pr1, pr2) /* compute conversion from RGB1 to RGB2 */
233 COLORMAT mat;
234 RGBPRIMS pr1, pr2;
235 {
236 COLORMAT pr1toxyz, xyztopr2;
237
238 if (pr1 == pr2) {
239 mat[0][0] = mat[1][1] = mat[2][2] = 1.0;
240 mat[0][1] = mat[0][2] = mat[1][0] =
241 mat[1][2] = mat[2][0] = mat[2][1] = 0.0;
242 return;
243 }
244 comprgb2xyzmat(pr1toxyz, pr1);
245 compxyz2rgbmat(xyztopr2, pr2);
246 /* combine transforms */
247 multcolormat(mat, pr1toxyz, xyztopr2);
248 }