ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/px/pcomb.c
Revision: 2.49
Committed: Mon Feb 5 20:07:17 2018 UTC (6 years, 3 months ago) by greg
Content type: text/plain
Branch: MAIN
Changes since 2.48: +10 -1 lines
Log Message:
Decided to share first input view in the output of pcomb

File Contents

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