ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/util/ranimove1.c
Revision: 3.14
Committed: Thu Apr 17 14:49:59 2008 UTC (16 years, 5 months ago) by greg
Content type: text/plain
Branch: MAIN
CVS Tags: rad3R9
Changes since 3.13: +5 -8 lines
Log Message:
Eliminated unnecessary bits of code

File Contents

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