ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/px/pcomb.c
Revision: 2.17
Committed: Fri Aug 30 17:39:39 1996 UTC (27 years, 8 months ago) by greg
Content type: text/plain
Branch: MAIN
Changes since 2.16: +57 -2 lines
Log Message:
added computation of pixel solid angle ("S" variable)

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