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

# Content
1 #ifndef lint
2 static const char RCSid[] = "$Id: ranimove1.c,v 3.2 2003/02/25 02:47:24 greg Exp $";
3 #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 #include "copyright.h"
13
14 #include "platform.h"
15 #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 SET_FILE_BINARY(fp);
878 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 }