ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/px/pcomb.c
Revision: 2.39
Committed: Fri Sep 8 21:38:25 2006 UTC (17 years, 7 months ago) by greg
Content type: text/plain
Branch: MAIN
CVS Tags: rad3R8
Changes since 2.38: +19 -10 lines
Log Message:
Added -h option to pcompos and pcomb to avoid uncontrolled header growth

File Contents

# Content
1 #ifndef lint
2 static const char RCSid[] = "$Id: pcomb.c,v 2.38 2005/05/25 04:44:25 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 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 'f':
202 fcompile(argv[++a]);
203 continue;
204 case 'e':
205 scompile(argv[++a], NULL, 0);
206 continue;
207 }
208 break;
209 }
210 /* set/get output resolution */
211 if (!vardefined(vxres))
212 varset(vxres, ':', (double)xmax);
213 if (!vardefined(vyres))
214 varset(vyres, ':', (double)ymax);
215 xres = varvalue(vxres) + .5;
216 yres = varvalue(vyres) + .5;
217 if (xres <= 0 || yres <= 0) {
218 eputs(argv[0]);
219 eputs(": illegal output resolution\n");
220 quit(1);
221 }
222 /* complete header */
223 printargs(argc, argv, stdout);
224 if (strcmp(ourfmt, PICFMT))
225 fputformat(ourfmt, stdout); /* print format if known */
226 putchar('\n');
227 fprtresolu(xres, yres, stdout);
228 /* combine pictures */
229 combine();
230 quit(0);
231 usage:
232 eputs("Usage: ");
233 eputs(argv[0]);
234 eputs(
235 " [-w][-h][-x xr][-y yr][-e expr][-f file] [ [-o][-s f][-c r g b] pic ..]\n");
236 quit(1);
237 return 1; /* pro forma return */
238 }
239
240
241 static int
242 headline( /* check header line & echo if requested */
243 char *s,
244 void *p
245 )
246 {
247 char fmt[32];
248 double d;
249 COLOR ctmp;
250
251 if (isheadid(s)) /* header id */
252 return(0); /* don't echo */
253 if (formatval(fmt, s)) { /* check format */
254 if (globmatch(ourfmt, fmt)) {
255 wrongformat = 0;
256 strcpy(ourfmt, fmt);
257 } else
258 wrongformat = globmatch(PICFMT, fmt) ? 1 : -1;
259 return(0); /* don't echo */
260 }
261 if (isexpos(s)) { /* exposure */
262 d = exposval(s);
263 scalecolor(input[nfiles].expos, d);
264 } else if (iscolcor(s)) { /* color correction */
265 colcorval(ctmp, s);
266 multcolor(input[nfiles].expos, ctmp);
267 } else if (isaspect(s))
268 input[nfiles].pa *= aspectval(s);
269 else if (isview(s) && sscanview(&input[nfiles].vw, s) > 0)
270 gotview++;
271
272 if (echoheader) { /* echo line */
273 putchar('\t');
274 return(fputs(s, stdout));
275 }
276 return(0);
277 }
278
279
280 static void
281 checkfile(void) /* ready a file */
282 {
283 register int i;
284 /* process header */
285 gotview = 0;
286 if (echoheader) {
287 fputs(input[nfiles].name, stdout);
288 fputs(":\n", stdout);
289 }
290 getheader(input[nfiles].fp, headline, NULL);
291 if (wrongformat < 0) {
292 eputs(input[nfiles].name);
293 eputs(": not a Radiance picture\n");
294 quit(1);
295 }
296 if (wrongformat > 0) {
297 wputs(input[nfiles].name);
298 wputs(": warning -- incompatible picture format\n");
299 }
300 if (!gotview || setview(&input[nfiles].vw) != NULL)
301 input[nfiles].vw.type = 0;
302 if (!fgetsresolu(&input[nfiles].rs, input[nfiles].fp)) {
303 eputs(input[nfiles].name);
304 eputs(": bad picture size\n");
305 quit(1);
306 }
307 if (xmax == 0 && ymax == 0) {
308 xmax = scanlen(&input[nfiles].rs);
309 ymax = numscans(&input[nfiles].rs);
310 } else if (scanlen(&input[nfiles].rs) != xmax ||
311 numscans(&input[nfiles].rs) != ymax) {
312 eputs(input[nfiles].name);
313 eputs(": resolution mismatch\n");
314 quit(1);
315 }
316 /* allocate scanlines */
317 for (i = 0; i < WINSIZ; i++)
318 input[nfiles].scan[i] = (COLOR *)emalloc(xmax*sizeof(COLOR));
319 }
320
321
322 static double
323 rgb_bright(
324 COLOR clr
325 )
326 {
327 return(bright(clr));
328 }
329
330
331 static double
332 xyz_bright(
333 COLOR clr
334 )
335 {
336 return(clr[CIEY]);
337 }
338
339
340 double (*ourbright)() = rgb_bright;
341
342
343 static void
344 init(void) /* perform final setup */
345 {
346 register int i;
347 /* define constants */
348 varset("PI", ':', PI);
349 varset(vnfiles, ':', (double)nfiles);
350 varset(vxmax, ':', (double)xmax);
351 varset(vymax, ':', (double)ymax);
352 /* set functions */
353 for (i = 0; i < 3; i++) {
354 funset(vcolexp[i], 1, ':', l_expos);
355 funset(vcolin[i], 1, '=', l_colin);
356 }
357 funset(vbrtexp, 1, ':', l_expos);
358 funset(vbrtin, 1, '=', l_colin);
359 funset(vpixaspect, 1, ':', l_pixaspect);
360 for (i = 0; i < 7; i++)
361 funset(vray[i], 1, '=', l_ray);
362 funset(vpsize, 1, '=', l_psize);
363 /* set brightness function */
364 if (!strcmp(ourfmt, CIEFMT)) {
365 varset(vwhteff, ':', 1.0);
366 ourbright = xyz_bright;
367 } else
368 varset(vwhteff, ':', WHTEFFICACY);
369 }
370
371
372 static void
373 combine(void) /* combine pictures */
374 {
375 EPNODE *coldef[3], *brtdef;
376 COLOR *scanout;
377 double d;
378 register int i, j;
379 /* check defined variables */
380 for (j = 0; j < 3; j++) {
381 if (vardefined(vcolout[j]))
382 coldef[j] = eparse(vcolout[j]);
383 else
384 coldef[j] = NULL;
385 }
386 if (vardefined(vbrtout))
387 brtdef = eparse(vbrtout);
388 else
389 brtdef = NULL;
390 /* allocate scanline */
391 scanout = (COLOR *)emalloc(xres*sizeof(COLOR));
392 /* set input position */
393 yscan = ymax+MIDSCN;
394 /* combine files */
395 for (ypos = yres-1; ypos >= 0; ypos--) {
396 advance();
397 varset(vypos, '=', (double)ypos);
398 for (xpos = 0; xpos < xres; xpos++) {
399 xscan = (long)xpos*xmax/xres;
400 varset(vxpos, '=', (double)xpos);
401 eclock++;
402 if (brtdef != NULL) {
403 d = evalue(brtdef);
404 if (d < 0.0)
405 d = 0.0;
406 setcolor(scanout[xpos], d, d, d);
407 } else {
408 for (j = 0; j < 3; j++) {
409 if (coldef[j] != NULL) {
410 d = evalue(coldef[j]);
411 } else {
412 d = 0.0;
413 for (i = 0; i < nfiles; i++)
414 d += colval(input[i].scan[MIDSCN][xscan],j);
415 }
416 if (d < 0.0)
417 d = 0.0;
418 colval(scanout[xpos],j) = d;
419 }
420 }
421 }
422 if (fwritescan(scanout, xres, stdout) < 0) {
423 perror("write error");
424 quit(1);
425 }
426 }
427 efree((char *)scanout);
428 }
429
430
431 static void
432 advance(void) /* read in data for next scanline */
433 {
434 int ytarget;
435 register COLOR *st;
436 register int i, j;
437
438 for (ytarget = (long)ypos*ymax/yres; yscan > ytarget; yscan--)
439 for (i = 0; i < nfiles; i++) {
440 st = input[i].scan[WINSIZ-1];
441 for (j = WINSIZ-1; j > 0; j--) /* rotate window */
442 input[i].scan[j] = input[i].scan[j-1];
443 input[i].scan[0] = st;
444 if (yscan <= MIDSCN) /* hit bottom? */
445 continue;
446 if (freadscan(st, xmax, input[i].fp) < 0) { /* read */
447 eputs(input[i].name);
448 eputs(": read error\n");
449 quit(1);
450 }
451 for (j = 0; j < xmax; j++) /* adjust color */
452 multcolor(st[j], input[i].coef);
453 }
454 }
455
456
457 static double
458 l_expos( /* return picture exposure */
459 register char *nam
460 )
461 {
462 register int fn, n;
463
464 fn = argument(1) - .5;
465 if (fn < 0 || fn >= nfiles)
466 return(1.0);
467 if (nam == vbrtexp)
468 return((*ourbright)(input[fn].expos));
469 n = 3;
470 while (n--)
471 if (nam == vcolexp[n])
472 return(colval(input[fn].expos,n));
473 eputs("Bad call to l_expos()!\n");
474 quit(1);
475 return 1; /* pro forma return */
476 }
477
478
479 static double
480 l_pixaspect(char *nm) /* return pixel aspect ratio */
481 {
482 register int fn;
483
484 fn = argument(1) - .5;
485 if (fn < 0 || fn >= nfiles)
486 return(1.0);
487 return(input[fn].pa);
488 }
489
490
491 static double
492 l_colin( /* return color value for picture */
493 register char *nam
494 )
495 {
496 int fn;
497 register int n, xoff, yoff;
498 double d;
499
500 fn = argument(1) - .5;
501 if (fn < 0 || fn >= nfiles) {
502 errno = EDOM;
503 return(0.0);
504 }
505 xoff = yoff = 0;
506 n = nargum();
507 if (n >= 2) {
508 d = argument(2);
509 if (d < 0.0) {
510 xoff = d-.5;
511 if (xscan+xoff < 0)
512 xoff = -xscan;
513 } else {
514 xoff = d+.5;
515 if (xscan+xoff >= xmax)
516 xoff = xmax-1-xscan;
517 }
518 }
519 if (n >= 3) {
520 d = argument(3);
521 if (d < 0.0) {
522 yoff = d-.5;
523 if (yoff+MIDSCN < 0)
524 yoff = -MIDSCN;
525 if (yscan+yoff < 0)
526 yoff = -yscan;
527 } else {
528 yoff = d+.5;
529 if (yoff+MIDSCN >= WINSIZ)
530 yoff = WINSIZ-1-MIDSCN;
531 if (yscan+yoff >= ymax)
532 yoff = ymax-1-yscan;
533 }
534 }
535 if (nam == vbrtin)
536 return((*ourbright)(input[fn].scan[MIDSCN+yoff][xscan+xoff]));
537 n = 3;
538 while (n--)
539 if (nam == vcolin[n])
540 return(colval(input[fn].scan[MIDSCN+yoff][xscan+xoff],n));
541 eputs("Bad call to l_colin()!\n");
542 quit(1);
543 return 1; /* pro forma return */
544 }
545
546
547 static double
548 l_ray( /* return ray origin or direction */
549 register char *nam
550 )
551 {
552 static unsigned long ltick[MAXINP];
553 static FVECT lorg[MAXINP], ldir[MAXINP];
554 static double ldist[MAXINP];
555 RREAL loc[2];
556 int fn;
557 register int i;
558
559 fn = argument(1) - .5;
560 if (fn < 0 || fn >= nfiles) {
561 errno = EDOM;
562 return(0.0);
563 }
564 if (ltick[fn] != eclock) { /* need to compute? */
565 lorg[fn][0] = lorg[fn][1] = lorg[fn][2] = 0.0;
566 ldir[fn][0] = ldir[fn][1] = ldir[fn][2] = 0.0;
567 ldist[fn] = -1.0;
568 if (input[fn].vw.type == 0)
569 errno = EDOM;
570 else {
571 pix2loc(loc, &input[fn].rs, xscan, ymax-1-yscan);
572 ldist[fn] = viewray(lorg[fn], ldir[fn],
573 &input[fn].vw, loc[0], loc[1]);
574 }
575 ltick[fn] = eclock;
576 }
577 if (nam == vray[i=6])
578 return(ldist[fn]);
579 while (i--)
580 if (nam == vray[i])
581 return(i < 3 ? lorg[fn][i] : ldir[fn][i-3]);
582 eputs("Bad call to l_ray()!\n");
583 quit(1);
584 return 1; /* pro forma return */
585 }
586
587
588 static double
589 l_psize(char *nm) /* compute pixel size in steradians */
590 {
591 static unsigned long ltick[MAXINP];
592 static double psize[MAXINP];
593 FVECT dir0, org, dirx, diry;
594 RREAL locx[2], locy[2];
595 double d;
596 int fn;
597 register int i;
598
599 d = argument(1);
600 if (d < .5 || d >= nfiles+.5) {
601 errno = EDOM;
602 return(0.0);
603 }
604 fn = d - .5;
605 if (ltick[fn] != eclock) { /* need to compute? */
606 psize[fn] = 0.0;
607 if (input[fn].vw.type == 0)
608 errno = EDOM;
609 else if (input[fn].vw.type != VT_PAR &&
610 funvalue(vray[6], 1, &d) >= -FTINY) {
611 for (i = 0; i < 3; i++)
612 dir0[i] = funvalue(vray[3+i], 1, &d);
613 pix2loc(locx, &input[fn].rs, xscan+1, ymax-1-yscan);
614 pix2loc(locy, &input[fn].rs, xscan, ymax-yscan);
615 if (viewray(org, dirx, &input[fn].vw,
616 locx[0], locx[1]) >= -FTINY &&
617 viewray(org, diry, &input[fn].vw,
618 locy[0], locy[1]) >= -FTINY) {
619 /* approximate solid angle */
620 for (i = 0; i < 3; i++) {
621 dirx[i] -= dir0[i];
622 diry[i] -= dir0[i];
623 }
624 fcross(dir0, dirx, diry);
625 psize[fn] = VLEN(dir0);
626 }
627 }
628 ltick[fn] = eclock;
629 }
630 return(psize[fn]);
631 }
632
633
634 extern void
635 wputs(char *msg)
636 {
637 if (!nowarn)
638 eputs(msg);
639 }
640
641
642 extern void
643 eputs(char *msg)
644 {
645 fputs(msg, stderr);
646 }
647
648
649 extern void
650 quit(int code) /* exit gracefully */
651 {
652 register int i;
653 /* close input files */
654 for (i = 0; i < nfiles; i++)
655 if (input[i].name == Command)
656 pclose(input[i].fp);
657 else
658 fclose(input[i].fp);
659 exit(code);
660 }