ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/px/pinterp.c
Revision: 1.14
Committed: Thu Jan 4 17:47:37 1990 UTC (34 years, 4 months ago) by greg
Content type: text/plain
Branch: MAIN
Changes since 1.13: +35 -19 lines
Log Message:
added error checking on calculation I/O

File Contents

# Content
1 #ifndef lint
2 static char SCCSid[] = "$SunId$ LBL";
3 #endif
4
5 /*
6 * Interpolate and extrapolate pictures with different view parameters.
7 *
8 * Greg Ward 09Dec89
9 */
10
11 #include "standard.h"
12
13 #include "view.h"
14
15 #include "color.h"
16
17 #define pscan(y) (ourpict+(y)*ourview.hresolu)
18 #define zscan(y) (ourzbuf+(y)*ourview.hresolu)
19
20 #define F_FORE 1 /* fill foreground */
21 #define F_BACK 2 /* fill background */
22
23 #define PACKSIZ 42 /* calculation packet size */
24
25 #define RTCOM "rtrace -h -ovl -fff -x %d %s"
26
27 #define ABS(x) ((x)>0?(x):-(x))
28
29 VIEW ourview = STDVIEW(512); /* desired view */
30
31 double zeps = .02; /* allowed z epsilon */
32
33 COLR *ourpict; /* output picture */
34 float *ourzbuf; /* corresponding z-buffer */
35
36 char *progname;
37
38 VIEW theirview = STDVIEW(512); /* input view */
39 int gotview; /* got input view? */
40
41 int fill = F_FORE|F_BACK; /* selected fill algorithm */
42 extern int backfill(), rcalfill(); /* fill functions */
43 int (*deffill)() = backfill; /* selected fill function */
44 COLR backcolr = BLKCOLR; /* background color */
45 double backz = 0.0; /* background z value */
46
47 double theirs2ours[4][4]; /* transformation matrix */
48 int normdist = 1; /* normalized distance? */
49
50 int childpid = -1; /* id of fill process */
51 FILE *psend, *precv; /* pipes to/from fill calculation */
52 int queue[PACKSIZ][2]; /* pending pixels */
53 int queuesiz; /* number of pixels pending */
54
55
56 main(argc, argv) /* interpolate pictures */
57 int argc;
58 char *argv[];
59 {
60 #define check(olen,narg) if (argv[i][olen] || narg >= argc-i) goto badopt
61 extern double atof();
62 int gotvfile = 0;
63 char *zfile = NULL;
64 char *err;
65 int i;
66
67 progname = argv[0];
68
69 for (i = 1; i < argc && argv[i][0] == '-'; i++)
70 switch (argv[i][1]) {
71 case 't': /* threshold */
72 check(2,1);
73 zeps = atof(argv[++i]);
74 break;
75 case 'n': /* dist. normalized? */
76 check(2,0);
77 normdist = !normdist;
78 break;
79 case 'f': /* fill type */
80 switch (argv[i][2]) {
81 case '0': /* none */
82 check(3,0);
83 fill = 0;
84 break;
85 case 'f': /* foreground */
86 check(3,0);
87 fill = F_FORE;
88 break;
89 case 'b': /* background */
90 check(3,0);
91 fill = F_BACK;
92 break;
93 case 'a': /* all */
94 check(3,0);
95 fill = F_FORE|F_BACK;
96 break;
97 case 'c': /* color */
98 check(3,3);
99 deffill = backfill;
100 setcolr(backcolr, atof(argv[i+1]),
101 atof(argv[i+2]), atof(argv[i+3]));
102 i += 3;
103 break;
104 case 'z': /* z value */
105 check(3,1);
106 deffill = backfill;
107 backz = atof(argv[++i]);
108 break;
109 case 'r': /* rtrace */
110 check(3,1);
111 deffill = rcalfill;
112 calstart(RTCOM, argv[++i]);
113 break;
114 default:
115 goto badopt;
116 }
117 break;
118 case 'z': /* z file */
119 check(2,1);
120 zfile = argv[++i];
121 break;
122 case 'x': /* x resolution */
123 check(2,1);
124 ourview.hresolu = atoi(argv[++i]);
125 break;
126 case 'y': /* y resolution */
127 check(2,1);
128 ourview.vresolu = atoi(argv[++i]);
129 break;
130 case 'v': /* view */
131 switch (argv[i][2]) {
132 case 't': /* type */
133 check(4,0);
134 ourview.type = argv[i][3];
135 break;
136 case 'p': /* point */
137 check(3,3);
138 ourview.vp[0] = atof(argv[++i]);
139 ourview.vp[1] = atof(argv[++i]);
140 ourview.vp[2] = atof(argv[++i]);
141 break;
142 case 'd': /* direction */
143 check(3,3);
144 ourview.vdir[0] = atof(argv[++i]);
145 ourview.vdir[1] = atof(argv[++i]);
146 ourview.vdir[2] = atof(argv[++i]);
147 break;
148 case 'u': /* up */
149 check(3,3);
150 ourview.vup[0] = atof(argv[++i]);
151 ourview.vup[1] = atof(argv[++i]);
152 ourview.vup[2] = atof(argv[++i]);
153 break;
154 case 'h': /* horizontal */
155 check(3,1);
156 ourview.horiz = atof(argv[++i]);
157 break;
158 case 'v': /* vertical */
159 check(3,1);
160 ourview.vert = atof(argv[++i]);
161 break;
162 case 'f': /* file */
163 check(3,1);
164 gotvfile = viewfile(argv[++i], &ourview);
165 if (gotvfile < 0) {
166 perror(argv[i]);
167 exit(1);
168 } else if (gotvfile == 0) {
169 fprintf(stderr, "%s: bad view file\n",
170 argv[i]);
171 exit(1);
172 }
173 break;
174 default:
175 goto badopt;
176 }
177 break;
178 default:
179 badopt:
180 fprintf(stderr, "%s: command line error at '%s'\n",
181 progname, argv[i]);
182 goto userr;
183 }
184 /* check arguments */
185 if ((argc-i)%2)
186 goto userr;
187 /* set view */
188 if (err = setview(&ourview)) {
189 fprintf(stderr, "%s: %s\n", progname, err);
190 exit(1);
191 }
192 /* allocate frame */
193 ourpict = (COLR *)malloc(ourview.hresolu*ourview.vresolu*sizeof(COLR));
194 ourzbuf = (float *)calloc(ourview.hresolu*ourview.vresolu,sizeof(float));
195 if (ourpict == NULL || ourzbuf == NULL) {
196 perror(progname);
197 exit(1);
198 }
199 /* get input */
200 for ( ; i < argc; i += 2)
201 addpicture(argv[i], argv[i+1]);
202 /* fill in spaces */
203 if (fill&F_BACK)
204 backpicture();
205 else
206 fillpicture();
207 /* close calculation */
208 caldone();
209 /* add to header */
210 printargs(argc, argv, stdout);
211 if (gotvfile) {
212 printf(VIEWSTR);
213 fprintview(&ourview, stdout);
214 printf("\n");
215 }
216 printf("\n");
217 /* write picture */
218 writepicture();
219 /* write z file */
220 if (zfile != NULL)
221 writedistance(zfile);
222
223 exit(0);
224 userr:
225 fprintf(stderr,
226 "Usage: %s [view opts][-t zthresh][-z zout][-fT][-n] pfile zspec ..\n",
227 progname);
228 exit(1);
229 #undef check
230 }
231
232
233 headline(s) /* process header string */
234 char *s;
235 {
236 static char *altname[] = {"rview","rpict","pinterp",VIEWSTR,NULL};
237 register char **an;
238
239 printf("\t%s", s);
240
241 for (an = altname; *an != NULL; an++)
242 if (!strncmp(*an, s, strlen(*an))) {
243 if (sscanview(&theirview, s+strlen(*an)) == 0)
244 gotview++;
245 break;
246 }
247 }
248
249
250 addpicture(pfile, zspec) /* add picture to output */
251 char *pfile, *zspec;
252 {
253 extern double atof();
254 FILE *pfp, *zfp;
255 char *err;
256 COLR *scanin;
257 float *zin, *zlast;
258 int *plast;
259 int y;
260 /* open picture file */
261 if ((pfp = fopen(pfile, "r")) == NULL) {
262 perror(pfile);
263 exit(1);
264 }
265 /* get header and view */
266 printf("%s:\n", pfile);
267 gotview = 0;
268 getheader(pfp, headline);
269 if (!gotview || fgetresolu(&theirview.hresolu, &theirview.vresolu, pfp)
270 != (YMAJOR|YDECR)) {
271 fprintf(stderr, "%s: picture view error\n", pfile);
272 exit(1);
273 }
274 if (err = setview(&theirview)) {
275 fprintf(stderr, "%s: %s\n", pfile, err);
276 exit(1);
277 }
278 /* compute transformation */
279 pixform(theirs2ours, &theirview, &ourview);
280 /* allocate scanlines */
281 scanin = (COLR *)malloc(theirview.hresolu*sizeof(COLR));
282 zin = (float *)malloc(theirview.hresolu*sizeof(float));
283 plast = (int *)calloc(theirview.hresolu, sizeof(int));
284 zlast = (float *)calloc(theirview.hresolu, sizeof(float));
285 if (scanin == NULL || zin == NULL || plast == NULL || zlast == NULL) {
286 perror(progname);
287 exit(1);
288 }
289 /* get z specification or file */
290 if ((zfp = fopen(zspec, "r")) == NULL) {
291 double zvalue;
292 register int x;
293 if (!isfloat(zspec) || (zvalue = atof(zspec)) <= 0.0) {
294 perror(zspec);
295 exit(1);
296 }
297 for (x = 0; x < theirview.hresolu; x++)
298 zin[x] = zvalue;
299 }
300 /* load image */
301 for (y = theirview.vresolu-1; y >= 0; y--) {
302 if (freadcolrs(scanin, theirview.hresolu, pfp) < 0) {
303 fprintf(stderr, "%s: read error\n", pfile);
304 exit(1);
305 }
306 if (zfp != NULL
307 && fread(zin,sizeof(float),theirview.hresolu,zfp)
308 < theirview.hresolu) {
309 fprintf(stderr, "%s: read error\n", zspec);
310 exit(1);
311 }
312 addscanline(y, scanin, zin, plast, zlast);
313 }
314 /* clean up */
315 free((char *)scanin);
316 free((char *)zin);
317 free((char *)plast);
318 free((char *)zlast);
319 fclose(pfp);
320 if (zfp != NULL)
321 fclose(zfp);
322 }
323
324
325 pixform(xfmat, vw1, vw2) /* compute view1 to view2 matrix */
326 register double xfmat[4][4];
327 register VIEW *vw1, *vw2;
328 {
329 double m4t[4][4];
330
331 setident4(xfmat);
332 xfmat[0][0] = vw1->vhinc[0];
333 xfmat[0][1] = vw1->vhinc[1];
334 xfmat[0][2] = vw1->vhinc[2];
335 xfmat[1][0] = vw1->vvinc[0];
336 xfmat[1][1] = vw1->vvinc[1];
337 xfmat[1][2] = vw1->vvinc[2];
338 xfmat[2][0] = vw1->vdir[0];
339 xfmat[2][1] = vw1->vdir[1];
340 xfmat[2][2] = vw1->vdir[2];
341 xfmat[3][0] = vw1->vp[0];
342 xfmat[3][1] = vw1->vp[1];
343 xfmat[3][2] = vw1->vp[2];
344 setident4(m4t);
345 m4t[0][0] = vw2->vhinc[0]/vw2->vhn2;
346 m4t[1][0] = vw2->vhinc[1]/vw2->vhn2;
347 m4t[2][0] = vw2->vhinc[2]/vw2->vhn2;
348 m4t[3][0] = -DOT(vw2->vp,vw2->vhinc)/vw2->vhn2;
349 m4t[0][1] = vw2->vvinc[0]/vw2->vvn2;
350 m4t[1][1] = vw2->vvinc[1]/vw2->vvn2;
351 m4t[2][1] = vw2->vvinc[2]/vw2->vvn2;
352 m4t[3][1] = -DOT(vw2->vp,vw2->vvinc)/vw2->vvn2;
353 m4t[0][2] = vw2->vdir[0];
354 m4t[1][2] = vw2->vdir[1];
355 m4t[2][2] = vw2->vdir[2];
356 m4t[3][2] = -DOT(vw2->vp,vw2->vdir);
357 multmat4(xfmat, xfmat, m4t);
358 }
359
360
361 addscanline(y, pline, zline, lasty, lastyz) /* add scanline to output */
362 int y;
363 COLR *pline;
364 float *zline;
365 int *lasty; /* input/output */
366 float *lastyz; /* input/output */
367 {
368 extern double sqrt();
369 double pos[3];
370 int lastx = 0;
371 double lastxz = 0;
372 double zt;
373 int xpos, ypos;
374 register int x;
375
376 for (x = theirview.hresolu-1; x >= 0; x--) {
377 pos[0] = x - .5*(theirview.hresolu-1);
378 pos[1] = y - .5*(theirview.vresolu-1);
379 pos[2] = zline[x];
380 if (theirview.type == VT_PER) {
381 if (normdist) /* adjust for eye-ray distance */
382 pos[2] /= sqrt( 1.
383 + pos[0]*pos[0]*theirview.vhn2
384 + pos[1]*pos[1]*theirview.vvn2 );
385 pos[0] *= pos[2];
386 pos[1] *= pos[2];
387 }
388 multp3(pos, pos, theirs2ours);
389 if (pos[2] <= 0)
390 continue;
391 if (ourview.type == VT_PER) {
392 pos[0] /= pos[2];
393 pos[1] /= pos[2];
394 }
395 pos[0] += .5*ourview.hresolu;
396 pos[1] += .5*ourview.vresolu;
397 if (pos[0] < 0 || (xpos = pos[0]) >= ourview.hresolu
398 || pos[1] < 0 || (ypos = pos[1]) >= ourview.vresolu)
399 continue;
400 /* add pixel to our image */
401 zt = 2.*zeps*zline[x];
402 addpixel(xpos, ypos,
403 (fill&F_FORE && ABS(zline[x]-lastxz) <= zt)
404 ? lastx - xpos : 1,
405 (fill&F_FORE && ABS(zline[x]-lastyz[x]) <= zt)
406 ? lasty[x] - ypos : 1,
407 pline[x], pos[2]);
408 lastx = xpos;
409 lasty[x] = ypos;
410 lastxz = lastyz[x] = zline[x];
411 }
412 }
413
414
415 addpixel(xstart, ystart, width, height, pix, z) /* fill in area for pixel */
416 int xstart, ystart;
417 int width, height;
418 COLR pix;
419 double z;
420 {
421 register int x, y;
422 /* make width and height positive */
423 if (width < 0) {
424 width = -width;
425 xstart = xstart-width+1;
426 } else if (width == 0)
427 width = 1;
428 if (height < 0) {
429 height = -height;
430 ystart = ystart-height+1;
431 } else if (height == 0)
432 height = 1;
433 /* fill pixel(s) within rectangle */
434 for (y = ystart; y < ystart+height; y++)
435 for (x = xstart; x < xstart+width; x++)
436 if (zscan(y)[x] <= 0
437 || zscan(y)[x]-z > zeps*zscan(y)[x]) {
438 zscan(y)[x] = z;
439 copycolr(pscan(y)[x], pix);
440 }
441 }
442
443
444 backpicture() /* background fill algorithm */
445 {
446 int *yback, xback;
447 int y;
448 COLR pfill;
449 register int x, i;
450 /* get back buffer */
451 yback = (int *)malloc(ourview.hresolu*sizeof(int));
452 if (yback == NULL) {
453 perror(progname);
454 return;
455 }
456 for (x = 0; x < ourview.hresolu; x++)
457 yback[x] = -2;
458 /*
459 * Xback and yback are the pixel locations of suitable
460 * background values in each direction.
461 * A value of -2 means unassigned, and -1 means
462 * that there is no suitable background in this direction.
463 */
464 /* fill image */
465 for (y = 0; y < ourview.vresolu; y++) {
466 xback = -2;
467 for (x = 0; x < ourview.hresolu; x++)
468 if (zscan(y)[x] <= 0) { /* empty pixel */
469 /*
470 * First, find background from above or below.
471 * (farthest assigned pixel)
472 */
473 if (yback[x] == -2) {
474 for (i = y+1; i < ourview.vresolu; i++)
475 if (zscan(i)[x] > 0)
476 break;
477 if (i < ourview.vresolu
478 && (y <= 0 || zscan(y-1)[x] < zscan(i)[x]))
479 yback[x] = i;
480 else
481 yback[x] = y-1;
482 }
483 /*
484 * Next, find background from left or right.
485 */
486 if (xback == -2) {
487 for (i = x+1; i < ourview.hresolu; i++)
488 if (zscan(y)[i] > 0)
489 break;
490 if (i < ourview.hresolu
491 && (x <= 0 || zscan(y)[x-1] < zscan(y)[i]))
492 xback = i;
493 else
494 xback = x-1;
495 }
496 /*
497 * Check to see if we have no background for
498 * this pixel. If not, use background color.
499 */
500 if (xback < 0 && yback[x] < 0) {
501 (*deffill)(x,y);
502 continue;
503 }
504 /*
505 * Compare, and use the background that is
506 * farther, unless one of them is next to us.
507 */
508 if ( yback[x] < 0
509 || (xback >= 0 && ABS(x-xback) <= 1)
510 || ( ABS(y-yback[x]) > 1
511 && zscan(yback[x])[x]
512 < zscan(y)[xback] ) ) {
513 copycolr(pscan(y)[x],pscan(y)[xback]);
514 zscan(y)[x] = zscan(y)[xback];
515 } else {
516 copycolr(pscan(y)[x],pscan(yback[x])[x]);
517 zscan(y)[x] = zscan(yback[x])[x];
518 }
519 } else { /* full pixel */
520 yback[x] = -2;
521 xback = -2;
522 }
523 }
524 free((char *)yback);
525 }
526
527
528 fillpicture() /* paint in empty pixels with default */
529 {
530 register int x, y;
531
532 for (y = 0; y < ourview.vresolu; y++)
533 for (x = 0; x < ourview.hresolu; x++)
534 if (zscan(y)[x] <= 0)
535 (*deffill)(x,y);
536 }
537
538
539 writepicture() /* write out picture */
540 {
541 int y;
542
543 fputresolu(YMAJOR|YDECR, ourview.hresolu, ourview.vresolu, stdout);
544 for (y = ourview.vresolu-1; y >= 0; y--)
545 if (fwritecolrs(pscan(y), ourview.hresolu, stdout) < 0) {
546 perror(progname);
547 exit(1);
548 }
549 }
550
551
552 writedistance(fname) /* write out z file */
553 char *fname;
554 {
555 extern double sqrt();
556 int donorm = normdist && ourview.type == VT_PER;
557 FILE *fp;
558 int y;
559 float *zout;
560
561 if ((fp = fopen(fname, "w")) == NULL) {
562 perror(fname);
563 exit(1);
564 }
565 if (donorm
566 && (zout = (float *)malloc(ourview.hresolu*sizeof(float))) == NULL) {
567 perror(progname);
568 exit(1);
569 }
570 for (y = ourview.vresolu-1; y >= 0; y--) {
571 if (donorm) {
572 double vx, yzn2;
573 register int x;
574 yzn2 = y - .5*(ourview.vresolu-1);
575 yzn2 = 1. + yzn2*yzn2*ourview.vvn2;
576 for (x = 0; x < ourview.hresolu; x++) {
577 vx = x - .5*(ourview.hresolu-1);
578 zout[x] = zscan(y)[x]
579 * sqrt(vx*vx*ourview.vhn2 + yzn2);
580 }
581 } else
582 zout = zscan(y);
583 if (fwrite(zout, sizeof(float), ourview.hresolu, fp)
584 < ourview.hresolu) {
585 perror(fname);
586 exit(1);
587 }
588 }
589 if (donorm)
590 free((char *)zout);
591 fclose(fp);
592 }
593
594
595 isfloat(s) /* see if string is floating number */
596 register char *s;
597 {
598 for ( ; *s; s++)
599 if ((*s < '0' || *s > '9') && *s != '.' && *s != '-'
600 && *s != 'e' && *s != 'E' && *s != '+')
601 return(0);
602 return(1);
603 }
604
605
606 backfill(x, y) /* fill pixel with background */
607 int x, y;
608 {
609 register BYTE *dest = pscan(y)[x];
610
611 copycolr(dest, backcolr);
612 zscan(y)[x] = backz;
613 }
614
615
616 calstart(prog, args) /* start fill calculation */
617 char *prog, *args;
618 {
619 char combuf[512];
620 int p0[2], p1[2];
621
622 if (childpid != -1) {
623 fprintf(stderr, "%s: too many calculations\n", progname);
624 exit(1);
625 }
626 sprintf(combuf, prog, PACKSIZ, args);
627 if (pipe(p0) < 0 || pipe(p1) < 0)
628 syserror();
629 if ((childpid = vfork()) == 0) { /* fork calculation */
630 close(p0[1]);
631 close(p1[0]);
632 if (p0[0] != 0) {
633 dup2(p0[0], 0);
634 close(p0[0]);
635 }
636 if (p1[1] != 1) {
637 dup2(p1[1], 1);
638 close(p1[1]);
639 }
640 execl("/bin/sh", "sh", "-c", combuf, 0);
641 perror("/bin/sh");
642 _exit(127);
643 }
644 if (childpid == -1)
645 syserror();
646 close(p0[0]);
647 close(p1[1]);
648 if ((psend = fdopen(p0[1], "w")) == NULL)
649 syserror();
650 if ((precv = fdopen(p1[0], "r")) == NULL)
651 syserror();
652 queuesiz = 0;
653 }
654
655
656 caldone() /* done with calculation */
657 {
658 int pid;
659
660 if (childpid == -1)
661 return;
662 if (fclose(psend) == EOF)
663 syserror();
664 clearqueue();
665 fclose(precv);
666 while ((pid = wait(0)) != -1 && pid != childpid)
667 ;
668 childpid = -1;
669 }
670
671
672 rcalfill(x, y) /* fill with ray-calculated pixel */
673 int x, y;
674 {
675 FVECT orig, dir;
676 float outbuf[6];
677
678 if (queuesiz >= PACKSIZ) { /* flush queue */
679 if (fflush(psend) == EOF)
680 syserror();
681 clearqueue();
682 }
683 /* send new ray */
684 rayview(orig, dir, &ourview, x+.5, y+.5);
685 outbuf[0] = orig[0]; outbuf[1] = orig[1]; outbuf[2] = orig[2];
686 outbuf[3] = dir[0]; outbuf[4] = dir[1]; outbuf[5] = dir[2];
687 if (fwrite(outbuf, sizeof(float), 6, psend) < 6)
688 syserror();
689 /* remember it */
690 queue[queuesiz][0] = x;
691 queue[queuesiz][1] = y;
692 queuesiz++;
693 }
694
695
696 clearqueue() /* get results from queue */
697 {
698 float inbuf[4];
699 register int i;
700
701 for (i = 0; i < queuesiz; i++) {
702 if (fread(inbuf, sizeof(float), 4, precv) < 4) {
703 fprintf(stderr, "%s: read error in clearqueue\n",
704 progname);
705 exit(1);
706 }
707 setcolr(pscan(queue[i][1])[queue[i][0]],
708 inbuf[0], inbuf[1], inbuf[2]);
709 zscan(queue[i][1])[queue[i][0]] = inbuf[3];
710 }
711 queuesiz = 0;
712 }
713
714
715 syserror() /* report error and exit */
716 {
717 perror(progname);
718 exit(1);
719 }