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

# User Rev Content
1 greg 1.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     }