ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/px/pcomb.c
Revision: 2.32
Committed: Sun Mar 28 20:33:14 2004 UTC (20 years, 1 month ago) by schorsch
Content type: text/plain
Branch: MAIN
Changes since 2.31: +55 -29 lines
Log Message:
Continued ANSIfication, and other fixes and clarifications.

File Contents

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