ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/px/pinterp.c
Revision: 1.11
Committed: Thu Jan 4 10:12:49 1990 UTC (34 years, 4 months ago) by greg
Content type: text/plain
Branch: MAIN
Changes since 1.10: +125 -15 lines
Log Message:
added -f and -n options, bug fixes in fillpicture()

File Contents

# User Rev Content
1 greg 1.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 greg 1.11 #define F_FORE 1 /* fill foreground */
21     #define F_BACK 2 /* fill background */
22    
23 greg 1.3 #define ABS(x) ((x)>0?(x):-(x))
24    
25 greg 1.1 VIEW ourview = STDVIEW(512); /* desired view */
26    
27 greg 1.8 double zeps = .02; /* allowed z epsilon */
28 greg 1.1
29     COLR *ourpict; /* output picture */
30     float *ourzbuf; /* corresponding z-buffer */
31    
32     char *progname;
33    
34     VIEW theirview = STDVIEW(512); /* input view */
35     int gotview; /* got input view? */
36    
37 greg 1.11 int fill = F_FORE|F_BACK; /* fill level */
38     COLR backcolr = BLKCOLR; /* background color */
39    
40 greg 1.5 double theirs2ours[4][4]; /* transformation matrix */
41 greg 1.11 int normdist = 1; /* normalized distance? */
42 greg 1.1
43 greg 1.5
44 greg 1.1 main(argc, argv) /* interpolate pictures */
45     int argc;
46     char *argv[];
47     {
48     #define check(olen,narg) if (argv[i][olen] || narg >= argc-i) goto badopt
49 greg 1.11 extern double atof();
50 greg 1.1 int gotvfile = 0;
51 greg 1.11 char *zfile = NULL;
52 greg 1.1 char *err;
53     int i;
54    
55     progname = argv[0];
56    
57     for (i = 1; i < argc && argv[i][0] == '-'; i++)
58     switch (argv[i][1]) {
59     case 't': /* threshold */
60     check(2,1);
61     zeps = atof(argv[++i]);
62     break;
63 greg 1.11 case 'n': /* dist. normalized? */
64 greg 1.10 check(2,0);
65 greg 1.11 normdist = !normdist;
66 greg 1.10 break;
67 greg 1.11 case 'f': /* fill type */
68     switch (argv[i][2]) {
69     case '0': /* none */
70     check(3,0);
71     fill = 0;
72     break;
73     case 'f': /* foreground */
74     check(3,0);
75     fill = F_FORE;
76     break;
77     case 'b': /* background */
78     check(3,0);
79     fill = F_BACK;
80     break;
81     case 'a': /* all */
82     check(3,0);
83     fill = F_FORE|F_BACK;
84     break;
85     case 'c': /* color */
86     check(3,3);
87     setcolr(backcolr, atof(argv[i+1]),
88     atof(argv[i+2]), atof(argv[i+3]));
89     i += 3;
90     break;
91     default:
92     goto badopt;
93     }
94     break;
95     case 'z': /* z file */
96     check(2,1);
97     zfile = argv[++i];
98     break;
99 greg 1.6 case 'x': /* x resolution */
100     check(2,1);
101     ourview.hresolu = atoi(argv[++i]);
102     break;
103     case 'y': /* y resolution */
104     check(2,1);
105     ourview.vresolu = atoi(argv[++i]);
106     break;
107 greg 1.1 case 'v': /* view */
108     switch (argv[i][2]) {
109     case 't': /* type */
110     check(4,0);
111     ourview.type = argv[i][3];
112     break;
113     case 'p': /* point */
114     check(3,3);
115     ourview.vp[0] = atof(argv[++i]);
116     ourview.vp[1] = atof(argv[++i]);
117     ourview.vp[2] = atof(argv[++i]);
118     break;
119     case 'd': /* direction */
120     check(3,3);
121     ourview.vdir[0] = atof(argv[++i]);
122     ourview.vdir[1] = atof(argv[++i]);
123     ourview.vdir[2] = atof(argv[++i]);
124     break;
125     case 'u': /* up */
126     check(3,3);
127     ourview.vup[0] = atof(argv[++i]);
128     ourview.vup[1] = atof(argv[++i]);
129     ourview.vup[2] = atof(argv[++i]);
130     break;
131     case 'h': /* horizontal */
132     check(3,1);
133     ourview.horiz = atof(argv[++i]);
134     break;
135     case 'v': /* vertical */
136     check(3,1);
137     ourview.vert = atof(argv[++i]);
138     break;
139     case 'f': /* file */
140     check(3,1);
141     gotvfile = viewfile(argv[++i], &ourview);
142     if (gotvfile < 0) {
143     perror(argv[i]);
144     exit(1);
145     } else if (gotvfile == 0) {
146     fprintf(stderr, "%s: bad view file\n",
147     argv[i]);
148     exit(1);
149     }
150     break;
151     default:
152     goto badopt;
153     }
154     break;
155     default:
156     badopt:
157 greg 1.10 fprintf(stderr, "%s: command line error at '%s'\n",
158 greg 1.1 progname, argv[i]);
159 greg 1.10 goto userr;
160 greg 1.1 }
161     /* check arguments */
162 greg 1.10 if (argc-i < 2 || (argc-i)%2)
163     goto userr;
164 greg 1.1 /* set view */
165     if (err = setview(&ourview)) {
166     fprintf(stderr, "%s: %s\n", progname, err);
167     exit(1);
168     }
169     /* allocate frame */
170     ourpict = (COLR *)calloc(ourview.hresolu*ourview.vresolu,sizeof(COLR));
171     ourzbuf = (float *)calloc(ourview.hresolu*ourview.vresolu,sizeof(float));
172     if (ourpict == NULL || ourzbuf == NULL) {
173     perror(progname);
174     exit(1);
175     }
176     /* get input */
177     for ( ; i < argc; i += 2)
178     addpicture(argv[i], argv[i+1]);
179     /* fill in spaces */
180 greg 1.11 if (fill&F_BACK)
181     fillpicture();
182     else
183     backpicture();
184 greg 1.1 /* add to header */
185     printargs(argc, argv, stdout);
186     if (gotvfile) {
187     printf(VIEWSTR);
188     fprintview(&ourview, stdout);
189     printf("\n");
190     }
191     printf("\n");
192 greg 1.11 /* write picture */
193 greg 1.1 writepicture();
194 greg 1.11 /* write z file */
195     if (zfile != NULL)
196     writedistance(zfile);
197 greg 1.1
198     exit(0);
199 greg 1.10 userr:
200     fprintf(stderr,
201 greg 1.11 "Usage: %s [view opts][-t zthresh][-z zout][-fT][-n] pfile zspec ..\n",
202 greg 1.10 progname);
203     exit(1);
204 greg 1.1 #undef check
205     }
206    
207    
208     headline(s) /* process header string */
209     char *s;
210     {
211     static char *altname[] = {"rview","rpict","pinterp",VIEWSTR,NULL};
212     register char **an;
213    
214     printf("\t%s", s);
215    
216     for (an = altname; *an != NULL; an++)
217     if (!strncmp(*an, s, strlen(*an))) {
218     if (sscanview(&theirview, s+strlen(*an)) == 0)
219     gotview++;
220     break;
221     }
222     }
223    
224    
225 greg 1.10 addpicture(pfile, zspec) /* add picture to output */
226     char *pfile, *zspec;
227 greg 1.1 {
228 greg 1.10 extern double atof();
229 greg 1.1 FILE *pfp, *zfp;
230 greg 1.8 char *err;
231 greg 1.1 COLR *scanin;
232 greg 1.9 float *zin, *zlast;
233     int *plast;
234 greg 1.1 int y;
235 greg 1.10 /* open picture file */
236 greg 1.1 if ((pfp = fopen(pfile, "r")) == NULL) {
237     perror(pfile);
238     exit(1);
239     }
240     /* get header and view */
241     printf("%s:\n", pfile);
242     gotview = 0;
243     getheader(pfp, headline);
244 greg 1.9 if (!gotview || fgetresolu(&theirview.hresolu, &theirview.vresolu, pfp)
245     != (YMAJOR|YDECR)) {
246 greg 1.1 fprintf(stderr, "%s: picture view error\n", pfile);
247     exit(1);
248     }
249     if (err = setview(&theirview)) {
250     fprintf(stderr, "%s: %s\n", pfile, err);
251     exit(1);
252     }
253 greg 1.5 /* compute transformation */
254     pixform(theirs2ours, &theirview, &ourview);
255 greg 1.1 /* allocate scanlines */
256 greg 1.9 scanin = (COLR *)malloc(theirview.hresolu*sizeof(COLR));
257     zin = (float *)malloc(theirview.hresolu*sizeof(float));
258 greg 1.10 plast = (int *)calloc(theirview.hresolu, sizeof(int));
259 greg 1.9 zlast = (float *)calloc(theirview.hresolu, sizeof(float));
260 greg 1.10 if (scanin == NULL || zin == NULL || plast == NULL || zlast == NULL) {
261 greg 1.1 perror(progname);
262     exit(1);
263     }
264 greg 1.10 /* get z specification or file */
265     if ((zfp = fopen(zspec, "r")) == NULL) {
266     double zvalue;
267     register int x;
268     if (!isfloat(zspec) || (zvalue = atof(zspec)) <= 0.0) {
269     perror(zspec);
270     exit(1);
271     }
272     for (x = 0; x < theirview.hresolu; x++)
273     zin[x] = zvalue;
274     }
275 greg 1.1 /* load image */
276 greg 1.9 for (y = theirview.vresolu-1; y >= 0; y--) {
277     if (freadcolrs(scanin, theirview.hresolu, pfp) < 0) {
278 greg 1.1 fprintf(stderr, "%s: read error\n", pfile);
279     exit(1);
280     }
281 greg 1.10 if (zfp != NULL
282     && fread(zin,sizeof(float),theirview.hresolu,zfp)
283 greg 1.9 < theirview.hresolu) {
284 greg 1.10 fprintf(stderr, "%s: read error\n", zspec);
285 greg 1.1 exit(1);
286     }
287 greg 1.9 addscanline(y, scanin, zin, plast, zlast);
288 greg 1.1 }
289     /* clean up */
290     free((char *)scanin);
291     free((char *)zin);
292 greg 1.9 free((char *)plast);
293     free((char *)zlast);
294 greg 1.1 fclose(pfp);
295 greg 1.10 if (zfp != NULL)
296     fclose(zfp);
297 greg 1.1 }
298    
299    
300 greg 1.5 pixform(xfmat, vw1, vw2) /* compute view1 to view2 matrix */
301     register double xfmat[4][4];
302     register VIEW *vw1, *vw2;
303     {
304     double m4t[4][4];
305    
306     setident4(xfmat);
307     xfmat[0][0] = vw1->vhinc[0];
308     xfmat[0][1] = vw1->vhinc[1];
309     xfmat[0][2] = vw1->vhinc[2];
310     xfmat[1][0] = vw1->vvinc[0];
311     xfmat[1][1] = vw1->vvinc[1];
312     xfmat[1][2] = vw1->vvinc[2];
313     xfmat[2][0] = vw1->vdir[0];
314     xfmat[2][1] = vw1->vdir[1];
315     xfmat[2][2] = vw1->vdir[2];
316     xfmat[3][0] = vw1->vp[0];
317     xfmat[3][1] = vw1->vp[1];
318     xfmat[3][2] = vw1->vp[2];
319     setident4(m4t);
320     m4t[0][0] = vw2->vhinc[0]/vw2->vhn2;
321     m4t[1][0] = vw2->vhinc[1]/vw2->vhn2;
322     m4t[2][0] = vw2->vhinc[2]/vw2->vhn2;
323     m4t[3][0] = -DOT(vw2->vp,vw2->vhinc)/vw2->vhn2;
324     m4t[0][1] = vw2->vvinc[0]/vw2->vvn2;
325     m4t[1][1] = vw2->vvinc[1]/vw2->vvn2;
326     m4t[2][1] = vw2->vvinc[2]/vw2->vvn2;
327     m4t[3][1] = -DOT(vw2->vp,vw2->vvinc)/vw2->vvn2;
328     m4t[0][2] = vw2->vdir[0];
329     m4t[1][2] = vw2->vdir[1];
330     m4t[2][2] = vw2->vdir[2];
331     m4t[3][2] = -DOT(vw2->vp,vw2->vdir);
332     multmat4(xfmat, xfmat, m4t);
333     }
334    
335    
336 greg 1.8 addscanline(y, pline, zline, lasty, lastyz) /* add scanline to output */
337 greg 1.1 int y;
338     COLR *pline;
339     float *zline;
340 greg 1.9 int *lasty; /* input/output */
341     float *lastyz; /* input/output */
342 greg 1.1 {
343 greg 1.11 extern double sqrt();
344 greg 1.5 double pos[3];
345 greg 1.8 int lastx = 0;
346     double lastxz = 0;
347     double zt;
348     int xpos, ypos;
349 greg 1.1 register int x;
350    
351 greg 1.8 for (x = theirview.hresolu-1; x >= 0; x--) {
352 greg 1.5 pos[0] = x - .5*(theirview.hresolu-1);
353     pos[1] = y - .5*(theirview.vresolu-1);
354     pos[2] = zline[x];
355     if (theirview.type == VT_PER) {
356 greg 1.11 if (normdist) /* adjust for eye-ray distance */
357 greg 1.10 pos[2] /= sqrt( 1.
358 greg 1.5 + pos[0]*pos[0]*theirview.vhn2
359     + pos[1]*pos[1]*theirview.vvn2 );
360     pos[0] *= pos[2];
361     pos[1] *= pos[2];
362     }
363     multp3(pos, pos, theirs2ours);
364 greg 1.8 if (pos[2] <= 0)
365 greg 1.1 continue;
366 greg 1.5 if (ourview.type == VT_PER) {
367     pos[0] /= pos[2];
368     pos[1] /= pos[2];
369     }
370     pos[0] += .5*ourview.hresolu;
371     pos[1] += .5*ourview.vresolu;
372 greg 1.8 if (pos[0] < 0 || (xpos = pos[0]) >= ourview.hresolu
373     || pos[1] < 0 || (ypos = pos[1]) >= ourview.vresolu)
374 greg 1.5 continue;
375 greg 1.8 /* add pixel to our image */
376     zt = 2.*zeps*zline[x];
377     addpixel(xpos, ypos,
378 greg 1.11 (fill&F_FORE && ABS(zline[x]-lastxz) <= zt)
379     ? lastx - xpos : 1,
380     (fill&F_FORE && ABS(zline[x]-lastyz[x]) <= zt)
381     ? lasty[x] - ypos : 1,
382 greg 1.8 pline[x], pos[2]);
383     lastx = xpos;
384     lasty[x] = ypos;
385     lastxz = lastyz[x] = zline[x];
386 greg 1.1 }
387     }
388    
389    
390 greg 1.8 addpixel(xstart, ystart, width, height, pix, z) /* fill in area for pixel */
391     int xstart, ystart;
392     int width, height;
393     COLR pix;
394     double z;
395     {
396     register int x, y;
397     /* make width and height positive */
398     if (width < 0) {
399     width = -width;
400     xstart = xstart-width+1;
401     } else if (width == 0)
402     width = 1;
403     if (height < 0) {
404     height = -height;
405     ystart = ystart-height+1;
406     } else if (height == 0)
407     height = 1;
408     /* fill pixel(s) within rectangle */
409     for (y = ystart; y < ystart+height; y++)
410     for (x = xstart; x < xstart+width; x++)
411     if (zscan(y)[x] <= 0
412     || zscan(y)[x]-z > zeps*zscan(y)[x]) {
413     zscan(y)[x] = z;
414     copycolr(pscan(y)[x], pix);
415     }
416     }
417    
418    
419 greg 1.1 fillpicture() /* fill in empty spaces */
420     {
421 greg 1.2 int *yback, xback;
422 greg 1.1 int y;
423 greg 1.2 COLR pfill;
424     register int x, i;
425     /* get back buffer */
426     yback = (int *)malloc(ourview.hresolu*sizeof(int));
427     if (yback == NULL) {
428     perror(progname);
429     return;
430     }
431     for (x = 0; x < ourview.hresolu; x++)
432 greg 1.4 yback[x] = -2;
433 greg 1.7 /*
434     * Xback and yback are the pixel locations of suitable
435     * background values in each direction.
436     * A value of -2 means unassigned, and -1 means
437     * that there is no suitable background in this direction.
438     */
439 greg 1.2 /* fill image */
440 greg 1.4 for (y = 0; y < ourview.vresolu; y++) {
441     xback = -2;
442 greg 1.1 for (x = 0; x < ourview.hresolu; x++)
443 greg 1.8 if (zscan(y)[x] <= 0) { /* empty pixel */
444 greg 1.7 /*
445     * First, find background from above or below.
446     * (farthest assigned pixel)
447     */
448 greg 1.4 if (yback[x] == -2) {
449     for (i = y+1; i < ourview.vresolu; i++)
450 greg 1.8 if (zscan(i)[x] > 0)
451 greg 1.4 break;
452     if (i < ourview.vresolu
453 greg 1.2 && (y <= 0 || zscan(y-1)[x] < zscan(i)[x]))
454 greg 1.4 yback[x] = i;
455     else
456     yback[x] = y-1;
457 greg 1.2 }
458 greg 1.7 /*
459     * Next, find background from left or right.
460     */
461 greg 1.4 if (xback == -2) {
462 greg 1.11 for (i = x+1; i < ourview.hresolu; i++)
463 greg 1.8 if (zscan(y)[i] > 0)
464 greg 1.4 break;
465     if (i < ourview.hresolu
466     && (x <= 0 || zscan(y)[x-1] < zscan(y)[i]))
467     xback = i;
468     else
469     xback = x-1;
470     }
471 greg 1.7 /*
472 greg 1.11 * Check to see if we have no background for
473     * this pixel. If not, use background color.
474     */
475     if (xback < 0 && yback[x] < 0) {
476     copycolr(pscan(y)[x], backcolr);
477     continue;
478     }
479     /*
480 greg 1.7 * Compare, and use the background that is
481     * farther, unless one of them is next to us.
482     */
483 greg 1.11 if ( yback[x] < 0
484     || (xback >= 0 && ABS(x-xback) <= 1)
485 greg 1.4 || ( ABS(y-yback[x]) > 1
486 greg 1.11 && zscan(yback[x])[x]
487     < zscan(y)[xback] ) )
488 greg 1.4 copycolr(pscan(y)[x],pscan(y)[xback]);
489     else
490     copycolr(pscan(y)[x],pscan(yback[x])[x]);
491     } else { /* full pixel */
492     yback[x] = -2;
493     xback = -2;
494     }
495     }
496 greg 1.2 free((char *)yback);
497 greg 1.1 }
498    
499    
500 greg 1.11 backpicture() /* paint in empty pixels */
501     {
502     register int x, y;
503    
504     for (y = 0; y < ourview.vresolu; y++)
505     for (x = 0; x < ourview.hresolu; x++)
506     if (zscan(y)[x] <= 0)
507     copycolr(pscan(y)[x], backcolr);
508     }
509    
510    
511 greg 1.1 writepicture() /* write out picture */
512     {
513     int y;
514    
515     fputresolu(YMAJOR|YDECR, ourview.hresolu, ourview.vresolu, stdout);
516     for (y = ourview.vresolu-1; y >= 0; y--)
517     if (fwritecolrs(pscan(y), ourview.hresolu, stdout) < 0) {
518     perror(progname);
519     exit(1);
520     }
521 greg 1.11 }
522    
523    
524     writedistance(fname) /* write out z file */
525     char *fname;
526     {
527     extern double sqrt();
528     int donorm = normdist && ourview.type == VT_PER;
529     FILE *fp;
530     int y;
531     float *zout;
532    
533     if ((fp = fopen(fname, "w")) == NULL) {
534     perror(fname);
535     exit(1);
536     }
537     if (donorm
538     && (zout = (float *)malloc(ourview.hresolu*sizeof(float))) == NULL) {
539     perror(progname);
540     exit(1);
541     }
542     for (y = ourview.vresolu-1; y >= 0; y--) {
543     if (donorm) {
544     double vx, yzn2;
545     register int x;
546     yzn2 = y - .5*(ourview.vresolu-1);
547     yzn2 = 1. + yzn2*yzn2*ourview.vvn2;
548     for (x = 0; x < ourview.hresolu; x++) {
549     vx = x - .5*(ourview.hresolu-1);
550     zout[x] = zscan(y)[x]
551     * sqrt(vx*vx*ourview.vhn2 + yzn2);
552     }
553     } else
554     zout = zscan(y);
555     if (fwrite(zout, sizeof(float), ourview.hresolu, fp)
556     < ourview.hresolu) {
557     perror(fname);
558     exit(1);
559     }
560     }
561     if (donorm)
562     free((char *)zout);
563     fclose(fp);
564 greg 1.10 }
565    
566    
567     isfloat(s) /* see if string is floating number */
568     register char *s;
569     {
570     for ( ; *s; s++)
571     if ((*s < '0' || *s > '9') && *s != '.' && *s != '-'
572     && *s != 'e' && *s != 'E' && *s != '+')
573     return(0);
574     return(1);
575 greg 1.1 }