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

# Content
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 }