ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/common/tmapcolrs.c
Revision: 3.25
Committed: Wed May 31 19:27:42 2006 UTC (17 years, 11 months ago) by greg
Content type: text/plain
Branch: MAIN
CVS Tags: rad3R8, rad3R9
Changes since 3.24: +1 -2 lines
Log Message:
Removed forgotten debug statement

File Contents

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