ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/util/ranimove1.c
Revision: 3.9
Committed: Thu May 13 15:45:43 2004 UTC (19 years, 11 months ago) by greg
Content type: text/plain
Branch: MAIN
CVS Tags: rad3R6, rad3R6P1
Changes since 3.8: +90 -96 lines
Log Message:
Fixed infinite loop introduced during "beautification" of for loops

File Contents

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