ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/common/tmap16bit.c
Revision: 1.2
Committed: Tue Jul 15 00:23:36 2003 UTC (20 years, 9 months ago) by greg
Content type: text/plain
Branch: MAIN
Changes since 1.1: +25 -6 lines
Log Message:
Bug fix for linear 16-bit and zero valued pixels

File Contents

# Content
1 #ifndef lint
2 static const char RCSid[] = "$Id: tmap16bit.c,v 1.1 2003/07/14 18:21:07 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
19 static float logtab[1<<LOGTABBITS];
20 static float gamtab[1<<GAMTABBITS];
21 static float gammul[16];
22 static double cur_gam = 0.;
23
24 #define imultpow2(i,s) ((s)>=0 ? (i)<<(s) : (i)>>-(s))
25
26
27 /* Fill our log table */
28 static void
29 mkLogTable()
30 {
31 int i;
32
33 if (logtab[0] != 0.f)
34 return;
35 for (i = 1<<LOGTABBITS; i--; )
36 logtab[i] = log(imultpow2(i,15-LOGTABBITS)*(1./(1L<<16))
37 + .5);
38 }
39
40
41 /* Fill our gamma table */
42 static void
43 mkGamTable(double gv)
44 {
45 int i;
46
47 if (gv == cur_gam)
48 return;
49 for (i = 1<<GAMTABBITS; i--; )
50 gamtab[i] = pow((i+.5)*(1./(1<<GAMTABBITS)), gv);
51 for (i = 16; i--; )
52 gammul[i] = pow((double)(1L<<i), -gv);
53 cur_gam = gv;
54 }
55
56
57 /* Find normalizing shift value for a 2-byte unsigned integer */
58 static int
59 normShift16(int i)
60 {
61 int s = 0;
62
63 if (!i)
64 return(-1);
65 while (!(i & 0x8000)) {
66 i <<= 1;
67 ++s;
68 }
69 return(s);
70 }
71
72
73 /* Find common normalizing shift for 3 2-byte unsigned integers */
74 static int
75 normShift48(uint16 clr48[3])
76 {
77 int imax = (clr48[1] > clr48[0] ? clr48[1] : clr48[0]);
78 if (clr48[2] > imax)
79 imax = clr48[2];
80 return(normShift16(imax));
81 }
82
83
84 /* convert at 48-bit tristimulus value to a COLOR */
85 static void
86 rgb48_color(COLOR col, uint16 clr48[3], double gv)
87 {
88 int nshft;
89
90 if (gv == 1.) { /* linear case */
91 col[0] = clr48[0]*(1./(1L<<16));
92 col[1] = clr48[1]*(1./(1L<<16));
93 col[2] = clr48[2]*(1./(1L<<16));
94 return;
95 }
96 /* non-linear case */
97 /* XXX Uncomment if routine is made public
98 if (gv != cur_gam)
99 mkGamTable(gv);
100 */
101 nshft = normShift48(clr48);
102 if (nshft < 0) {
103 col[0] = col[1] = col[2] = .0f;
104 return;
105 }
106 col[0] = gamtab[imultpow2(clr48[0],GAMTABBITS-16+nshft)] *
107 gammul[nshft];
108 col[1] = gamtab[imultpow2(clr48[1],GAMTABBITS-16+nshft)] *
109 gammul[nshft];
110 col[2] = gamtab[imultpow2(clr48[2],GAMTABBITS-16+nshft)] *
111 gammul[nshft];
112 }
113
114
115 /* Convert 16-bit gray scanline to encoded luminance */
116 int
117 tmCvGray16(TMbright *ls, uint16 *scan, int len, double gv)
118 {
119 static char funcName[] = "tmCvGray16";
120 static double cur_inpsf = 1.;
121 static double log_inpsf = 0.;
122 int nshft;
123 double d;
124
125 if (tmTop == NULL)
126 returnErr(TM_E_TMINVAL);
127 if (ls == NULL | scan == NULL | len < 0)
128 returnErr(TM_E_ILLEGAL);
129 if (gv <= 0.)
130 gv = DEFGAM;
131 /* initialize log table */
132 if (logtab[0] == 0.f)
133 mkLogTable();
134 if (cur_inpsf != tmTop->inpsf)
135 log_inpsf = log(cur_inpsf = tmTop->inpsf);
136 /* convert 16-bit grays */
137 while (len--) {
138 nshft = normShift16(*scan);
139 if (nshft < 0) { /* bogus value */
140 *ls++ = TM_NOBRT;
141 scan++;
142 continue;
143 }
144 d = logtab[ imultpow2(*scan,LOGTABBITS-15+nshft) &
145 ((1L<<LOGTABBITS)-1) ]
146 - M_LN2*nshft;
147 d = (double)TM_BRTSCALE * (gv*d + log_inpsf);
148 *ls++ = (d>0. ? d+.5 : d-.5);
149 scan++;
150 }
151 returnOK;
152 }
153
154 /* Convert a 48-bit RGB scanline to encoded luminance/chrominance */
155 int
156 tmCvRGB48(TMbright *ls, BYTE *cs, uint16 (*scan)[3], int len, double gv)
157 {
158 static char funcName[] = "tmCvRGB48";
159 static double cur_inpsf = 1.;
160 static double log_inpsf = 0.;
161 int i;
162
163 if (tmTop == NULL)
164 returnErr(TM_E_TMINVAL);
165 if (ls == NULL | scan == NULL | len < 0)
166 returnErr(TM_E_ILLEGAL);
167 if (gv <= 0.)
168 gv = DEFGAM;
169 /* update gamma table */
170 if (gv != 1. & gv != cur_gam)
171 mkGamTable(gv);
172 #if 0
173 if (tmNeedMatrix(tmTop)) { /* need floating point */
174 #else
175 {
176 #endif
177 COLOR *newscan;
178 newscan = (COLOR *)tempbuffer(len*sizeof(COLOR));
179 if (newscan == NULL)
180 returnErr(TM_E_NOMEM);
181 for (i = len; i--; )
182 rgb48_color(newscan[i], scan[i], gv);
183 return(tmCvColors(ls, cs, newscan, len));
184 }
185 #if 0
186 /* initialize log table */
187 if (logtab[0] == 0.f)
188 mkLogTable();
189 if (cur_inpsf != tmTop->inpsf)
190 log_inpsf = log(cur_inpsf = tmTop->inpsf);
191 /* convert scanline */
192 for (i = len; i--; ) {
193 copycolr(cmon, scan[i]);
194 /* world luminance */
195 li = ( cd->clfb[RED]*cmon[RED] +
196 cd->clfb[GRN]*cmon[GRN] +
197 cd->clfb[BLU]*cmon[BLU] ) >> 8;
198 bi = BRT2SCALE(cmon[EXP]-COLXS) +
199 logi[li] + cd->inpsfb;
200 if (li <= 0) {
201 bi = TM_NOBRT; /* bogus value */
202 li = 1; /* avoid li==0 */
203 }
204 ls[i] = bi;
205 if (cs == TM_NOCHROM) /* no color? */
206 continue;
207 /* mesopic adj. */
208 if (tmTop->flags & TM_F_MESOPIC && bi < BMESUPPER) {
209 int pf, sli = normscot(cmon);
210 if (bi < BMESLOWER)
211 cmon[RED] = cmon[GRN] = cmon[BLU] = sli;
212 else {
213 if (tmTop->flags & TM_F_BW)
214 cmon[RED] = cmon[GRN] = cmon[BLU] = li;
215 pf = tmMesofact[bi-BMESLOWER];
216 sli *= 256 - pf;
217 cmon[RED] = ( sli + pf*cmon[RED] ) >> 8;
218 cmon[GRN] = ( sli + pf*cmon[GRN] ) >> 8;
219 cmon[BLU] = ( sli + pf*cmon[BLU] ) >> 8;
220 }
221 } else if (tmTop->flags & TM_F_BW) {
222 cmon[RED] = cmon[GRN] = cmon[BLU] = li;
223 }
224 bi = ( (int32)GAMTSZ*cd->clfb[RED]*cmon[RED]/li ) >> 8;
225 cs[3*i ] = bi>=GAMTSZ ? 255 : cd->gamb[bi];
226 bi = ( (int32)GAMTSZ*cd->clfb[GRN]*cmon[GRN]/li ) >> 8;
227 cs[3*i+1] = bi>=GAMTSZ ? 255 : cd->gamb[bi];
228 bi = ( (int32)GAMTSZ*cd->clfb[BLU]*cmon[BLU]/li ) >> 8;
229 cs[3*i+2] = bi>=GAMTSZ ? 255 : cd->gamb[bi];
230 }
231 returnOK;
232 #endif
233 }