ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/px/pinterp.c
Revision: 1.17
Committed: Mon Jan 8 14:47:15 1990 UTC (34 years, 3 months ago) by greg
Content type: text/plain
Branch: MAIN
Changes since 1.16: +88 -116 lines
Log Message:
changed handling of view parameters

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)*hresolu)
18 #define zscan(y) (ourzbuf+(y)*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 struct position {int x,y; float z;};
30
31 VIEW ourview = STDVIEW; /* desired view */
32 int hresolu = 512; /* horizontal resolution */
33 int vresolu = 512; /* vertical resolution */
34
35 double zeps = .02; /* allowed z epsilon */
36
37 COLR *ourpict; /* output picture */
38 float *ourzbuf; /* corresponding z-buffer */
39
40 char *progname;
41
42 int fill = F_FORE|F_BACK; /* selected fill algorithm */
43 extern int backfill(), rcalfill(); /* fill functions */
44 int (*deffill)() = backfill; /* selected fill function */
45 COLR backcolr = BLKCOLR; /* background color */
46 double backz = 0.0; /* background z value */
47 int normdist = 1; /* normalized distance? */
48 double ourexp = -1; /* output picture exposure */
49
50 VIEW theirview = STDVIEW; /* input view */
51 int gotview; /* got input view? */
52 int thresolu, tvresolu; /* input resolution */
53 double theirexp; /* input picture exposure */
54 double theirs2ours[4][4]; /* transformation matrix */
55
56 int childpid = -1; /* id of fill process */
57 FILE *psend, *precv; /* pipes to/from fill calculation */
58 int queue[PACKSIZ][2]; /* pending pixels */
59 int queuesiz; /* number of pixels pending */
60
61
62 main(argc, argv) /* interpolate pictures */
63 int argc;
64 char *argv[];
65 {
66 #define check(olen,narg) if (argv[i][olen] || narg >= argc-i) goto badopt
67 extern double atof();
68 int gotvfile = 0;
69 char *zfile = NULL;
70 char *err;
71 int i, rval;
72
73 progname = argv[0];
74
75 for (i = 1; i < argc && argv[i][0] == '-'; i++) {
76 rval = getviewopt(&ourview, argc-i, argv+i);
77 if (rval >= 0) {
78 i += rval;
79 continue;
80 }
81 switch (argv[i][1]) {
82 case 't': /* threshold */
83 check(2,1);
84 zeps = atof(argv[++i]);
85 break;
86 case 'n': /* dist. normalized? */
87 check(2,0);
88 normdist = !normdist;
89 break;
90 case 'f': /* fill type */
91 switch (argv[i][2]) {
92 case '0': /* none */
93 check(3,0);
94 fill = 0;
95 break;
96 case 'f': /* foreground */
97 check(3,0);
98 fill = F_FORE;
99 break;
100 case 'b': /* background */
101 check(3,0);
102 fill = F_BACK;
103 break;
104 case 'a': /* all */
105 check(3,0);
106 fill = F_FORE|F_BACK;
107 break;
108 case 'c': /* color */
109 check(3,3);
110 deffill = backfill;
111 setcolr(backcolr, atof(argv[i+1]),
112 atof(argv[i+2]), atof(argv[i+3]));
113 i += 3;
114 break;
115 case 'z': /* z value */
116 check(3,1);
117 deffill = backfill;
118 backz = atof(argv[++i]);
119 break;
120 case 'r': /* rtrace */
121 check(3,1);
122 deffill = rcalfill;
123 calstart(RTCOM, argv[++i]);
124 break;
125 default:
126 goto badopt;
127 }
128 break;
129 case 'z': /* z file */
130 check(2,1);
131 zfile = argv[++i];
132 break;
133 case 'x': /* x resolution */
134 check(2,1);
135 hresolu = atoi(argv[++i]);
136 break;
137 case 'y': /* y resolution */
138 check(2,1);
139 vresolu = atoi(argv[++i]);
140 break;
141 case 'v': /* view file */
142 if (argv[i][2] != 'f')
143 goto badopt;
144 check(3,1);
145 gotvfile = viewfile(argv[++i], &ourview);
146 if (gotvfile < 0) {
147 perror(argv[i]);
148 exit(1);
149 } else if (gotvfile == 0) {
150 fprintf(stderr, "%s: bad view file\n",
151 argv[i]);
152 exit(1);
153 }
154 break;
155 default:
156 badopt:
157 fprintf(stderr, "%s: command line error at '%s'\n",
158 progname, argv[i]);
159 goto userr;
160 }
161 }
162 /* check arguments */
163 if ((argc-i)%2)
164 goto userr;
165 /* set view */
166 if (err = setview(&ourview)) {
167 fprintf(stderr, "%s: %s\n", progname, err);
168 exit(1);
169 }
170 /* allocate frame */
171 ourpict = (COLR *)malloc(hresolu*vresolu*sizeof(COLR));
172 ourzbuf = (float *)calloc(hresolu*vresolu,sizeof(float));
173 if (ourpict == NULL || ourzbuf == NULL)
174 syserror();
175 /* get input */
176 for ( ; i < argc; i += 2)
177 addpicture(argv[i], argv[i+1]);
178 /* fill in spaces */
179 if (fill&F_BACK)
180 backpicture();
181 else
182 fillpicture();
183 /* close calculation */
184 caldone();
185 /* add to header */
186 printargs(argc, argv, stdout);
187 if (gotvfile) {
188 printf(VIEWSTR);
189 fprintview(&ourview, stdout);
190 printf("\n");
191 }
192 if (ourexp > 0 && ourexp != 1.0)
193 fputexpos(ourexp, stdout);
194 printf("\n");
195 /* write picture */
196 writepicture();
197 /* write z file */
198 if (zfile != NULL)
199 writedistance(zfile);
200
201 exit(0);
202 userr:
203 fprintf(stderr,
204 "Usage: %s [view opts][-t eps][-z zout][-fT][-n] pfile zspec ..\n",
205 progname);
206 exit(1);
207 #undef check
208 }
209
210
211 headline(s) /* process header string */
212 char *s;
213 {
214 static char *altname[] = {"rview","rpict","pinterp",VIEWSTR,NULL};
215 register char **an;
216
217 printf("\t%s", s);
218
219 if (isexpos(s)) {
220 theirexp *= exposval(s);
221 return;
222 }
223 for (an = altname; *an != NULL; an++)
224 if (!strncmp(*an, s, strlen(*an))) {
225 if (sscanview(&theirview, s+strlen(*an)) > 0)
226 gotview++;
227 break;
228 }
229 }
230
231
232 addpicture(pfile, zspec) /* add picture to output */
233 char *pfile, *zspec;
234 {
235 extern double atof();
236 FILE *pfp, *zfp;
237 char *err;
238 COLR *scanin;
239 float *zin;
240 struct position *plast;
241 int y;
242 /* open picture file */
243 if ((pfp = fopen(pfile, "r")) == NULL) {
244 perror(pfile);
245 exit(1);
246 }
247 /* get header with exposure and view */
248 theirexp = 1.0;
249 gotview = 0;
250 printf("%s:\n", pfile);
251 getheader(pfp, headline);
252 if (!gotview || fgetresolu(&thresolu, &tvresolu, pfp)
253 != (YMAJOR|YDECR)) {
254 fprintf(stderr, "%s: picture view error\n", pfile);
255 exit(1);
256 }
257 if (ourexp <= 0)
258 ourexp = theirexp;
259 else if (ABS(theirexp-ourexp) > .01*ourexp)
260 fprintf(stderr, "%s: different exposure (warning)\n", pfile);
261 if (err = setview(&theirview)) {
262 fprintf(stderr, "%s: %s\n", pfile, err);
263 exit(1);
264 }
265 /* compute transformation */
266 pixform(theirs2ours, &theirview, &ourview);
267 /* allocate scanlines */
268 scanin = (COLR *)malloc(thresolu*sizeof(COLR));
269 zin = (float *)malloc(thresolu*sizeof(float));
270 plast = (struct position *)calloc(thresolu, sizeof(struct position));
271 if (scanin == NULL || zin == NULL || plast == NULL)
272 syserror();
273 /* get z specification or file */
274 if ((zfp = fopen(zspec, "r")) == NULL) {
275 double zvalue;
276 register int x;
277 if (!isfloat(zspec) || (zvalue = atof(zspec)) <= 0.0) {
278 perror(zspec);
279 exit(1);
280 }
281 for (x = 0; x < thresolu; x++)
282 zin[x] = zvalue;
283 }
284 /* load image */
285 for (y = tvresolu-1; y >= 0; y--) {
286 if (freadcolrs(scanin, thresolu, pfp) < 0) {
287 fprintf(stderr, "%s: read error\n", pfile);
288 exit(1);
289 }
290 if (zfp != NULL
291 && fread(zin,sizeof(float),thresolu,zfp) < thresolu) {
292 fprintf(stderr, "%s: read error\n", zspec);
293 exit(1);
294 }
295 addscanline(y, scanin, zin, plast);
296 }
297 /* clean up */
298 free((char *)scanin);
299 free((char *)zin);
300 free((char *)plast);
301 fclose(pfp);
302 if (zfp != NULL)
303 fclose(zfp);
304 }
305
306
307 pixform(xfmat, vw1, vw2) /* compute view1 to view2 matrix */
308 register double xfmat[4][4];
309 register VIEW *vw1, *vw2;
310 {
311 double m4t[4][4];
312
313 setident4(xfmat);
314 xfmat[0][0] = vw1->hvec[0];
315 xfmat[0][1] = vw1->hvec[1];
316 xfmat[0][2] = vw1->hvec[2];
317 xfmat[1][0] = vw1->vvec[0];
318 xfmat[1][1] = vw1->vvec[1];
319 xfmat[1][2] = vw1->vvec[2];
320 xfmat[2][0] = vw1->vdir[0];
321 xfmat[2][1] = vw1->vdir[1];
322 xfmat[2][2] = vw1->vdir[2];
323 xfmat[3][0] = vw1->vp[0];
324 xfmat[3][1] = vw1->vp[1];
325 xfmat[3][2] = vw1->vp[2];
326 setident4(m4t);
327 m4t[0][0] = vw2->hvec[0]/vw2->hn2;
328 m4t[1][0] = vw2->hvec[1]/vw2->hn2;
329 m4t[2][0] = vw2->hvec[2]/vw2->hn2;
330 m4t[3][0] = -DOT(vw2->vp,vw2->hvec)/vw2->hn2;
331 m4t[0][1] = vw2->vvec[0]/vw2->vn2;
332 m4t[1][1] = vw2->vvec[1]/vw2->vn2;
333 m4t[2][1] = vw2->vvec[2]/vw2->vn2;
334 m4t[3][1] = -DOT(vw2->vp,vw2->vvec)/vw2->vn2;
335 m4t[0][2] = vw2->vdir[0];
336 m4t[1][2] = vw2->vdir[1];
337 m4t[2][2] = vw2->vdir[2];
338 m4t[3][2] = -DOT(vw2->vp,vw2->vdir);
339 multmat4(xfmat, xfmat, m4t);
340 }
341
342
343 addscanline(y, pline, zline, lasty) /* add scanline to output */
344 int y;
345 COLR *pline;
346 float *zline;
347 struct position *lasty; /* input/output */
348 {
349 extern double sqrt();
350 double pos[3];
351 struct position lastx, newpos;
352 register int x;
353
354 for (x = thresolu-1; x >= 0; x--) {
355 pos[0] = (x+.5)/thresolu + theirview.hoff - .5;
356 pos[1] = (y+.5)/tvresolu + theirview.voff - .5;
357 pos[2] = zline[x];
358 if (theirview.type == VT_PER) {
359 if (normdist) /* adjust for eye-ray distance */
360 pos[2] /= sqrt( 1.
361 + pos[0]*pos[0]*theirview.hn2
362 + pos[1]*pos[1]*theirview.vn2 );
363 pos[0] *= pos[2];
364 pos[1] *= pos[2];
365 }
366 multp3(pos, pos, theirs2ours);
367 if (pos[2] <= 0) {
368 lasty[x].z = lastx.z = 0; /* mark invalid */
369 continue;
370 }
371 if (ourview.type == VT_PER) {
372 pos[0] /= pos[2];
373 pos[1] /= pos[2];
374 }
375 pos[0] += .5 - ourview.hoff;
376 pos[1] += .5 - ourview.voff;
377 newpos.x = pos[0] * hresolu;
378 newpos.y = pos[1] * vresolu;
379 newpos.z = zline[x];
380 /* add pixel to our image */
381 if (pos[0] >= 0 && newpos.x < hresolu
382 && pos[1] >= 0 && newpos.y < vresolu) {
383 addpixel(&newpos, &lastx, &lasty[x], pline[x], pos[2]);
384 lasty[x].x = lastx.x = newpos.x;
385 lasty[x].y = lastx.y = newpos.y;
386 lasty[x].z = lastx.z = newpos.z;
387 } else
388 lasty[x].z = lastx.z = 0; /* mark invalid */
389 }
390 }
391
392
393 addpixel(p0, p1, p2, pix, z) /* fill in pixel parallelogram */
394 struct position *p0, *p1, *p2;
395 COLR pix;
396 double z;
397 {
398 double zt = 2.*zeps*p0->z; /* threshold */
399 int s1x, s1y, s2x, s2y; /* step sizes */
400 int l1, l2, c1, c2; /* side lengths and counters */
401 int p1isy; /* p0p1 along y? */
402 int x1, y1; /* p1 position */
403 register int x, y; /* final position */
404
405 /* compute vector p0p1 */
406 if (fill&F_FORE && ABS(p1->z-p0->z) <= zt) {
407 s1x = p1->x - p0->x;
408 s1y = p1->y - p0->y;
409 l1 = ABS(s1x);
410 if (p1isy = (ABS(s1y) > l1))
411 l1 = ABS(s1y);
412 } else {
413 l1 = s1x = s1y = 1;
414 p1isy = -1;
415 }
416 /* compute vector p0p2 */
417 if (fill&F_FORE && ABS(p2->z-p0->z) <= zt) {
418 s2x = p2->x - p0->x;
419 s2y = p2->y - p0->y;
420 if (p1isy == 1)
421 l2 = ABS(s2x);
422 else {
423 l2 = ABS(s2y);
424 if (p1isy != 0 && ABS(s2x) > l2)
425 l2 = ABS(s2x);
426 }
427 } else
428 l2 = s2x = s2y = 1;
429 /* fill the parallelogram */
430 for (c1 = l1; c1-- > 0; ) {
431 x1 = p0->x + c1*s1x/l1;
432 y1 = p0->y + c1*s1y/l1;
433 for (c2 = l2; c2-- > 0; ) {
434 x = x1 + c2*s2x/l2;
435 y = y1 + c2*s2y/l2;
436 if (zscan(y)[x] <= 0 || zscan(y)[x]-z
437 > zeps*zscan(y)[x]) {
438 zscan(y)[x] = z;
439 copycolr(pscan(y)[x], pix);
440 }
441 }
442 }
443 }
444
445
446 backpicture() /* background fill algorithm */
447 {
448 int *yback, xback;
449 int y;
450 COLR pfill;
451 register int x, i;
452 /* get back buffer */
453 yback = (int *)malloc(hresolu*sizeof(int));
454 if (yback == NULL)
455 syserror();
456 for (x = 0; x < 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 < vresolu; y++) {
466 xback = -2;
467 for (x = 0; x < 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 < vresolu; i++)
475 if (zscan(i)[x] > 0)
476 break;
477 if (i < 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 < hresolu; i++)
488 if (zscan(y)[i] > 0)
489 break;
490 if (i < 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 < vresolu; y++)
533 for (x = 0; x < 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, hresolu, vresolu, stdout);
544 for (y = vresolu-1; y >= 0; y--)
545 if (fwritecolrs(pscan(y), hresolu, stdout) < 0)
546 syserror();
547 }
548
549
550 writedistance(fname) /* write out z file */
551 char *fname;
552 {
553 extern double sqrt();
554 int donorm = normdist && ourview.type == VT_PER;
555 FILE *fp;
556 int y;
557 float *zout;
558
559 if ((fp = fopen(fname, "w")) == NULL) {
560 perror(fname);
561 exit(1);
562 }
563 if (donorm
564 && (zout = (float *)malloc(hresolu*sizeof(float))) == NULL)
565 syserror();
566 for (y = vresolu-1; y >= 0; y--) {
567 if (donorm) {
568 double vx, yzn2;
569 register int x;
570 yzn2 = y - .5*(vresolu-1);
571 yzn2 = 1. + yzn2*yzn2*ourview.vn2;
572 for (x = 0; x < hresolu; x++) {
573 vx = x - .5*(hresolu-1);
574 zout[x] = zscan(y)[x]
575 * sqrt(vx*vx*ourview.hn2 + yzn2);
576 }
577 } else
578 zout = zscan(y);
579 if (fwrite(zout, sizeof(float), hresolu, fp) < hresolu) {
580 perror(fname);
581 exit(1);
582 }
583 }
584 if (donorm)
585 free((char *)zout);
586 fclose(fp);
587 }
588
589
590 isfloat(s) /* see if string is floating number */
591 register char *s;
592 {
593 for ( ; *s; s++)
594 if ((*s < '0' || *s > '9') && *s != '.' && *s != '-'
595 && *s != 'e' && *s != 'E' && *s != '+')
596 return(0);
597 return(1);
598 }
599
600
601 backfill(x, y) /* fill pixel with background */
602 int x, y;
603 {
604 register BYTE *dest = pscan(y)[x];
605
606 copycolr(dest, backcolr);
607 zscan(y)[x] = backz;
608 }
609
610
611 calstart(prog, args) /* start fill calculation */
612 char *prog, *args;
613 {
614 char combuf[512];
615 int p0[2], p1[2];
616
617 if (childpid != -1) {
618 fprintf(stderr, "%s: too many calculations\n", progname);
619 exit(1);
620 }
621 sprintf(combuf, prog, PACKSIZ, args);
622 if (pipe(p0) < 0 || pipe(p1) < 0)
623 syserror();
624 if ((childpid = vfork()) == 0) { /* fork calculation */
625 close(p0[1]);
626 close(p1[0]);
627 if (p0[0] != 0) {
628 dup2(p0[0], 0);
629 close(p0[0]);
630 }
631 if (p1[1] != 1) {
632 dup2(p1[1], 1);
633 close(p1[1]);
634 }
635 execl("/bin/sh", "sh", "-c", combuf, 0);
636 perror("/bin/sh");
637 _exit(127);
638 }
639 if (childpid == -1)
640 syserror();
641 close(p0[0]);
642 close(p1[1]);
643 if ((psend = fdopen(p0[1], "w")) == NULL)
644 syserror();
645 if ((precv = fdopen(p1[0], "r")) == NULL)
646 syserror();
647 queuesiz = 0;
648 }
649
650
651 caldone() /* done with calculation */
652 {
653 int pid;
654
655 if (childpid == -1)
656 return;
657 if (fclose(psend) == EOF)
658 syserror();
659 clearqueue();
660 fclose(precv);
661 while ((pid = wait(0)) != -1 && pid != childpid)
662 ;
663 childpid = -1;
664 }
665
666
667 rcalfill(x, y) /* fill with ray-calculated pixel */
668 int x, y;
669 {
670 FVECT orig, dir;
671 float outbuf[6];
672
673 if (queuesiz >= PACKSIZ) { /* flush queue */
674 if (fflush(psend) == EOF)
675 syserror();
676 clearqueue();
677 }
678 /* send new ray */
679 viewray(orig, dir, &ourview, (x+.5)/hresolu, (y+.5)/vresolu);
680 outbuf[0] = orig[0]; outbuf[1] = orig[1]; outbuf[2] = orig[2];
681 outbuf[3] = dir[0]; outbuf[4] = dir[1]; outbuf[5] = dir[2];
682 if (fwrite(outbuf, sizeof(float), 6, psend) < 6)
683 syserror();
684 /* remember it */
685 queue[queuesiz][0] = x;
686 queue[queuesiz][1] = y;
687 queuesiz++;
688 }
689
690
691 clearqueue() /* get results from queue */
692 {
693 float inbuf[4];
694 register int i;
695
696 for (i = 0; i < queuesiz; i++) {
697 if (fread(inbuf, sizeof(float), 4, precv) < 4) {
698 fprintf(stderr, "%s: read error in clearqueue\n",
699 progname);
700 exit(1);
701 }
702 if (ourexp > 0 && ourexp != 1.0) {
703 inbuf[0] *= ourexp;
704 inbuf[1] *= ourexp;
705 inbuf[2] *= ourexp;
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 }