ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/px/pcomb.c
Revision: 2.22
Committed: Sat Feb 22 02:07:27 2003 UTC (21 years, 2 months ago) by greg
Content type: text/plain
Branch: MAIN
CVS Tags: rad3R5
Changes since 2.21: +20 -16 lines
Log Message:
Changes and check-in for 3.5 release
Includes new source files and modifications not recorded for many years
See ray/doc/notes/ReleaseNotes for notes between 3.1 and 3.5 release

File Contents

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