ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/util/ranimove1.c
Revision: 3.4
Committed: Mon Jun 30 14:59:13 2003 UTC (20 years, 10 months ago) by schorsch
Content type: text/plain
Branch: MAIN
Changes since 3.3: +7 -5 lines
Log Message:
Replaced most outdated BSD function calls with their posix equivalents, and cleaned up a few other platform dependencies.

File Contents

# User Rev Content
1 greg 3.1 #ifndef lint
2 schorsch 3.4 static const char RCSid[] = "$Id: ranimove1.c,v 3.3 2003/06/05 19:29:35 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     copystruct(&vwprev, &vw);
83     else if (fcur > 1 && (fv = getview(fcur-1)) != NULL) {
84     copystruct(&vwprev, fv);
85     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     copystruct(&vw, fv);
94     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     if (restart > 0)
644     if (nprocs > 1)
645     ray_pdone(1);
646     else
647     ray_done(1);
648     /* post low quality parameters */
649     if (curparams != &lorendparams)
650     ray_restore(curparams = &lorendparams);
651     if (restart > 0) { /* load new octree */
652     char *oct = getoctspec(fcur);
653     if (oct == NULL) {
654     sprintf(errmsg, "cannot get scene for frame %d", fcur);
655     error(USER, errmsg);
656     }
657     if (!silent) {
658     printf("\tLoading octree...");
659     fflush(stdout);
660     }
661     if (nprocs > 1)
662     ray_pinit(oct, nprocs);
663     else
664     ray_init(oct);
665     } else if (restart < 0) { /* update children */
666     if (!silent) {
667     printf("\tRestarting %d processes...", nprocs);
668     fflush(stdout);
669     }
670     ray_pclose(0);
671     ray_popen(nprocs);
672     }
673     if (restart && !silent)
674     printf("done\n");
675     /* sample frame buffer */
676     init_frame_sample();
677     /* initialize frame error */
678     comp_frame_error();
679     return;
680     {
681     float *ebuf = (float *)malloc(sizeof(float)*hres*vres);
682     char fnm[256];
683     register int n;
684     for (n = hres*vres; n--; )
685     ebuf[n] = acctab[abuffer[n]];
686     sprintf(fnm, vval(BASENAME), fcur);
687     strcat(fnm, "_inerr.pic");
688     write_map(ebuf, fnm);
689     free((void *)ebuf);
690     }
691     }
692    
693    
694     void
695     filter_frame() /* interpolation, motion-blur, and exposure */
696     {
697     double expval = expspec_val(getexp(fcur));
698     int x, y;
699     int neigh[NPINTERP];
700     int nc;
701     COLOR cval;
702     double w, wsum;
703     register int n;
704    
705     #if 0
706     /* XXX TEMPORARY!! */
707     conspicuity();
708     write_map(cerrmap, "outcmap.pic");
709     {
710     float *ebuf = (float *)malloc(sizeof(float)*hres*vres);
711     for (n = hres*vres; n--; )
712     ebuf[n] = acctab[abuffer[n]];
713     write_map(ebuf, "outerr.pic");
714     free((void *)ebuf);
715     }
716     #endif
717    
718     if (!silent) {
719     printf("\tFiltering frame\n");
720     fflush(stdout);
721     }
722     /* normalize samples */
723     for (y = vres; y--; )
724     for (x = hres; x--; ) {
725     n = fndx(x, y);
726     if (sbuffer[n] <= 1)
727     continue;
728     w = 1.0/(double)sbuffer[n];
729     scalecolor(cbuffer[n], w);
730     }
731     /* interpolate samples */
732     for (y = vres; y--; )
733     for (x = hres; x--; ) {
734     n = fndx(x, y);
735     if (sbuffer[n])
736     continue;
737     nc = getclosest(neigh, NPINTERP, x, y);
738     setcolor(cbuffer[n], 0., 0., 0.);
739     wsum = 0.;
740     while (nc-- > 0) {
741     copycolor(cval, cbuffer[neigh[nc]]);
742     w = sample_wt((neigh[nc]%hres) - x,
743     (neigh[nc]/hres) - y);
744     scalecolor(cval, w);
745     addcolor(cbuffer[n], cval);
746     wsum += w;
747     }
748     if (wsum > FTINY) {
749     w = 1.0/wsum;
750     scalecolor(cbuffer[n], w);
751     }
752     }
753     /* motion blur if requested */
754     if (mblur > .02) {
755     int len;
756     int xs, ys, xl, yl;
757     int rise, run;
758     long rise2, run2;
759     int n2;
760     int cnt;
761     /* sum in motion streaks */
762 schorsch 3.4 memset(outbuffer, '\0', sizeof(COLOR)*hres*vres);
763     memset(wbuffer, '\0', sizeof(float)*hres*vres);
764 greg 3.1 for (y = vres; y--; )
765     for (x = hres; x--; ) {
766     n = fndx(x, y);
767     if (xmbuffer[n] == MO_UNK) {
768     run = rise = 0;
769     } else {
770     run = (int)(mblur*xmbuffer[n]);
771     rise = (int)(mblur*ymbuffer[n]);
772     }
773     if (!(run | rise)) {
774     addcolor(outbuffer[n], cbuffer[n]);
775     wbuffer[n] += 1.;
776     continue;
777     }
778     xl = x - run/4;
779     yl = y - rise/4;
780     if (run < 0) { xs = -1; run = -run; }
781     else xs = 1;
782     if (rise < 0) { ys = -1; rise = -rise; }
783     else ys = 1;
784     rise2 = run2 = 0L;
785     if (rise > run) {
786     cnt = rise + 1;
787     w = 1./cnt;
788     copycolor(cval, cbuffer[n]);
789     scalecolor(cval, w);
790     while (cnt)
791     if (rise2 >= run2) {
792     if ((xl >= 0 & xl < hres &
793     yl >= 0 & yl < vres)) {
794     n2 = fndx(xl, yl);
795     addcolor(outbuffer[n2],
796     cval);
797     wbuffer[n2] += w;
798     }
799     yl += ys;
800     run2 += run;
801     cnt--;
802     } else {
803     xl += xs;
804     rise2 += rise;
805     }
806     } else {
807     cnt = run + 1;
808     w = 1./cnt;
809     copycolor(cval, cbuffer[n]);
810     scalecolor(cval, w);
811     while (cnt)
812     if (run2 >= rise2) {
813     if ((xl >= 0 & xl < hres &
814     yl >= 0 & yl < vres)) {
815     n2 = fndx(xl, yl);
816     addcolor(outbuffer[n2],
817     cval);
818     wbuffer[n2] += w;
819     }
820     xl += xs;
821     rise2 += rise;
822     cnt--;
823     } else {
824     yl += ys;
825     run2 += run;
826     }
827     }
828     }
829     /* compute final results */
830     for (y = vres; y--; )
831     for (x = hres; x--; ) {
832     n = fndx(x, y);
833     if (wbuffer[n] <= FTINY)
834     continue;
835     w = 1./wbuffer[n];
836     scalecolor(outbuffer[n], w);
837     }
838     } else
839     for (n = hres*vres; n--; )
840     copycolor(outbuffer[n], cbuffer[n]);
841     /*
842     for (n = hres*vres; n--; )
843     if (!sbuffer[n])
844     setcolor(outbuffer[n], 0., 0., 0.);
845     */
846     /* adjust exposure */
847     if ((expval < 0.99 | expval > 1.01))
848     for (n = hres*vres; n--; )
849     scalecolor(outbuffer[n], expval);
850     return;
851     {
852     float *sbuf = (float *)malloc(sizeof(float)*hres*vres);
853     char fnm[256];
854     sprintf(fnm, vval(BASENAME), fcur);
855     strcat(fnm, "_outsamp.pic");
856     for (n = hres*vres; n--; )
857     sbuf[n] = (float)sbuffer[n];
858     write_map(sbuf, fnm);
859     free((void *)sbuf);
860     }
861     }
862    
863    
864     void
865     send_frame() /* send frame to destination */
866     {
867     char pfname[1024];
868     double d;
869     FILE *fp;
870     int y;
871     /* open output picture */
872     sprintf(pfname, vval(BASENAME), fcur);
873     strcat(pfname, ".pic");
874     fp = fopen(pfname, "w");
875     if (fp == NULL) {
876     sprintf(errmsg, "cannot open output frame \"%s\"", pfname);
877     error(SYSTEM, errmsg);
878     }
879 schorsch 3.3 SET_FILE_BINARY(fp);
880 greg 3.1 if (!silent) {
881     printf("\tWriting to \"%s\"\n", pfname);
882     fflush(stdout);
883     }
884     /* write header */
885     newheader("RADIANCE", fp);
886     printargs(gargc, gargv, fp);
887     fprintf(fp, "SOFTWARE= %s\n", VersionID);
888     fprintf(fp, "FRAME=%d\n", fcur);
889     fputnow(fp);
890     fputs(VIEWSTR, fp); fprintview(&vw, fp); fputc('\n', fp);
891     d = expspec_val(getexp(fcur));
892     if ((d < 0.99 | d > 1.01))
893     fputexpos(d, fp);
894     d = viewaspect(&vw) * hres / vres;
895     if ((d < 0.99 | d > 1.01))
896     fputaspect(d, fp);
897     fputformat(COLRFMT, fp);
898     fputc('\n', fp); /* end header */
899     fprtresolu(hres, vres, fp);
900     if (fflush(fp) == EOF)
901     goto writerr;
902     #if (PIXSTANDARD != (YMAJOR|YDECR))
903     error(CONSISTENCY, "bad code in send_frame");
904     #endif
905     for (y = vres; y--; ) /* write scanlines */
906     if (fwritescan(outbuffer+y*hres, hres, fp) < 0)
907     goto writerr;
908     if (fclose(fp) == EOF)
909     goto writerr;
910     return; /* all is well */
911     writerr:
912     sprintf(errmsg, "error writing frame \"%s\"", pfname);
913     error(SYSTEM, errmsg);
914     }
915    
916    
917     void
918     free_frame() /* free frame allocation */
919     {
920     if (cbuffer == NULL)
921     return;
922     free((void *)cbuffer); cbuffer = NULL;
923     free((void *)zbuffer); zbuffer = NULL;
924     free((void *)obuffer); obuffer = NULL;
925     free((void *)xmbuffer); xmbuffer = NULL;
926     free((void *)ymbuffer); ymbuffer = NULL;
927     free((void *)cprev); cprev = NULL;
928     free((void *)zprev); zprev = NULL;
929     free((void *)oprev); oprev = NULL;
930     cerrmap = NULL;
931     val2map = NULL;
932     hres = vres = 0;
933     vw.type = vwprev.type = 0;
934     frm_stop = 0;
935     }