ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/common/tmapcolrs.c
Revision: 3.30
Committed: Tue Jun 28 21:11:04 2011 UTC (12 years, 9 months ago) by greg
Content type: text/plain
Branch: MAIN
CVS Tags: rad4R2P2, rad5R0, rad4R2, rad4R1, rad4R2P1
Changes since 3.29: +2 -2 lines
Log Message:
Minor compile fixes

File Contents

# Content
1 #ifndef lint
2 static const char RCSid[] = "$Id: tmapcolrs.c,v 3.29 2011/05/20 02:06:38 greg Exp $";
3 #endif
4 /*
5 * Routines for tone mapping on Radiance RGBE and XYZE pictures.
6 *
7 * Externals declared in tonemap.h
8 */
9
10 #include "copyright.h"
11
12 #include <stdio.h>
13 #include <stdlib.h>
14 #include <string.h>
15 #include <math.h>
16 #include <time.h>
17
18 #ifdef PCOND
19 #include "rtprocess.h"
20 #endif
21 #include "tmprivat.h"
22 #include "resolu.h"
23
24 #define GAMTSZ 4096
25
26 typedef struct {
27 uby8 gamb[GAMTSZ]; /* gamma lookup table */
28 int clfb[3]; /* encoded tm->clf */
29 int32 cmatb[3][3]; /* encoded color transform */
30 TMbright inpsfb; /* encoded tm->inpsf */
31 } COLRDATA;
32
33 static MEM_PTR colrInit(TMstruct *);
34 static void colrNewSpace(TMstruct *);
35 static gethfunc headline;
36
37 static struct tmPackage colrPkg = { /* our package functions */
38 colrInit, colrNewSpace, free
39 };
40 static int colrReg = -1; /* our package registration number */
41
42 static TMbright logi[256];
43
44
45 int
46 tmCvColrs( /* convert RGBE/XYZE colors */
47 TMstruct *tms,
48 TMbright *ls,
49 uby8 *cs,
50 COLR *scan,
51 int len
52 )
53 {
54 static const char funcName[] = "tmCvColrs";
55 int cmon[4];
56 COLRDATA *cd;
57 int i, j, bi;
58 int32 li, vl;
59
60 if (tms == NULL)
61 returnErr(TM_E_TMINVAL);
62 if ((ls == NULL) | (scan == NULL) | (len < 0))
63 returnErr(TM_E_ILLEGAL);
64 if (colrReg < 0) { /* build tables if necessary */
65 colrReg = tmRegPkg(&colrPkg);
66 if (colrReg < 0)
67 returnErr(TM_E_CODERR1);
68 for (i = 256; i--; )
69 logi[i] = TM_BRTSCALE*log((i+.5)/256.) - .5;
70 tmMkMesofact();
71 }
72 if ((cd = (COLRDATA *)tmPkgData(tms,colrReg)) == NULL)
73 returnErr(TM_E_NOMEM);
74 for (i = len; i--; ) {
75 if (tmNeedMatrix(tms)) { /* apply color xform */
76 for (j = 3; j--; ) {
77 vl = cd->cmatb[j][RED]*(int32)scan[i][RED] +
78 cd->cmatb[j][GRN]*(int32)scan[i][GRN] +
79 cd->cmatb[j][BLU]*(int32)scan[i][BLU] ;
80 if (vl < 0) cmon[j] = vl/0x10000;
81 else cmon[j] = vl>>16;
82 }
83 cmon[EXP] = scan[i][EXP];
84 } else
85 copycolr(cmon, scan[i]);
86 /* world luminance */
87 li = cd->clfb[RED]*(int32)cmon[RED] +
88 cd->clfb[GRN]*(int32)cmon[GRN] +
89 cd->clfb[BLU]*(int32)cmon[BLU] ;
90 if (li >= 1L<<(12+8)) li = 255;
91 else li >>= 12;
92 bi = BRT2SCALE(cmon[EXP]-COLXS) + cd->inpsfb;
93 if (li > 0)
94 bi += logi[li];
95 else {
96 bi += logi[0];
97 li = 1; /* avoid /0 */
98 }
99 ls[i] = bi;
100 if (cs == TM_NOCHROM) /* no color? */
101 continue;
102 /* mesopic adj. */
103 if (tms->flags & TM_F_MESOPIC && bi < BMESUPPER) {
104 int pf, sli = normscot(cmon);
105 if (bi < BMESLOWER) {
106 cmon[RED] = cmon[GRN] = cmon[BLU] = sli;
107 } else {
108 if (tms->flags & TM_F_BW)
109 cmon[RED] = cmon[GRN] = cmon[BLU] = li;
110 pf = tmMesofact[bi-BMESLOWER];
111 sli *= 256 - pf;
112 for (j = 3; j--; ) {
113 cmon[j] = sli + pf*cmon[j];
114 if (cmon[j] <= 0) cmon[j] = 0;
115 else cmon[j] >>= 8;
116 }
117 }
118 } else if (tms->flags & TM_F_BW) {
119 cmon[RED] = cmon[GRN] = cmon[BLU] = li;
120 } else {
121 for (j = 3; j--; )
122 if (cmon[j] < 0) cmon[j] = 0;
123 }
124 bi = ( (uint32)GAMTSZ*cd->clfb[RED]*cmon[RED]/li ) >> 12;
125 cs[3*i ] = bi>=GAMTSZ ? 255 : cd->gamb[bi];
126 bi = ( (uint32)GAMTSZ*cd->clfb[GRN]*cmon[GRN]/li ) >> 12;
127 cs[3*i+1] = bi>=GAMTSZ ? 255 : cd->gamb[bi];
128 bi = ( (uint32)GAMTSZ*cd->clfb[BLU]*cmon[BLU]/li ) >> 12;
129 cs[3*i+2] = bi>=GAMTSZ ? 255 : cd->gamb[bi];
130 }
131 returnOK;
132 }
133
134
135 #define FMTRGB 1 /* Input is RGBE */
136 #define FMTCIE 2 /* Input is CIE XYZE */
137 #define FMTUNK 3 /* Input format is unspecified */
138 #define FMTBAD 4 /* Input is not a recognized format */
139
140 static struct radhead {
141 int format; /* FMTRGB, FMTCIE, FMTUNK, FMTBAD */
142 double expos; /* input exposure value */
143 RGBPRIMP primp; /* input primaries */
144 RGBPRIMS mypri; /* custom primaries */
145 } rhdefault = {FMTUNK, 1., stdprims, STDPRIMS};
146
147
148 static int
149 headline( /* grok a header line */
150 char *s,
151 void *vrh
152 )
153 {
154 char fmt[32];
155 struct radhead *rh = vrh;
156
157 if (formatval(fmt, s)) {
158 if (!strcmp(fmt, COLRFMT))
159 rh->format = FMTRGB;
160 else if (!strcmp(fmt, CIEFMT))
161 rh->format = FMTCIE;
162 else
163 rh->format = FMTBAD;
164 return(0);
165 }
166 if (isexpos(s)) {
167 rh->expos *= exposval(s);
168 return(0);
169 }
170 if (isprims(s)) {
171 primsval(rh->mypri, s);
172 rh->primp = rh->mypri;
173 return(0);
174 }
175 return(0);
176 }
177
178
179 int
180 tmLoadPicture( /* convert Radiance picture */
181 TMstruct *tms,
182 TMbright **lpp,
183 uby8 **cpp,
184 int *xp,
185 int *yp,
186 char *fname,
187 FILE *fp
188 )
189 {
190 char *funcName = fname==NULL ? "tmLoadPicture" : fname;
191 FILE *inpf;
192 struct radhead info;
193 int err;
194 COLR *scanin = NULL;
195 int i;
196 /* check arguments */
197 if (tms == NULL)
198 returnErr(TM_E_TMINVAL);
199 if ((lpp == NULL) | (xp == NULL) | (yp == NULL) |
200 ((fname == NULL) & (fp == TM_GETFILE)))
201 returnErr(TM_E_ILLEGAL);
202 *xp = *yp = 0; /* error precaution */
203 if ((inpf = fp) == TM_GETFILE && (inpf = fopen(fname, "rb")) == NULL)
204 returnErr(TM_E_BADFILE);
205 *lpp = NULL;
206 if (cpp != TM_NOCHROMP) *cpp = NULL;
207 info = rhdefault; /* get our header */
208 getheader(inpf, headline, &info);
209 if ((info.format == FMTBAD) | (info.expos <= 0.) ||
210 fgetresolu(xp, yp, inpf) < 0) {
211 err = TM_E_BADFILE; goto done;
212 }
213 if (info.format == FMTUNK) /* assume RGBE format */
214 info.format = FMTRGB;
215 if (info.format == FMTRGB)
216 info.expos /= WHTEFFICACY;
217 else if (info.format == FMTCIE)
218 info.primp = TM_XYZPRIM;
219 /* prepare library */
220 if ((err = tmSetSpace(tms, info.primp, 1./info.expos, NULL)) != TM_E_OK)
221 goto done;
222 err = TM_E_NOMEM; /* allocate arrays */
223 *lpp = (TMbright *)malloc(sizeof(TMbright) * *xp * *yp);
224 if (*lpp == NULL)
225 goto done;
226 if (cpp != TM_NOCHROMP) {
227 *cpp = (uby8 *)malloc(3*sizeof(uby8) * *xp * *yp);
228 if (*cpp == NULL)
229 goto done;
230 }
231 scanin = (COLR *)malloc(sizeof(COLR) * *xp);
232 if (scanin == NULL)
233 goto done;
234 err = TM_E_BADFILE; /* read & convert scanlines */
235 for (i = 0; i < *yp; i++) {
236 if (freadcolrs(scanin, *xp, inpf) < 0) {
237 err = TM_E_BADFILE; break;
238 }
239 err = tmCvColrs(tms, *lpp + (i * *xp),
240 cpp==TM_NOCHROMP ? TM_NOCHROM : *cpp + (i * 3 * *xp),
241 scanin, *xp);
242 if (err != TM_E_OK)
243 break;
244 }
245 done: /* clean up */
246 if (fp == NULL)
247 fclose(inpf);
248 if (scanin != NULL)
249 free((MEM_PTR)scanin);
250 if (err != TM_E_OK) {
251 if (*lpp != NULL)
252 free((MEM_PTR)*lpp);
253 if (cpp != TM_NOCHROMP && *cpp != NULL)
254 free((MEM_PTR)*cpp);
255 returnErr(err);
256 }
257 returnOK;
258 }
259
260
261 #ifdef PCOND
262 static int /* run pcond to map picture */
263 dopcond(psp, xp, yp, flags, monpri, gamval, Lddyn, Ldmax, fname)
264 uby8 **psp;
265 int *xp, *yp;
266 int flags;
267 RGBPRIMP monpri;
268 double gamval, Lddyn, Ldmax;
269 char *fname;
270 {
271 char *funcName = fname;
272 TMstruct *tms = NULL;
273 char cmdbuf[1024];
274 FILE *infp;
275 COLR *scan;
276 uby8 *rp;
277 int y;
278 int x;
279 /* set up gamma correction */
280 if (setcolrcor(pow, 1./gamval) < 0)
281 returnErr(TM_E_NOMEM);
282 /* create command */
283 strcpy(cmdbuf, PCOND);
284 if (flags & TM_F_HCONTR)
285 strcat(cmdbuf, " -s");
286 if (flags & TM_F_MESOPIC)
287 strcat(cmdbuf, " -c");
288 if (flags & TM_F_LINEAR)
289 strcat(cmdbuf, " -l");
290 if (flags & TM_F_ACUITY)
291 strcat(cmdbuf, " -a");
292 if (flags & TM_F_VEIL)
293 strcat(cmdbuf, " -v");
294 if (flags & TM_F_CWEIGHT)
295 strcat(cmdbuf, " -w");
296 if (monpri != stdprims)
297 sprintf(cmdbuf+strlen(cmdbuf), " -p %f %f %f %f %f %f %f %f",
298 monpri[RED][CIEX], monpri[RED][CIEY],
299 monpri[GRN][CIEX], monpri[GRN][CIEY],
300 monpri[BLU][CIEX], monpri[BLU][CIEY],
301 monpri[WHT][CIEX], monpri[WHT][CIEY]);
302 sprintf(cmdbuf+strlen(cmdbuf), " -d %f -u %f %s", Lddyn, Ldmax, fname);
303 /* start pcond */
304 if ((infp = popen(cmdbuf, "r")) == NULL)
305 returnErr(TM_E_BADFILE);
306 /* check picture format and size */
307 if (checkheader(infp, COLRFMT, NULL) < 0 ||
308 fgetresolu(xp, yp, infp) < 0) {
309 pclose(infp);
310 returnErr(TM_E_BADFILE);
311 }
312 /* allocate arrays */
313 scan = (COLR *)malloc(sizeof(COLR) * *xp);
314 if (flags & TM_F_BW)
315 rp = (uby8 *)malloc(sizeof(uby8) * *xp * *yp);
316 else
317 rp = (uby8 *)malloc(3*sizeof(uby8) * *xp * *yp);
318 if (((*psp = rp) == NULL) | (scan == NULL)) {
319 pclose(infp);
320 returnErr(TM_E_NOMEM);
321 }
322 /* read and gamma map file */
323 for (y = 0; y < *yp; y++) {
324 if (freadcolrs(scan, *xp, infp) < 0) {
325 pclose(infp);
326 free((MEM_PTR)scan);
327 free((MEM_PTR)*psp);
328 *psp = NULL;
329 returnErr(TM_E_BADFILE);
330 }
331 colrs_gambs(scan, *xp);
332 if (flags & TM_F_BW)
333 for (x = 0; x < *xp; x++)
334 *rp++ = normbright(scan[x]);
335 else
336 for (x = 0; x < *xp; x++) {
337 *rp++ = scan[x][RED];
338 *rp++ = scan[x][GRN];
339 *rp++ = scan[x][BLU];
340 }
341 }
342 free((MEM_PTR)scan);
343 pclose(infp);
344 returnOK;
345 }
346 #endif
347
348
349 int /* map a Radiance picture */
350 tmMapPicture(psp, xp, yp, flags, monpri, gamval, Lddyn, Ldmax, fname, fp)
351 uby8 **psp;
352 int *xp, *yp;
353 int flags;
354 RGBPRIMP monpri;
355 double gamval, Lddyn, Ldmax;
356 char *fname;
357 FILE *fp;
358 {
359 char *funcName = fname==NULL ? "tmMapPicture" : fname;
360 TMstruct *tms = NULL;
361 uby8 *cp;
362 TMbright *lp;
363 int err;
364 /* check arguments */
365 if ((psp == NULL) | (xp == NULL) | (yp == NULL) | (monpri == NULL) |
366 ((fname == NULL) & (fp == TM_GETFILE)))
367 returnErr(TM_E_ILLEGAL);
368 /* set defaults */
369 if (gamval < MINGAM) gamval = DEFGAM;
370 if (Lddyn < MINLDDYN) Lddyn = DEFLDDYN;
371 if (Ldmax < MINLDMAX) Ldmax = DEFLDMAX;
372 if (flags & TM_F_BW) monpri = stdprims;
373 #ifdef PCOND
374 /* check for pcond run */
375 if (fp == TM_GETFILE && flags & TM_F_UNIMPL)
376 return( dopcond(psp, xp, yp, flags,
377 monpri, gamval, Lddyn, Ldmax, fname) );
378 #endif
379 /* initialize tone mapping */
380 if ((tms = tmInit(flags, monpri, gamval)) == NULL)
381 returnErr(TM_E_NOMEM);
382 /* load & convert picture */
383 err = tmLoadPicture(tms, &lp, (flags&TM_F_BW) ? TM_NOCHROMP : &cp,
384 xp, yp, fname, fp);
385 if (err != TM_E_OK) {
386 tmDone(tms);
387 return(err);
388 }
389 /* allocate space for result */
390 if (flags & TM_F_BW) {
391 *psp = (uby8 *)malloc(sizeof(uby8) * *xp * *yp);
392 if (*psp == NULL) {
393 free((MEM_PTR)lp);
394 tmDone(tms);
395 returnErr(TM_E_NOMEM);
396 }
397 cp = TM_NOCHROM;
398 } else
399 *psp = cp;
400 /* compute color mapping */
401 err = tmAddHisto(tms, lp, *xp * *yp, 1);
402 if (err != TM_E_OK)
403 goto done;
404 err = tmComputeMapping(tms, gamval, Lddyn, Ldmax);
405 if (err != TM_E_OK)
406 goto done;
407 /* map colors */
408 err = tmMapPixels(tms, *psp, lp, cp, *xp * *yp);
409
410 done: /* clean up */
411 free((MEM_PTR)lp);
412 tmDone(tms);
413 if (err != TM_E_OK) { /* free memory on error */
414 free((MEM_PTR)*psp);
415 *psp = NULL;
416 returnErr(err);
417 }
418 returnOK;
419 }
420
421
422 static void
423 colrNewSpace(tms) /* color space changed for tone mapping */
424 TMstruct *tms;
425 {
426 COLRDATA *cd;
427 double d;
428 int i, j;
429
430 cd = (COLRDATA *)tms->pd[colrReg];
431 for (i = 3; i--; )
432 cd->clfb[i] = 0x1000*tms->clf[i] + .5;
433 cd->inpsfb = tmCvLuminance(tms->inpsf);
434 for (i = 3; i--; )
435 for (j = 3; j--; ) {
436 d = tms->cmat[i][j] / tms->inpsf;
437 cd->cmatb[i][j] = 0x10000*d + (d<0. ? -.5 : .5);
438 }
439 }
440
441
442 static MEM_PTR
443 colrInit(tms) /* initialize private data for tone mapping */
444 TMstruct *tms;
445 {
446 COLRDATA *cd;
447 int i;
448 /* allocate our data */
449 cd = (COLRDATA *)malloc(sizeof(COLRDATA));
450 if (cd == NULL)
451 return(NULL);
452 tms->pd[colrReg] = (MEM_PTR)cd;
453 /* compute gamma table */
454 for (i = GAMTSZ; i--; )
455 cd->gamb[i] = 256.*pow((i+.5)/GAMTSZ, 1./tms->mongam);
456 /* compute color and scale factors */
457 colrNewSpace(tms);
458 return((MEM_PTR)cd);
459 }