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

# Content
1 #ifndef lint
2 static const char RCSid[] = "$Id: tmapcolrs.c,v 3.25 2006/05/31 19:27:42 greg Exp $";
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 <stdlib.h>
14 #include <string.h>
15 #include <math.h>
16 #include <time.h>
17
18 #include "tmprivat.h"
19 #include "resolu.h"
20 #ifdef PCOND
21 #include "rtprocess.h"
22 #endif
23
24 #define GAMTSZ 1024
25
26 typedef struct {
27 BYTE gamb[GAMTSZ]; /* gamma lookup table */
28 int clfb[3]; /* encoded tm->clf */
29 int32 cmatb[3][3]; /* encoded color transform */
30 TMbright inpsfb; /* encoded tm->inpsf */
31 } COLRDATA;
32
33 static MEM_PTR colrInit(TMstruct *);
34 static void colrNewSpace(TMstruct *);
35 static gethfunc headline;
36
37 static struct tmPackage colrPkg = { /* our package functions */
38 colrInit, colrNewSpace, free
39 };
40 static int colrReg = -1; /* our package registration number */
41
42 #define LOGISZ 260
43 static TMbright logi[LOGISZ];
44
45
46 int
47 tmCvColrs( /* convert RGBE/XYZE colors */
48 TMstruct *tms,
49 TMbright *ls,
50 BYTE *cs,
51 COLR *scan,
52 int len
53 )
54 {
55 static const char funcName[] = "tmCvColrs";
56 int cmon[4];
57 register COLRDATA *cd;
58 register int i, j, li, bi;
59 int32 vl;
60
61 if (tms == NULL)
62 returnErr(TM_E_TMINVAL);
63 if ((ls == NULL) | (scan == NULL) | (len < 0))
64 returnErr(TM_E_ILLEGAL);
65 if (colrReg < 0) { /* build tables if necessary */
66 colrReg = tmRegPkg(&colrPkg);
67 if (colrReg < 0)
68 returnErr(TM_E_CODERR1);
69 for (i = 256; i--; )
70 logi[i] = TM_BRTSCALE*log((i+.5)/256.) - .5;
71 for (i = 256; i < LOGISZ; i++)
72 logi[i] = 0;
73 tmMkMesofact();
74 }
75 if ((cd = (COLRDATA *)tmPkgData(tms,colrReg)) == NULL)
76 returnErr(TM_E_NOMEM);
77 for (i = len; i--; ) {
78 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 /* world luminance */
90 li = cd->clfb[RED]*cmon[RED] +
91 cd->clfb[GRN]*cmon[GRN] +
92 cd->clfb[BLU]*cmon[BLU] ;
93 if (li >= 0xfff00) li = 255;
94 else li >>= 12;
95 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 }
102 ls[i] = bi;
103 if (cs == TM_NOCHROM) /* no color? */
104 continue;
105 /* mesopic adj. */
106 if (tms->flags & TM_F_MESOPIC && bi < BMESUPPER) {
107 int pf, sli = normscot(cmon);
108 if (bi < BMESLOWER) {
109 cmon[RED] = cmon[GRN] = cmon[BLU] = sli;
110 } else {
111 if (tms->flags & TM_F_BW)
112 cmon[RED] = cmon[GRN] = cmon[BLU] = li;
113 pf = tmMesofact[bi-BMESLOWER];
114 sli *= 256 - pf;
115 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 }
121 } else if (tms->flags & TM_F_BW) {
122 cmon[RED] = cmon[GRN] = cmon[BLU] = li;
123 } else {
124 for (j = 3; j--; )
125 if (cmon[j] < 0) cmon[j] = 0;
126 }
127 bi = ( (int32)GAMTSZ*cd->clfb[RED]*cmon[RED]/li ) >> 12;
128 cs[3*i ] = bi>=GAMTSZ ? 255 : cd->gamb[bi];
129 bi = ( (int32)GAMTSZ*cd->clfb[GRN]*cmon[GRN]/li ) >> 12;
130 cs[3*i+1] = bi>=GAMTSZ ? 255 : cd->gamb[bi];
131 bi = ( (int32)GAMTSZ*cd->clfb[BLU]*cmon[BLU]/li ) >> 12;
132 cs[3*i+2] = bi>=GAMTSZ ? 255 : cd->gamb[bi];
133 }
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 headline( /* grok a header line */
153 register char *s,
154 void *vrh
155 )
156 {
157 char fmt[32];
158 register struct radhead *rh = vrh;
159
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 return(0);
168 }
169 if (isexpos(s)) {
170 rh->expos *= exposval(s);
171 return(0);
172 }
173 if (isprims(s)) {
174 primsval(rh->mypri, s);
175 rh->primp = rh->mypri;
176 return(0);
177 }
178 return(0);
179 }
180
181
182 int
183 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 {
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 if (tms == NULL)
201 returnErr(TM_E_TMINVAL);
202 if ((lpp == NULL) | (xp == NULL) | (yp == NULL) |
203 ((fname == NULL) & (fp == TM_GETFILE)))
204 returnErr(TM_E_ILLEGAL);
205 *xp = *yp = 0; /* error precaution */
206 if ((inpf = fp) == TM_GETFILE && (inpf = fopen(fname, "rb")) == NULL)
207 returnErr(TM_E_BADFILE);
208 *lpp = NULL;
209 if (cpp != TM_NOCHROMP) *cpp = NULL;
210 info = rhdefault; /* get our header */
211 getheader(inpf, headline, &info);
212 if ((info.format == FMTBAD) | (info.expos <= 0.) ||
213 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 if ((err = tmSetSpace(tms, info.primp, 1./info.expos, NULL)) != TM_E_OK)
224 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 err = tmCvColrs(tms, *lpp + (i * *xp),
243 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 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 returnErr(err);
259 }
260 returnOK;
261 }
262
263
264 #ifdef PCOND
265 static int /* run pcond to map picture */
266 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 TMstruct *tms = NULL;
276 char cmdbuf[1024];
277 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 strcpy(cmdbuf, PCOND);
287 if (flags & TM_F_HCONTR)
288 strcat(cmdbuf, " -s");
289 if (flags & TM_F_MESOPIC)
290 strcat(cmdbuf, " -c");
291 if (flags & TM_F_LINEAR)
292 strcat(cmdbuf, " -l");
293 if (flags & TM_F_ACUITY)
294 strcat(cmdbuf, " -a");
295 if (flags & TM_F_VEIL)
296 strcat(cmdbuf, " -v");
297 if (flags & TM_F_CWEIGHT)
298 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 /* 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 scan = (COLR *)malloc(sizeof(COLR) * *xp);
317 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 if (((*psp = rp) == NULL) | (scan == NULL)) {
322 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 free((MEM_PTR)scan);
330 free((MEM_PTR)*psp);
331 *psp = NULL;
332 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 free((MEM_PTR)scan);
346 pclose(infp);
347 returnOK;
348 }
349 #endif
350
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 TMstruct *tms;
364 BYTE *cp;
365 TMbright *lp;
366 int err;
367 /* check arguments */
368 if ((psp == NULL) | (xp == NULL) | (yp == NULL) | (monpri == NULL) |
369 ((fname == NULL) & (fp == TM_GETFILE)))
370 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 #ifdef PCOND
377 /* 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 #endif
382 /* initialize tone mapping */
383 if ((tms = tmInit(flags, monpri, gamval)) == NULL)
384 returnErr(TM_E_NOMEM);
385 /* load & convert picture */
386 err = tmLoadPicture(tms, &lp, (flags&TM_F_BW) ? TM_NOCHROMP : &cp,
387 xp, yp, fname, fp);
388 if (err != TM_E_OK) {
389 tmDone(tms);
390 return(err);
391 }
392 /* allocate space for result */
393 if (flags & TM_F_BW) {
394 *psp = (BYTE *)malloc(sizeof(BYTE) * *xp * *yp);
395 if (*psp == NULL) {
396 free((MEM_PTR)lp);
397 tmDone(tms);
398 returnErr(TM_E_NOMEM);
399 }
400 cp = TM_NOCHROM;
401 } else
402 *psp = cp;
403 /* compute color mapping */
404 err = tmAddHisto(tms, lp, *xp * *yp, 1);
405 if (err != TM_E_OK)
406 goto done;
407 err = tmComputeMapping(tms, gamval, Lddyn, Ldmax);
408 if (err != TM_E_OK)
409 goto done;
410 /* map colors */
411 err = tmMapPixels(tms, *psp, lp, cp, *xp * *yp);
412
413 done: /* clean up */
414 free((MEM_PTR)lp);
415 tmDone(tms);
416 if (err != TM_E_OK) { /* free memory on error */
417 free((MEM_PTR)*psp);
418 *psp = NULL;
419 returnErr(err);
420 }
421 returnOK;
422 }
423
424
425 static void
426 colrNewSpace(tms) /* color space changed for tone mapping */
427 register TMstruct *tms;
428 {
429 register COLRDATA *cd;
430 double d;
431 int i, j;
432
433 cd = (COLRDATA *)tms->pd[colrReg];
434 for (i = 3; i--; )
435 cd->clfb[i] = 0x1000*tms->clf[i] + .5;
436 cd->inpsfb = tmCvLuminance(tms->inpsf);
437 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 }
443
444
445 static MEM_PTR
446 colrInit(tms) /* initialize private data for tone mapping */
447 register TMstruct *tms;
448 {
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 }