ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/common/tmap16bit.c
Revision: 1.9
Committed: Mon Mar 7 20:49:19 2011 UTC (13 years, 7 months ago) by greg
Content type: text/plain
Branch: MAIN
Changes since 1.8: +2 -2 lines
Log Message:
Minor improvement in round-off method

File Contents

# Content
1 #ifndef lint
2 static const char RCSid[] = "$Id: tmap16bit.c,v 1.8 2008/05/15 22:15:16 greg Exp $";
3 #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 #define MONGAMTSZ 1024 /* monitor gamma table length */
19
20 static float logtab[1<<LOGTABBITS];
21 static float gamtab[1<<GAMTABBITS];
22 static float gammul[16];
23 static double cur_gam = 0.;
24 static BYTE mongamtab[MONGAMTSZ];
25 static double cur_mongam = 0.;
26
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 /* Fill our input gamma table */
45 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 /* Fill our monitor gamma table */
61 static void
62 mkMonGamTable(TMstruct *tms)
63 {
64 int i;
65
66 if (tms->mongam == cur_mongam)
67 return;
68 for (i = MONGAMTSZ; i--; )
69 mongamtab[i] = 256.*pow((i+.5)*(1./MONGAMTSZ), 1./tms->mongam);
70 cur_mongam = tms->mongam;
71 }
72
73
74 /* Find normalizing shift value for a 2-byte unsigned integer */
75 static int
76 normShift16(int i)
77 {
78 int s = 0;
79
80 if (!i)
81 return(-1);
82 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 rgb48_color(COLOR col, uint16 clr48[3], double gv)
104 {
105 int nshft;
106
107 if (gv == 1.) { /* linear case */
108 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 /* XXX Uncomment if this routine is made public
115 if (gv != cur_gam)
116 mkGamTable(gv);
117 */
118 nshft = normShift48(clr48);
119 if (nshft < 0) {
120 col[0] = col[1] = col[2] = .0f;
121 return;
122 }
123 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(TMstruct *tms, TMbright *ls, uint16 *scan, int len, double gv)
135 {
136 static const char funcName[] = "tmCvGray16";
137 static double cur_inpsf = 1.;
138 static double log_inpsf = 0.;
139 int nshft;
140 double d;
141
142 if (tms == NULL)
143 returnErr(TM_E_TMINVAL);
144 if ((ls == NULL) | (scan == NULL) | (len < 0))
145 returnErr(TM_E_ILLEGAL);
146 if (gv <= 0.)
147 gv = DEFGAM;
148 /* initialize log table */
149 if (logtab[0] == 0.f)
150 mkLogTable();
151 if (cur_inpsf != tms->inpsf)
152 log_inpsf = log(cur_inpsf = tms->inpsf);
153 /* convert 16-bit grays */
154 while (len--) {
155 nshft = normShift16(*scan);
156 if (nshft < 0) { /* bogus value */
157 *ls++ = TM_NOBRT;
158 scan++;
159 continue;
160 }
161 d = logtab[ imultpow2(*scan,LOGTABBITS-15+nshft) &
162 ((1L<<LOGTABBITS)-1) ];
163 d -= M_LN2*nshft;
164 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(TMstruct *tms, TMbright *ls, BYTE *cs,
174 uint16 (*scan)[3], int len, double gv)
175 {
176 static const char funcName[] = "tmCvRGB48";
177 static double cur_inpsf = 1.;
178 static double log_inpsf = 0.;
179 int i;
180
181 if (tms == NULL)
182 returnErr(TM_E_TMINVAL);
183 if ((ls == NULL) | (scan == NULL) | (len < 0))
184 returnErr(TM_E_ILLEGAL);
185 if (gv <= 0.)
186 gv = DEFGAM;
187 /* sync input gamma table */
188 if (gv != cur_gam)
189 mkGamTable(gv);
190 if (tmNeedMatrix(tms)) { /* need floating point */
191 COLOR *newscan;
192 newscan = (COLOR *)tempbuffer(len*sizeof(COLOR));
193 if (newscan == NULL)
194 returnErr(TM_E_NOMEM);
195 for (i = len; i--; )
196 rgb48_color(newscan[i], scan[i], gv);
197 return(tmCvColors(tms, ls, cs, newscan, len));
198 }
199 /* sync monitor gamma table */
200 if (cs != TM_NOCHROM && tms->mongam != cur_mongam)
201 mkMonGamTable(tms);
202 /* initialize log table */
203 if (logtab[0] == 0.f)
204 mkLogTable();
205 if (cur_inpsf != tms->inpsf)
206 log_inpsf = log(cur_inpsf = tms->inpsf);
207 if (tms->flags & TM_F_MESOPIC)
208 tmMkMesofact();
209 /* convert scanline */
210 for (i = len; i--; ) {
211 int nshft = normShift48(scan[i]);
212 COLOR cmon;
213 double lum;
214 int bi;
215
216 if (nshft < 0) {
217 bi = TM_NOBRT; /* bogus value */
218 lum = 1.;
219 setcolor(cmon, 1., 1., 1.);
220 } else {
221 int j = GAMTABBITS-16+nshft;
222 int nshft2;
223 double d;
224 /* normalized linear */
225 setcolor(cmon, gamtab[imultpow2(scan[i][0],j)],
226 gamtab[imultpow2(scan[i][1],j)],
227 gamtab[imultpow2(scan[i][2],j)] );
228 lum = tms->clf[RED]*cmon[RED];
229 lum += tms->clf[GRN]*cmon[GRN];
230 lum += tms->clf[BLU]*cmon[BLU];
231 /* convert to log Y */
232 j = lum * (double)(1L<<16);
233 nshft2 = normShift16(j);
234 d = logtab[ imultpow2(j,LOGTABBITS-15+nshft2) &
235 ((1L<<LOGTABBITS)-1) ];
236 d -= M_LN2*(gv*nshft + nshft2);
237 d = (double)TM_BRTSCALE*(d + log_inpsf);
238 bi = (int)(d + .5 - (d < 0.));
239 }
240 /* world luminance */
241 ls[i] = bi;
242 if (cs == TM_NOCHROM) /* no color? */
243 continue;
244 /* mesopic adj. */
245 if (tms->flags & TM_F_MESOPIC && bi < BMESUPPER) {
246 double slum = scotlum(cmon);
247 if (bi < BMESLOWER)
248 setcolor(cmon, slum, slum, slum);
249 else {
250 double pf;
251 pf = (1./256.)*tmMesofact[bi-BMESLOWER];
252 if (tms->flags & TM_F_BW)
253 cmon[RED] = cmon[GRN] = cmon[BLU] = lum;
254 slum *= 1. - pf;
255 cmon[RED] = slum + pf*cmon[RED];
256 cmon[GRN] = slum + pf*cmon[GRN];
257 cmon[BLU] = slum + pf*cmon[BLU];
258 }
259 } else if (tms->flags & TM_F_BW) {
260 cmon[RED] = cmon[GRN] = cmon[BLU] = lum;
261 }
262 bi = (double)MONGAMTSZ*tms->clf[RED]*cmon[RED]/lum;
263 cs[3*i ] = bi>=MONGAMTSZ ? 255 : mongamtab[bi];
264 bi = (double)MONGAMTSZ*tms->clf[GRN]*cmon[GRN]/lum;
265 cs[3*i+1] = bi>=MONGAMTSZ ? 255 : mongamtab[bi];
266 bi = (double)MONGAMTSZ*tms->clf[BLU]*cmon[BLU]/lum;
267 cs[3*i+2] = bi>=MONGAMTSZ ? 255 : mongamtab[bi];
268 }
269 returnOK;
270 }