ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/common/color.h
Revision: 2.45
Committed: Wed Jan 17 17:36:20 2024 UTC (3 months, 1 week ago) by greg
Content type: text/plain
Branch: MAIN
CVS Tags: HEAD
Changes since 2.44: +6 -3 lines
Log Message:
feat: Added convertscolorcol() to generate better RGB result

File Contents

# Content
1 /* RCSid $Id: color.h,v 2.44 2023/12/16 01:00:02 greg Exp $ */
2 /*
3 * color.h - header for routines using pixel color and spectral values
4 *
5 * Two color representations are used, one for calculation and
6 * another for storage. Calculation is done with three floats
7 * for speed. Stored color values use 4 bytes which contain
8 * three single byte mantissas and a common exponent.
9 *
10 * Spectral colors have between 3 and MAXCSAMP samples, and cover
11 * wavelengths from WLPART[0] to WLPART[3] (max to min nanometers).
12 * Wavelengths WLPART[1] and WLPART[2] mark the separation
13 * of red/green and green/blue intervals, respectively.
14 * The wavelength range may go well beyond visible in either
15 * direction, but some routines will average over each interval
16 * and designate the means as R, G, and B, regardless.
17 * The number of samples is set in CNDX[3], and CNDX[0,1,2]
18 * give peak wavelength indices corresponding to stdprims.
19 * For best accuracy, internal calculations are promoted to
20 * the current number of samples and final conversions
21 * to tristimulus should use scolor_rgb() or scolor_cie().
22 *
23 * A new Radiance format is provided for spectral pictures,
24 * and spectral colors must be converted by caller if the
25 * sampling doesn't match.
26 */
27 #ifndef _RAD_COLOR_H_
28 #define _RAD_COLOR_H_
29
30 #include <stdio.h>
31 #include <stdlib.h>
32 #include <string.h>
33
34 #ifdef __cplusplus
35 extern "C" {
36 #endif
37
38 #ifndef MAXCSAMP
39 #define MAXCSAMP 24 /* maximum # spectral samples */
40 #endif
41
42 #define RED 0
43 #define GRN 1
44 #define BLU 2
45 #define CIEX 0 /* or, if input is XYZ... */
46 #define CIEY 1
47 #define CIEZ 2
48 #define EXP 3 /* exponent same for either format */
49 #define COLXS 128 /* excess used for exponent */
50 #define WHT 3 /* used for RGBPRIMS type */
51
52 #undef uby8
53 #define uby8 unsigned char /* 8-bit unsigned integer */
54
55 typedef uby8 COLR[4]; /* red, green, blue (or X,Y,Z), exponent */
56 typedef uby8 SCOLR[MAXCSAMP+1]; /* spectral color, common exponent */
57
58 typedef float COLORV;
59 typedef COLORV COLOR[3]; /* red, green, blue (or X,Y,Z) */
60 typedef COLORV SCOLOR[MAXCSAMP]; /* spectral color */
61
62 typedef float RGBPRIMS[4][2]; /* (x,y) chromaticities for RGBW */
63 typedef float (*RGBPRIMP)[2]; /* pointer to RGBPRIMS array */
64
65 typedef float COLORMAT[3][3]; /* color coordinate conversion matrix */
66
67 #define copycolr(c1,c2) (c1[0]=c2[0],c1[1]=c2[1], \
68 c1[2]=c2[2],c1[3]=c2[3])
69
70 #define colval(col,pri) (col)[pri]
71
72 #define setcolor(col,r,g,b) ((col)[RED]=(r),(col)[GRN]=(g),(col)[BLU]=(b))
73
74 #define scalecolor(col,sf) ((col)[0]*=(sf),(col)[1]*=(sf),(col)[2]*=(sf))
75
76 #define opcolor(c1,op,c2) ((c1)[0]op(c2)[0],(c1)[1]op(c2)[1],(c1)[2]op(c2)[2])
77
78 #define copycolor(c1,c2) opcolor(c1,=,c2)
79
80 #define addcolor(c1,c2) opcolor(c1,+=,c2)
81
82 #define multcolor(c1,c2) opcolor(c1,*=,c2)
83
84 #define NCSAMP CNDX[EXP] /* current number of spectral samples */
85 #define LSCOLR (NCSAMP+1)
86
87 #define copyscolr(sc1,sc2) memcpy(sc1,sc2,LSCOLR)
88
89 #define scolval(sc,pri) (sc)[CNDX[pri]]
90
91 #define copyscolor(sc1,sc2) memcpy(sc1,sc2,sizeof(COLORV)*NCSAMP)
92
93 #define scalescolor(sc,sf) {const float _f=sf; int _i=NCSAMP; \
94 while (_i--) (sc)[_i] *= _f;}
95
96 /* faster, use principal colors for RGB */
97 #define pcolor_color(col,scol) setcolor(col,scolval(scol,RED),\
98 scolval(scol,GRN),scolval(scol,BLU))
99 #define pcolor_colr(clr,scol) setcolr(clr,scolval(scol,RED),\
100 scolval(scol,GRN),scolval(scol,BLU))
101
102 #define sopscolor(sc1,op,sc2) {int _i=NCSAMP; while (_i--) (sc1)[_i] op (sc2)[_i];}
103
104 #define saddscolor(sc1,sc2) sopscolor(sc1,+=,sc2)
105
106 #define smultscolor(sc1,sc2) sopscolor(sc1,*=,sc2)
107
108 #define scolrblack(c) memset(c,0,LSCOLR)
109
110 #define scolorblack(c) memset(c,0,sizeof(COLORV)*NCSAMP)
111
112 #define scolor_color(col,scol) scolor2color(col,scol,NCSAMP,WLPART)
113 #define scolor_colr(clr,scol) scolor2colr(clr,scol,NCSAMP,WLPART)
114 #define scolor_scolr(sclr,scol) scolor2scolr(sclr,scol,NCSAMP)
115 #define scolr_scolor(scol,sclr) scolr2scolor(scol,sclr,NCSAMP)
116 #define scolr_color(col,sclr) scolr2color(col,sclr,NCSAMP,WLPART)
117
118 #define sopcolor(sc1,op,c2) {SCOLOR _sct;\
119 setscolor(_sct,(c2)[RED],(c2)[GRN],(c2)[BLU]);\
120 sopscolor(sc1,op,_sct);}
121
122 #define saddcolor(sc1,c2) sopcolor(sc1,+=,c2)
123
124 #define smultcolor(sc1,c2) sopcolor(sc1,*=,c2)
125
126 #define opscolor(c1,op,sc2) {COLOR _ct; scolor_color(_ct,sc2);\
127 opcolor(c1,op,_ct);}
128
129 #define addscolor(c1,sc2) opscolor(c1,+=,sc2)
130
131 #define multscolor(c1,sc2) opscolor(c1,*=,sc2)
132
133 #if defined(NTSC_RGB)
134 #define CIE_x_r 0.670 /* standard NTSC primaries */
135 #define CIE_y_r 0.330
136 #define CIE_x_g 0.210
137 #define CIE_y_g 0.710
138 #define CIE_x_b 0.140
139 #define CIE_y_b 0.080
140 #define CIE_x_w (1./3.) /* use EE white */
141 #define CIE_y_w (1./3.)
142 #elif defined(SHARP_RGB)
143 #define CIE_x_r 0.6898 /* "sharp" RGB primaries */
144 #define CIE_y_r 0.3206
145 #define CIE_x_g 0.0736
146 #define CIE_y_g 0.9003
147 #define CIE_x_b 0.1166
148 #define CIE_y_b 0.0374
149 #define CIE_x_w (1./3.) /* use EE white */
150 #define CIE_y_w (1./3.)
151 #else
152 #define CIE_x_r 0.640 /* nominal CRT primaries */
153 #define CIE_y_r 0.330
154 #define CIE_x_g 0.290
155 #define CIE_y_g 0.600
156 #define CIE_x_b 0.150
157 #define CIE_y_b 0.060
158 #define CIE_x_w (1./3.) /* use EE white */
159 #define CIE_y_w (1./3.)
160 #endif
161
162 #define STDPRIMS {{CIE_x_r,CIE_y_r},{CIE_x_g,CIE_y_g}, \
163 {CIE_x_b,CIE_y_b},{CIE_x_w,CIE_y_w}}
164
165 #define CIE_D ( CIE_x_r*(CIE_y_g - CIE_y_b) + \
166 CIE_x_g*(CIE_y_b - CIE_y_r) + \
167 CIE_x_b*(CIE_y_r - CIE_y_g) )
168 #define CIE_C_rD ( (1./CIE_y_w) * \
169 ( CIE_x_w*(CIE_y_g - CIE_y_b) - \
170 CIE_y_w*(CIE_x_g - CIE_x_b) + \
171 CIE_x_g*CIE_y_b - CIE_x_b*CIE_y_g ) )
172 #define CIE_C_gD ( (1./CIE_y_w) * \
173 ( CIE_x_w*(CIE_y_b - CIE_y_r) - \
174 CIE_y_w*(CIE_x_b - CIE_x_r) - \
175 CIE_x_r*CIE_y_b + CIE_x_b*CIE_y_r ) )
176 #define CIE_C_bD ( (1./CIE_y_w) * \
177 ( CIE_x_w*(CIE_y_r - CIE_y_g) - \
178 CIE_y_w*(CIE_x_r - CIE_x_g) + \
179 CIE_x_r*CIE_y_g - CIE_x_g*CIE_y_r ) )
180
181 #define CIE_rf (CIE_y_r*CIE_C_rD/CIE_D)
182 #define CIE_gf (CIE_y_g*CIE_C_gD/CIE_D)
183 #define CIE_bf (CIE_y_b*CIE_C_bD/CIE_D)
184
185 /* Default CIE_rf=.265074126, CIE_gf=.670114631 and CIE_bf=.064811243 */
186
187 /***** The following definitions are not for XYZ colors *****/
188
189 #define bright(col) (CIE_rf*(col)[RED]+CIE_gf*(col)[GRN]+CIE_bf*(col)[BLU])
190 #define pbright(col) (CIE_rf*scolval(col,RED) + CIE_gf*scolval(col,GRN) + \
191 CIE_bf*scolval(col,BLU))
192 #define normbright(c) ( ( (long)(CIE_rf*256.+.5)*(c)[RED] + \
193 (long)(CIE_gf*256.+.5)*(c)[GRN] + \
194 (long)(CIE_bf*256.+.5)*(c)[BLU] ) >> 8 )
195 #define normpbright(c) ( ( (long)(CIE_rf*256.+.5)*(c)[CNDX[RED]] + \
196 (long)(CIE_gf*256.+.5)*(c)[CNDX[GRN]] + \
197 (long)(CIE_bf*256.+.5)*(c)[CNDX[BLU]] ) >> 8 )
198
199 /* luminous efficacies over visible spectrum */
200 #define MAXEFFICACY 683. /* defined maximum at 550 nm */
201 #define WHTEFFICACY 179. /* equal energy white 380-780nm */
202 #define D65EFFICACY 203. /* standard illuminant D65 */
203 #define INCEFFICACY 160. /* illuminant A (incand.) */
204 #define SUNEFFICACY 208. /* illuminant B (solar dir.) */
205 #define SKYEFFICACY D65EFFICACY /* skylight (should be 110) */
206 #define DAYEFFICACY D65EFFICACY /* combined sky and solar */
207 #define WHTSCOTOPIC 412. /* scotopic EE white 380-780nm */
208 #define WHTMELANOPIC 179. /* melanopic EE white 380-780nm */
209
210 #define luminance(col) (WHTEFFICACY * bright(col))
211 #define pluminance(scol) (WHTEFFICACY * pbright(scol))
212
213 #define scolor_rgb(col,scol) scolor2rgb(col,scol,NCSAMP,WLPART)
214
215 /***** ...end of stuff specific to RGB colors *****/
216
217 #define scolor_cie(col,scol) scolor2cie(col,scol,NCSAMP,WLPART)
218
219 #define sluminance(scol) (WHTEFFICACY * scolor_photopic(scol))
220
221 #define intens(col) ( (col)[0] > (col)[1] \
222 ? (col)[0] > (col)[2] ? (col)[0] : (col)[2] \
223 : (col)[1] > (col)[2] ? (col)[1] : (col)[2] )
224
225 #define colrval(c,p) ( (c)[EXP] ? \
226 ldexp((c)[p]+.5,(int)(c)[EXP]-(COLXS+8)) : \
227 0. )
228
229 #define scolrval(c,p) ( (c)[CNDX[EXP]] ? \
230 ldexp((c)[CNDX[p]]+.5,(int)(c)[CNDX[EXP]]-(COLXS+8)) : \
231 0. )
232
233 #define WHTCOLOR {1.0,1.0,1.0}
234 #define BLKCOLOR {0.0,0.0,0.0}
235 #define WHTCOLR {128,128,128,COLXS+1}
236 #define BLKCOLR {0,0,0,0}
237
238 /* picture format identifier */
239 #define COLRFMT "32-bit_rle_rgbe"
240 #define CIEFMT "32-bit_rle_xyze"
241 #define PICFMT "32-bit_rle_???e" /* matches either */
242 #define SPECFMT "Radiance_spectra" /* spectral data w/ exponent */
243
244 /* Number of spectral components */
245 #define NCOMPSTR "NCOMP="
246 #define LNCOMPSTR 6
247 #define isncomp(hl) !strncmp(hl,NCOMPSTR,LNCOMPSTR)
248 #define ncompval(hl) atoi((hl)+LNCOMPSTR)
249 #define fputncomp(nc,fp) fprintf(fp,"%s%d\n",NCOMPSTR,nc)
250
251 /* 4 wavelength partitions for (IR+)R,G,B(+UV) */
252 #define WLSPLTSTR "WAVELENGTH_SPLITS="
253 #define LWLSPLTSTR 18
254 #define iswlsplit(hl) !strncmp(hl,WLSPLTSTR,LWLSPLTSTR)
255 #define wlsplitval(w,hl) (sscanf((hl)+LWLSPLTSTR,"%f %f %f %f",\
256 &(w)[0],&(w)[1],&(w)[2],&(w)[3]) == 4)
257 #define fputwlsplit(w,fp) fprintf(fp,"%s %g %g %g %g\n",WLSPLTSTR,\
258 (w)[0],(w)[1],(w)[2],(w)[3])
259
260 /* macros for exposures */
261 #define EXPOSSTR "EXPOSURE="
262 #define LEXPOSSTR 9
263 #define isexpos(hl) !strncmp(hl,EXPOSSTR,LEXPOSSTR)
264 #define exposval(hl) atof((hl)+LEXPOSSTR)
265 #define fputexpos(ex,fp) fprintf(fp,"%s%.4e\n",EXPOSSTR,ex)
266
267 /* macros for pixel aspect ratios */
268 #define ASPECTSTR "PIXASPECT="
269 #define LASPECTSTR 10
270 #define isaspect(hl) !strncmp(hl,ASPECTSTR,LASPECTSTR)
271 #define aspectval(hl) atof((hl)+LASPECTSTR)
272 #define fputaspect(pa,fp) fprintf(fp,"%s%f\n",ASPECTSTR,pa)
273
274 /* macros for primary specifications */
275 #define PRIMARYSTR "PRIMARIES="
276 #define LPRIMARYSTR 10
277 #define isprims(hl) !strncmp(hl,PRIMARYSTR,LPRIMARYSTR)
278 #define primsval(p,hl) (sscanf((hl)+LPRIMARYSTR, \
279 "%f %f %f %f %f %f %f %f", \
280 &(p)[RED][CIEX],&(p)[RED][CIEY], \
281 &(p)[GRN][CIEX],&(p)[GRN][CIEY], \
282 &(p)[BLU][CIEX],&(p)[BLU][CIEY], \
283 &(p)[WHT][CIEX],&(p)[WHT][CIEY]) == 8)
284 #define fputprims(p,fp) fprintf(fp, \
285 "%s %.4f %.4f %.4f %.4f %.4f %.4f %.4f %.4f\n",\
286 PRIMARYSTR, \
287 (p)[RED][CIEX],(p)[RED][CIEY], \
288 (p)[GRN][CIEX],(p)[GRN][CIEY], \
289 (p)[BLU][CIEX],(p)[BLU][CIEY], \
290 (p)[WHT][CIEX],(p)[WHT][CIEY])
291
292 /* macros for color correction */
293 #define COLCORSTR "COLORCORR="
294 #define LCOLCORSTR 10
295 #define iscolcor(hl) !strncmp(hl,COLCORSTR,LCOLCORSTR)
296 #define colcorval(cc,hl) sscanf((hl)+LCOLCORSTR,"%f %f %f", \
297 &(cc)[RED],&(cc)[GRN],&(cc)[BLU])
298 #define fputcolcor(cc,fp) fprintf(fp,"%s %f %f %f\n",COLCORSTR, \
299 (cc)[RED],(cc)[GRN],(cc)[BLU])
300
301 /*
302 * Conversions to and from XYZ space generally don't apply WHTEFFICACY.
303 * If you need Y to be luminance (cd/m^2), this must be applied when
304 * converting from radiance (watts/sr/m^2).
305 */
306
307 extern int CNDX[4]; /* RGBE indices for SCOLOR, SCOLR */
308 extern float WLPART[4]; /* RGB wavelength limits+partitions (nm) */
309 extern RGBPRIMS stdprims; /* standard primary chromaticities */
310 extern RGBPRIMS xyzprims; /* to indicate XYZ input or output */
311 extern COLORMAT rgb2xyzmat; /* RGB to XYZ conversion matrix */
312 extern COLORMAT xyz2rgbmat; /* XYZ to RGB conversion matrix */
313 extern COLOR cblack, cwhite; /* black (0,0,0) and white (1,1,1) */
314
315 #define CGAMUT_LOWER 01
316 #define CGAMUT_UPPER 02
317 #define CGAMUT (CGAMUT_LOWER|CGAMUT_UPPER)
318
319 #define rgb_cie(xyz,rgb) colortrans(xyz,rgb2xyzmat,rgb)
320
321 #define cpcolormat(md,ms) memcpy((void *)md,(void *)ms,sizeof(COLORMAT))
322
323 /* defined in color.c */
324 extern void *tempbuffer(size_t len);
325 /* in cn[3]=nsamps, wlpt[0],wlpt[3]=extrema */
326 extern int setspectrsamp(int cn[4], float wlpt[4]);
327 extern int fwritecolrs(COLR *scanline, int len, FILE *fp);
328 extern int fwritescan(COLOR *scanline, int len, FILE *fp);
329 extern int fwritescolrs(uby8 *sscanline, int nc, int len, FILE *fp);
330 extern int fwritesscan(COLORV *sscanline, int nc, int len, FILE *fp);
331 extern int freadcolrs(COLR *scanline, int len, FILE *fp);
332 extern int freadscan(COLOR *scanline, int len, FILE *fp);
333 extern int freadscolrs(uby8 *scanline, int nc, int len, FILE *fp);
334 extern int freadsscan(COLORV *sscanline, int nc, int len, FILE *fp);
335 /* spectrum conversion, zero-fill past ends */
336 extern void convertscolor(SCOLOR dst, int dnc, double dwl0, double dwl1,
337 const COLORV src[], int snc, double swl0, double swl1);
338 /* the following use avg spectral ranges */
339 /* compare scolor_rgb() and scolor_cie() */
340 /* also, pcolor_color() and pcolor_colr() */
341 extern void setscolor(SCOLOR scol, double r, double g, double b);
342 extern void scolor2color(COLOR col, SCOLOR scol, int ncs, const float wlpt[4]);
343 extern void scolor2colr(COLR clr, SCOLOR scol, int ncs, const float wlpt[4]);
344 extern void scolor2scolr(SCOLR sclr, SCOLOR scol, int ncs);
345 extern void colr_color(COLOR col, COLR clr);
346 extern void scolr2scolor(SCOLOR scol, SCOLR sclr, int ncs);
347 extern void scolr2color(COLOR col, SCOLR sclr, int ncs, const float wlpt[4]);
348 extern void colr_scolor(SCOLOR scol, COLR clr);
349 extern void setcolr(COLR clr, double r, double g, double b);
350 extern void setscolr(SCOLR sclr, double r, double g, double b);
351 extern double scolor_mean(SCOLOR scol);
352 extern double sintens(SCOLOR scol);
353 extern int bigdiff(COLOR c1, COLOR c2, double md);
354 extern int sbigsdiff(SCOLOR sc1, SCOLOR sc2, double md);
355 /* defined in spec_rgb.c */
356 extern void spec_cie(COLOR col, int s, int e);
357 extern void spec_rgb(COLOR col, int s, int e);
358 extern void cie_rgb(COLOR rgb, COLOR xyz);
359 extern int clipgamut(COLOR col, double brt, int gamut,
360 COLOR lower, COLOR upper);
361 extern void colortrans(COLOR c2, COLORMAT mat, COLOR c1);
362 extern void multcolormat(COLORMAT m3, COLORMAT m2,
363 COLORMAT m1);
364 extern int colorprimsOK(RGBPRIMS pr);
365 extern int compxyz2rgbmat(COLORMAT mat, RGBPRIMS pr);
366 extern int comprgb2xyzmat(COLORMAT mat, RGBPRIMS pr);
367 extern int comprgb2rgbmat(COLORMAT mat, RGBPRIMS pr1, RGBPRIMS pr2);
368 extern int compxyzWBmat(COLORMAT mat, float wht1[2],
369 float wht2[2]);
370 extern int compxyz2rgbWBmat(COLORMAT mat, RGBPRIMS pr);
371 extern int comprgb2xyzWBmat(COLORMAT mat, RGBPRIMS pr);
372 extern int comprgb2rgbWBmat(COLORMAT mat, RGBPRIMS pr1, RGBPRIMS pr2);
373 /* any uniform spectrum to working */
374 extern void convertscolorcol(SCOLOR rcol, const COLORV src[], int snc,
375 double swl0, double swl1);
376 /* most accurate spectral->tristim */
377 extern void scolor2cie(COLOR col, SCOLOR scol, int ncs, const float wlpt[4]);
378 extern void scolor2rgb(COLOR col, SCOLOR scol, int ncs, const float wlpt[4]);
379 extern double scolor2photopic(SCOLOR scol, int ncs, const float wlpt[4]);
380 extern double scolor2scotopic(SCOLOR scol, int ncs, const float wlpt[4]);
381 extern double scolor2melanopic(SCOLOR scol, int ncs, const float wlpt[4]);
382 extern double scolor_photopic(SCOLOR scol);
383 extern double scolor_scotopic(SCOLOR scol);
384 extern double scolor_melanopic(SCOLOR scol);
385 /* defined in colrops.c */
386 extern int setcolrcor(double (*f)(double, double), double a2);
387 extern int setcolrinv(double (*f)(double, double), double a2);
388 extern int setcolrgam(double g);
389 extern int colrs_gambs(COLR *scan, int len);
390 extern int gambs_colrs(COLR *scan, int len);
391 extern void shiftcolrs(COLR *scan, int len, int adjust);
392 extern void normcolrs(COLR *scan, int len, int adjust);
393
394 #ifdef __cplusplus
395 }
396 #endif
397 #endif /* _RAD_COLOR_H_ */
398