ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/common/tmap16bit.c
Revision: 1.4
Committed: Sun Jul 27 22:12:01 2003 UTC (20 years, 9 months ago) by schorsch
Content type: text/plain
Branch: MAIN
CVS Tags: rad3R6, rad3R6P1
Changes since 1.3: +4 -4 lines
Log Message:
Added grouping parens to reduce ambiguity warnings.

File Contents

# User Rev Content
1 greg 1.1 #ifndef lint
2 schorsch 1.4 static const char RCSid[] = "$Id: tmap16bit.c,v 1.3 2003/07/15 07:28:09 greg Exp $";
3 greg 1.1 #endif
4     /*
5     * Routines for tone-mapping 16-bit/primary pixels
6     *
7     * Externals declared in tonemap.h
8     */
9    
10     #include "copyright.h"
11    
12     #include <stdio.h>
13     #include <math.h>
14     #include "tmprivat.h"
15    
16     #define LOGTABBITS 11 /* log table is 1<<LOGTABBITS long */
17     #define GAMTABBITS 9 /* gamma table is 1<<GAMTABBITS long */
18 greg 1.3 #define MONGAMTSZ 1024 /* monitor gamma table length */
19 greg 1.1
20     static float logtab[1<<LOGTABBITS];
21     static float gamtab[1<<GAMTABBITS];
22     static float gammul[16];
23     static double cur_gam = 0.;
24 greg 1.3 static BYTE mongamtab[MONGAMTSZ];
25     static double cur_mongam = 0.;
26 greg 1.1
27     #define imultpow2(i,s) ((s)>=0 ? (i)<<(s) : (i)>>-(s))
28    
29    
30     /* Fill our log table */
31     static void
32     mkLogTable()
33     {
34     int i;
35    
36     if (logtab[0] != 0.f)
37     return;
38     for (i = 1<<LOGTABBITS; i--; )
39     logtab[i] = log(imultpow2(i,15-LOGTABBITS)*(1./(1L<<16))
40     + .5);
41     }
42    
43    
44 greg 1.3 /* Fill our input gamma table */
45 greg 1.1 static void
46     mkGamTable(double gv)
47     {
48     int i;
49    
50     if (gv == cur_gam)
51     return;
52     for (i = 1<<GAMTABBITS; i--; )
53     gamtab[i] = pow((i+.5)*(1./(1<<GAMTABBITS)), gv);
54     for (i = 16; i--; )
55     gammul[i] = pow((double)(1L<<i), -gv);
56     cur_gam = gv;
57     }
58    
59    
60 greg 1.3 /* Fill our monitor gamma table */
61     static void
62     mkMonGamTable()
63     {
64     int i;
65    
66     if (tmTop->mongam == cur_mongam)
67     return;
68     for (i = MONGAMTSZ; i--; )
69     mongamtab[i] = 256.*pow((i+.5)*(1./MONGAMTSZ), 1./tmTop->mongam);
70     cur_mongam = tmTop->mongam;
71     }
72    
73    
74 greg 1.1 /* Find normalizing shift value for a 2-byte unsigned integer */
75     static int
76     normShift16(int i)
77     {
78     int s = 0;
79    
80 greg 1.2 if (!i)
81     return(-1);
82 greg 1.1 while (!(i & 0x8000)) {
83     i <<= 1;
84     ++s;
85     }
86     return(s);
87     }
88    
89    
90     /* Find common normalizing shift for 3 2-byte unsigned integers */
91     static int
92     normShift48(uint16 clr48[3])
93     {
94     int imax = (clr48[1] > clr48[0] ? clr48[1] : clr48[0]);
95     if (clr48[2] > imax)
96     imax = clr48[2];
97     return(normShift16(imax));
98     }
99    
100    
101     /* convert at 48-bit tristimulus value to a COLOR */
102     static void
103 greg 1.2 rgb48_color(COLOR col, uint16 clr48[3], double gv)
104 greg 1.1 {
105     int nshft;
106    
107 greg 1.2 if (gv == 1.) { /* linear case */
108 greg 1.1 col[0] = clr48[0]*(1./(1L<<16));
109     col[1] = clr48[1]*(1./(1L<<16));
110     col[2] = clr48[2]*(1./(1L<<16));
111     return;
112     }
113     /* non-linear case */
114 greg 1.3 /* XXX Uncomment if this routine is made public
115 greg 1.2 if (gv != cur_gam)
116     mkGamTable(gv);
117     */
118 greg 1.1 nshft = normShift48(clr48);
119 greg 1.2 if (nshft < 0) {
120     col[0] = col[1] = col[2] = .0f;
121     return;
122     }
123 greg 1.1 col[0] = gamtab[imultpow2(clr48[0],GAMTABBITS-16+nshft)] *
124     gammul[nshft];
125     col[1] = gamtab[imultpow2(clr48[1],GAMTABBITS-16+nshft)] *
126     gammul[nshft];
127     col[2] = gamtab[imultpow2(clr48[2],GAMTABBITS-16+nshft)] *
128     gammul[nshft];
129     }
130    
131    
132     /* Convert 16-bit gray scanline to encoded luminance */
133     int
134     tmCvGray16(TMbright *ls, uint16 *scan, int len, double gv)
135     {
136     static char funcName[] = "tmCvGray16";
137     static double cur_inpsf = 1.;
138     static double log_inpsf = 0.;
139     int nshft;
140     double d;
141    
142     if (tmTop == NULL)
143     returnErr(TM_E_TMINVAL);
144 schorsch 1.4 if ((ls == NULL) | (scan == NULL) | (len < 0))
145 greg 1.1 returnErr(TM_E_ILLEGAL);
146 greg 1.2 if (gv <= 0.)
147     gv = DEFGAM;
148 greg 1.1 /* initialize log table */
149     if (logtab[0] == 0.f)
150     mkLogTable();
151     if (cur_inpsf != tmTop->inpsf)
152     log_inpsf = log(cur_inpsf = tmTop->inpsf);
153     /* convert 16-bit grays */
154     while (len--) {
155     nshft = normShift16(*scan);
156 greg 1.2 if (nshft < 0) { /* bogus value */
157     *ls++ = TM_NOBRT;
158     scan++;
159     continue;
160     }
161 greg 1.1 d = logtab[ imultpow2(*scan,LOGTABBITS-15+nshft) &
162 greg 1.3 ((1L<<LOGTABBITS)-1) ];
163     d -= M_LN2*nshft;
164 greg 1.1 d = (double)TM_BRTSCALE * (gv*d + log_inpsf);
165     *ls++ = (d>0. ? d+.5 : d-.5);
166     scan++;
167     }
168     returnOK;
169     }
170    
171     /* Convert a 48-bit RGB scanline to encoded luminance/chrominance */
172     int
173     tmCvRGB48(TMbright *ls, BYTE *cs, uint16 (*scan)[3], int len, double gv)
174     {
175     static char funcName[] = "tmCvRGB48";
176     static double cur_inpsf = 1.;
177     static double log_inpsf = 0.;
178     int i;
179    
180     if (tmTop == NULL)
181     returnErr(TM_E_TMINVAL);
182 schorsch 1.4 if ((ls == NULL) | (scan == NULL) | (len < 0))
183 greg 1.1 returnErr(TM_E_ILLEGAL);
184 greg 1.2 if (gv <= 0.)
185     gv = DEFGAM;
186 greg 1.3 /* sync input gamma table */
187 schorsch 1.4 if ((gv != 1.) & (gv != cur_gam))
188 greg 1.1 mkGamTable(gv);
189     if (tmNeedMatrix(tmTop)) { /* need floating point */
190     COLOR *newscan;
191     newscan = (COLOR *)tempbuffer(len*sizeof(COLOR));
192     if (newscan == NULL)
193     returnErr(TM_E_NOMEM);
194     for (i = len; i--; )
195 greg 1.2 rgb48_color(newscan[i], scan[i], gv);
196 greg 1.1 return(tmCvColors(ls, cs, newscan, len));
197     }
198 greg 1.3 /* sync monitor gamma table */
199     if (cs != TM_NOCHROM && tmTop->mongam != cur_mongam)
200     mkMonGamTable();
201 greg 1.1 /* initialize log table */
202     if (logtab[0] == 0.f)
203     mkLogTable();
204     if (cur_inpsf != tmTop->inpsf)
205     log_inpsf = log(cur_inpsf = tmTop->inpsf);
206 greg 1.3 if (tmTop->flags & TM_F_MESOPIC)
207     tmMkMesofact();
208 greg 1.1 /* convert scanline */
209     for (i = len; i--; ) {
210 greg 1.3 int nshft = normShift48(scan[i]);
211     COLOR cmon;
212     double lum;
213     int bi;
214    
215     if (nshft < 0) {
216 greg 1.1 bi = TM_NOBRT; /* bogus value */
217 greg 1.3 lum = 1.;
218     } else {
219     int j = GAMTABBITS-16+nshft;
220     int nshft2;
221     double d;
222     /* normalized linear */
223     setcolor(cmon, gamtab[imultpow2(scan[i][0],j)],
224     gamtab[imultpow2(scan[i][1],j)],
225     gamtab[imultpow2(scan[i][2],j)] );
226     lum = tmTop->clf[RED]*cmon[RED];
227     lum += tmTop->clf[GRN]*cmon[GRN];
228     lum += tmTop->clf[BLU]*cmon[BLU];
229     /* convert to log Y */
230     j = lum * (double)(1L<<16);
231     nshft2 = normShift16(j);
232     d = logtab[ imultpow2(j,LOGTABBITS-15+nshft2) &
233     ((1L<<LOGTABBITS)-1) ];
234     d -= M_LN2*(gv*nshft + nshft2);
235     d = (double)TM_BRTSCALE*(d + log_inpsf);
236     bi = (int)(d>0. ? d+.5 : d-.5);
237 greg 1.1 }
238 greg 1.3 /* world luminance */
239 greg 1.1 ls[i] = bi;
240     if (cs == TM_NOCHROM) /* no color? */
241     continue;
242     /* mesopic adj. */
243     if (tmTop->flags & TM_F_MESOPIC && bi < BMESUPPER) {
244 greg 1.3 double slum = scotlum(cmon);
245 greg 1.1 if (bi < BMESLOWER)
246 greg 1.3 setcolor(cmon, slum, slum, slum);
247 greg 1.1 else {
248 greg 1.3 double pf;
249     pf = (1./256.)*tmMesofact[bi-BMESLOWER];
250 greg 1.1 if (tmTop->flags & TM_F_BW)
251 greg 1.3 cmon[RED] = cmon[GRN] = cmon[BLU] = lum;
252     slum *= 1. - pf;
253     cmon[RED] = slum + pf*cmon[RED];
254     cmon[GRN] = slum + pf*cmon[GRN];
255     cmon[BLU] = slum + pf*cmon[BLU];
256 greg 1.1 }
257     } else if (tmTop->flags & TM_F_BW) {
258 greg 1.3 cmon[RED] = cmon[GRN] = cmon[BLU] = lum;
259 greg 1.1 }
260 greg 1.3 bi = (double)MONGAMTSZ*tmTop->clf[RED]*cmon[RED]/lum;
261     cs[3*i ] = bi>=MONGAMTSZ ? 255 : mongamtab[bi];
262     bi = (double)MONGAMTSZ*tmTop->clf[GRN]*cmon[GRN]/lum;
263     cs[3*i+1] = bi>=MONGAMTSZ ? 255 : mongamtab[bi];
264     bi = (double)MONGAMTSZ*tmTop->clf[BLU]*cmon[BLU]/lum;
265     cs[3*i+2] = bi>=MONGAMTSZ ? 255 : mongamtab[bi];
266 greg 1.1 }
267     returnOK;
268     }