ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/common/tmapcolrs.c
Revision: 3.1
Committed: Tue Apr 15 16:53:02 1997 UTC (27 years ago) by greg
Content type: text/plain
Branch: MAIN
Log Message:
Initial revision

File Contents

# User Rev Content
1 greg 3.1 /* Copyright (c) 1997 Regents of the University of California */
2    
3     #ifndef lint
4     static char SCCSid[] = "$SunId$ LBL";
5     #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     #define LOGISZ 260
21     static TMbright logi[LOGISZ];
22     static BYTE photofact[BMESUPPER-BMESLOWER];
23    
24    
25     int
26     tmCvColrs(ls, cs, scan, len) /* tone map RGBE/XYZE colors */
27     TMbright *ls;
28     BYTE *cs;
29     COLR *scan;
30     int len;
31     {
32     static char funcName[] = "tmCvColrs";
33     COLR cmon;
34     register int i, bi, li;
35    
36     if (tmTop == NULL)
37     returnErr(TM_E_TMINVAL);
38     if (ls == NULL | scan == NULL | len <= 0)
39     returnErr(TM_E_ILLEGAL);
40     if (tmTop->flags & TM_F_NEEDMAT) { /* need floating point */
41     register COLOR *newscan;
42     newscan = (COLOR *)tempbuffer(len*sizeof(COLOR));
43     if (newscan == NULL)
44     returnErr(TM_E_NOMEM);
45     for (i = len; i--; )
46     colr_color(newscan[i], scan[i]);
47     return(tmCvColors(ls, cs, newscan, len));
48     }
49     if (logi[0] == 0) { /* build tables if necessary */
50     for (i = 256; i--; )
51     logi[i] = TM_BRTSCALE*log((i+.5)/256.) - .5;
52     for (i = 256; i < LOGISZ; i++)
53     logi[i] = logi[255];
54     for (i = BMESLOWER; i < BMESUPPER; i++)
55     photofact[i-BMESLOWER] = 256. *
56     (tmLuminance(i) - LMESLOWER) /
57     (LMESUPPER - LMESLOWER);
58     }
59     for (i = len; i--; ) {
60     copycolr(cmon, scan[i]);
61     /* world luminance */
62     li = ( tmTop->clfb[RED]*cmon[RED] +
63     tmTop->clfb[GRN]*cmon[GRN] +
64     tmTop->clfb[BLU]*cmon[BLU] ) >> 8;
65     bi = BRT2SCALE*(cmon[EXP]-COLXS) +
66     logi[li] + tmTop->inpsfb;
67     if (bi < MINBRT) {
68     bi = MINBRT-1; /* bogus value */
69     li++; /* avoid li==0 */
70     }
71     ls[i] = bi;
72     if (cs == TM_NOCHROM) /* no color? */
73     continue;
74     /* mesopic adj. */
75     if (tmTop->flags & TM_F_MESOPIC && bi < BMESUPPER) {
76     register int pf, sli = normscot(cmon);
77     if (bi < BMESLOWER)
78     cmon[RED] = cmon[GRN] = cmon[BLU] = sli;
79     else {
80     if (tmTop->flags & TM_F_BW)
81     cmon[RED] = cmon[GRN] = cmon[BLU] = li;
82     pf = photofact[bi-BMESLOWER];
83     sli *= 256 - pf;
84     cmon[RED] = ( sli + pf*cmon[RED] ) >> 8;
85     cmon[GRN] = ( sli + pf*cmon[GRN] ) >> 8;
86     cmon[BLU] = ( sli + pf*cmon[BLU] ) >> 8;
87     }
88     } else if (tmTop->flags & TM_F_BW) {
89     cmon[RED] = cmon[GRN] = cmon[BLU] = li;
90     }
91     bi = ( (int4)TM_GAMTSZ*tmTop->clfb[RED]*cmon[RED]/li ) >> 8;
92     cs[3*i ] = bi>=TM_GAMTSZ ? 255 : tmTop->gamb[bi];
93     bi = ( (int4)TM_GAMTSZ*tmTop->clfb[GRN]*cmon[GRN]/li ) >> 8;
94     cs[3*i+1] = bi>=TM_GAMTSZ ? 255 : tmTop->gamb[bi];
95     bi = ( (int4)TM_GAMTSZ*tmTop->clfb[BLU]*cmon[BLU]/li ) >> 8;
96     cs[3*i+2] = bi>=TM_GAMTSZ ? 255 : tmTop->gamb[bi];
97     }
98     returnOK;
99     }
100    
101    
102     #define FMTRGB 1 /* Input is RGBE */
103     #define FMTCIE 2 /* Input is CIE XYZE */
104     #define FMTUNK 3 /* Input format is unspecified */
105     #define FMTBAD 4 /* Input is not a recognized format */
106    
107     static struct radhead {
108     int format; /* FMTRGB, FMTCIE, FMTUNK, FMTBAD */
109     double expos; /* input exposure value */
110     RGBPRIMP primp; /* input primaries */
111     RGBPRIMS mypri; /* custom primaries */
112     } rhdefault = {FMTUNK, 1., stdprims, STDPRIMS};
113    
114    
115     static int
116     headline(s, rh) /* grok a header line */
117     register char *s;
118     register struct radhead *rh;
119     {
120     char fmt[32];
121    
122     if (formatval(fmt, s)) {
123     if (!strcmp(fmt, COLRFMT))
124     rh->format = FMTRGB;
125     else if (!strcmp(fmt, CIEFMT))
126     rh->format = FMTCIE;
127     else
128     rh->format = FMTBAD;
129     return;
130     }
131     if (isexpos(s)) {
132     rh->expos *= exposval(s);
133     return;
134     }
135     if (isprims(s)) {
136     primsval(rh->mypri, s);
137     rh->primp = rh->mypri;
138     return;
139     }
140     }
141    
142    
143     int
144     tmLoadPicture(lpp, cpp, xp, yp, fname, fp) /* convert Radiance picture */
145     TMbright **lpp;
146     BYTE **cpp;
147     int *xp, *yp;
148     char *fname;
149     FILE *fp;
150     {
151     char *funcName = fname==NULL ? "tmLoadPicture" : fname;
152     FILE *inpf;
153     struct radhead info;
154     int err;
155     COLR *scanin = NULL;
156     int i;
157     /* check arguments */
158     if (tmTop == NULL)
159     returnErr(TM_E_TMINVAL);
160     if (lpp == NULL | xp == NULL | yp == NULL |
161     (fname == NULL & fp == TM_GETFILE))
162     returnErr(TM_E_ILLEGAL);
163     *xp = *yp = 0; /* error precaution */
164     if ((inpf = fp) == TM_GETFILE && (inpf = fopen(fname, "r")) == NULL)
165     returnErr(TM_E_BADFILE);
166     info = rhdefault; /* get our header */
167     getheader(inpf, headline, (char *)&info);
168     if (info.format == FMTBAD | info.expos <= 0. ||
169     fgetresolu(xp, yp, inpf) < 0) {
170     err = TM_E_BADFILE; goto done;
171     }
172     if (info.format == FMTUNK) /* assume RGBE format */
173     info.format = FMTRGB;
174     if (info.format == FMTRGB)
175     info.expos /= WHTEFFICACY;
176     else if (info.format == FMTCIE)
177     info.primp = TM_XYZPRIM;
178     /* prepare library */
179     if ((err = tmSetSpace(info.primp, 1./info.expos)) != TM_E_OK)
180     goto done;
181     err = TM_E_NOMEM; /* allocate arrays */
182     *lpp = (TMbright *)malloc(sizeof(TMbright) * *xp * *yp);
183     if (*lpp == NULL)
184     goto done;
185     if (cpp != TM_NOCHROMP) {
186     *cpp = (BYTE *)malloc(3*sizeof(BYTE) * *xp * *yp);
187     if (*cpp == NULL)
188     goto done;
189     }
190     scanin = (COLR *)malloc(sizeof(COLR) * *xp);
191     if (scanin == NULL)
192     goto done;
193     err = TM_E_BADFILE; /* read & convert scanlines */
194     for (i = 0; i < *yp; i++) {
195     if (freadcolrs(scanin, *xp, inpf) < 0) {
196     err = TM_E_BADFILE; break;
197     }
198     err = tmCvColrs(*lpp + (i * *xp),
199     cpp==TM_NOCHROMP ? TM_NOCHROM : *cpp + (i * 3 * *xp),
200     scanin, *xp);
201     if (err != TM_E_OK)
202     break;
203     }
204     done: /* clean up */
205     if (fp == NULL)
206     fclose(inpf);
207     if (scanin != NULL)
208     free((char *)scanin);
209     if (err != TM_E_OK)
210     returnErr(err);
211     returnOK;
212     }
213    
214    
215     int /* run pcond to map picture */
216     dopcond(psp, xp, yp, flags, monpri, gamval, Lddyn, Ldmax, fname)
217     BYTE **psp;
218     int *xp, *yp;
219     int flags;
220     RGBPRIMP monpri;
221     double gamval, Lddyn, Ldmax;
222     char *fname;
223     {
224     char *funcName = fname;
225     char cmdbuf[512];
226     FILE *infp;
227     register COLR *scan;
228     register BYTE *rp;
229     int y;
230     register int x;
231     /* set up gamma correction */
232     if (setcolrcor(pow, 1./gamval) < 0)
233     returnErr(TM_E_NOMEM);
234     /* create command */
235     strcpy(cmdbuf, "pcond ");
236     if (flags & TM_F_HCONTR)
237     strcat(cmdbuf, "-s ");
238     if (flags & TM_F_MESOPIC)
239     strcat(cmdbuf, "-c ");
240     if (flags & TM_F_LINEAR)
241     strcat(cmdbuf, "-l ");
242     if (flags & TM_F_ACUITY)
243     strcat(cmdbuf, "-a ");
244     if (flags & TM_F_VEIL)
245     strcat(cmdbuf, "-v ");
246     if (flags & TM_F_CWEIGHT)
247     strcat(cmdbuf, "-w ");
248     sprintf(cmdbuf+strlen(cmdbuf),
249     "-p %f %f %f %f %f %f %f %f -d %f -u %f %s",
250     monpri[RED][CIEX], monpri[RED][CIEY],
251     monpri[GRN][CIEX], monpri[GRN][CIEY],
252     monpri[BLU][CIEX], monpri[BLU][CIEY],
253     monpri[WHT][CIEX], monpri[WHT][CIEY],
254     Lddyn, Ldmax, fname);
255     /* start pcond */
256     if ((infp = popen(cmdbuf, "r")) == NULL)
257     returnErr(TM_E_BADFILE);
258     /* check picture format and size */
259     if (checkheader(infp, COLRFMT, NULL) < 0 ||
260     fgetresolu(xp, yp, infp) < 0) {
261     pclose(infp);
262     returnErr(TM_E_BADFILE);
263     }
264     /* allocate arrays */
265     if (flags & TM_F_BW)
266     rp = (BYTE *)malloc(sizeof(BYTE) * *xp * *yp);
267     else
268     rp = (BYTE *)malloc(3*sizeof(BYTE) * *xp * *yp);
269     scan = (COLR *)malloc(sizeof(COLR) * *xp);
270     if ((*psp = rp) == NULL | scan == NULL) {
271     pclose(infp);
272     returnErr(TM_E_NOMEM);
273     }
274     /* read and gamma map file */
275     for (y = 0; y < *yp; y++) {
276     if (freadcolrs(scan, *xp, infp) < 0) {
277     pclose(infp);
278     returnErr(TM_E_BADFILE);
279     }
280     colrs_gambs(scan, *xp);
281     if (flags & TM_F_BW)
282     for (x = 0; x < *xp; x++)
283     *rp++ = normbright(scan[x]);
284     else
285     for (x = 0; x < *xp; x++) {
286     *rp++ = scan[x][RED];
287     *rp++ = scan[x][GRN];
288     *rp++ = scan[x][BLU];
289     }
290     }
291     free((char *)scan);
292     pclose(infp);
293     returnOK;
294     }
295    
296    
297     int /* map a Radiance picture */
298     tmMapPicture(psp, xp, yp, flags, monpri, gamval, Lddyn, Ldmax, fname, fp)
299     BYTE **psp;
300     int *xp, *yp;
301     int flags;
302     RGBPRIMP monpri;
303     double gamval, Lddyn, Ldmax;
304     char *fname;
305     FILE *fp;
306     {
307     char *funcName = fname==NULL ? "tmMapPicture" : fname;
308     FILE *inpf;
309     BYTE *cp;
310     TMbright *lp;
311     int err;
312     /* check arguments */
313     if (psp == NULL | xp == NULL | yp == NULL | monpri == NULL |
314     (fname == NULL & fp == TM_GETFILE))
315     returnErr(TM_E_ILLEGAL);
316     /* set defaults */
317     if (gamval < MINGAM) gamval = DEFGAM;
318     if (Lddyn < MINLDDYN) Lddyn = DEFLDDYN;
319     if (Ldmax < MINLDMAX) Ldmax = DEFLDMAX;
320     if (flags & TM_F_BW) monpri = stdprims;
321     /* check for pcond run */
322     if (fp == TM_GETFILE && flags & TM_F_UNIMPL)
323     return( dopcond(psp, xp, yp, flags,
324     monpri, gamval, Lddyn, Ldmax, fname) );
325     /* initialize tone mapping */
326     if (tmInit(flags, monpri, gamval) == NULL)
327     returnErr(TM_E_NOMEM);
328     /* load & convert picture */
329     err = tmLoadPicture(&lp, (flags&TM_F_BW) ? TM_NOCHROMP : &cp,
330     xp, yp, fname, fp);
331     if (err != TM_E_OK) {
332     tmDone(NULL);
333     return(err);
334     }
335     /* allocate space for result */
336     if (flags & TM_F_BW) {
337     *psp = (BYTE *)malloc(sizeof(BYTE) * *xp * *yp);
338     if (*psp == NULL)
339     returnErr(TM_E_NOMEM);
340     cp = TM_NOCHROM;
341     } else
342     *psp = cp;
343     /* compute color mapping */
344     err = tmAddHisto(lp, *xp * *yp, 1);
345     if (err != TM_E_OK)
346     goto done;
347     err = tmComputeMapping(gamval, Lddyn, Ldmax);
348     if (err != TM_E_OK)
349     goto done;
350     /* map colors */
351     err = tmMapPixels(*psp, lp, cp, *xp * *yp);
352    
353     done: /* clean up */
354     free((char *)lp);
355     tmDone(NULL);
356     if (err != TM_E_OK) { /* free memory on error */
357     free((char *)*psp);
358     *psp = NULL;
359     returnErr(err);
360     }
361     returnOK;
362     }