ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/px/pcomb.c
Revision: 2.30
Committed: Fri Jan 2 12:47:01 2004 UTC (20 years, 4 months ago) by schorsch
Content type: text/plain
Branch: MAIN
Changes since 2.29: +7 -3 lines
Log Message:
Fixed typing/prototype of getheader() and its callback.

File Contents

# Content
1 #ifndef lint
2 static const char RCSid[] = "$Id: pcomb.c,v 2.29 2003/10/27 10:24:51 schorsch 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 "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 Command[] = "<Command>";
37 char vcolin[3][4] = {"ri", "gi", "bi"};
38 char vcolout[3][4] = {"ro", "go", "bo"};
39 char vbrtin[] = "li";
40 char vbrtout[] = "lo";
41 char vcolexp[3][4] = {"re", "ge", "be"};
42 char vbrtexp[] = "le";
43 char vpixaspect[] = "pa";
44
45 char vray[7][4] = {"Ox", "Oy", "Oz", "Dx", "Dy", "Dz", "T"};
46
47 char vpsize[] = "S";
48
49 char vnfiles[] = "nfiles";
50 char vwhteff[] = "WE";
51 char vxmax[] = "xmax";
52 char vymax[] = "ymax";
53 char vxres[] = "xres";
54 char vyres[] = "yres";
55 char vxpos[] = "x";
56 char vypos[] = "y";
57
58 int nowarn = 0; /* no warning messages? */
59
60 int xmax = 0, ymax = 0; /* input resolution */
61
62 int xscan, yscan; /* input position */
63
64 int xres, yres; /* output resolution */
65
66 int xpos, ypos; /* output position */
67
68 char *progname; /* global argv[0] */
69
70 int wrongformat = 0;
71 int gotview;
72
73
74 extern char *emalloc();
75
76 static gethfunc tabputs;
77
78 main(argc, argv)
79 int argc;
80 char *argv[];
81 {
82 int original;
83 double f;
84 int a, i;
85 SET_DEFAULT_BINARY();
86 SET_FILE_BINARY(stdin);
87 SET_FILE_BINARY(stdout);
88 progname = argv[0];
89 /* scan options */
90 for (a = 1; a < argc; a++) {
91 if (argv[a][0] == '-')
92 switch (argv[a][1]) {
93 case 'x':
94 case 'y':
95 a++;
96 continue;
97 case 'w':
98 nowarn = !nowarn;
99 continue;
100 case 'f':
101 case 'e':
102 a++;
103 continue;
104 }
105 break;
106 }
107 newheader("RADIANCE", stdout); /* start header */
108 fputnow(stdout);
109 /* process files */
110 for (nfiles = 0; nfiles < MAXINP; nfiles++) {
111 setcolor(input[nfiles].coef, 1.0, 1.0, 1.0);
112 setcolor(input[nfiles].expos, 1.0, 1.0, 1.0);
113 input[nfiles].vw = stdview;
114 input[nfiles].pa = 1.0;
115 }
116 nfiles = 0;
117 original = 0;
118 for ( ; a < argc; a++) {
119 if (nfiles >= MAXINP) {
120 eputs(argv[0]);
121 eputs(": too many picture files\n");
122 quit(1);
123 }
124 if (argv[a][0] == '-')
125 switch (argv[a][1]) {
126 case '\0':
127 input[nfiles].name = "<stdin>";
128 input[nfiles].fp = stdin;
129 break;
130 case 'o':
131 original++;
132 continue;
133 case 's':
134 f = atof(argv[++a]);
135 scalecolor(input[nfiles].coef, f);
136 continue;
137 case 'c':
138 colval(input[nfiles].coef,RED)*=atof(argv[++a]);
139 colval(input[nfiles].coef,GRN)*=atof(argv[++a]);
140 colval(input[nfiles].coef,BLU)*=atof(argv[++a]);
141 continue;
142 default:
143 goto usage;
144 }
145 else {
146 if (argv[a][0] == '!') {
147 input[nfiles].name = Command;
148 input[nfiles].fp = popen(argv[a]+1, "r");
149 } else {
150 input[nfiles].name = argv[a];
151 input[nfiles].fp = fopen(argv[a], "r");
152 }
153 if (input[nfiles].fp == NULL) {
154 perror(argv[a]);
155 quit(1);
156 }
157 }
158 checkfile();
159 if (original) {
160 colval(input[nfiles].coef,RED) /=
161 colval(input[nfiles].expos,RED);
162 colval(input[nfiles].coef,GRN) /=
163 colval(input[nfiles].expos,GRN);
164 colval(input[nfiles].coef,BLU) /=
165 colval(input[nfiles].expos,BLU);
166 setcolor(input[nfiles].expos, 1.0, 1.0, 1.0);
167 }
168 nfiles++;
169 original = 0;
170 }
171 init(); /* set constants */
172 /* go back and get expressions */
173 for (a = 1; a < argc; a++) {
174 if (argv[a][0] == '-')
175 switch (argv[a][1]) {
176 case 'x':
177 varset(vxres, ':', eval(argv[++a]));
178 continue;
179 case 'y':
180 varset(vyres, ':', eval(argv[++a]));
181 continue;
182 case 'w':
183 continue;
184 case 'f':
185 fcompile(argv[++a]);
186 continue;
187 case 'e':
188 scompile(argv[++a], NULL, 0);
189 continue;
190 }
191 break;
192 }
193 /* set/get output resolution */
194 if (!vardefined(vxres))
195 varset(vxres, ':', (double)xmax);
196 if (!vardefined(vyres))
197 varset(vyres, ':', (double)ymax);
198 xres = varvalue(vxres) + .5;
199 yres = varvalue(vyres) + .5;
200 if (xres <= 0 || yres <= 0) {
201 eputs(argv[0]);
202 eputs(": illegal output resolution\n");
203 quit(1);
204 }
205 /* complete header */
206 printargs(argc, argv, stdout);
207 if (strcmp(ourfmt, PICFMT))
208 fputformat(ourfmt, stdout); /* print format if known */
209 putchar('\n');
210 fprtresolu(xres, yres, stdout);
211 /* combine pictures */
212 combine();
213 quit(0);
214 usage:
215 eputs("Usage: ");
216 eputs(argv[0]);
217 eputs(
218 " [-w][-x xr][-y yr][-e expr][-f file] [ [-o][-s f][-c r g b] pic ..]\n");
219 quit(1);
220 }
221
222
223 static int
224 tabputs( /* put out string preceded by a tab */
225 char *s,
226 void *p
227 )
228 {
229 char fmt[32];
230 double d;
231 COLOR ctmp;
232
233 if (isheadid(s)) /* header id */
234 return(0); /* don't echo */
235 if (formatval(fmt, s)) { /* check format */
236 if (globmatch(ourfmt, fmt)) {
237 wrongformat = 0;
238 strcpy(ourfmt, fmt);
239 } else
240 wrongformat = globmatch(PICFMT, fmt) ? 1 : -1;
241 return(0); /* don't echo */
242 }
243 if (isexpos(s)) { /* exposure */
244 d = exposval(s);
245 scalecolor(input[nfiles].expos, d);
246 } else if (iscolcor(s)) { /* color correction */
247 colcorval(ctmp, s);
248 multcolor(input[nfiles].expos, ctmp);
249 } else if (isaspect(s))
250 input[nfiles].pa *= aspectval(s);
251 else if (isview(s) && sscanview(&input[nfiles].vw, s) > 0)
252 gotview++;
253 /* echo line */
254 putchar('\t');
255 return(fputs(s, stdout));
256 }
257
258
259 checkfile() /* ready a file */
260 {
261 register int i;
262 /* process header */
263 gotview = 0;
264 fputs(input[nfiles].name, stdout);
265 fputs(":\n", stdout);
266 getheader(input[nfiles].fp, tabputs, NULL);
267 if (wrongformat < 0) {
268 eputs(input[nfiles].name);
269 eputs(": not a Radiance picture\n");
270 quit(1);
271 }
272 if (wrongformat > 0) {
273 wputs(input[nfiles].name);
274 wputs(": warning -- incompatible picture format\n");
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(char *), l_expos(char *), l_pixaspect(char *),
320 l_ray(char *), l_psize(char *);
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(char *nm) /* 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 RREAL 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(char *nm) /* compute pixel size in steradians */
560 {
561 static unsigned long ltick[MAXINP];
562 static double psize[MAXINP];
563 FVECT dir0, org, dirx, diry;
564 RREAL 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 extern void
605 wputs(char *msg)
606 {
607 if (!nowarn)
608 eputs(msg);
609 }
610
611
612 extern void
613 eputs(char *msg)
614 {
615 fputs(msg, stderr);
616 }
617
618
619 extern void
620 quit(int code) /* exit gracefully */
621 {
622 register int i;
623 /* close input files */
624 for (i = 0; i < nfiles; i++)
625 if (input[i].name == Command)
626 pclose(input[i].fp);
627 else
628 fclose(input[i].fp);
629 exit(code);
630 }