ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/common/tmapcolrs.c
Revision: 3.11
Committed: Tue Feb 25 02:47:22 2003 UTC (21 years, 2 months ago) by greg
Content type: text/plain
Branch: MAIN
CVS Tags: rad3R5
Changes since 3.10: +1 -56 lines
Log Message:
Replaced inline copyright notice with #include "copyright.h"

File Contents

# Content
1 #ifndef lint
2 static const char RCSid[] = "$Id$";
3 #endif
4 /*
5 * Routines for tone mapping on Radiance RGBE and XYZE pictures.
6 *
7 * Externals declared in tonemap.h
8 */
9
10 #include "copyright.h"
11
12 #include <stdio.h>
13 #include <string.h>
14 #include <math.h>
15 #include <time.h>
16 #include "tmprivat.h"
17 #include "resolu.h"
18
19 #ifndef TM_PIC_CTRANS
20 #define TM_PIC_CTRANS 1 /* transform colors? (expensive) */
21 #endif
22
23 #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 #ifdef NOPROTO
32 static MEM_PTR colrInit();
33 static void colrNewSpace();
34 #else
35 static MEM_PTR colrInit(struct tmStruct *);
36 static void colrNewSpace(struct tmStruct *);
37 #endif
38 static struct tmPackage colrPkg = { /* our package functions */
39 colrInit, colrNewSpace, free
40 };
41 static int colrReg = -1; /* our package registration number */
42
43 #define LOGISZ 260
44 static TMbright logi[LOGISZ];
45
46
47 int
48 tmCvColrs(ls, cs, scan, len) /* convert RGBE/XYZE colors */
49 TMbright *ls;
50 BYTE *cs;
51 COLR *scan;
52 int len;
53 {
54 static char funcName[] = "tmCvColrs";
55 COLR cmon;
56 register COLRDATA *cd;
57 register int i, bi, li;
58
59 if (tmTop == NULL)
60 returnErr(TM_E_TMINVAL);
61 if (ls == NULL | scan == NULL | len < 0)
62 returnErr(TM_E_ILLEGAL);
63 #if TM_PIC_CTRANS
64 if (tmNeedMatrix(tmTop)) { /* need floating point */
65 #else
66 if (tmTop->inppri == TM_XYZPRIM) { /* no way around this */
67 #endif
68 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 if (colrReg < 0) { /* build tables if necessary */
77 colrReg = tmRegPkg(&colrPkg);
78 if (colrReg < 0)
79 returnErr(TM_E_CODERR1);
80 for (i = 256; i--; )
81 logi[i] = TM_BRTSCALE*log((i+.5)/256.) - .5;
82 for (i = 256; i < LOGISZ; i++)
83 logi[i] = 0;
84 tmMkMesofact();
85 }
86 if ((cd = (COLRDATA *)tmPkgData(tmTop,colrReg)) == NULL)
87 returnErr(TM_E_NOMEM);
88 for (i = len; i--; ) {
89 copycolr(cmon, scan[i]);
90 /* world luminance */
91 li = ( cd->clfb[RED]*cmon[RED] +
92 cd->clfb[GRN]*cmon[GRN] +
93 cd->clfb[BLU]*cmon[BLU] ) >> 8;
94 bi = BRT2SCALE(cmon[EXP]-COLXS) +
95 logi[li] + cd->inpsfb;
96 if (li <= 0) {
97 bi = TM_NOBRT; /* bogus value */
98 li = 1; /* avoid li==0 */
99 }
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 if (tmTop->flags & TM_F_BW)
110 cmon[RED] = cmon[GRN] = cmon[BLU] = li;
111 pf = tmMesofact[bi-BMESLOWER];
112 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 } else if (tmTop->flags & TM_F_BW) {
118 cmon[RED] = cmon[GRN] = cmon[BLU] = li;
119 }
120 bi = ( (int4)GAMTSZ*cd->clfb[RED]*cmon[RED]/li ) >> 8;
121 cs[3*i ] = bi>=GAMTSZ ? 255 : cd->gamb[bi];
122 bi = ( (int4)GAMTSZ*cd->clfb[GRN]*cmon[GRN]/li ) >> 8;
123 cs[3*i+1] = bi>=GAMTSZ ? 255 : cd->gamb[bi];
124 bi = ( (int4)GAMTSZ*cd->clfb[BLU]*cmon[BLU]/li ) >> 8;
125 cs[3*i+2] = bi>=GAMTSZ ? 255 : cd->gamb[bi];
126 }
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 return(0);
159 }
160 if (isexpos(s)) {
161 rh->expos *= exposval(s);
162 return(0);
163 }
164 if (isprims(s)) {
165 primsval(rh->mypri, s);
166 rh->primp = rh->mypri;
167 return(0);
168 }
169 return(0);
170 }
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 if (lpp == NULL | xp == NULL | yp == NULL |
191 (fname == NULL & fp == TM_GETFILE))
192 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 *lpp = NULL;
197 if (cpp != TM_NOCHROMP) *cpp = NULL;
198 info = rhdefault; /* get our header */
199 getheader(inpf, headline, (char *)&info);
200 if (info.format == FMTBAD | info.expos <= 0. ||
201 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 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 returnErr(err);
247 }
248 returnOK;
249 }
250
251
252 #ifdef PCOND
253 int /* run pcond to map picture */
254 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 char cmdbuf[1024];
264 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 strcpy(cmdbuf, PCOND);
274 if (flags & TM_F_HCONTR)
275 strcat(cmdbuf, " -s");
276 if (flags & TM_F_MESOPIC)
277 strcat(cmdbuf, " -c");
278 if (flags & TM_F_LINEAR)
279 strcat(cmdbuf, " -l");
280 if (flags & TM_F_ACUITY)
281 strcat(cmdbuf, " -a");
282 if (flags & TM_F_VEIL)
283 strcat(cmdbuf, " -v");
284 if (flags & TM_F_CWEIGHT)
285 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 /* 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 scan = (COLR *)malloc(sizeof(COLR) * *xp);
304 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 if ((*psp = rp) == NULL | scan == NULL) {
309 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 free((MEM_PTR)scan);
317 free((MEM_PTR)*psp);
318 *psp = NULL;
319 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 free((MEM_PTR)scan);
333 pclose(infp);
334 returnOK;
335 }
336 #endif
337
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 if (psp == NULL | xp == NULL | yp == NULL | monpri == NULL |
355 (fname == NULL & fp == TM_GETFILE))
356 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 #ifdef PCOND
363 /* 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 #endif
368 /* 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 if (*psp == NULL) {
382 free((MEM_PTR)lp);
383 tmDone(NULL);
384 returnErr(TM_E_NOMEM);
385 }
386 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 free((MEM_PTR)lp);
401 tmDone(NULL);
402 if (err != TM_E_OK) { /* free memory on error */
403 free((MEM_PTR)*psp);
404 *psp = NULL;
405 returnErr(err);
406 }
407 returnOK;
408 }
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 }