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, 8 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

# Content
1 #ifndef lint
2 static const char RCSid[] = "$Id: tmap16bit.c,v 1.3 2003/07/15 07:28:09 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()
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 /* 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(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 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 != tmTop->inpsf)
152 log_inpsf = log(cur_inpsf = tmTop->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(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 if ((ls == NULL) | (scan == NULL) | (len < 0))
183 returnErr(TM_E_ILLEGAL);
184 if (gv <= 0.)
185 gv = DEFGAM;
186 /* sync input gamma table */
187 if ((gv != 1.) & (gv != cur_gam))
188 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 rgb48_color(newscan[i], scan[i], gv);
196 return(tmCvColors(ls, cs, newscan, len));
197 }
198 /* sync monitor gamma table */
199 if (cs != TM_NOCHROM && tmTop->mongam != cur_mongam)
200 mkMonGamTable();
201 /* 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 if (tmTop->flags & TM_F_MESOPIC)
207 tmMkMesofact();
208 /* convert scanline */
209 for (i = len; i--; ) {
210 int nshft = normShift48(scan[i]);
211 COLOR cmon;
212 double lum;
213 int bi;
214
215 if (nshft < 0) {
216 bi = TM_NOBRT; /* bogus value */
217 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 }
238 /* world luminance */
239 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 double slum = scotlum(cmon);
245 if (bi < BMESLOWER)
246 setcolor(cmon, slum, slum, slum);
247 else {
248 double pf;
249 pf = (1./256.)*tmMesofact[bi-BMESLOWER];
250 if (tmTop->flags & TM_F_BW)
251 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 }
257 } else if (tmTop->flags & TM_F_BW) {
258 cmon[RED] = cmon[GRN] = cmon[BLU] = lum;
259 }
260 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 }
267 returnOK;
268 }