ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/px/pcomb.c
Revision: 2.34
Committed: Tue Aug 31 18:52:27 2004 UTC (19 years, 7 months ago) by greg
Content type: text/plain
Branch: MAIN
CVS Tags: rad3R6, rad3R6P1
Changes since 2.33: +1 -3 lines
Log Message:
Removed redundant function declarations

File Contents

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