ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/px/pinterp.c
Revision: 1.8
Committed: Wed Jan 3 09:37:16 1990 UTC (34 years, 4 months ago) by greg
Content type: text/plain
Branch: MAIN
Changes since 1.7: +68 -24 lines
Log Message:
improved initial fill to use object coherence

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