ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/px/pcomb.c
Revision: 2.52
Committed: Wed Apr 3 20:16:31 2019 UTC (5 years ago) by greg
Content type: text/plain
Branch: MAIN
CVS Tags: rad5R3
Changes since 2.51: +6 -6 lines
Log Message:
Changed common view parameters to a pointer

File Contents

# Content
1 #ifndef lint
2 static const char RCSid[] = "$Id: pcomb.c,v 2.51 2018/08/02 18:33:43 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 *commvp = NULL; /* 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 char *fpath;
197 if (argv[a][0] == '-')
198 switch (argv[a][1]) {
199 case 'x':
200 varset(vxres, ':', eval(argv[++a]));
201 continue;
202 case 'y':
203 varset(vyres, ':', eval(argv[++a]));
204 continue;
205 case 'w':
206 continue;
207 case 'h':
208 continue;
209 case 'f':
210 fpath = getpath(argv[++a], getrlibpath(), 0);
211 if (fpath == NULL) {
212 eputs(argv[0]);
213 eputs(": cannot find file '");
214 eputs(argv[a]);
215 eputs("'\n");
216 quit(1);
217 }
218 fcompile(fpath);
219 continue;
220 case 'e':
221 scompile(argv[++a], NULL, 0);
222 continue;
223 }
224 break;
225 }
226 /* get output resolution */
227 xres = varvalue(vxres) + .5;
228 yres = varvalue(vyres) + .5;
229 if (xres <= 0 || yres <= 0) {
230 eputs(argv[0]);
231 eputs(": illegal output resolution\n");
232 quit(1);
233 }
234 /* complete header */
235 printargs(argc, argv, stdout);
236 if (commvp != NULL) {
237 fputs(VIEWSTR, stdout);
238 fprintview(commvp, stdout);
239 fputc('\n', stdout);
240 }
241 if (strcmp(ourfmt, PICFMT))
242 fputformat(ourfmt, stdout); /* print format if known */
243 putchar('\n');
244 fprtresolu(xres, yres, stdout);
245 /* combine pictures */
246 combine();
247 quit(0);
248 usage:
249 eputs("Usage: ");
250 eputs(argv[0]);
251 eputs(
252 " [-w][-h][-x xr][-y yr][-e expr][-f file] [ [-o][-s f][-c r g b] hdr ..]\n");
253 quit(1);
254 return 1; /* pro forma return */
255 }
256
257
258 static int
259 headline( /* check header line & echo if requested */
260 char *s,
261 void *p
262 )
263 {
264 char fmt[MAXFMTLEN];
265 double d;
266 COLOR ctmp;
267
268 if (isheadid(s)) /* header id */
269 return(0); /* don't echo */
270 if (formatval(fmt, s)) { /* check format */
271 if (globmatch(ourfmt, fmt)) {
272 wrongformat = 0;
273 strcpy(ourfmt, fmt);
274 } else
275 wrongformat = globmatch(PICFMT, fmt) ? 1 : -1;
276 return(0); /* don't echo */
277 }
278 if (isexpos(s)) { /* exposure */
279 d = exposval(s);
280 scalecolor(input[nfiles].expos, d);
281 } else if (iscolcor(s)) { /* color correction */
282 colcorval(ctmp, s);
283 multcolor(input[nfiles].expos, ctmp);
284 } else if (isaspect(s))
285 input[nfiles].pa *= aspectval(s);
286 else if (isview(s) && sscanview(&input[nfiles].vw, s) > 0)
287 gotview++;
288
289 if (echoheader) { /* echo line */
290 putchar('\t');
291 return(fputs(s, stdout));
292 }
293 return(0);
294 }
295
296
297 static void
298 checkfile(void) /* ready a file */
299 {
300 int i;
301 /* process header */
302 gotview = 0;
303 if (echoheader) {
304 fputs(input[nfiles].name, stdout);
305 fputs(":\n", stdout);
306 }
307 getheader(input[nfiles].fp, headline, NULL);
308 if (wrongformat < 0) {
309 eputs(input[nfiles].name);
310 eputs(": not a Radiance picture\n");
311 quit(1);
312 }
313 if (wrongformat > 0) {
314 wputs(input[nfiles].name);
315 wputs(": warning -- incompatible picture format\n");
316 }
317 if (!gotview || setview(&input[nfiles].vw) != NULL)
318 input[nfiles].vw.type = 0;
319 else if (commvp == NULL)
320 commvp = &input[nfiles].vw;
321 if (!fgetsresolu(&input[nfiles].rs, input[nfiles].fp)) {
322 eputs(input[nfiles].name);
323 eputs(": bad picture size\n");
324 quit(1);
325 }
326 if (xmax == 0 && ymax == 0) {
327 xmax = scanlen(&input[nfiles].rs);
328 ymax = numscans(&input[nfiles].rs);
329 } else if (scanlen(&input[nfiles].rs) != xmax ||
330 numscans(&input[nfiles].rs) != ymax) {
331 eputs(input[nfiles].name);
332 eputs(": resolution mismatch\n");
333 quit(1);
334 }
335 /* allocate scanlines */
336 for (i = 0; i < WINSIZ; i++)
337 input[nfiles].scan[i] = (COLOR *)emalloc(xmax*sizeof(COLOR));
338 }
339
340
341 static double
342 rgb_bright(
343 COLOR clr
344 )
345 {
346 return(bright(clr));
347 }
348
349
350 static double
351 xyz_bright(
352 COLOR clr
353 )
354 {
355 return(clr[CIEY]);
356 }
357
358
359 double (*ourbright)() = rgb_bright;
360
361
362 static void
363 init(void) /* perform final setup */
364 {
365 int i;
366 /* define constants */
367 varset("PI", ':', PI);
368 varset(vnfiles, ':', (double)nfiles);
369 varset(vxmax, ':', (double)xmax);
370 varset(vymax, ':', (double)ymax);
371 /* set functions */
372 for (i = 0; i < 3; i++) {
373 funset(vcolexp[i], 1, ':', l_expos);
374 funset(vcolin[i], 1, '=', l_colin);
375 }
376 funset(vbrtexp, 1, ':', l_expos);
377 funset(vbrtin, 1, '=', l_colin);
378 funset(vpixaspect, 1, ':', l_pixaspect);
379 for (i = 0; i < 7; i++)
380 funset(vray[i], 1, '=', l_ray);
381 funset(vpsize, 1, '=', l_psize);
382 /* set brightness function */
383 if (!strcmp(ourfmt, CIEFMT)) {
384 varset(vwhteff, ':', 1.0);
385 ourbright = xyz_bright;
386 } else
387 varset(vwhteff, ':', WHTEFFICACY);
388 /* these may be overridden */
389 varset(vxres, ':', (double)xmax);
390 varset(vyres, ':', (double)ymax);
391 }
392
393
394 static void
395 combine(void) /* combine pictures */
396 {
397 EPNODE *coldef[3], *brtdef;
398 COLOR *scanout;
399 double d;
400 int i, j;
401 /* check defined variables */
402 for (j = 0; j < 3; j++) {
403 if (vardefined(vcolout[j]))
404 coldef[j] = eparse(vcolout[j]);
405 else
406 coldef[j] = NULL;
407 }
408 if (vardefined(vbrtout))
409 brtdef = eparse(vbrtout);
410 else
411 brtdef = NULL;
412 /* allocate scanline */
413 scanout = (COLOR *)emalloc(xres*sizeof(COLOR));
414 /* set input position */
415 yscan = ymax+MIDSCN;
416 /* combine files */
417 for (ypos = yres-1; ypos >= 0; ypos--) {
418 advance();
419 varset(vypos, '=', (double)ypos);
420 for (xpos = 0; xpos < xres; xpos++) {
421 xscan = (xpos+.5)*xmax/xres;
422 varset(vxpos, '=', (double)xpos);
423 eclock++;
424 if (brtdef != NULL) {
425 d = evalue(brtdef);
426 if (d < 0.0)
427 d = 0.0;
428 setcolor(scanout[xpos], d, d, d);
429 } else {
430 for (j = 0; j < 3; j++) {
431 if (coldef[j] != NULL) {
432 d = evalue(coldef[j]);
433 } else {
434 d = 0.0;
435 for (i = 0; i < nfiles; i++)
436 d += colval(input[i].scan[MIDSCN][xscan],j);
437 }
438 if (d < 0.0)
439 d = 0.0;
440 colval(scanout[xpos],j) = d;
441 }
442 }
443 }
444 if (fwritescan(scanout, xres, stdout) < 0) {
445 perror("write error");
446 quit(1);
447 }
448 }
449 efree((char *)scanout);
450 }
451
452
453 static void
454 advance(void) /* read in data for next scanline */
455 {
456 int ytarget;
457 COLOR *st;
458 int i, j;
459
460 for (ytarget = (ypos+.5)*ymax/yres; yscan > ytarget; yscan--)
461 for (i = 0; i < nfiles; i++) {
462 st = input[i].scan[WINSIZ-1];
463 for (j = WINSIZ-1; j > 0; j--) /* rotate window */
464 input[i].scan[j] = input[i].scan[j-1];
465 input[i].scan[0] = st;
466 if (yscan <= MIDSCN) /* hit bottom? */
467 continue;
468 if (freadscan(st, xmax, input[i].fp) < 0) { /* read */
469 eputs(input[i].name);
470 eputs(": read error\n");
471 quit(1);
472 }
473 for (j = 0; j < xmax; j++) /* adjust color */
474 multcolor(st[j], input[i].coef);
475 }
476 }
477
478
479 static double
480 l_expos( /* return picture exposure */
481 char *nam
482 )
483 {
484 int fn, n;
485 double d;
486
487 d = argument(1);
488 if (d <= -0.5 || d >= nfiles+0.5) {
489 errno = EDOM;
490 return(0.0);
491 }
492 if (d < 0.5)
493 return((double)nfiles);
494 fn = d - 0.5;
495 if (nam == vbrtexp)
496 return((*ourbright)(input[fn].expos));
497 n = 3;
498 while (n--)
499 if (nam == vcolexp[n])
500 return(colval(input[fn].expos,n));
501 eputs("Bad call to l_expos()!\n");
502 quit(1);
503 return 1; /* pro forma return */
504 }
505
506
507 static double
508 l_pixaspect(char *nm) /* return pixel aspect ratio */
509 {
510 int fn;
511 double d;
512
513 d = argument(1);
514 if (d <= -0.5 || d >= nfiles+0.5) {
515 errno = EDOM;
516 return(0.0);
517 }
518 if (d < 0.5)
519 return((double)nfiles);
520 fn = d - 0.5;
521 return(input[fn].pa);
522 }
523
524
525 static double
526 l_colin( /* return color value for picture */
527 char *nam
528 )
529 {
530 int fn;
531 int n, xoff, yoff;
532 double d;
533
534 d = argument(1);
535 if (d <= -0.5 || d >= nfiles+0.5) {
536 errno = EDOM;
537 return(0.0);
538 }
539 if (d < 0.5)
540 return((double)nfiles);
541 fn = d - 0.5;
542 xoff = yoff = 0;
543 n = nargum();
544 if (n >= 2) {
545 d = argument(2);
546 if (d < 0.0) {
547 xoff = d-.5;
548 if (xscan+xoff < 0)
549 xoff = -xscan;
550 } else {
551 xoff = d+.5;
552 if (xscan+xoff >= xmax)
553 xoff = xmax-1-xscan;
554 }
555 }
556 if (n >= 3) {
557 d = argument(3);
558 if (d < 0.0) {
559 yoff = d-.5;
560 if (yoff+MIDSCN < 0)
561 yoff = -MIDSCN;
562 if (yscan+yoff < 0)
563 yoff = -yscan;
564 } else {
565 yoff = d+.5;
566 if (yoff+MIDSCN >= WINSIZ)
567 yoff = WINSIZ-1-MIDSCN;
568 if (yscan+yoff >= ymax)
569 yoff = ymax-1-yscan;
570 }
571 }
572 if (nam == vbrtin)
573 return((*ourbright)(input[fn].scan[MIDSCN+yoff][xscan+xoff]));
574 n = 3;
575 while (n--)
576 if (nam == vcolin[n])
577 return(colval(input[fn].scan[MIDSCN+yoff][xscan+xoff],n));
578 eputs("Bad call to l_colin()!\n");
579 quit(1);
580 return 1; /* pro forma return */
581 }
582
583
584 static double
585 l_ray( /* return ray origin or direction */
586 char *nam
587 )
588 {
589 static unsigned long ltick[MAXINP];
590 static FVECT lorg[MAXINP], ldir[MAXINP];
591 static double ldist[MAXINP];
592 RREAL loc[2];
593 double d;
594 int fn;
595 int i;
596
597 d = argument(1);
598 if (d <= -0.5 || d >= nfiles+0.5) {
599 errno = EDOM;
600 return(0.0);
601 }
602 if (d < 0.5)
603 return((double)nfiles);
604 fn = d - 0.5;
605 if (ltick[fn] != eclock) { /* need to compute? */
606 lorg[fn][0] = lorg[fn][1] = lorg[fn][2] = 0.0;
607 ldir[fn][0] = ldir[fn][1] = ldir[fn][2] = 0.0;
608 ldist[fn] = -1.0;
609 if (input[fn].vw.type == 0)
610 errno = EDOM;
611 else {
612 pix2loc(loc, &input[fn].rs, xscan, ymax-1-yscan);
613 ldist[fn] = viewray(lorg[fn], ldir[fn],
614 &input[fn].vw, loc[0], loc[1]);
615 }
616 ltick[fn] = eclock;
617 }
618 if (nam == vray[i=6])
619 return(ldist[fn]);
620 while (i--)
621 if (nam == vray[i])
622 return(i < 3 ? lorg[fn][i] : ldir[fn][i-3]);
623 eputs("Bad call to l_ray()!\n");
624 quit(1);
625 return 1; /* pro forma return */
626 }
627
628
629 static double
630 l_psize(char *nm) /* compute pixel size in steradians */
631 {
632 static unsigned long ltick[MAXINP];
633 static double psize[MAXINP];
634 FVECT dir0, org, dirx, diry;
635 RREAL locx[2], locy[2];
636 double d;
637 int fn;
638 int i;
639
640 d = argument(1);
641 if (d <= -0.5 || d >= nfiles+0.5) {
642 errno = EDOM;
643 return(0.0);
644 }
645 if (d < 0.5)
646 return((double)nfiles);
647 fn = d - 0.5;
648 if (ltick[fn] != eclock) { /* need to compute? */
649 psize[fn] = 0.0;
650 if (input[fn].vw.type == 0)
651 errno = EDOM;
652 else if (input[fn].vw.type != VT_PAR &&
653 funvalue(vray[6], 1, &d) >= -FTINY) {
654 for (i = 0; i < 3; i++)
655 dir0[i] = funvalue(vray[3+i], 1, &d);
656 pix2loc(locx, &input[fn].rs, xscan+1, ymax-1-yscan);
657 pix2loc(locy, &input[fn].rs, xscan, ymax-yscan);
658 if (viewray(org, dirx, &input[fn].vw,
659 locx[0], locx[1]) >= -FTINY &&
660 viewray(org, diry, &input[fn].vw,
661 locy[0], locy[1]) >= -FTINY) {
662 /* approximate solid angle */
663 for (i = 0; i < 3; i++) {
664 dirx[i] -= dir0[i];
665 diry[i] -= dir0[i];
666 }
667 fcross(dir0, dirx, diry);
668 psize[fn] = VLEN(dir0);
669 }
670 }
671 ltick[fn] = eclock;
672 }
673 return(psize[fn]);
674 }
675
676
677 extern void
678 wputs(char *msg)
679 {
680 if (!nowarn)
681 eputs(msg);
682 }
683
684
685 extern void
686 eputs(char *msg)
687 {
688 fputs(msg, stderr);
689 }
690
691
692 extern void
693 quit(int code) /* exit gracefully */
694 {
695 int i;
696 /* close input files */
697 for (i = 0; i < nfiles; i++)
698 if (input[i].name == Command)
699 pclose(input[i].fp);
700 else
701 fclose(input[i].fp);
702 exit(code);
703 }