ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/common/tmapcolrs.c
Revision: 3.2
Committed: Wed Apr 16 20:28:05 1997 UTC (27 years ago) by greg
Content type: text/plain
Branch: MAIN
Changes since 3.1: +8 -2 lines
Log Message:
minor bug fixes and added tmDup()

File Contents

# Content
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 scan = (COLR *)malloc(sizeof(COLR) * *xp);
266 if (flags & TM_F_BW)
267 rp = (BYTE *)malloc(sizeof(BYTE) * *xp * *yp);
268 else
269 rp = (BYTE *)malloc(3*sizeof(BYTE) * *xp * *yp);
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 free((char *)scan);
279 free((char *)*psp);
280 *psp = NULL;
281 returnErr(TM_E_BADFILE);
282 }
283 colrs_gambs(scan, *xp);
284 if (flags & TM_F_BW)
285 for (x = 0; x < *xp; x++)
286 *rp++ = normbright(scan[x]);
287 else
288 for (x = 0; x < *xp; x++) {
289 *rp++ = scan[x][RED];
290 *rp++ = scan[x][GRN];
291 *rp++ = scan[x][BLU];
292 }
293 }
294 free((char *)scan);
295 pclose(infp);
296 returnOK;
297 }
298
299
300 int /* map a Radiance picture */
301 tmMapPicture(psp, xp, yp, flags, monpri, gamval, Lddyn, Ldmax, fname, fp)
302 BYTE **psp;
303 int *xp, *yp;
304 int flags;
305 RGBPRIMP monpri;
306 double gamval, Lddyn, Ldmax;
307 char *fname;
308 FILE *fp;
309 {
310 char *funcName = fname==NULL ? "tmMapPicture" : fname;
311 FILE *inpf;
312 BYTE *cp;
313 TMbright *lp;
314 int err;
315 /* check arguments */
316 if (psp == NULL | xp == NULL | yp == NULL | monpri == NULL |
317 (fname == NULL & fp == TM_GETFILE))
318 returnErr(TM_E_ILLEGAL);
319 /* set defaults */
320 if (gamval < MINGAM) gamval = DEFGAM;
321 if (Lddyn < MINLDDYN) Lddyn = DEFLDDYN;
322 if (Ldmax < MINLDMAX) Ldmax = DEFLDMAX;
323 if (flags & TM_F_BW) monpri = stdprims;
324 /* check for pcond run */
325 if (fp == TM_GETFILE && flags & TM_F_UNIMPL)
326 return( dopcond(psp, xp, yp, flags,
327 monpri, gamval, Lddyn, Ldmax, fname) );
328 /* initialize tone mapping */
329 if (tmInit(flags, monpri, gamval) == NULL)
330 returnErr(TM_E_NOMEM);
331 /* load & convert picture */
332 err = tmLoadPicture(&lp, (flags&TM_F_BW) ? TM_NOCHROMP : &cp,
333 xp, yp, fname, fp);
334 if (err != TM_E_OK) {
335 tmDone(NULL);
336 return(err);
337 }
338 /* allocate space for result */
339 if (flags & TM_F_BW) {
340 *psp = (BYTE *)malloc(sizeof(BYTE) * *xp * *yp);
341 if (*psp == NULL) {
342 free((char *)lp);
343 tmDone(NULL);
344 returnErr(TM_E_NOMEM);
345 }
346 cp = TM_NOCHROM;
347 } else
348 *psp = cp;
349 /* compute color mapping */
350 err = tmAddHisto(lp, *xp * *yp, 1);
351 if (err != TM_E_OK)
352 goto done;
353 err = tmComputeMapping(gamval, Lddyn, Ldmax);
354 if (err != TM_E_OK)
355 goto done;
356 /* map colors */
357 err = tmMapPixels(*psp, lp, cp, *xp * *yp);
358
359 done: /* clean up */
360 free((char *)lp);
361 tmDone(NULL);
362 if (err != TM_E_OK) { /* free memory on error */
363 free((char *)*psp);
364 *psp = NULL;
365 returnErr(err);
366 }
367 returnOK;
368 }