ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/px/pcomb.c
Revision: 2.21
Committed: Tue Oct 27 09:08:25 1998 UTC (25 years, 6 months ago) by gwlarson
Content type: text/plain
Branch: MAIN
Changes since 2.20: +3 -3 lines
Log Message:
changed getheader() to listen to return value of passed function

File Contents

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