ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/common/tmapcolrs.c
Revision: 3.9
Committed: Wed Oct 28 09:26:03 1998 UTC (25 years, 6 months ago) by gwlarson
Content type: text/plain
Branch: MAIN
Changes since 3.8: +18 -14 lines
Log Message:
made pcond calling optional

File Contents

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