ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/px/pcomb.c
Revision: 2.38
Committed: Wed May 25 04:44:25 2005 UTC (18 years, 10 months ago) by greg
Content type: text/plain
Branch: MAIN
CVS Tags: rad3R7P2, rad3R7P1
Changes since 2.37: +2 -2 lines
Log Message:
Created rtcontrib program for computing ray contributions and coefficients

File Contents

# Content
1 #ifndef lint
2 static const char RCSid[] = "$Id: pcomb.c,v 2.37 2005/03/01 23:16:42 greg Exp $";
3 #endif
4 /*
5 * Combine picture files according to calcomp functions.
6 *
7 * 1/4/89
8 */
9
10 #include "platform.h"
11 #include "standard.h"
12 #include "rtprocess.h"
13 #include "color.h"
14 #include "calcomp.h"
15 #include "view.h"
16
17 #define MAXINP 512 /* maximum number of input files */
18 #define WINSIZ 64 /* scanline window size */
19 #define MIDSCN ((WINSIZ-1)/2+1)
20
21 struct {
22 char *name; /* file or command name */
23 FILE *fp; /* stream pointer */
24 VIEW vw; /* view for picture */
25 RESOLU rs; /* image resolution and orientation */
26 float pa; /* pixel aspect ratio */
27 COLOR *scan[WINSIZ]; /* input scanline window */
28 COLOR coef; /* coefficient */
29 COLOR expos; /* recorded exposure */
30 } input[MAXINP]; /* input pictures */
31
32 int nfiles; /* number of input files */
33
34 char ourfmt[LPICFMT+1] = PICFMT; /* input picture format */
35
36 char StandardInput[] = "<stdin>";
37 char Command[] = "<Command>";
38 char vcolin[3][4] = {"ri", "gi", "bi"};
39 char vcolout[3][4] = {"ro", "go", "bo"};
40 char vbrtin[] = "li";
41 char vbrtout[] = "lo";
42 char vcolexp[3][4] = {"re", "ge", "be"};
43 char vbrtexp[] = "le";
44 char vpixaspect[] = "pa";
45
46 char vray[7][4] = {"Ox", "Oy", "Oz", "Dx", "Dy", "Dz", "T"};
47
48 char vpsize[] = "S";
49
50 char vnfiles[] = "nfiles";
51 char vwhteff[] = "WE";
52 char vxmax[] = "xmax";
53 char vymax[] = "ymax";
54 char vxres[] = "xres";
55 char vyres[] = "yres";
56 char vxpos[] = "x";
57 char vypos[] = "y";
58
59 int nowarn = 0; /* no warning messages? */
60
61 int xmax = 0, ymax = 0; /* input resolution */
62
63 int xscan, yscan; /* input position */
64
65 int xres, yres; /* output resolution */
66
67 int xpos, ypos; /* output position */
68
69 char *progname; /* global argv[0] */
70
71 int wrongformat = 0;
72 int gotview;
73
74
75 static gethfunc tabputs;
76 static void checkfile(void);
77 static double rgb_bright(COLOR clr);
78 static double xyz_bright(COLOR clr);
79 static void init(void);
80 static void combine(void);
81 static void advance(void);
82 static double l_expos(char *nam);
83 static double l_pixaspect(char *nm);
84 static double l_colin(char *nam);
85 static double l_ray(char *nam);
86 static double l_psize(char *nm);
87
88
89 int
90 main(
91 int argc,
92 char *argv[]
93 )
94 {
95 int original;
96 double f;
97 int a;
98 SET_DEFAULT_BINARY();
99 SET_FILE_BINARY(stdin);
100 SET_FILE_BINARY(stdout);
101 progname = argv[0];
102 /* scan options */
103 for (a = 1; a < argc; a++) {
104 if (argv[a][0] == '-')
105 switch (argv[a][1]) {
106 case 'x':
107 case 'y':
108 a++;
109 continue;
110 case 'w':
111 nowarn = !nowarn;
112 continue;
113 case 'f':
114 case 'e':
115 a++;
116 continue;
117 }
118 break;
119 }
120 newheader("RADIANCE", stdout); /* start header */
121 fputnow(stdout);
122 /* process files */
123 for (nfiles = 0; nfiles < MAXINP; nfiles++) {
124 setcolor(input[nfiles].coef, 1.0, 1.0, 1.0);
125 setcolor(input[nfiles].expos, 1.0, 1.0, 1.0);
126 input[nfiles].vw = stdview;
127 input[nfiles].pa = 1.0;
128 }
129 nfiles = 0;
130 original = 0;
131 for ( ; a < argc; a++) {
132 if (nfiles >= MAXINP) {
133 eputs(argv[0]);
134 eputs(": too many picture files\n");
135 quit(1);
136 }
137 if (argv[a][0] == '-')
138 switch (argv[a][1]) {
139 case '\0':
140 input[nfiles].name = StandardInput;
141 input[nfiles].fp = stdin;
142 break;
143 case 'o':
144 original++;
145 continue;
146 case 's':
147 f = atof(argv[++a]);
148 scalecolor(input[nfiles].coef, f);
149 continue;
150 case 'c':
151 colval(input[nfiles].coef,RED)*=atof(argv[++a]);
152 colval(input[nfiles].coef,GRN)*=atof(argv[++a]);
153 colval(input[nfiles].coef,BLU)*=atof(argv[++a]);
154 continue;
155 default:
156 goto usage;
157 }
158 else {
159 if (argv[a][0] == '!') {
160 input[nfiles].name = Command;
161 input[nfiles].fp = popen(argv[a]+1, "r");
162 } else {
163 input[nfiles].name = argv[a];
164 input[nfiles].fp = fopen(argv[a], "r");
165 }
166 if (input[nfiles].fp == NULL) {
167 perror(argv[a]);
168 quit(1);
169 }
170 }
171 checkfile();
172 if (original) {
173 colval(input[nfiles].coef,RED) /=
174 colval(input[nfiles].expos,RED);
175 colval(input[nfiles].coef,GRN) /=
176 colval(input[nfiles].expos,GRN);
177 colval(input[nfiles].coef,BLU) /=
178 colval(input[nfiles].expos,BLU);
179 setcolor(input[nfiles].expos, 1.0, 1.0, 1.0);
180 }
181 nfiles++;
182 original = 0;
183 }
184 init(); /* set constants */
185 /* go back and get expressions */
186 for (a = 1; a < argc; a++) {
187 if (argv[a][0] == '-')
188 switch (argv[a][1]) {
189 case 'x':
190 varset(vxres, ':', eval(argv[++a]));
191 continue;
192 case 'y':
193 varset(vyres, ':', eval(argv[++a]));
194 continue;
195 case 'w':
196 continue;
197 case 'f':
198 fcompile(argv[++a]);
199 continue;
200 case 'e':
201 scompile(argv[++a], NULL, 0);
202 continue;
203 }
204 break;
205 }
206 /* set/get output resolution */
207 if (!vardefined(vxres))
208 varset(vxres, ':', (double)xmax);
209 if (!vardefined(vyres))
210 varset(vyres, ':', (double)ymax);
211 xres = varvalue(vxres) + .5;
212 yres = varvalue(vyres) + .5;
213 if (xres <= 0 || yres <= 0) {
214 eputs(argv[0]);
215 eputs(": illegal output resolution\n");
216 quit(1);
217 }
218 /* complete header */
219 printargs(argc, argv, stdout);
220 if (strcmp(ourfmt, PICFMT))
221 fputformat(ourfmt, stdout); /* print format if known */
222 putchar('\n');
223 fprtresolu(xres, yres, stdout);
224 /* combine pictures */
225 combine();
226 quit(0);
227 usage:
228 eputs("Usage: ");
229 eputs(argv[0]);
230 eputs(
231 " [-w][-x xr][-y yr][-e expr][-f file] [ [-o][-s f][-c r g b] pic ..]\n");
232 quit(1);
233 return 1; /* pro forma return */
234 }
235
236
237 static int
238 tabputs( /* put out string preceded by a tab */
239 char *s,
240 void *p
241 )
242 {
243 char fmt[32];
244 double d;
245 COLOR ctmp;
246
247 if (isheadid(s)) /* header id */
248 return(0); /* don't echo */
249 if (formatval(fmt, s)) { /* check format */
250 if (globmatch(ourfmt, fmt)) {
251 wrongformat = 0;
252 strcpy(ourfmt, fmt);
253 } else
254 wrongformat = globmatch(PICFMT, fmt) ? 1 : -1;
255 return(0); /* don't echo */
256 }
257 if (isexpos(s)) { /* exposure */
258 d = exposval(s);
259 scalecolor(input[nfiles].expos, d);
260 } else if (iscolcor(s)) { /* color correction */
261 colcorval(ctmp, s);
262 multcolor(input[nfiles].expos, ctmp);
263 } else if (isaspect(s))
264 input[nfiles].pa *= aspectval(s);
265 else if (isview(s) && sscanview(&input[nfiles].vw, s) > 0)
266 gotview++;
267 /* echo line */
268 putchar('\t');
269 return(fputs(s, stdout));
270 }
271
272
273 static void
274 checkfile(void) /* ready a file */
275 {
276 register int i;
277 /* process header */
278 gotview = 0;
279 fputs(input[nfiles].name, stdout);
280 fputs(":\n", stdout);
281 getheader(input[nfiles].fp, tabputs, NULL);
282 if (wrongformat < 0) {
283 eputs(input[nfiles].name);
284 eputs(": not a Radiance picture\n");
285 quit(1);
286 }
287 if (wrongformat > 0) {
288 wputs(input[nfiles].name);
289 wputs(": warning -- incompatible picture format\n");
290 }
291 if (!gotview || setview(&input[nfiles].vw) != NULL)
292 input[nfiles].vw.type = 0;
293 if (!fgetsresolu(&input[nfiles].rs, input[nfiles].fp)) {
294 eputs(input[nfiles].name);
295 eputs(": bad picture size\n");
296 quit(1);
297 }
298 if (xmax == 0 && ymax == 0) {
299 xmax = scanlen(&input[nfiles].rs);
300 ymax = numscans(&input[nfiles].rs);
301 } else if (scanlen(&input[nfiles].rs) != xmax ||
302 numscans(&input[nfiles].rs) != ymax) {
303 eputs(input[nfiles].name);
304 eputs(": resolution mismatch\n");
305 quit(1);
306 }
307 /* allocate scanlines */
308 for (i = 0; i < WINSIZ; i++)
309 input[nfiles].scan[i] = (COLOR *)emalloc(xmax*sizeof(COLOR));
310 }
311
312
313 static double
314 rgb_bright(
315 COLOR clr
316 )
317 {
318 return(bright(clr));
319 }
320
321
322 static double
323 xyz_bright(
324 COLOR clr
325 )
326 {
327 return(clr[CIEY]);
328 }
329
330
331 double (*ourbright)() = rgb_bright;
332
333
334 static void
335 init(void) /* perform final setup */
336 {
337 register int i;
338 /* define constants */
339 varset("PI", ':', PI);
340 varset(vnfiles, ':', (double)nfiles);
341 varset(vxmax, ':', (double)xmax);
342 varset(vymax, ':', (double)ymax);
343 /* set functions */
344 for (i = 0; i < 3; i++) {
345 funset(vcolexp[i], 1, ':', l_expos);
346 funset(vcolin[i], 1, '=', l_colin);
347 }
348 funset(vbrtexp, 1, ':', l_expos);
349 funset(vbrtin, 1, '=', l_colin);
350 funset(vpixaspect, 1, ':', l_pixaspect);
351 for (i = 0; i < 7; i++)
352 funset(vray[i], 1, '=', l_ray);
353 funset(vpsize, 1, '=', l_psize);
354 /* set brightness function */
355 if (!strcmp(ourfmt, CIEFMT)) {
356 varset(vwhteff, ':', 1.0);
357 ourbright = xyz_bright;
358 } else
359 varset(vwhteff, ':', WHTEFFICACY);
360 }
361
362
363 static void
364 combine(void) /* combine pictures */
365 {
366 EPNODE *coldef[3], *brtdef;
367 COLOR *scanout;
368 double d;
369 register int i, j;
370 /* check defined variables */
371 for (j = 0; j < 3; j++) {
372 if (vardefined(vcolout[j]))
373 coldef[j] = eparse(vcolout[j]);
374 else
375 coldef[j] = NULL;
376 }
377 if (vardefined(vbrtout))
378 brtdef = eparse(vbrtout);
379 else
380 brtdef = NULL;
381 /* allocate scanline */
382 scanout = (COLOR *)emalloc(xres*sizeof(COLOR));
383 /* set input position */
384 yscan = ymax+MIDSCN;
385 /* combine files */
386 for (ypos = yres-1; ypos >= 0; ypos--) {
387 advance();
388 varset(vypos, '=', (double)ypos);
389 for (xpos = 0; xpos < xres; xpos++) {
390 xscan = (long)xpos*xmax/xres;
391 varset(vxpos, '=', (double)xpos);
392 eclock++;
393 if (brtdef != NULL) {
394 d = evalue(brtdef);
395 if (d < 0.0)
396 d = 0.0;
397 setcolor(scanout[xpos], d, d, d);
398 } else {
399 for (j = 0; j < 3; j++) {
400 if (coldef[j] != NULL) {
401 d = evalue(coldef[j]);
402 } else {
403 d = 0.0;
404 for (i = 0; i < nfiles; i++)
405 d += colval(input[i].scan[MIDSCN][xscan],j);
406 }
407 if (d < 0.0)
408 d = 0.0;
409 colval(scanout[xpos],j) = d;
410 }
411 }
412 }
413 if (fwritescan(scanout, xres, stdout) < 0) {
414 perror("write error");
415 quit(1);
416 }
417 }
418 efree((char *)scanout);
419 }
420
421
422 static void
423 advance(void) /* read in data for next scanline */
424 {
425 int ytarget;
426 register COLOR *st;
427 register int i, j;
428
429 for (ytarget = (long)ypos*ymax/yres; yscan > ytarget; yscan--)
430 for (i = 0; i < nfiles; i++) {
431 st = input[i].scan[WINSIZ-1];
432 for (j = WINSIZ-1; j > 0; j--) /* rotate window */
433 input[i].scan[j] = input[i].scan[j-1];
434 input[i].scan[0] = st;
435 if (yscan <= MIDSCN) /* hit bottom? */
436 continue;
437 if (freadscan(st, xmax, input[i].fp) < 0) { /* read */
438 eputs(input[i].name);
439 eputs(": read error\n");
440 quit(1);
441 }
442 for (j = 0; j < xmax; j++) /* adjust color */
443 multcolor(st[j], input[i].coef);
444 }
445 }
446
447
448 static double
449 l_expos( /* return picture exposure */
450 register char *nam
451 )
452 {
453 register int fn, n;
454
455 fn = argument(1) - .5;
456 if (fn < 0 || fn >= nfiles)
457 return(1.0);
458 if (nam == vbrtexp)
459 return((*ourbright)(input[fn].expos));
460 n = 3;
461 while (n--)
462 if (nam == vcolexp[n])
463 return(colval(input[fn].expos,n));
464 eputs("Bad call to l_expos()!\n");
465 quit(1);
466 return 1; /* pro forma return */
467 }
468
469
470 static double
471 l_pixaspect(char *nm) /* return pixel aspect ratio */
472 {
473 register int fn;
474
475 fn = argument(1) - .5;
476 if (fn < 0 || fn >= nfiles)
477 return(1.0);
478 return(input[fn].pa);
479 }
480
481
482 static double
483 l_colin( /* return color value for picture */
484 register char *nam
485 )
486 {
487 int fn;
488 register int n, xoff, yoff;
489 double d;
490
491 fn = argument(1) - .5;
492 if (fn < 0 || fn >= nfiles) {
493 errno = EDOM;
494 return(0.0);
495 }
496 xoff = yoff = 0;
497 n = nargum();
498 if (n >= 2) {
499 d = argument(2);
500 if (d < 0.0) {
501 xoff = d-.5;
502 if (xscan+xoff < 0)
503 xoff = -xscan;
504 } else {
505 xoff = d+.5;
506 if (xscan+xoff >= xmax)
507 xoff = xmax-1-xscan;
508 }
509 }
510 if (n >= 3) {
511 d = argument(3);
512 if (d < 0.0) {
513 yoff = d-.5;
514 if (yoff+MIDSCN < 0)
515 yoff = -MIDSCN;
516 if (yscan+yoff < 0)
517 yoff = -yscan;
518 } else {
519 yoff = d+.5;
520 if (yoff+MIDSCN >= WINSIZ)
521 yoff = WINSIZ-1-MIDSCN;
522 if (yscan+yoff >= ymax)
523 yoff = ymax-1-yscan;
524 }
525 }
526 if (nam == vbrtin)
527 return((*ourbright)(input[fn].scan[MIDSCN+yoff][xscan+xoff]));
528 n = 3;
529 while (n--)
530 if (nam == vcolin[n])
531 return(colval(input[fn].scan[MIDSCN+yoff][xscan+xoff],n));
532 eputs("Bad call to l_colin()!\n");
533 quit(1);
534 return 1; /* pro forma return */
535 }
536
537
538 static double
539 l_ray( /* return ray origin or direction */
540 register char *nam
541 )
542 {
543 static unsigned long ltick[MAXINP];
544 static FVECT lorg[MAXINP], ldir[MAXINP];
545 static double ldist[MAXINP];
546 RREAL loc[2];
547 int fn;
548 register int i;
549
550 fn = argument(1) - .5;
551 if (fn < 0 || fn >= nfiles) {
552 errno = EDOM;
553 return(0.0);
554 }
555 if (ltick[fn] != eclock) { /* need to compute? */
556 lorg[fn][0] = lorg[fn][1] = lorg[fn][2] = 0.0;
557 ldir[fn][0] = ldir[fn][1] = ldir[fn][2] = 0.0;
558 ldist[fn] = -1.0;
559 if (input[fn].vw.type == 0)
560 errno = EDOM;
561 else {
562 pix2loc(loc, &input[fn].rs, xscan, ymax-1-yscan);
563 ldist[fn] = viewray(lorg[fn], ldir[fn],
564 &input[fn].vw, loc[0], loc[1]);
565 }
566 ltick[fn] = eclock;
567 }
568 if (nam == vray[i=6])
569 return(ldist[fn]);
570 while (i--)
571 if (nam == vray[i])
572 return(i < 3 ? lorg[fn][i] : ldir[fn][i-3]);
573 eputs("Bad call to l_ray()!\n");
574 quit(1);
575 return 1; /* pro forma return */
576 }
577
578
579 static double
580 l_psize(char *nm) /* compute pixel size in steradians */
581 {
582 static unsigned long ltick[MAXINP];
583 static double psize[MAXINP];
584 FVECT dir0, org, dirx, diry;
585 RREAL locx[2], locy[2];
586 double d;
587 int fn;
588 register int i;
589
590 d = argument(1);
591 if (d < .5 || d >= nfiles+.5) {
592 errno = EDOM;
593 return(0.0);
594 }
595 fn = d - .5;
596 if (ltick[fn] != eclock) { /* need to compute? */
597 psize[fn] = 0.0;
598 if (input[fn].vw.type == 0)
599 errno = EDOM;
600 else if (input[fn].vw.type != VT_PAR &&
601 funvalue(vray[6], 1, &d) >= -FTINY) {
602 for (i = 0; i < 3; i++)
603 dir0[i] = funvalue(vray[3+i], 1, &d);
604 pix2loc(locx, &input[fn].rs, xscan+1, ymax-1-yscan);
605 pix2loc(locy, &input[fn].rs, xscan, ymax-yscan);
606 if (viewray(org, dirx, &input[fn].vw,
607 locx[0], locx[1]) >= -FTINY &&
608 viewray(org, diry, &input[fn].vw,
609 locy[0], locy[1]) >= -FTINY) {
610 /* approximate solid angle */
611 for (i = 0; i < 3; i++) {
612 dirx[i] -= dir0[i];
613 diry[i] -= dir0[i];
614 }
615 fcross(dir0, dirx, diry);
616 psize[fn] = VLEN(dir0);
617 }
618 }
619 ltick[fn] = eclock;
620 }
621 return(psize[fn]);
622 }
623
624
625 extern void
626 wputs(char *msg)
627 {
628 if (!nowarn)
629 eputs(msg);
630 }
631
632
633 extern void
634 eputs(char *msg)
635 {
636 fputs(msg, stderr);
637 }
638
639
640 extern void
641 quit(int code) /* exit gracefully */
642 {
643 register int i;
644 /* close input files */
645 for (i = 0; i < nfiles; i++)
646 if (input[i].name == Command)
647 pclose(input[i].fp);
648 else
649 fclose(input[i].fp);
650 exit(code);
651 }