ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/px/pinterp.c
Revision: 1.10
Committed: Wed Jan 3 15:33:44 1990 UTC (34 years, 4 months ago) by greg
Content type: text/plain
Branch: MAIN
Changes since 1.9: +49 -25 lines
Log Message:
added constant z specification and -r option

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