--- ray/src/px/pinterp.c 1994/12/23 22:35:12 2.19 +++ ray/src/px/pinterp.c 1994/12/27 18:04:29 2.22 @@ -20,13 +20,17 @@ static char SCCSid[] = "$SunId$ LBL"; #include "resolu.h" +#define LOG2 0.69314718055994530942 + #define pscan(y) (ourpict+(y)*hresolu) #define sscan(y) (ourspict+(y)*hresolu) #define wscan(y) (ourweigh+(y)*hresolu) #define zscan(y) (ourzbuf+(y)*hresolu) #define averaging (ourweigh != NULL) +#define usematrix (hasmatrix & !averaging) +#define zisnorm (!usematrix | ourview.type != VT_PER) -#define MAXWT 100. /* maximum pixel weight (averaging) */ +#define MAXWT 1000. /* maximum pixel weight (averaging) */ #define F_FORE 1 /* fill foreground */ #define F_BACK 2 /* fill background */ @@ -52,8 +56,8 @@ double pixaspect = 1.0; /* pixel aspect ratio */ double zeps = .02; /* allowed z epsilon */ COLR *ourpict; /* output picture (COLR's) */ -COLOR *ourspict; /* output pixel sums (-a option) */ -float *ourweigh = NULL; /* output pixel weights (-a option) */ +COLOR *ourspict; /* output pixel sums (averaging) */ +float *ourweigh = NULL; /* output pixel weights (averaging) */ float *ourzbuf; /* corresponding z-buffer */ char *progname; @@ -65,8 +69,10 @@ int (*fillfunc)() = backfill; /* selected fill functio COLR backcolr = BLKCOLR; /* background color */ COLOR backcolor = BLKCOLOR; /* background color (float) */ double backz = 0.0; /* background z value */ -int normdist = 1; /* normalized distance? */ -double ourexp = -1; /* output picture exposure */ +int normdist = 1; /* i/o normalized distance? */ +double ourexp = -1; /* original picture exposure */ +int expadj = 0; /* exposure adjustment (f-stops) */ +double rexpadj = 1; /* real exposure adjustment */ VIEW theirview = STDVIEW; /* input view */ int gotview; /* got input view? */ @@ -95,6 +101,7 @@ char *argv[]; int gotvfile = 0; int doavg = -1; char *zfile = NULL; + char *expcomp = NULL; char *err; int i, rval; @@ -107,6 +114,10 @@ char *argv[]; continue; } switch (argv[i][1]) { + case 'e': /* exposure */ + check(2,"f"); + expcomp = argv[++i]; + break; case 't': /* threshold */ check(2,"f"); zeps = atof(argv[++i]); @@ -212,6 +223,23 @@ char *argv[]; goto userr; if (fillsamp == 1) fillo &= ~F_BACK; + if (doavg < 0) + doavg = (argc-i) > 2; + if (expcomp != NULL) + if (expcomp[0] == '+' | expcomp[0] == '-') { + expadj = atof(expcomp) + (expcomp[0]=='+' ? .5 : -.5); + if (doavg) + rexpadj = pow(2.0, atof(expcomp)); + else + rexpadj = pow(2.0, (double)expadj); + } else { + if (!isflt(expcomp)) + goto userr; + rexpadj = atof(expcomp); + expadj = log(rexpadj)/LOG2 + (rexpadj>1 ? .5 : -.5); + if (!doavg) + rexpadj = pow(2.0, (double)expadj); + } /* set view */ if ((err = setview(&ourview)) != NULL) { fprintf(stderr, "%s: %s\n", progname, err); @@ -219,8 +247,6 @@ char *argv[]; } normaspect(viewaspect(&ourview), &pixaspect, &hresolu, &vresolu); /* allocate frame */ - if (doavg < 0) - doavg = (argc-i) > 2; if (doavg) { ourspict = (COLOR *)bmalloc(hresolu*vresolu*sizeof(COLOR)); ourweigh = (float *)bmalloc(hresolu*vresolu*sizeof(float)); @@ -256,9 +282,13 @@ char *argv[]; fprintview(&ourview, stdout); putc('\n', stdout); } - if (pixaspect < .99 || pixaspect > 1.01) + if (pixaspect < .99 | pixaspect > 1.01) fputaspect(pixaspect, stdout); - if (ourexp > 0 && (ourexp < .995 || ourexp > 1.005)) + if (ourexp > 0) + ourexp *= rexpadj; + else + ourexp = rexpadj; + if (ourexp < .995 | ourexp > 1.005) fputexpos(ourexp, stdout); fputformat(COLRFMT, stdout); putc('\n', stdout); @@ -271,7 +301,7 @@ char *argv[]; exit(0); userr: fprintf(stderr, - "Usage: %s [view opts][-t eps][-z zout][-fT][-n] pfile zspec ..\n", + "Usage: %s [view opts][-t eps][-z zout][-e spec][-a|-q][-fT][-n] pfile zspec ..\n", progname); exit(1); #undef check @@ -490,7 +520,7 @@ double z; l1 = ABS(s1x); if (p1isy = (ABS(s1y) > l1)) l1 = ABS(s1y); - if (l1 < 1) + else if (l1 < 1) l1 = 1; } else { l1 = s1x = s1y = 1; @@ -548,23 +578,21 @@ double z; double movepixel(pos) /* reposition image point */ -FVECT pos; +register FVECT pos; { - double d0, d1; FVECT pt, tdir, odir; + double d; register int i; if (pos[2] <= 0) /* empty pixel */ return(0); - if (normdist && theirview.type == VT_PER) { /* adjust distance */ - d0 = pos[0] + theirview.hoff - .5; - d1 = pos[1] + theirview.voff - .5; - pos[2] /= sqrt(1. + d0*d0*theirview.hn2 + d1*d1*theirview.vn2); - } - if (!averaging && hasmatrix) { + if (usematrix) { pos[0] += theirview.hoff - .5; pos[1] += theirview.voff - .5; if (theirview.type == VT_PER) { + if (normdist) /* adjust distance */ + pos[2] /= sqrt(1. + pos[0]*pos[0]*theirview.hn2 + + pos[1]*pos[1]*theirview.vn2); pos[0] *= pos[2]; pos[1] *= pos[2]; } @@ -580,6 +608,9 @@ FVECT pos; } else { if (viewray(pt, tdir, &theirview, pos[0], pos[1]) < -FTINY) return(0); + if (!normdist & theirview.type == VT_PER) /* adjust */ + pos[2] *= sqrt(1. + pos[0]*pos[0]*theirview.hn2 + + pos[1]*pos[1]*theirview.vn2); pt[0] += tdir[0]*pos[2]; pt[1] += tdir[1]*pos[2]; pt[2] += tdir[2]*pos[2]; @@ -596,12 +627,10 @@ FVECT pos; else for (i = 0; i < 3; i++) odir[i] = (pt[i] - ourview.vp[i])/pos[2]; - d0 = DOT(odir,tdir); /* compute pixel weight */ - if (d0 <= FTINY) - return(0); /* relative angle >= 90 degrees */ - if (d0 >= 1.-1./MAXWT/MAXWT) + d = DOT(odir,tdir); /* compute pixel weight */ + if (d >= 1.-1./MAXWT/MAXWT) return(MAXWT); /* clip to maximum weight */ - return(1./sqrt(1.-d0)); + return(1./sqrt(1.-d)); } @@ -682,6 +711,7 @@ int zfd; } if (yl->max >= numscans(&tresolu)) yl->max = numscans(&tresolu) - 1; + y -= step; for (x = numscans(&tresolu) - 1; x > y; x--) /* fill bottom rows */ copystruct(xl+x, xl+y); return(yl->max >= yl->min); @@ -811,6 +841,7 @@ int (*fill)(); clipaft() /* perform aft clipping as indicated */ { register int x, y; + int adjtest = ourview.type == VT_PER & zisnorm; double tstdist; double yzn2, vx; @@ -818,14 +849,14 @@ clipaft() /* perform aft clipping as indicated */ return; tstdist = ourview.vaft - ourview.vfore; for (y = 0; y < vresolu; y++) { - if (ourview.type == VT_PER) { /* adjust distance */ + if (adjtest) { /* adjust test */ yzn2 = (y+.5)/vresolu + ourview.voff - .5; yzn2 = 1. + yzn2*yzn2*ourview.vn2; tstdist = (ourview.vaft - ourview.vfore)*sqrt(yzn2); } for (x = 0; x < hresolu; x++) if (zscan(y)[x] > tstdist) { - if (ourview.type == VT_PER) { + if (adjtest) { vx = (x+.5)/hresolu + ourview.hoff - .5; if (zscan(y)[x] <= (ourview.vaft - ourview.vfore) * @@ -842,7 +873,7 @@ clipaft() /* perform aft clipping as indicated */ } -writepicture() /* write out picture */ +writepicture() /* write out picture (alters buffer) */ { int y; register int x; @@ -852,48 +883,49 @@ writepicture() /* write out picture */ for (y = vresolu-1; y >= 0; y--) if (averaging) { for (x = 0; x < hresolu; x++) { /* average pixels */ - d = 1./wscan(y)[x]; + d = rexpadj/wscan(y)[x]; scalecolor(sscan(y)[x], d); } if (fwritescan(sscan(y), hresolu, stdout) < 0) syserror(progname); - } else if (fwritecolrs(pscan(y), hresolu, stdout) < 0) - syserror(progname); + } else { + if (expadj) + shiftcolrs(pscan(y), hresolu, expadj); + if (fwritecolrs(pscan(y), hresolu, stdout) < 0) + syserror(progname); + } } -writedistance(fname) /* write out z file */ +writedistance(fname) /* write out z file (alters buffer) */ char *fname; { - int donorm = normdist && ourview.type == VT_PER; + int donorm = normdist & !zisnorm ? 1 : + ourview.type == VT_PER & !normdist & zisnorm ? -1 : 0; int fd; int y; - float *zout; if ((fd = open(fname, O_WRONLY|O_CREAT|O_TRUNC, 0666)) == -1) syserror(fname); - if (donorm - && (zout = (float *)malloc(hresolu*sizeof(float))) == NULL) - syserror(progname); for (y = vresolu-1; y >= 0; y--) { if (donorm) { - double vx, yzn2; + double vx, yzn2, d; register int x; yzn2 = (y+.5)/vresolu + ourview.voff - .5; yzn2 = 1. + yzn2*yzn2*ourview.vn2; for (x = 0; x < hresolu; x++) { vx = (x+.5)/hresolu + ourview.hoff - .5; - zout[x] = zscan(y)[x] - * sqrt(vx*vx*ourview.hn2 + yzn2); + d = sqrt(vx*vx*ourview.hn2 + yzn2); + if (donorm > 0) + zscan(y)[x] *= d; + else + zscan(y)[x] /= d; } - } else - zout = zscan(y); - if (write(fd, (char *)zout, hresolu*sizeof(float)) + } + if (write(fd, (char *)zscan(y), hresolu*sizeof(float)) < hresolu*sizeof(float)) syserror(fname); } - if (donorm) - free((char *)zout); close(fd); } @@ -978,6 +1010,7 @@ clearqueue() /* process queue */ float fbuf[6*(PACKSIZ+1)]; register float *fbp; register int i; + double vx, vy; if (queuesiz == 0) return; @@ -1012,7 +1045,14 @@ clearqueue() /* process queue */ } else setcolr(pscan(queue[i][1])[queue[i][0]], fbp[0], fbp[1], fbp[2]); - zscan(queue[i][1])[queue[i][0]] = fbp[3]; + if (zisnorm) + zscan(queue[i][1])[queue[i][0]] = fbp[3]; + else { + vx = (queue[i][0]+.5)/hresolu + ourview.hoff - .5; + vy = (queue[i][1]+.5)/vresolu + ourview.voff - .5; + zscan(queue[i][1])[queue[i][0]] = fbp[3] / sqrt(1. + + vx*vx*ourview.hn2 + vy*vy*ourview.vn2); + } fbp += 4; } queuesiz = 0;