ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/common/tmap16bit.c
Revision: 1.1
Committed: Mon Jul 14 18:21:07 2003 UTC (20 years, 9 months ago) by greg
Content type: text/plain
Branch: MAIN
Log Message:
Added tone-mapping support for 16-bit/sample int and IEEE float TIFF images

File Contents

# Content
1 #ifndef lint
2 static const char RCSid[] = "$Id$";
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 while (!(i & 0x8000)) {
64 i <<= 1;
65 ++s;
66 }
67 return(s);
68 }
69
70
71 /* Find common normalizing shift for 3 2-byte unsigned integers */
72 static int
73 normShift48(uint16 clr48[3])
74 {
75 int imax = (clr48[1] > clr48[0] ? clr48[1] : clr48[0]);
76 if (clr48[2] > imax)
77 imax = clr48[2];
78 return(normShift16(imax));
79 }
80
81
82 /* convert at 48-bit tristimulus value to a COLOR */
83 static void
84 rgb48_color(COLOR col, uint16 clr48[3])
85 {
86 int nshft;
87
88 if (cur_gam == 1.) { /* linear case */
89 col[0] = clr48[0]*(1./(1L<<16));
90 col[1] = clr48[1]*(1./(1L<<16));
91 col[2] = clr48[2]*(1./(1L<<16));
92 return;
93 }
94 /* non-linear case */
95 nshft = normShift48(clr48);
96 col[0] = gamtab[imultpow2(clr48[0],GAMTABBITS-16+nshft)] *
97 gammul[nshft];
98 col[1] = gamtab[imultpow2(clr48[1],GAMTABBITS-16+nshft)] *
99 gammul[nshft];
100 col[2] = gamtab[imultpow2(clr48[2],GAMTABBITS-16+nshft)] *
101 gammul[nshft];
102 }
103
104
105 /* Convert 16-bit gray scanline to encoded luminance */
106 int
107 tmCvGray16(TMbright *ls, uint16 *scan, int len, double gv)
108 {
109 static char funcName[] = "tmCvGray16";
110 static double cur_inpsf = 1.;
111 static double log_inpsf = 0.;
112 int nshft;
113 double d;
114
115 if (tmTop == NULL)
116 returnErr(TM_E_TMINVAL);
117 if (ls == NULL | scan == NULL | len < 0 | gv <= MINGAM)
118 returnErr(TM_E_ILLEGAL);
119 /* initialize log table */
120 if (logtab[0] == 0.f)
121 mkLogTable();
122 if (cur_inpsf != tmTop->inpsf)
123 log_inpsf = log(cur_inpsf = tmTop->inpsf);
124 /* convert 16-bit grays */
125 while (len--) {
126 nshft = normShift16(*scan);
127 d = logtab[ imultpow2(*scan,LOGTABBITS-15+nshft) &
128 ((1L<<LOGTABBITS)-1) ]
129 - M_LN2*nshft;
130 d = (double)TM_BRTSCALE * (gv*d + log_inpsf);
131 *ls++ = (d>0. ? d+.5 : d-.5);
132 scan++;
133 }
134 returnOK;
135 }
136
137 /* Convert a 48-bit RGB scanline to encoded luminance/chrominance */
138 int
139 tmCvRGB48(TMbright *ls, BYTE *cs, uint16 (*scan)[3], int len, double gv)
140 {
141 static char funcName[] = "tmCvRGB48";
142 static double cur_inpsf = 1.;
143 static double log_inpsf = 0.;
144 int i;
145
146 if (tmTop == NULL)
147 returnErr(TM_E_TMINVAL);
148 if (ls == NULL | scan == NULL | len < 0 | gv <= MINGAM)
149 returnErr(TM_E_ILLEGAL);
150 /* update gamma table */
151 if (gv != 1. & gv != cur_gam)
152 mkGamTable(gv);
153 #if 0
154 if (tmNeedMatrix(tmTop)) { /* need floating point */
155 #else
156 {
157 #endif
158 COLOR *newscan;
159 newscan = (COLOR *)tempbuffer(len*sizeof(COLOR));
160 if (newscan == NULL)
161 returnErr(TM_E_NOMEM);
162 for (i = len; i--; )
163 rgb48_color(newscan[i], scan[i]);
164 return(tmCvColors(ls, cs, newscan, len));
165 }
166 #if 0
167 /* initialize log table */
168 if (logtab[0] == 0.f)
169 mkLogTable();
170 if (cur_inpsf != tmTop->inpsf)
171 log_inpsf = log(cur_inpsf = tmTop->inpsf);
172 /* convert scanline */
173 for (i = len; i--; ) {
174 copycolr(cmon, scan[i]);
175 /* world luminance */
176 li = ( cd->clfb[RED]*cmon[RED] +
177 cd->clfb[GRN]*cmon[GRN] +
178 cd->clfb[BLU]*cmon[BLU] ) >> 8;
179 bi = BRT2SCALE(cmon[EXP]-COLXS) +
180 logi[li] + cd->inpsfb;
181 if (li <= 0) {
182 bi = TM_NOBRT; /* bogus value */
183 li = 1; /* avoid li==0 */
184 }
185 ls[i] = bi;
186 if (cs == TM_NOCHROM) /* no color? */
187 continue;
188 /* mesopic adj. */
189 if (tmTop->flags & TM_F_MESOPIC && bi < BMESUPPER) {
190 int pf, sli = normscot(cmon);
191 if (bi < BMESLOWER)
192 cmon[RED] = cmon[GRN] = cmon[BLU] = sli;
193 else {
194 if (tmTop->flags & TM_F_BW)
195 cmon[RED] = cmon[GRN] = cmon[BLU] = li;
196 pf = tmMesofact[bi-BMESLOWER];
197 sli *= 256 - pf;
198 cmon[RED] = ( sli + pf*cmon[RED] ) >> 8;
199 cmon[GRN] = ( sli + pf*cmon[GRN] ) >> 8;
200 cmon[BLU] = ( sli + pf*cmon[BLU] ) >> 8;
201 }
202 } else if (tmTop->flags & TM_F_BW) {
203 cmon[RED] = cmon[GRN] = cmon[BLU] = li;
204 }
205 bi = ( (int32)GAMTSZ*cd->clfb[RED]*cmon[RED]/li ) >> 8;
206 cs[3*i ] = bi>=GAMTSZ ? 255 : cd->gamb[bi];
207 bi = ( (int32)GAMTSZ*cd->clfb[GRN]*cmon[GRN]/li ) >> 8;
208 cs[3*i+1] = bi>=GAMTSZ ? 255 : cd->gamb[bi];
209 bi = ( (int32)GAMTSZ*cd->clfb[BLU]*cmon[BLU]/li ) >> 8;
210 cs[3*i+2] = bi>=GAMTSZ ? 255 : cd->gamb[bi];
211 }
212 returnOK;
213 #endif
214 }