ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/common/tmapluv.c
Revision: 3.1
Committed: Thu Oct 22 13:53:06 1998 UTC (25 years, 6 months ago) by gwlarson
Content type: text/plain
Branch: MAIN
Log Message:
Initial revision

File Contents

# User Rev Content
1 gwlarson 3.1 /* Copyright (c) 1998 Silicon Graphics, Inc. */
2    
3     #ifndef lint
4     static char SCCSid[] = "$SunId$ SGI";
5     #endif
6    
7     /*
8     * Routines for tone-mapping LogLuv encoded pixels.
9     */
10    
11     #include <stdio.h>
12     #include <math.h>
13     #include "tiffio.h"
14     #include "tmprivat.h"
15     #include "uvcode.h"
16    
17     #ifndef BSD
18     #define bzero(d,n) (void)memset(d,0,n)
19     #endif
20     #define uvflgop(p,uv,op) ((p)->rgbflg[(uv)>>5] op (1L<<((uv)&0x1f)))
21     #define isuvset(p,uv) uvflgop(p,uv,&)
22     #define setuv(p,uv) uvflgop(p,uv,|=)
23     #define clruv(p,uv) uvflgop(p,uv,&=~)
24     #define clruvall(p) bzero((MEM_PTR)(p)->rgbflg,sizeof((p)->rgbflg))
25    
26     #define U_NEU 0.210526316
27     #define V_NEU 0.473684211
28    
29     static MEM_PTR luv32Init();
30     static void luv32NewSpace();
31     static MEM_PTR luv24Init();
32     static void luv24NewSpace();
33     extern void free();
34    
35     typedef struct {
36     int offset; /* computed luminance offset */
37     BYTE rgbval[1<<16][3]; /* computed RGB value for given uv */
38     uint32 rgbflg[1<<(16-5)]; /* flags for computed values */
39     } LUV32DATA; /* LogLuv 32-bit conversion data */
40    
41     #define UVSCALE 410.
42     #define UVNEU ((int)(UVSCALE*U_NEU)<<8 \
43     | (int)(UVSCALE*V_NEU))
44    
45     static struct tmPackage luv32Pkg = { /* 32-bit package functions */
46     luv32Init, luv32NewSpace, free
47     };
48     static int luv32Reg = -1; /* 32-bit package reg. number */
49    
50     typedef struct {
51     int offset; /* computed luminance offset */
52     BYTE rgbval[1<<14][3]; /* computed rgb value for uv index */
53     uint32 rgbflg[1<<(14-5)]; /* flags for computed values */
54     } LUV24DATA; /* LogLuv 24-bit conversion data */
55    
56     static struct tmPackage luv24Pkg = { /* 24-bit package functions */
57     luv24Init, luv24NewSpace, free
58     };
59     static int luv24Reg = -1; /* 24-bit package reg. number */
60    
61     static int uv14neu = -1; /* neutral index for 14-bit (u',v') */
62    
63    
64     static
65     uv2rgb(rgb, tm, uvp) /* compute RGB from uv coordinate */
66     BYTE rgb[3];
67     register struct tmStruct *tm;
68     double uvp[2];
69     { /* Should check that tm->inppri==TM_XYZPRIM beforehand... */
70     double d, x, y;
71     COLR XYZ, RGB;
72     /* convert to XYZ */
73     d = 1./(6.*uvp[0] - 16.*uvp[1] + 12.);
74     x = 9.*uvp[0] * d;
75     y = 4.*uvp[1] * d;
76     XYZ[CIEY] = 1./tm->inpsf;
77     XYZ[CIEX] = x/y * XYZ[CIEY];
78     XYZ[CIEZ] = (1.-x-y)/y * XYZ[CIEY];
79     /* convert to RGB and clip */
80     colortrans(RGB, tm->cmat, XYZ);
81     clipgamut(RGB, XYZ[CIEY], CGAMUT_LOWER, cblack, cwhite);
82     /* perform final scaling & gamma */
83     d = tm->clf[RED] * RGB[RED];
84     rgb[RED] = d>=.999 ? 255 : (int)(256.*pow(d, 1./tm->mongam));
85     d = tm->clf[GRN] * RGB[GRN];
86     rgb[GRN] = d>=.999 ? 255 : (int)(256.*pow(d, 1./tm->mongam));
87     d = tm->clf[BLU] * RGB[BLU];
88     rgb[BLU] = d>=.999 ? 255 : (int)(256.*pow(d, 1./tm->mongam));
89     }
90    
91    
92     static TMbright
93     compmeshift(li, uvp) /* compute mesopic color shift */
94     TMbright li; /* encoded world luminance */
95     double uvp[2]; /* world (u',v') -> returned desaturated */
96     {
97     /* UNIMPLEMENTED */
98     return(li);
99     }
100    
101    
102     static int
103     uvpencode(uvp) /* encode (u',v') coordinates */
104     double uvp[2];
105     {
106     register int vi, ui;
107    
108     if (uvp[1] < UV_VSTART)
109     return(-1);
110     vi = (uvp[1] - UV_VSTART)*(1./UV_SQSIZ);
111     if (vi >= UV_NVS)
112     return(-1);
113     if (uvp[0] < uv_row[vi].ustart)
114     return(-1);
115     ui = (uvp[0] - uv_row[vi].ustart)*(1./UV_SQSIZ);
116     if (ui >= uv_row[vi].nus)
117     return(-1);
118     return(uv_row[vi].ncum + ui);
119     }
120    
121    
122     static int
123     uvpdecode(uvp, c) /* decode (u',v') index */
124     double uvp[2];
125     int c;
126     {
127     int upper, lower;
128     register int ui, vi;
129    
130     if (c < 0 || c >= UV_NDIVS)
131     return(-1);
132     lower = 0; /* binary search */
133     upper = UV_NVS;
134     do {
135     vi = (lower + upper) >> 1;
136     ui = c - uv_row[vi].ncum;
137     if (ui > 0)
138     lower = vi;
139     else if (ui < 0)
140     upper = vi;
141     else
142     break;
143     } while (upper - lower > 1);
144     vi = lower;
145     ui = c - uv_row[vi].ncum;
146     uvp[0] = uv_row[vi].ustart + (ui+.5)*UV_SQSIZ;
147     uvp[1] = UV_VSTART + (vi+.5)*UV_SQSIZ;
148     return(0);
149     }
150    
151    
152     int
153     tmCvLuv32(ls, cs, luvs, len) /* convert raw 32-bit LogLuv values */
154     TMbright *ls;
155     BYTE *cs;
156     uint32 *luvs;
157     int len;
158     {
159     static char funcName[] = "tmCvLuv32";
160     double uvp[2];
161     register LUV32DATA *ld;
162     register int i, j;
163     /* check arguments */
164     if (tmTop == NULL)
165     returnErr(TM_E_TMINVAL);
166     if (ls == NULL | luvs == NULL | len < 0)
167     returnErr(TM_E_ILLEGAL);
168     /* check package registration */
169     if (luv32Reg < 0 && (luv32Reg = tmRegPkg(&luv32Pkg)) < 0)
170     returnErr(TM_E_CODERR1);
171     /* get package data */
172     if ((ld = (LUV32DATA *)tmPkgData(tmTop,luv32Reg)) == NULL)
173     returnErr(TM_E_NOMEM);
174     /* convert each pixel */
175     for (i = len; i--; ) {
176     j = luvs[i] >> 16; /* get luminance */
177     if (j & 0x8000) /* negative luminance */
178     ls[i] = MINBRT-1; /* assign bogus value */
179     else /* else convert to lnL */
180     ls[i] = (BRT2SCALE*j >> 8) - ld->offset;
181     if (cs == TM_NOCHROM) /* no color? */
182     continue;
183     /* get chrominance */
184     if (tmTop->flags & TM_F_MESOPIC && ls[i] < BMESUPPER) {
185     uvp[0] = 1./UVSCALE*((luvs[i]>>8 & 0xff) + .5);
186     uvp[1] = 1./UVSCALE*((luvs[i] & 0xff) + .5);
187     ls[i] = compmeshift(ls[i], uvp);
188     j = tmTop->flags & TM_F_BW || ls[i] < BMESLOWER
189     ? UVNEU
190     : (int)(uvp[0]*UVSCALE)<<8
191     | (int)(uvp[1]*UVSCALE);
192     } else {
193     j = tmTop->flags&TM_F_BW ? UVNEU : luvs[i]&0xffff;
194     }
195     if (!isuvset(ld, j)) {
196     uvp[0] = 1./UVSCALE*((luvs[i]>>8 & 0xff) + .5);
197     uvp[1] = 1./UVSCALE*((luvs[i] & 0xff) + .5);
198     uv2rgb(ld->rgbval[j], tmTop, uvp);
199     setuv(ld, j);
200     }
201     cs[3*i ] = ld->rgbval[j][RED];
202     cs[3*i+1] = ld->rgbval[j][GRN];
203     cs[3*i+2] = ld->rgbval[j][BLU];
204     }
205     returnOK;
206     }
207    
208    
209     int
210     tmCvLuv24(ls, cs, luvs, len) /* convert raw 24-bit LogLuv values */
211     TMbright *ls;
212     BYTE *cs;
213     uint32 *luvs;
214     int len;
215     {
216     char funcName[] = "tmCvLuv24";
217     double uvp[2];
218     register LUV24DATA *ld;
219     register int i, j;
220     /* check arguments */
221     if (tmTop == NULL)
222     returnErr(TM_E_TMINVAL);
223     if (ls == NULL | luvs == NULL | len < 0)
224     returnErr(TM_E_ILLEGAL);
225     /* check package registration */
226     if (luv24Reg < 0 && (luv24Reg = tmRegPkg(&luv24Pkg)) < 0)
227     returnErr(TM_E_CODERR1);
228     /* get package data */
229     if ((ld = (LUV24DATA *)tmPkgData(tmTop,luv24Reg)) == NULL)
230     returnErr(TM_E_NOMEM);
231     /* convert each pixel */
232     for (i = len; i--; ) {
233     j = luvs[i] >> 14; /* get luminance */
234     ls[i] = (BRT2SCALE*j >> 6) - ld->offset;
235     if (cs == TM_NOCHROM) /* no color? */
236     continue;
237     /* get chrominance */
238     if (tmTop->flags & TM_F_MESOPIC && ls[i] < BMESUPPER) {
239     if (uvpdecode(uvp, luvs[i]&0x3fff) < 0) {
240     uvp[0] = U_NEU; /* should barf? */
241     uvp[1] = V_NEU;
242     }
243     ls[i] = compmeshift(ls[i], uvp);
244     if (tmTop->flags & TM_F_BW || ls[i] < BMESLOWER
245     || (j = uvpencode(uvp)) < 0)
246     j = uv14neu;
247     } else {
248     j = tmTop->flags&TM_F_BW ? uv14neu : luvs[i]&0x3fff;
249     }
250     if (!isuvset(ld, j)) {
251     if (uvpdecode(uvp, j) < 0) {
252     uvp[0] = U_NEU;
253     uvp[1] = V_NEU;
254     }
255     uv2rgb(ld->rgbval[j], tmTop, uvp);
256     setuv(ld, j);
257     }
258     cs[3*i ] = ld->rgbval[j][RED];
259     cs[3*i+1] = ld->rgbval[j][GRN];
260     cs[3*i+2] = ld->rgbval[j][BLU];
261     }
262     returnOK;
263     }
264    
265    
266     int
267     tmCvL16(ls, l16s, len) /* convert 16-bit LogL values */
268     TMbright *ls;
269     uint16 *l16s;
270     int len;
271     {
272     static char funcName[] = "tmCvL16";
273     static double lastsf;
274     static int offset;
275     register int i;
276     /* check arguments */
277     if (tmTop == NULL)
278     returnErr(TM_E_TMINVAL);
279     if (ls == NULL | l16s == NULL | len < 0)
280     returnErr(TM_E_ILLEGAL);
281     /* check scaling offset */
282     if (!FEQ(tmTop->inpsf, lastsf)) {
283     offset = BRT2SCALE*64;
284     if (tmTop->inpsf > 1.0001)
285     offset -= (int)(TM_BRTSCALE*log(tmTop->inpsf)+.5);
286     else if (tmTop->inpsf < 0.9999)
287     offset -= (int)(TM_BRTSCALE*log(tmTop->inpsf)-.5);
288     lastsf = tmTop->inpsf;
289     }
290     /* convert each pixel */
291     for (i = len; i--; ) {
292     if (l16s[i] & 0x8000) /* negative luminance */
293     ls[i] = MINBRT-1; /* assign bogus value */
294     else /* else convert to lnL */
295     ls[i] = (BRT2SCALE*l16s[i] >> 8) - offset;
296     }
297     returnOK;
298     }
299    
300    
301     static void
302     luv32NewSpace(tm) /* initialize 32-bit LogLuv color space */
303     struct tmStruct *tm;
304     {
305     register LUV32DATA *ld;
306    
307     if (tm->inppri != TM_XYZPRIM) { /* panic time! */
308     fputs("Improper input color space in luv32NewSpace!\n", stderr);
309     exit(1);
310     }
311     ld = (LUV32DATA *)tm->pd[luv32Reg];
312     ld->offset = BRT2SCALE*64;
313     if (tm->inpsf > 1.0001)
314     ld->offset -= (int)(TM_BRTSCALE*log(tmTop->inpsf)+.5);
315     else if (tm->inpsf < 0.9999)
316     ld->offset -= (int)(TM_BRTSCALE*log(tmTop->inpsf)-.5);
317     clruvall(ld);
318     }
319    
320    
321     static MEM_PTR
322     luv32Init(tm) /* allocate data for 32-bit LogLuv decoder */
323     struct tmStruct *tm;
324     {
325     register LUV32DATA *ld;
326    
327     ld = (LUV32DATA *)malloc(sizeof(LUV32DATA));
328     if (ld == NULL)
329     return(NULL);
330     tm->pd[luv32Reg] = (MEM_PTR)ld;
331     luv32NewSpace(tm);
332     return((MEM_PTR)ld);
333     }
334    
335    
336     static void
337     luv24NewSpace(tm) /* initialize 24-bit LogLuv color space */
338     struct tmStruct *tm;
339     {
340     register LUV24DATA *ld;
341     double uvp[2];
342    
343     if (tm->inppri != TM_XYZPRIM) { /* panic time! */
344     fputs("Improper input color space in luv24NewSpace!\n", stderr);
345     exit(1);
346     }
347     ld = (LUV24DATA *)tm->pd[luv24Reg];
348     ld->offset = BRT2SCALE*12;
349     if (tm->inpsf > 1.0001)
350     ld->offset -= (int)(TM_BRTSCALE*log(tmTop->inpsf)+.5);
351     else if (tm->inpsf < 0.9999)
352     ld->offset -= (int)(TM_BRTSCALE*log(tmTop->inpsf)-.5);
353     clruvall(ld);
354     }
355    
356    
357     static MEM_PTR
358     luv24Init(tm) /* allocate data for 24-bit LogLuv decoder */
359     struct tmStruct *tm;
360     {
361     register LUV24DATA *ld;
362    
363     ld = (LUV24DATA *)malloc(sizeof(LUV24DATA));
364     if (ld == NULL)
365     return(NULL);
366     tm->pd[luv24Reg] = (MEM_PTR)ld;
367     if (uv14neu < 0) { /* initialize neutral color index */
368     double uvp[2];
369     uvp[0] = U_NEU; uvp[1] = V_NEU;
370     uv14neu = uvpencode(uvp);
371     }
372     luv24NewSpace(tm);
373     return((MEM_PTR)ld);
374     }