ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/common/tmapcolrs.c
Revision: 3.14
Committed: Sun Jul 27 22:12:01 2003 UTC (20 years, 9 months ago) by schorsch
Content type: text/plain
Branch: MAIN
Changes since 3.13: +8 -8 lines
Log Message:
Added grouping parens to reduce ambiguity warnings.

File Contents

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