ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/common/tmapcolrs.c
Revision: 3.34
Committed: Sat Dec 28 18:05:14 2019 UTC (4 years, 4 months ago) by greg
Content type: text/plain
Branch: MAIN
CVS Tags: rad5R3
Changes since 3.33: +1 -4 lines
Log Message:
Removed redundant include files

File Contents

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