ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/common/tmap16bit.c
Revision: 1.6
Committed: Fri Jan 7 21:41:06 2005 UTC (19 years, 3 months ago) by greg
Content type: text/plain
Branch: MAIN
CVS Tags: rad3R7P2, rad3R7P1, rad3R8
Changes since 1.5: +3 -3 lines
Log Message:
Moved error codes inside passed TMstruct

File Contents

# User Rev Content
1 greg 1.1 #ifndef lint
2 greg 1.6 static const char RCSid[] = "$Id: tmap16bit.c,v 1.5 2005/01/07 20:33:02 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 greg 1.5 mkMonGamTable(TMstruct *tms)
63 greg 1.3 {
64     int i;
65    
66 greg 1.5 if (tms->mongam == cur_mongam)
67 greg 1.3 return;
68     for (i = MONGAMTSZ; i--; )
69 greg 1.5 mongamtab[i] = 256.*pow((i+.5)*(1./MONGAMTSZ), 1./tms->mongam);
70     cur_mongam = tms->mongam;
71 greg 1.3 }
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 greg 1.5 tmCvGray16(TMstruct *tms, TMbright *ls, uint16 *scan, int len, double gv)
135 greg 1.1 {
136 greg 1.6 static const char funcName[] = "tmCvGray16";
137 greg 1.1 static double cur_inpsf = 1.;
138     static double log_inpsf = 0.;
139     int nshft;
140     double d;
141    
142 greg 1.5 if (tms == NULL)
143 greg 1.1 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 greg 1.5 if (cur_inpsf != tms->inpsf)
152     log_inpsf = log(cur_inpsf = tms->inpsf);
153 greg 1.1 /* 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 greg 1.5 tmCvRGB48(TMstruct *tms, TMbright *ls, BYTE *cs,
174     uint16 (*scan)[3], int len, double gv)
175 greg 1.1 {
176 greg 1.6 static const char funcName[] = "tmCvRGB48";
177 greg 1.1 static double cur_inpsf = 1.;
178     static double log_inpsf = 0.;
179     int i;
180    
181 greg 1.5 if (tms == NULL)
182 greg 1.1 returnErr(TM_E_TMINVAL);
183 schorsch 1.4 if ((ls == NULL) | (scan == NULL) | (len < 0))
184 greg 1.1 returnErr(TM_E_ILLEGAL);
185 greg 1.2 if (gv <= 0.)
186     gv = DEFGAM;
187 greg 1.3 /* sync input gamma table */
188 schorsch 1.4 if ((gv != 1.) & (gv != cur_gam))
189 greg 1.1 mkGamTable(gv);
190 greg 1.5 if (tmNeedMatrix(tms)) { /* need floating point */
191 greg 1.1 COLOR *newscan;
192     newscan = (COLOR *)tempbuffer(len*sizeof(COLOR));
193     if (newscan == NULL)
194     returnErr(TM_E_NOMEM);
195     for (i = len; i--; )
196 greg 1.2 rgb48_color(newscan[i], scan[i], gv);
197 greg 1.5 return(tmCvColors(tms, ls, cs, newscan, len));
198 greg 1.1 }
199 greg 1.3 /* sync monitor gamma table */
200 greg 1.5 if (cs != TM_NOCHROM && tms->mongam != cur_mongam)
201     mkMonGamTable(tms);
202 greg 1.1 /* initialize log table */
203     if (logtab[0] == 0.f)
204     mkLogTable();
205 greg 1.5 if (cur_inpsf != tms->inpsf)
206     log_inpsf = log(cur_inpsf = tms->inpsf);
207     if (tms->flags & TM_F_MESOPIC)
208 greg 1.3 tmMkMesofact();
209 greg 1.1 /* convert scanline */
210     for (i = len; i--; ) {
211 greg 1.3 int nshft = normShift48(scan[i]);
212     COLOR cmon;
213     double lum;
214     int bi;
215    
216     if (nshft < 0) {
217 greg 1.1 bi = TM_NOBRT; /* bogus value */
218 greg 1.3 lum = 1.;
219     } else {
220     int j = GAMTABBITS-16+nshft;
221     int nshft2;
222     double d;
223     /* normalized linear */
224     setcolor(cmon, gamtab[imultpow2(scan[i][0],j)],
225     gamtab[imultpow2(scan[i][1],j)],
226     gamtab[imultpow2(scan[i][2],j)] );
227 greg 1.5 lum = tms->clf[RED]*cmon[RED];
228     lum += tms->clf[GRN]*cmon[GRN];
229     lum += tms->clf[BLU]*cmon[BLU];
230 greg 1.3 /* convert to log Y */
231     j = lum * (double)(1L<<16);
232     nshft2 = normShift16(j);
233     d = logtab[ imultpow2(j,LOGTABBITS-15+nshft2) &
234     ((1L<<LOGTABBITS)-1) ];
235     d -= M_LN2*(gv*nshft + nshft2);
236     d = (double)TM_BRTSCALE*(d + log_inpsf);
237     bi = (int)(d>0. ? d+.5 : d-.5);
238 greg 1.1 }
239 greg 1.3 /* world luminance */
240 greg 1.1 ls[i] = bi;
241     if (cs == TM_NOCHROM) /* no color? */
242     continue;
243     /* mesopic adj. */
244 greg 1.5 if (tms->flags & TM_F_MESOPIC && bi < BMESUPPER) {
245 greg 1.3 double slum = scotlum(cmon);
246 greg 1.1 if (bi < BMESLOWER)
247 greg 1.3 setcolor(cmon, slum, slum, slum);
248 greg 1.1 else {
249 greg 1.3 double pf;
250     pf = (1./256.)*tmMesofact[bi-BMESLOWER];
251 greg 1.5 if (tms->flags & TM_F_BW)
252 greg 1.3 cmon[RED] = cmon[GRN] = cmon[BLU] = lum;
253     slum *= 1. - pf;
254     cmon[RED] = slum + pf*cmon[RED];
255     cmon[GRN] = slum + pf*cmon[GRN];
256     cmon[BLU] = slum + pf*cmon[BLU];
257 greg 1.1 }
258 greg 1.5 } else if (tms->flags & TM_F_BW) {
259 greg 1.3 cmon[RED] = cmon[GRN] = cmon[BLU] = lum;
260 greg 1.1 }
261 greg 1.5 bi = (double)MONGAMTSZ*tms->clf[RED]*cmon[RED]/lum;
262 greg 1.3 cs[3*i ] = bi>=MONGAMTSZ ? 255 : mongamtab[bi];
263 greg 1.5 bi = (double)MONGAMTSZ*tms->clf[GRN]*cmon[GRN]/lum;
264 greg 1.3 cs[3*i+1] = bi>=MONGAMTSZ ? 255 : mongamtab[bi];
265 greg 1.5 bi = (double)MONGAMTSZ*tms->clf[BLU]*cmon[BLU]/lum;
266 greg 1.3 cs[3*i+2] = bi>=MONGAMTSZ ? 255 : mongamtab[bi];
267 greg 1.1 }
268     returnOK;
269     }