ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/px/pcomb.c
Revision: 2.44
Committed: Mon Aug 10 04:26:38 2009 UTC (14 years, 7 months ago) by greg
Content type: text/plain
Branch: MAIN
CVS Tags: rad4R2P2, rad5R0, rad4R2, rad4R1, rad4R0, rad4R2P1
Changes since 2.43: +2 -2 lines
Log Message:
Upped limit on open files to 1024

File Contents

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