ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/common/tmapcolrs.c
Revision: 3.26
Committed: Mon Feb 9 20:48:08 2009 UTC (15 years, 2 months ago) by greg
Content type: text/plain
Branch: MAIN
CVS Tags: rad4R0
Changes since 3.25: +2 -1 lines
Log Message:
Eliminated redefinition of malloc(3)

File Contents

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