ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/util/ranimove1.c
Revision: 3.21
Committed: Fri Oct 5 00:59:38 2012 UTC (11 years, 6 months ago) by greg
Content type: text/plain
Branch: MAIN
Changes since 3.20: +43 -28 lines
Log Message:
Created pmblur2 command to compute better motion blur from ranimove runs

File Contents

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