ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/util/ranimove1.c
Revision: 3.5
Committed: Mon Jul 21 22:30:19 2003 UTC (20 years, 9 months ago) by schorsch
Content type: text/plain
Branch: MAIN
Changes since 3.4: +6 -5 lines
Log Message:
Eliminated copystruct() macro, which is unnecessary in ANSI.
Reduced ambiguity warnings for nested if/if/else clauses.

File Contents

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