ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/px/pcomb.c
Revision: 2.40
Committed: Mon Oct 22 17:56:36 2007 UTC (16 years, 6 months ago) by greg
Content type: text/plain
Branch: MAIN
Changes since 2.39: +3 -1 lines
Log Message:
Fixed bug in -h option

File Contents

# Content
1 #ifndef lint
2 static const char RCSid[] = "$Id: pcomb.c,v 2.39 2006/09/08 21:38: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 '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] pic ..]\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 = (long)xpos*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 = (long)ypos*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 register char *nam
462 )
463 {
464 register int fn, n;
465
466 fn = argument(1) - .5;
467 if (fn < 0 || fn >= nfiles)
468 return(1.0);
469 if (nam == vbrtexp)
470 return((*ourbright)(input[fn].expos));
471 n = 3;
472 while (n--)
473 if (nam == vcolexp[n])
474 return(colval(input[fn].expos,n));
475 eputs("Bad call to l_expos()!\n");
476 quit(1);
477 return 1; /* pro forma return */
478 }
479
480
481 static double
482 l_pixaspect(char *nm) /* return pixel aspect ratio */
483 {
484 register int fn;
485
486 fn = argument(1) - .5;
487 if (fn < 0 || fn >= nfiles)
488 return(1.0);
489 return(input[fn].pa);
490 }
491
492
493 static double
494 l_colin( /* return color value for picture */
495 register char *nam
496 )
497 {
498 int fn;
499 register int n, xoff, yoff;
500 double d;
501
502 fn = argument(1) - .5;
503 if (fn < 0 || fn >= nfiles) {
504 errno = EDOM;
505 return(0.0);
506 }
507 xoff = yoff = 0;
508 n = nargum();
509 if (n >= 2) {
510 d = argument(2);
511 if (d < 0.0) {
512 xoff = d-.5;
513 if (xscan+xoff < 0)
514 xoff = -xscan;
515 } else {
516 xoff = d+.5;
517 if (xscan+xoff >= xmax)
518 xoff = xmax-1-xscan;
519 }
520 }
521 if (n >= 3) {
522 d = argument(3);
523 if (d < 0.0) {
524 yoff = d-.5;
525 if (yoff+MIDSCN < 0)
526 yoff = -MIDSCN;
527 if (yscan+yoff < 0)
528 yoff = -yscan;
529 } else {
530 yoff = d+.5;
531 if (yoff+MIDSCN >= WINSIZ)
532 yoff = WINSIZ-1-MIDSCN;
533 if (yscan+yoff >= ymax)
534 yoff = ymax-1-yscan;
535 }
536 }
537 if (nam == vbrtin)
538 return((*ourbright)(input[fn].scan[MIDSCN+yoff][xscan+xoff]));
539 n = 3;
540 while (n--)
541 if (nam == vcolin[n])
542 return(colval(input[fn].scan[MIDSCN+yoff][xscan+xoff],n));
543 eputs("Bad call to l_colin()!\n");
544 quit(1);
545 return 1; /* pro forma return */
546 }
547
548
549 static double
550 l_ray( /* return ray origin or direction */
551 register char *nam
552 )
553 {
554 static unsigned long ltick[MAXINP];
555 static FVECT lorg[MAXINP], ldir[MAXINP];
556 static double ldist[MAXINP];
557 RREAL loc[2];
558 int fn;
559 register int i;
560
561 fn = argument(1) - .5;
562 if (fn < 0 || fn >= nfiles) {
563 errno = EDOM;
564 return(0.0);
565 }
566 if (ltick[fn] != eclock) { /* need to compute? */
567 lorg[fn][0] = lorg[fn][1] = lorg[fn][2] = 0.0;
568 ldir[fn][0] = ldir[fn][1] = ldir[fn][2] = 0.0;
569 ldist[fn] = -1.0;
570 if (input[fn].vw.type == 0)
571 errno = EDOM;
572 else {
573 pix2loc(loc, &input[fn].rs, xscan, ymax-1-yscan);
574 ldist[fn] = viewray(lorg[fn], ldir[fn],
575 &input[fn].vw, loc[0], loc[1]);
576 }
577 ltick[fn] = eclock;
578 }
579 if (nam == vray[i=6])
580 return(ldist[fn]);
581 while (i--)
582 if (nam == vray[i])
583 return(i < 3 ? lorg[fn][i] : ldir[fn][i-3]);
584 eputs("Bad call to l_ray()!\n");
585 quit(1);
586 return 1; /* pro forma return */
587 }
588
589
590 static double
591 l_psize(char *nm) /* compute pixel size in steradians */
592 {
593 static unsigned long ltick[MAXINP];
594 static double psize[MAXINP];
595 FVECT dir0, org, dirx, diry;
596 RREAL locx[2], locy[2];
597 double d;
598 int fn;
599 register int i;
600
601 d = argument(1);
602 if (d < .5 || d >= nfiles+.5) {
603 errno = EDOM;
604 return(0.0);
605 }
606 fn = d - .5;
607 if (ltick[fn] != eclock) { /* need to compute? */
608 psize[fn] = 0.0;
609 if (input[fn].vw.type == 0)
610 errno = EDOM;
611 else if (input[fn].vw.type != VT_PAR &&
612 funvalue(vray[6], 1, &d) >= -FTINY) {
613 for (i = 0; i < 3; i++)
614 dir0[i] = funvalue(vray[3+i], 1, &d);
615 pix2loc(locx, &input[fn].rs, xscan+1, ymax-1-yscan);
616 pix2loc(locy, &input[fn].rs, xscan, ymax-yscan);
617 if (viewray(org, dirx, &input[fn].vw,
618 locx[0], locx[1]) >= -FTINY &&
619 viewray(org, diry, &input[fn].vw,
620 locy[0], locy[1]) >= -FTINY) {
621 /* approximate solid angle */
622 for (i = 0; i < 3; i++) {
623 dirx[i] -= dir0[i];
624 diry[i] -= dir0[i];
625 }
626 fcross(dir0, dirx, diry);
627 psize[fn] = VLEN(dir0);
628 }
629 }
630 ltick[fn] = eclock;
631 }
632 return(psize[fn]);
633 }
634
635
636 extern void
637 wputs(char *msg)
638 {
639 if (!nowarn)
640 eputs(msg);
641 }
642
643
644 extern void
645 eputs(char *msg)
646 {
647 fputs(msg, stderr);
648 }
649
650
651 extern void
652 quit(int code) /* exit gracefully */
653 {
654 register int i;
655 /* close input files */
656 for (i = 0; i < nfiles; i++)
657 if (input[i].name == Command)
658 pclose(input[i].fp);
659 else
660 fclose(input[i].fp);
661 exit(code);
662 }