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

# User Rev Content
1 greg 1.1 #ifndef lint
2 greg 1.2 static const char RCSid[] = "$Id: tmap16bit.c,v 1.1 2003/07/14 18:21:07 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    
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 greg 1.2 if (!i)
64     return(-1);
65 greg 1.1 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 greg 1.2 rgb48_color(COLOR col, uint16 clr48[3], double gv)
87 greg 1.1 {
88     int nshft;
89    
90 greg 1.2 if (gv == 1.) { /* linear case */
91 greg 1.1 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 greg 1.2 /* XXX Uncomment if routine is made public
98     if (gv != cur_gam)
99     mkGamTable(gv);
100     */
101 greg 1.1 nshft = normShift48(clr48);
102 greg 1.2 if (nshft < 0) {
103     col[0] = col[1] = col[2] = .0f;
104     return;
105     }
106 greg 1.1 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 greg 1.2 if (ls == NULL | scan == NULL | len < 0)
128 greg 1.1 returnErr(TM_E_ILLEGAL);
129 greg 1.2 if (gv <= 0.)
130     gv = DEFGAM;
131 greg 1.1 /* 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 greg 1.2 if (nshft < 0) { /* bogus value */
140     *ls++ = TM_NOBRT;
141     scan++;
142     continue;
143     }
144 greg 1.1 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 greg 1.2 if (ls == NULL | scan == NULL | len < 0)
166 greg 1.1 returnErr(TM_E_ILLEGAL);
167 greg 1.2 if (gv <= 0.)
168     gv = DEFGAM;
169 greg 1.1 /* 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 greg 1.2 rgb48_color(newscan[i], scan[i], gv);
183 greg 1.1 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     }