ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/util/ranimove1.c
Revision: 3.3
Committed: Thu Jun 5 19:29:35 2003 UTC (20 years, 10 months ago) by schorsch
Content type: text/plain
Branch: MAIN
Changes since 3.2: +3 -4 lines
Log Message:
Macros for setting binary file mode. Replacing MSDOS by _WIN32.

File Contents

# User Rev Content
1 greg 3.1 #ifndef lint
2 schorsch 3.3 static const char RCSid[] = "$Id: ranimove1.c,v 3.2 2003/02/25 02:47:24 greg Exp $";
3 greg 3.1 #endif
4     /*
5     * ranimove1.c
6     *
7     * Basic frame rendering routines for ranimate(1).
8     *
9     * Created by Gregory Ward on Wed Jan 08 2003.
10     */
11    
12 greg 3.2 #include "copyright.h"
13 greg 3.1
14 schorsch 3.3 #include "platform.h"
15 greg 3.1 #include "ranimove.h"
16     #include "otypes.h"
17     #include "random.h"
18    
19     double acctab[256]; /* accuracy value table */
20    
21     int hres, vres; /* frame resolution (fcur) */
22     double pixaspect; /* pixel aspect ratio */
23    
24     VIEW vw; /* view for this frame */
25     COLOR *cbuffer; /* color at each pixel */
26     float *zbuffer; /* depth at each pixel */
27     OBJECT *obuffer; /* object id at each pixel */
28     short *xmbuffer; /* x motion at each pixel */
29     short *ymbuffer; /* y motion at each pixel */
30     BYTE *abuffer; /* accuracy at each pixel */
31     BYTE *sbuffer; /* sample count per pixel */
32    
33     VIEW vwprev; /* last frame's view */
34     COLOR *cprev; /* last frame colors */
35     float *zprev; /* last frame depth */
36     OBJECT *oprev; /* last frame objects */
37     BYTE *aprev; /* last frame accuracy */
38    
39     float *cerrmap; /* conspicuous error map */
40     COLOR *val2map; /* value-squared map for variance */
41    
42     double frm_stop; /* when to stop rendering this frame */
43    
44     double hlsmax; /* maximum high-level saliency this frame */
45    
46    
47     void
48     write_map(mp, fn) /* write out float map (debugging) */
49     float *mp;
50     char *fn;
51     {
52     FILE *fp = fopen(fn, "w");
53     COLOR scanbuf[2048];
54     int x, y;
55    
56     if (fp == NULL)
57     return;
58     newheader("RADIANCE", fp);
59     fputformat(COLRFMT, fp);
60     fputc('\n', fp); /* end header */
61     fprtresolu(hres, vres, fp);
62     for (y = vres; y--; ) { /* write scanlines */
63     float *bp = mp + (y+1)*hres - 1;
64     for (x = hres; x--; bp--)
65     setcolor(scanbuf[x], *bp, *bp, *bp);
66     if (fwritescan(scanbuf, hres, fp) < 0)
67     break;
68     }
69     fclose(fp);
70     }
71    
72    
73     static void
74     next_frame() /* prepare next frame buffer */
75     {
76     VIEW *fv;
77     char *err;
78     /* get previous view */
79     if (vw.type != 0)
80     copystruct(&vwprev, &vw);
81     else if (fcur > 1 && (fv = getview(fcur-1)) != NULL) {
82     copystruct(&vwprev, fv);
83     if (setview(&vwprev) != NULL)
84     vwprev.type = 0;
85     }
86     /* get current view */
87     if ((fv = getview(fcur)) == NULL) {
88     sprintf(errmsg, "cannot get view for frame %d", fcur);
89     error(USER, errmsg);
90     }
91     copystruct(&vw, fv);
92     if ((err = setview(&vw)) != NULL) {
93     sprintf(errmsg, "view error at frame %d: %s", fcur, err);
94     error(USER, errmsg);
95     }
96     if (cbuffer == NULL) {
97     /* compute resolution and allocate */
98     switch (sscanf(vval(RESOLUTION), "%d %d %lf",
99     &hres, &vres, &pixaspect)) {
100     case 1:
101     vres = hres;
102     /* fall through */
103     case 2:
104     pixaspect = 1.;
105     /* fall through */
106     case 3:
107     if ((hres > 0 & vres > 0))
108     break;
109     /* fall through */
110     default:
111     sprintf(errmsg, "bad %s value", vnam(RESOLUTION));
112     error(USER, errmsg);
113     }
114     normaspect(viewaspect(&vw), &pixaspect, &hres, &vres);
115     cbuffer = (COLOR *)malloc(sizeof(COLOR)*hres*vres);
116     zbuffer = (float *)malloc(sizeof(float)*hres*vres);
117     obuffer = (OBJECT *)malloc(sizeof(OBJECT)*hres*vres);
118     xmbuffer = (short *)malloc(sizeof(short)*hres*vres);
119     ymbuffer = (short *)malloc(sizeof(short)*hres*vres);
120     abuffer = (BYTE *)calloc(hres*vres, sizeof(BYTE));
121     sbuffer = (BYTE *)calloc(hres*vres, sizeof(BYTE));
122     cprev = (COLOR *)malloc(sizeof(COLOR)*hres*vres);
123     zprev = (float *)malloc(sizeof(float)*hres*vres);
124     oprev = (OBJECT *)malloc(sizeof(OBJECT)*hres*vres);
125     aprev = (BYTE *)malloc(sizeof(BYTE)*hres*vres);
126     if ((cbuffer==NULL | zbuffer==NULL | obuffer==NULL |
127     xmbuffer==NULL | ymbuffer==NULL |
128     abuffer==NULL | sbuffer==NULL |
129     cprev==NULL | zprev == NULL |
130     oprev==NULL | aprev==NULL))
131     error(SYSTEM, "out of memory in init_frame");
132     frm_stop = getTime() + rtperfrm;
133     } else {
134     COLOR *cp; /* else just swap buffers */
135     float *fp;
136     OBJECT *op;
137     BYTE *bp;
138     cp = cprev; cprev = cbuffer; cbuffer = cp;
139     fp = zprev; zprev = zbuffer; zbuffer = fp;
140     op = oprev; oprev = obuffer; obuffer = op;
141     bp = aprev; aprev = abuffer; abuffer = bp;
142     bzero(abuffer, sizeof(BYTE)*hres*vres);
143     bzero(sbuffer, sizeof(BYTE)*hres*vres);
144     frm_stop += rtperfrm;
145     }
146     cerrmap = NULL;
147     val2map = NULL;
148     }
149    
150    
151     #define SAMPDIST 3 /* Maximum distance to neighbor sample */
152     #define SAMPDIST2 (SAMPDIST*SAMPDIST)
153    
154    
155     static int
156     sample_here(x, y) /* 4x4 quincunx sample at this pixel? */
157     register int x, y;
158     {
159     if (y & 0x1) /* every other row has samples */
160     return(0);
161     if (y & 0x3) /* every fourth row is offset */
162     x += 2;
163     return((x & 0x3) == 0); /* every fourth column is sampled */
164     }
165    
166    
167     void
168     sample_pos(hv, x, y, sn) /* compute jittered sample position */
169     double hv[2];
170     int x, y;
171     int sn;
172     {
173     int hl[2];
174    
175     hl[0] = x; hl[1] = y;
176     multisamp(hv, 2, urand(ilhash(hl,2) + sn));
177     hv[0] = ((double)x + hv[0]) / (double)hres;
178     hv[1] = ((double)y + hv[1]) / (double)vres;
179     }
180    
181    
182     double
183     sample_wt(xo, yo) /* compute interpolant sample weight */
184     int xo, yo;
185     {
186     static double etab[400];
187     int rad2 = xo*xo + yo*yo;
188     int i;
189    
190     if (etab[0] <= FTINY) /* initialize exponent table */
191     for (i = 400; i--; )
192     etab[i] = exp(-0.1*i);
193    
194     /* look up Gaussian */
195     i = (int)((10.*3./(double)SAMPDIST2)*rad2 + .5);
196     if (i >= 400)
197     return(0.0);
198     return(etab[i]);
199     }
200    
201    
202     static int
203     offset_cmp(p1, p2) /* compare offset distances */
204     const void *p1, *p2;
205     {
206     return(*(const int *)p1 - *(const int *)p2);
207     }
208    
209    
210     int
211     getclosest(iarr, nc, x, y) /* get nc closest neighbors on same object */
212     int *iarr;
213     int nc;
214     int x, y;
215     {
216     #define NSCHECK ((2*SAMPDIST+1)*(2*SAMPDIST+1))
217     static int hro, vro;
218     static int ioffs[NSCHECK];
219     OBJECT myobj;
220     int i0, nf;
221     register int i, j;
222     /* get our object number */
223     myobj = obuffer[fndx(x, y)];
224     /* special case for borders */
225     if ((x < SAMPDIST | x >= hres-SAMPDIST |
226     y < SAMPDIST | y >= vres-SAMPDIST)) {
227     int tndx[NSCHECK][2];
228     nf = 0;
229     for (j = y - SAMPDIST; j <= y + SAMPDIST; j++) {
230     if (j >= vres) break;
231     if (j < 0) j = 0;
232     for (i = x - SAMPDIST; i <= x + SAMPDIST; i++) {
233     if (i >= hres) break;
234     if (i < 0) i = 0;
235     i0 = fndx(i, j);
236     if (!sbuffer[i0])
237     continue;
238     if ((myobj != OVOID & obuffer[i0] != myobj))
239     continue;
240     tndx[nf][0] = (i-x)*(i-x) + (j-y)*(j-y);
241     tndx[nf][1] = i0;
242     nf++;
243     }
244     }
245     qsort((void *)tndx, nf, 2*sizeof(int), offset_cmp);
246     if (nf > nc)
247     nf = nc;
248     for (i = nf; i--; )
249     iarr[i] = tndx[i][1];
250     return(nf);
251     }
252     /* initialize offset array */
253     if ((hres != hro | vres != vro)) {
254     int toffs[NSCHECK][2];
255     i0 = fndx(SAMPDIST, SAMPDIST);
256     nf = 0;
257     for (i = 0; i <= 2*SAMPDIST; i++)
258     for (j = 0; j <= 2*SAMPDIST; j++) {
259     toffs[nf][0] = (i-SAMPDIST)*(i-SAMPDIST) +
260     (j-SAMPDIST)*(j-SAMPDIST);
261     toffs[nf][1] = fndx(i, j) - i0;
262     nf++;
263     }
264     qsort((void *)toffs, nf, 2*sizeof(int), offset_cmp);
265     for (i = NSCHECK; i--; )
266     ioffs[i] = toffs[i][1];
267     hro = hres;
268     vro = vres;
269     }
270     /* find up to nc neighbors */
271     i0 = fndx(x, y);
272     for (j = 0, nf = 0; (j < NSCHECK & nf < nc); j++) {
273     i = i0 + ioffs[j];
274     if (sbuffer[i] && (myobj == OVOID | obuffer[i] == myobj))
275     iarr[nf++] = i;
276     }
277     /* return number found */
278     return(nf);
279     #undef NSCHECK
280     }
281    
282    
283     static void
284     setmotion(n, wpos) /* compute motion vector for this pixel */
285     register int n;
286     FVECT wpos;
287     {
288     FVECT ovp;
289     MAT4 xfm;
290     double d;
291     int moi;
292     int xp, yp;
293     /* ID object and update maximum HLS */
294     moi = getmove(obuffer[n]);
295     if (moi >= 0 && obj_move[moi].cprio > hlsmax)
296     hlsmax = obj_move[moi].cprio;
297     if (vwprev.type == 0) /* return leaves MO_UNK */
298     return;
299     if (moi >= 0) { /* move object point back */
300     multp3(ovp, wpos, obj_move[moi].bxfm);
301     wpos = ovp;
302     }
303     viewloc(ovp, &vwprev, wpos);
304     if (ovp[2] <= FTINY)
305     return;
306     xp = (int)(ovp[0]*hres);
307     yp = (int)(ovp[1]*vres);
308     xmbuffer[n] = xp - (n % hres);
309     ymbuffer[n] = yp - (n / hres);
310     if ((xp < 0 | xp >= hres))
311     return;
312     if ((yp < 0 | yp >= vres))
313     return;
314     n = fndx(xp, yp);
315     if ((zprev[n] < 0.97*ovp[2] | zprev[n] > 1.03*ovp[2]))
316     oprev[n] = OVOID; /* assume it's a bad match */
317     }
318    
319    
320     static void
321     init_frame_sample() /* sample our initial frame */
322     {
323     RAY ir;
324     int x, y;
325     register int n;
326    
327     if (!silent) {
328     printf("\tComputing initial samples...");
329     fflush(stdout);
330     }
331     hlsmax = CSF_SMN;
332     for (y = vres; y--; )
333     for (x = hres; x--; ) {
334     double hv[2];
335     n = fndx(x, y);
336     xmbuffer[n] = MO_UNK;
337     ymbuffer[n] = MO_UNK;
338     sample_pos(hv, x, y, 0);
339     ir.rmax = viewray(ir.rorg, ir.rdir, &vw, hv[0], hv[1]);
340     if (ir.rmax < -FTINY) {
341     setcolor(cbuffer[n], 0., 0., 0.);
342     zbuffer[n] = FHUGE;
343     obuffer[n] = OVOID;
344     abuffer[n] = ADISTANT;
345     continue;
346     }
347     if (!sample_here(x, y)) { /* just cast */
348     rayorigin(&ir, NULL, PRIMARY, 1.0);
349     if (!localhit(&ir, &thescene)) {
350     if (ir.ro != &Aftplane)
351     sourcehit(&ir);
352     copycolor(cbuffer[n], ir.rcol);
353     zbuffer[n] = ir.rot;
354     obuffer[n] = ir.robj;
355     abuffer[n] = ADISTANT;
356     sbuffer[n] = 1;
357     } else {
358     zbuffer[n] = ir.rot;
359     obuffer[n] = ir.robj;
360     setmotion(n, ir.rop);
361     }
362     continue;
363     }
364     if (nprocs > 1) { /* get sample */
365     int rval;
366     rayorigin(&ir, NULL, PRIMARY, 1.0);
367     ir.rno = n;
368     rval = ray_pqueue(&ir);
369     if (!rval)
370     continue;
371     if (rval < 0)
372     quit(1);
373     n = ir.rno;
374     } else
375     ray_trace(&ir);
376     copycolor(cbuffer[n], ir.rcol);
377     zbuffer[n] = ir.rot;
378     obuffer[n] = ir.robj;
379     sbuffer[n] = 1;
380     if (ir.rot >= FHUGE)
381     abuffer[n] = ADISTANT;
382     else {
383     abuffer[n] = ALOWQ;
384     setmotion(n, ir.rop);
385     }
386     }
387     if (nprocs > 1) /* get stragglers */
388     while (ray_presult(&ir, 0)) {
389     n = ir.rno;
390     copycolor(cbuffer[n], ir.rcol);
391     zbuffer[n] = ir.rot;
392     obuffer[n] = ir.robj;
393     sbuffer[n] = 1;
394     if (ir.rot >= FHUGE)
395     abuffer[n] = ADISTANT;
396     else {
397     abuffer[n] = ALOWQ;
398     setmotion(n, ir.rop);
399     }
400     }
401     /* ambiguate object boundaries */
402     for (y = vres-1; y--; )
403     for (x = hres-1; x--; ) {
404     OBJECT obj;
405     n = fndx(x, y);
406     if ((obj = obuffer[n]) == OVOID)
407     continue;
408     if ((obuffer[n+1] != OVOID & obuffer[n+1] != obj)) {
409     obuffer[n] = OVOID;
410     obuffer[n+1] = OVOID;
411     }
412     if ((obuffer[n+hres] != OVOID & obuffer[n+hres] != obj)) {
413     obuffer[n] = OVOID;
414     obuffer[n+hres] = OVOID;
415     }
416     }
417    
418     if (!silent)
419     printf("done\n");
420     }
421    
422    
423     int
424     getambcolor(clr, obj) /* get ambient color for object if we can */
425     COLOR clr;
426     int obj;
427     {
428     register OBJREC *op;
429    
430     if (obj == OVOID)
431     return(0);
432     op = objptr(obj);
433     if ((op->otype == OBJ_INSTANCE & op->omod == OVOID))
434     return(0);
435     /* search for material */
436     do {
437     if (op->omod == OVOID || ofun[op->otype].flags & T_X)
438     return(0);
439     op = objptr(op->omod);
440     } while (!ismaterial(op->otype));
441     /*
442     * Since this routine is called to compute the difference
443     * from rendering with and without interreflections,
444     * we don't want to return colors for materials that are
445     * explicitly excluded from the HQ ambient calculation.
446     */
447     if (hirendparams.ambincl >= 0) {
448     int i;
449     char *lv;
450     for (i = 0; (lv = rpambmod(&hirendparams,i)) != NULL; i++)
451     if (lv[0] == op->oname[0] &&
452     !strcmp(lv+1, op->oname+1))
453     break;
454     if ((lv != NULL) != hirendparams.ambincl)
455     return(0);
456     }
457     switch (op->otype) {
458     case MAT_PLASTIC:
459     case MAT_METAL:
460     case MAT_PLASTIC2:
461     case MAT_METAL2:
462     case MAT_PFUNC:
463     case MAT_MFUNC:
464     case MAT_PDATA:
465     case MAT_MDATA:
466     case MAT_TRANS:
467     case MAT_TRANS2:
468     case MAT_TFUNC:
469     case MAT_TDATA:
470     if (op->oargs.nfargs < 3)
471     return(0);
472     setcolor(clr, op->oargs.farg[0], op->oargs.farg[1],
473     op->oargs.farg[2]);
474     return(1);
475     case MAT_BRTDF:
476     if (op->oargs.nfargs < 6)
477     return(0);
478     setcolor(clr, op->oargs.farg[0]+op->oargs.farg[3],
479     op->oargs.farg[1]+op->oargs.farg[4],
480     op->oargs.farg[2]+op->oargs.farg[5]);
481     scalecolor(clr, 0.5);
482     return(1);
483     case MAT_LIGHT:
484     case MAT_GLOW:
485     case MAT_ILLUM:
486     setcolor(clr, 0., 0., 0.);
487     return(1);
488     }
489     return(0);
490     }
491    
492    
493     double
494     estimaterr(cs, cs2, ns, ns0) /* estimate relative error from samples */
495     COLOR cs, cs2;
496     int ns;
497     {
498     double d, d2, brt;
499    
500     if (ns <= 1 || (brt = bright(cs)/ns) < 1e-14)
501     return(1.0);
502     /* use largest of RGB std. dev. */
503     d2 = colval(cs2,RED) - colval(cs,RED)*colval(cs,RED)/ns;
504     d = colval(cs2,GRN) - colval(cs,GRN)*colval(cs,GRN)/ns;
505     if (d > d2) d2 = d;
506     d = colval(cs2,BLU) - colval(cs,BLU)*colval(cs,BLU)/ns;
507     if (d > d2) d2 = d;
508     /* use s.d. if <= 1 central sample */
509     if (ns0 <= 1)
510     return(sqrt(d2/(ns-1))/brt);
511     /* use s.d./sqrt(ns0) otherwise */
512     return(sqrt(d2/((ns-1)*ns0))/brt);
513     }
514    
515    
516     double
517     comperr(neigh, nc, ns0) /* estimate relative error in neighborhood */
518     int *neigh;
519     int nc;
520     int ns0;
521     {
522     COLOR csum, csum2;
523     COLOR ctmp;
524     int i;
525     int ns;
526     register int n;
527     /* add together samples */
528     setcolor(csum, 0., 0., 0.);
529     setcolor(csum2, 0., 0., 0.);
530     for (i = 0, ns = 0; (i < nc & ns < NSAMPOK); i++) {
531     n = neigh[i];
532     addcolor(csum, cbuffer[n]);
533     if (val2map != NULL) {
534     addcolor(csum2, val2map[n]);
535     ns += sbuffer[n];
536     continue;
537     }
538     if (sbuffer[n] != 1)
539     error(CONSISTENCY, "bad count in comperr");
540     setcolor(ctmp,
541     colval(cbuffer[n],RED)*colval(cbuffer[n],RED),
542     colval(cbuffer[n],GRN)*colval(cbuffer[n],GRN),
543     colval(cbuffer[n],BLU)*colval(cbuffer[n],BLU));
544     addcolor(csum2, ctmp);
545     ns++;
546     }
547     return(estimaterr(csum, csum2, ns, ns0));
548     }
549    
550    
551     void
552     comp_frame_error() /* initialize frame error values */
553     {
554     BYTE *edone = NULL;
555     COLOR objamb;
556     double eest;
557     int neigh[NSAMPOK];
558     int nc;
559     int x, y, i, j;
560     register int n;
561    
562     if (!silent) {
563     printf("\tComputing error map\n");
564     fflush(stdout);
565     }
566     if (acctab[0] <= FTINY) /* initialize accuracy table */
567     for (i = 256; i--; )
568     acctab[i] = errorf(i);
569     /* estimate sample error */
570     if (!curparams->ambounce && hirendparams.ambounce) {
571     /*
572     * Our error estimate for the initial value is based
573     * on the assumption that most of it comes from the
574     * lack of an interreflection calculation. The relative
575     * error should be less than the ambient value divided
576     * by the returned ray value -- we take half of this.
577     */
578     edone = (BYTE *)calloc(hres*vres, sizeof(BYTE));
579     for (y = vres; y--; )
580     for (x = hres; x--; ) {
581     n = fndx(x, y);
582     if ((abuffer[n] != ALOWQ | obuffer[n] == OVOID))
583     continue;
584     if (!getambcolor(objamb, obuffer[n]))
585     continue;
586     multcolor(objamb, ambval);
587     if ((eest = bright(cbuffer[n])) <= FTINY)
588     continue;
589     eest = bright(objamb) / eest;
590     if (eest > 1.) /* should we report this? */
591     continue;
592     eest *= 0.50; /* use 50% ambient error */
593     i = errori(eest);
594     if (i < AMIN) i = AMIN;
595     else if (i >= ADISTANT/2) i = ADISTANT/2-1;
596     abuffer[n] = i;
597     edone[n] = 1;
598     }
599     }
600     /* final statistical estimate */
601     for (y = vres; y--; )
602     for (x = hres; x--; ) {
603     n = fndx(x, y);
604     if (abuffer[n] == ADISTANT)
605     continue; /* don't update these */
606     if (edone != NULL && edone[n])
607     continue; /* already done this */
608     if (sbuffer[n] >= 255) {
609     abuffer[n] = ADISTANT;
610     continue; /* can't take any more */
611     }
612     nc = getclosest(neigh, NSAMPOK, x, y);
613     if (nc <= 0) {
614     abuffer[n] = ANOVAL;
615     continue; /* no clue what to do for him */
616     }
617     i = errori(comperr(neigh, nc, sbuffer[n]));
618     if (i < AMIN) i = AMIN;
619     else if (i >= ADISTANT) i = ADISTANT-1;
620     abuffer[n] = i;
621     /* can't be better than closest */
622     if (i < abuffer[neigh[0]] && abuffer[neigh[0]] >= AMIN)
623     abuffer[n] = abuffer[neigh[0]];
624     }
625     if (edone != NULL)
626     free((void *)edone);
627     }
628    
629    
630     void
631     init_frame() /* render base (low quality) frame */
632     {
633     int restart;
634    
635     /* allocate/swap buffers */
636     next_frame();
637     /* check rendering status */
638     restart = (!nobjects || vdef(MOVE));
639     if (!restart && curparams != &lorendparams && nprocs > 1)
640     restart = -1;
641     if (restart > 0)
642     if (nprocs > 1)
643     ray_pdone(1);
644     else
645     ray_done(1);
646     /* post low quality parameters */
647     if (curparams != &lorendparams)
648     ray_restore(curparams = &lorendparams);
649     if (restart > 0) { /* load new octree */
650     char *oct = getoctspec(fcur);
651     if (oct == NULL) {
652     sprintf(errmsg, "cannot get scene for frame %d", fcur);
653     error(USER, errmsg);
654     }
655     if (!silent) {
656     printf("\tLoading octree...");
657     fflush(stdout);
658     }
659     if (nprocs > 1)
660     ray_pinit(oct, nprocs);
661     else
662     ray_init(oct);
663     } else if (restart < 0) { /* update children */
664     if (!silent) {
665     printf("\tRestarting %d processes...", nprocs);
666     fflush(stdout);
667     }
668     ray_pclose(0);
669     ray_popen(nprocs);
670     }
671     if (restart && !silent)
672     printf("done\n");
673     /* sample frame buffer */
674     init_frame_sample();
675     /* initialize frame error */
676     comp_frame_error();
677     return;
678     {
679     float *ebuf = (float *)malloc(sizeof(float)*hres*vres);
680     char fnm[256];
681     register int n;
682     for (n = hres*vres; n--; )
683     ebuf[n] = acctab[abuffer[n]];
684     sprintf(fnm, vval(BASENAME), fcur);
685     strcat(fnm, "_inerr.pic");
686     write_map(ebuf, fnm);
687     free((void *)ebuf);
688     }
689     }
690    
691    
692     void
693     filter_frame() /* interpolation, motion-blur, and exposure */
694     {
695     double expval = expspec_val(getexp(fcur));
696     int x, y;
697     int neigh[NPINTERP];
698     int nc;
699     COLOR cval;
700     double w, wsum;
701     register int n;
702    
703     #if 0
704     /* XXX TEMPORARY!! */
705     conspicuity();
706     write_map(cerrmap, "outcmap.pic");
707     {
708     float *ebuf = (float *)malloc(sizeof(float)*hres*vres);
709     for (n = hres*vres; n--; )
710     ebuf[n] = acctab[abuffer[n]];
711     write_map(ebuf, "outerr.pic");
712     free((void *)ebuf);
713     }
714     #endif
715    
716     if (!silent) {
717     printf("\tFiltering frame\n");
718     fflush(stdout);
719     }
720     /* normalize samples */
721     for (y = vres; y--; )
722     for (x = hres; x--; ) {
723     n = fndx(x, y);
724     if (sbuffer[n] <= 1)
725     continue;
726     w = 1.0/(double)sbuffer[n];
727     scalecolor(cbuffer[n], w);
728     }
729     /* interpolate samples */
730     for (y = vres; y--; )
731     for (x = hres; x--; ) {
732     n = fndx(x, y);
733     if (sbuffer[n])
734     continue;
735     nc = getclosest(neigh, NPINTERP, x, y);
736     setcolor(cbuffer[n], 0., 0., 0.);
737     wsum = 0.;
738     while (nc-- > 0) {
739     copycolor(cval, cbuffer[neigh[nc]]);
740     w = sample_wt((neigh[nc]%hres) - x,
741     (neigh[nc]/hres) - y);
742     scalecolor(cval, w);
743     addcolor(cbuffer[n], cval);
744     wsum += w;
745     }
746     if (wsum > FTINY) {
747     w = 1.0/wsum;
748     scalecolor(cbuffer[n], w);
749     }
750     }
751     /* motion blur if requested */
752     if (mblur > .02) {
753     int len;
754     int xs, ys, xl, yl;
755     int rise, run;
756     long rise2, run2;
757     int n2;
758     int cnt;
759     /* sum in motion streaks */
760     bzero(outbuffer, sizeof(COLOR)*hres*vres);
761     bzero(wbuffer, sizeof(float)*hres*vres);
762     for (y = vres; y--; )
763     for (x = hres; x--; ) {
764     n = fndx(x, y);
765     if (xmbuffer[n] == MO_UNK) {
766     run = rise = 0;
767     } else {
768     run = (int)(mblur*xmbuffer[n]);
769     rise = (int)(mblur*ymbuffer[n]);
770     }
771     if (!(run | rise)) {
772     addcolor(outbuffer[n], cbuffer[n]);
773     wbuffer[n] += 1.;
774     continue;
775     }
776     xl = x - run/4;
777     yl = y - rise/4;
778     if (run < 0) { xs = -1; run = -run; }
779     else xs = 1;
780     if (rise < 0) { ys = -1; rise = -rise; }
781     else ys = 1;
782     rise2 = run2 = 0L;
783     if (rise > run) {
784     cnt = rise + 1;
785     w = 1./cnt;
786     copycolor(cval, cbuffer[n]);
787     scalecolor(cval, w);
788     while (cnt)
789     if (rise2 >= run2) {
790     if ((xl >= 0 & xl < hres &
791     yl >= 0 & yl < vres)) {
792     n2 = fndx(xl, yl);
793     addcolor(outbuffer[n2],
794     cval);
795     wbuffer[n2] += w;
796     }
797     yl += ys;
798     run2 += run;
799     cnt--;
800     } else {
801     xl += xs;
802     rise2 += rise;
803     }
804     } else {
805     cnt = run + 1;
806     w = 1./cnt;
807     copycolor(cval, cbuffer[n]);
808     scalecolor(cval, w);
809     while (cnt)
810     if (run2 >= rise2) {
811     if ((xl >= 0 & xl < hres &
812     yl >= 0 & yl < vres)) {
813     n2 = fndx(xl, yl);
814     addcolor(outbuffer[n2],
815     cval);
816     wbuffer[n2] += w;
817     }
818     xl += xs;
819     rise2 += rise;
820     cnt--;
821     } else {
822     yl += ys;
823     run2 += run;
824     }
825     }
826     }
827     /* compute final results */
828     for (y = vres; y--; )
829     for (x = hres; x--; ) {
830     n = fndx(x, y);
831     if (wbuffer[n] <= FTINY)
832     continue;
833     w = 1./wbuffer[n];
834     scalecolor(outbuffer[n], w);
835     }
836     } else
837     for (n = hres*vres; n--; )
838     copycolor(outbuffer[n], cbuffer[n]);
839     /*
840     for (n = hres*vres; n--; )
841     if (!sbuffer[n])
842     setcolor(outbuffer[n], 0., 0., 0.);
843     */
844     /* adjust exposure */
845     if ((expval < 0.99 | expval > 1.01))
846     for (n = hres*vres; n--; )
847     scalecolor(outbuffer[n], expval);
848     return;
849     {
850     float *sbuf = (float *)malloc(sizeof(float)*hres*vres);
851     char fnm[256];
852     sprintf(fnm, vval(BASENAME), fcur);
853     strcat(fnm, "_outsamp.pic");
854     for (n = hres*vres; n--; )
855     sbuf[n] = (float)sbuffer[n];
856     write_map(sbuf, fnm);
857     free((void *)sbuf);
858     }
859     }
860    
861    
862     void
863     send_frame() /* send frame to destination */
864     {
865     char pfname[1024];
866     double d;
867     FILE *fp;
868     int y;
869     /* open output picture */
870     sprintf(pfname, vval(BASENAME), fcur);
871     strcat(pfname, ".pic");
872     fp = fopen(pfname, "w");
873     if (fp == NULL) {
874     sprintf(errmsg, "cannot open output frame \"%s\"", pfname);
875     error(SYSTEM, errmsg);
876     }
877 schorsch 3.3 SET_FILE_BINARY(fp);
878 greg 3.1 if (!silent) {
879     printf("\tWriting to \"%s\"\n", pfname);
880     fflush(stdout);
881     }
882     /* write header */
883     newheader("RADIANCE", fp);
884     printargs(gargc, gargv, fp);
885     fprintf(fp, "SOFTWARE= %s\n", VersionID);
886     fprintf(fp, "FRAME=%d\n", fcur);
887     fputnow(fp);
888     fputs(VIEWSTR, fp); fprintview(&vw, fp); fputc('\n', fp);
889     d = expspec_val(getexp(fcur));
890     if ((d < 0.99 | d > 1.01))
891     fputexpos(d, fp);
892     d = viewaspect(&vw) * hres / vres;
893     if ((d < 0.99 | d > 1.01))
894     fputaspect(d, fp);
895     fputformat(COLRFMT, fp);
896     fputc('\n', fp); /* end header */
897     fprtresolu(hres, vres, fp);
898     if (fflush(fp) == EOF)
899     goto writerr;
900     #if (PIXSTANDARD != (YMAJOR|YDECR))
901     error(CONSISTENCY, "bad code in send_frame");
902     #endif
903     for (y = vres; y--; ) /* write scanlines */
904     if (fwritescan(outbuffer+y*hres, hres, fp) < 0)
905     goto writerr;
906     if (fclose(fp) == EOF)
907     goto writerr;
908     return; /* all is well */
909     writerr:
910     sprintf(errmsg, "error writing frame \"%s\"", pfname);
911     error(SYSTEM, errmsg);
912     }
913    
914    
915     void
916     free_frame() /* free frame allocation */
917     {
918     if (cbuffer == NULL)
919     return;
920     free((void *)cbuffer); cbuffer = NULL;
921     free((void *)zbuffer); zbuffer = NULL;
922     free((void *)obuffer); obuffer = NULL;
923     free((void *)xmbuffer); xmbuffer = NULL;
924     free((void *)ymbuffer); ymbuffer = NULL;
925     free((void *)cprev); cprev = NULL;
926     free((void *)zprev); zprev = NULL;
927     free((void *)oprev); oprev = NULL;
928     cerrmap = NULL;
929     val2map = NULL;
930     hres = vres = 0;
931     vw.type = vwprev.type = 0;
932     frm_stop = 0;
933     }