Back to index

radiance  4R0+20100331
ranimove2.c
Go to the documentation of this file.
00001 #ifndef lint
00002 static const char    RCSid[] = "$Id: ranimove2.c,v 3.9 2005/07/24 21:11:53 greg Exp $";
00003 #endif
00004 /*
00005  *  ranimove2.c
00006  *
00007  *  Frame refinement routines for ranimove(1).
00008  *
00009  *  Created by Gregory Ward on Wed Jan 08 2003.
00010  */
00011 
00012 #include "copyright.h"
00013 
00014 #include <string.h>
00015 
00016 #include "ranimove.h"
00017 #include "random.h"
00018 
00019 
00020 #define       HL_ERR 0.32          /* highlight error threshold */
00021 
00022 int    cerrzero;            /* is cerrmap all zeroes? */
00023 
00024 static int ppri_cmp(const void *pp1, const void *pp2);
00025 static int ray_refine(int   n);
00026 static long refine_rays(long       nrays);
00027 
00028 
00029 extern int
00030 refine_first(void)                 /* initial refinement pass */
00031 {
00032        int    *esamp = (int *)zprev;      /* OK to reuse */
00033        int    hl_erri = errori(HL_ERR);
00034        int    nextra = 0;
00035        int    x, y, xp, yp;
00036        int    neigh;
00037        register int  n, np;
00038 
00039        if (sizeof(int) < sizeof(*zprev))
00040               error(CONSISTENCY, "code error in refine_first");
00041        if (!silent) {
00042               printf("\tFirst refinement pass...");
00043               fflush(stdout);
00044        }
00045        memset((void *)esamp, '\0', sizeof(int)*hres*vres);
00046        /*
00047         * In our initial pass, we look for lower error pixels from
00048         * the same objects in the previous frame, and copy them here.
00049         */
00050        for (y = vres; y--; )
00051            for (x = hres; x--; ) {
00052               n = fndx(x, y);
00053               if (obuffer[n] == OVOID)
00054                      continue;
00055               if (xmbuffer[n] == MO_UNK)
00056                      continue;
00057               xp = x + xmbuffer[n];
00058               if ((xp < 0) | (xp >= hres))
00059                      continue;
00060               yp = y + ymbuffer[n];
00061               if ((yp < 0) | (yp >= vres))
00062                      continue;
00063               np = fndx(xp, yp);
00064                                    /* make sure we hit same object */
00065               if (oprev[np] != obuffer[n])
00066                      continue;
00067                                    /* is previous frame error lower? */
00068               if (aprev[np] < AMIN + ATIDIFF)
00069                      continue;
00070               if (aprev[np] <= abuffer[n] + ATIDIFF)
00071                      continue;
00072                                    /* shadow & highlight detection */
00073               if (abuffer[n] > hl_erri &&
00074                             getclosest(&neigh, 1, x, y) &&
00075                             bigdiff(cbuffer[neigh], cprev[np],
00076                                    HL_ERR*(.9+.2*frandom())))
00077                      continue;
00078               abuffer[n] = aprev[np] - ATIDIFF;
00079               copycolor(cbuffer[n], cprev[np]);
00080               esamp[n] = 1;        /* record extrapolated sample */
00081               nextra++;
00082            }
00083        for (n = hres*vres; n--; )  /* update sample counts */
00084               if (esamp[n])
00085                      sbuffer[n] = 1;
00086        if (!silent)
00087               printf("extrapolated %d pixels\n", nextra);
00088        return(1);
00089 }
00090 
00091 
00092 /*
00093  * We use a recursive computation of the conspicuity
00094  * map to avoid associated memory costs and simplify
00095  * coding.  We create a virtual image pyramid, pooling
00096  * variance calculations, etc.  The top of the pyramid
00097  * corresponds to the foveal resolution, as there should
00098  * not be any interesting mechanisms above this level.
00099  */
00100 
00101 #define CSF_C0       1.14
00102 #define CSF_C1       0.67
00103 #define CSF_C2       1.7
00104 #define CSF_S1       6.1
00105 #define CSF_S2       7.3
00106 #define CSF_P1       45.9
00107 #define CSF_PC       (30./45.9*CSF_P1)
00108 #define CSF_VR0      0.15
00109 #define CSF_VRC      80.
00110 
00111 struct ConspSum {
00112        COLOR         vsum;         /* value sum */
00113        COLOR         v2sum;        /* value^2 sum */
00114        long          nsamp;        /* number of samples */
00115        long          xmsum;        /* x-motion sum */
00116        long          ymsum;        /* y-motion sum */
00117        int           npix;         /* number of pixels */
00118        double        hls;          /* high-level saliency */
00119 };
00120 
00121 static double pixel_deg;    /* base pixel frequency */
00122 static int    fhsiz, fvsiz; /* foveal subimage size */
00123 
00124 static void clr_consp(struct ConspSum *cs);
00125 static void sum_consp(struct ConspSum *cdest, struct ConspSum *cs);
00126 static void est_consp(int x0, int y0, int x1, int y1, struct ConspSum *cs);
00127 static void subconspicuity(int x0, int y0, int x1, int y1, struct ConspSum *cs);
00128 
00129 static void
00130 clr_consp(                  /* initialize a conspicuity sum */
00131        register struct ConspSum    *cs
00132 )
00133 {
00134        if (cs == NULL)
00135               return;
00136        setcolor(cs->vsum, 0., 0., 0.);
00137        setcolor(cs->v2sum, 0., 0., 0.);
00138        cs->nsamp = 0;
00139        cs->xmsum = cs->ymsum = 0;
00140        cs->npix = 0;
00141        cs->hls = 0;
00142 }
00143 
00144 static void
00145 sum_consp(           /* sum in conspicuity result */
00146        register struct ConspSum    *cdest,
00147        register struct ConspSum    *cs
00148 )
00149 {
00150        if ((cdest == NULL) | (cs == NULL))
00151               return;
00152        addcolor(cdest->vsum, cs->vsum);
00153        addcolor(cdest->v2sum, cs->v2sum);
00154        cdest->nsamp += cs->nsamp;
00155        cdest->xmsum += cs->xmsum;
00156        cdest->ymsum += cs->ymsum;
00157        cdest->npix += cs->npix;
00158        if (cs->hls > cdest->hls)
00159               cdest->hls = cs->hls;
00160 }
00161 
00162 static void
00163 est_consp(    /* estimate error conspicuity & update */
00164        int    x0,
00165        int    y0,
00166        int    x1,
00167        int    y1,
00168        register struct ConspSum    *cs
00169 )
00170 {
00171        double rad2, mtn2, cpd, vm, vr, csf, eest;
00172                                           /* do we care? */
00173        if (cs->hls <= FTINY)
00174               return;
00175                                           /* get relative error */
00176        if (cs->nsamp < NSAMPOK) {
00177               int    neigh[NSAMPOK];             /* gather neighbors */
00178               eest = comperr(neigh,
00179                      getclosest(neigh, NSAMPOK, (x0+x1)>>1, (y0+y1)>>1),
00180                             cs->nsamp);
00181        } else
00182               eest = estimaterr(cs->vsum, cs->v2sum, cs->nsamp, cs->nsamp);
00183        
00184        if ((x0 == x1-1) & (y0 == y1-1)) { /* update pixel error */
00185               int    n = fndx(x0, y0);
00186               int    ai;
00187               int    ne;
00188               if (sbuffer[n] >= 255) {
00189                      abuffer[n] = ADISTANT;
00190               } else {
00191                      ai = errori(eest);
00192                      if (ai < AMIN) ai = AMIN;
00193                      else if (ai >= ADISTANT) ai = ADISTANT-1;
00194                      abuffer[n] = ai;
00195                                           /* can't improve on closest */
00196                      if (!cs->nsamp && getclosest(&ne, 1, x0, y0) &&
00197                                    abuffer[ne] < ai &&
00198                                    abuffer[ne] >= AMIN)
00199                             abuffer[n] = abuffer[ne];
00200               }
00201        }
00202                                           /* compute radius^2 */
00203        rad2 = 0.125*((x1-x0)*(x1-x0) + (y1-y0)*(y1-y0));
00204 
00205                                           /* average motion^2 */
00206        mtn2 = (double)cs->xmsum*cs->xmsum + (double)cs->ymsum*cs->ymsum;
00207        mtn2 /= (double)(cs->npix*cs->npix);
00208                                           /* motion blur hides us? */
00209        if (mblur*mblur*mtn2 >= 4.*rad2)
00210               return;
00211                                           /* too small to see? */
00212        cpd = pixel_deg * pixel_deg / rad2;
00213        if (cpd > CSF_PC*CSF_PC)
00214               return;
00215        cpd = sqrt(cpd);
00216                                           /* compute CSF [Daley98] */
00217        vm = rate * sqrt(mtn2) / pixel_deg;
00218        vr = cs->hls/hlsmax*vm + CSF_VR0;  /* use hls tracking eff. */
00219        if (vr > CSF_VRC) vr = CSF_VRC;
00220        vr = vm - vr;
00221        if (vr < 0) vr = -vr;
00222        csf = log(CSF_C2*(1./3.)*vr);
00223        if (csf < 0) csf = -csf;
00224        csf = CSF_S1 + CSF_S2*csf*csf*csf;
00225        csf *= CSF_C0*CSF_C2*4.*PI*PI*CSF_C1*CSF_C1*cpd*cpd;
00226        csf *= exp(-CSF_C1*4.*PI/CSF_P1*(CSF_C2*vr + 2.)*cpd);
00227                                           /* compute visible error */
00228        eest = eest*csf/ndthresh - 1.;
00229        if (eest <= FTINY)
00230               return;
00231                                           /* scale by saleincy */
00232        eest *= cs->hls;
00233                                           /* worth the bother? */
00234        if (eest <= .01)
00235               return;
00236                                           /* put into map */
00237        for ( ; y0 < y1; y0++) {
00238               float  *em0 = cerrmap + fndx(x0, y0);
00239               register float       *emp = em0 + (x1-x0);
00240               while (emp-- > em0)
00241                      if (eest > *emp)
00242                             *emp = eest;
00243        }
00244        cerrzero = 0;
00245 }
00246 
00247 static void
00248 subconspicuity(      /* compute subportion of conspicuity */
00249        int    x0,
00250        int    y0,
00251        int    x1,
00252        int    y1,
00253        struct ConspSum      *cs
00254 )
00255 {
00256        struct ConspSum      mysum;
00257        int    i;
00258 
00259        if ((x0 >= x1) | (y0 >= y1))
00260               error(CONSISTENCY, "bad call to subconspicuity");
00261 
00262        clr_consp(&mysum);                 /* prepare sum */
00263 
00264        if ((x0 == x1-1) & (y0 == y1-1)) { /* single pixel */
00265               double hls;
00266               register int  n = fndx(x0, y0);
00267               if (sbuffer[n]) {
00268                      copycolor(mysum.vsum, cbuffer[n]);
00269                      copycolor(mysum.v2sum, val2map[n]);
00270                      mysum.nsamp = sbuffer[n];
00271               }
00272               if ((mysum.xmsum = xmbuffer[n]) == MO_UNK)
00273                      mysum.xmsum = 0;
00274               else
00275                      mysum.ymsum = ymbuffer[n];
00276               mysum.npix = 1;
00277                                           /* max. hls in fovea */
00278               mysum.hls = obj_prio(obuffer[n]);
00279               if (x0 >= fhsiz) {
00280                      hls = obj_prio(obuffer[fndx(x0-fhsiz,y0)]);
00281                      if (hls > mysum.hls) mysum.hls = hls;
00282               }
00283               if (x0 < hres-fhsiz) {
00284                      hls = obj_prio(obuffer[fndx(x0+fhsiz,y0)]);
00285                      if (hls > mysum.hls) mysum.hls = hls;
00286               }
00287               if (y0 >= fvsiz) {
00288                      hls = obj_prio(obuffer[fndx(x0,y0-fvsiz)]);
00289                      if (hls > mysum.hls) mysum.hls = hls;
00290               }
00291               if (y0 < vres-fvsiz) {
00292                      hls = obj_prio(obuffer[fndx(x0,y0+fvsiz)]);
00293                      if (hls > mysum.hls) mysum.hls = hls;
00294               }
00295        } else if (x0 == x1-1) {           /* vertical pair */
00296               for (i = y0 ; i < y1; i++)
00297                      subconspicuity(x0, i, x1, i+1, &mysum);
00298        } else if (y0 == y1-1) {           /* horizontal pair */
00299               for (i = x0 ; i < x1; i++)
00300                      subconspicuity(i, y0, i+1, y1, &mysum);
00301        } else {                           /* rectangle */
00302               subconspicuity(x0, y0, (x0+x1)>>1, (y0+y1)>>1, &mysum);
00303               subconspicuity((x0+x1)>>1, y0, x1, (y0+y1)>>1, &mysum);
00304               subconspicuity(x0, (y0+y1)>>1, (x0+x1)>>1, y1, &mysum);
00305               subconspicuity((x0+x1)>>1, (y0+y1)>>1, x1, y1, &mysum);
00306        }
00307                                           /* update conspicuity */
00308        est_consp(x0, y0, x1, y1, &mysum);
00309                                           /* sum into return value */
00310        sum_consp(cs, &mysum);
00311 }
00312 
00313 extern void
00314 conspicuity(void)                  /* compute conspicuous error map */
00315 {
00316        int    fhres, fvres;
00317        int    fx, fy;
00318                                    /* reuse previous z-buffer */
00319        cerrmap = (float *)zprev;
00320        memset((void *)cerrmap, '\0', sizeof(float)*hres*vres);
00321        cerrzero = 1;
00322                                    /* compute base pixel frequency */
00323        pixel_deg = .5*(hres/vw.horiz + vres/vw.vert);
00324                                    /* compute foveal resolution */
00325        fhres = vw.horiz/FOV_DEG + 0.5;
00326        if (fhres <= 0) fhres = 1;
00327        else if (fhres > hres) fhres = hres;
00328        fvres = vw.vert/FOV_DEG + 0.5;
00329        if (fvres <= 0) fvres = 1;
00330        else if (fvres > vres) fvres = vres;
00331        fhsiz = hres/fhres;
00332        fvsiz = vres/fvres;
00333                                    /* call our foveal subroutine */
00334        for (fy = fvres; fy--; )
00335               for (fx = fhres; fx--; )
00336                      subconspicuity(hres*fx/fhres, vres*fy/fvres,
00337                                    hres*(fx+1)/fhres, vres*(fy+1)/fvres,
00338                                    NULL);
00339 }
00340 
00341 
00342 /*
00343  * The following structure is used to collect data on the
00344  * initial error in the ambient value estimate, in order
00345  * to correct for it in the subsequent frames.
00346  */
00347 static struct AmbSum {
00348        double        diffsum[3];   /* sum of (correct - ambval) */
00349        long          nsamps;              /* number of values in sum */
00350 }             *asump = NULL;
00351 
00352 
00353 static int
00354 ppri_cmp(            /* pixel priority comparison */
00355        const void *pp1,
00356        const void *pp2
00357 )
00358 {
00359        double se1 = cerrmap[*(const int *)pp1];
00360        double se2 = cerrmap[*(const int *)pp2];
00361        int    adiff;
00362                                    /* higher conspicuity to front */
00363        if (se1 < se2) return(1);
00364        if (se1 > se2) return(-1);
00365                                    /* else higher error to front */
00366        adiff = (int)abuffer[*(const int *)pp1] -
00367                      (int)abuffer[*(const int *)pp2];
00368        if (adiff)
00369               return(adiff);
00370                                    /* else fewer samples to front */
00371        return((int)sbuffer[*(const int *)pp1] -
00372                      (int)sbuffer[*(const int *)pp2]);
00373 }
00374 
00375 
00376 static int
00377 ray_refine(                 /* refine the given pixel by tracing a ray */
00378        register int  n
00379 )
00380 {
00381        RAY    ir;
00382        COLOR  ctmp;
00383        int    i;
00384 
00385        if (n < 0) {                /* fetching stragglers */
00386               if (nprocs <= 1 || !ray_presult(&ir, 0))
00387                      return(-1);
00388               n = ir.rno;
00389        } else {                    /* else tracing a new ray */
00390               double hv[2];
00391               if (sbuffer[n] >= 255)      /* reached limit? */
00392                      return(-1);
00393               sample_pos(hv, n%hres, n/hres, sbuffer[n]);
00394               ir.rmax = viewray(ir.rorg, ir.rdir, &vw, hv[0], hv[1]);
00395               if (ir.rmax < -FTINY)
00396                      return(-1);
00397               if (nprocs > 1) {
00398                      int    rval;
00399                      rayorigin(&ir, PRIMARY, NULL, NULL);
00400                      ir.rno = n;
00401                      rval = ray_pqueue(&ir);
00402                      if (!rval)
00403                             return(-1);
00404                      if (rval < 0)
00405                             quit(1);
00406                      n = ir.rno;
00407               } else
00408                      ray_trace(&ir);
00409        }
00410        if (abuffer[n] == ALOWQ && asump != NULL) {
00411               if (sbuffer[n] != 1)
00412                      error(CONSISTENCY, "bad code in ray_refine");
00413               if (getambcolor(ctmp, obuffer[n]) &&
00414                             (colval(ctmp,RED) > 0.01) &
00415                             (colval(ctmp,GRN) > 0.01) &
00416                             (colval(ctmp,BLU) > 0.01)) {
00417                      for (i = 0; i < 3; i++)
00418                             asump->diffsum[i] +=
00419                                 (colval(ir.rcol,i) - colval(cbuffer[n],i))
00420                                    / colval(ctmp,i);
00421                      asump->nsamps++;
00422               }
00423               sbuffer[n] = 0;
00424        }
00425        setcolor(ctmp,
00426               colval(ir.rcol,RED)*colval(ir.rcol,RED),
00427               colval(ir.rcol,GRN)*colval(ir.rcol,GRN),
00428               colval(ir.rcol,BLU)*colval(ir.rcol,BLU));
00429        if (!sbuffer[n]) {                 /* first sample */
00430               copycolor(cbuffer[n], ir.rcol);
00431               copycolor(val2map[n], ctmp);
00432               abuffer[n] = AHIGHQ;
00433               sbuffer[n] = 1;
00434        } else {                           /* else sum in sample */
00435               addcolor(cbuffer[n], ir.rcol);
00436               addcolor(val2map[n], ctmp);
00437               sbuffer[n]++;
00438        }
00439        return(n);
00440 }
00441 
00442 
00443 static long
00444 refine_rays(         /* compute refinement rays */
00445        long   nrays
00446 )
00447 {
00448        int    *pord;
00449        int    ntodo;
00450        long   rdone;
00451        int    i;
00452                                    /* skip if nothing significant */
00453        if (ndtset && cerrzero)
00454               return(0);
00455                                    /* initialize priority list */
00456        pord = (int *)malloc(sizeof(int)*hres*vres);
00457        for (i = hres*vres; i--; )
00458               pord[i] = i;
00459                                    /* sort our priorities */
00460        ntodo = hres*vres;
00461        if (nrays < ntodo)
00462               qsort((void *)pord, hres*vres, sizeof(int), ppri_cmp);
00463        i = 0;
00464                                    /* trace rays in list */
00465        for (rdone = 0; rdone < nrays; rdone++) {
00466               if (ndtset && i >= 1000 && cerrmap[pord[i]] <= FTINY)
00467                      ntodo = i;
00468               if (i >= ntodo) {    /* redo conspicuity & priority */
00469                      while (ray_refine(-1) >= 0)
00470                             ;
00471                      conspicuity();
00472                      if (ndtset && cerrzero)
00473                             break;
00474                      qsort((void *)pord, hres*vres, sizeof(int), ppri_cmp);
00475                      ntodo = hres*vres/8;
00476                      i = 0;
00477               }
00478                                    /* sample next pixel */
00479               ray_refine(pord[i++]);
00480        }
00481                                    /* clean up and return */
00482        while (ray_refine(-1) >= 0)
00483               ;
00484        free((void *)pord);
00485        return(rdone);
00486 }
00487 
00488 
00489 extern int
00490 refine_frame(        /* refine current frame */
00491        int    pass
00492 )
00493 {
00494        static double rtime_used = 0;
00495        static long   ray_cnt = 0;
00496        static double ctime_used = 0;
00497        static int    csp_cnt = 0;
00498        int    timed = (fcur > fbeg) | (pass > 0) | (quickstart);
00499        double time_start, rtime_start, time_done;
00500        struct AmbSum myAmbSum;
00501        long   rays_todo, nr;
00502        register int  n;
00503                                    /* IBR refinement? */
00504        if ((pass == 0) & (fcur > fbeg))
00505               return(refine_first());
00506                                    /* any time left? */
00507        time_start = getTime();
00508        if (timed) {
00509               if (time_start >= frm_stop)
00510                      goto nomore;
00511               if (csp_cnt > 0 && time_start + ctime_used/csp_cnt >= frm_stop)
00512                      goto nomore;
00513        }
00514        asump = NULL;               /* use resampling to update ambval? */
00515        if (!curparams->ambounce && hirendparams.ambounce) {
00516               myAmbSum.diffsum[RED] =
00517               myAmbSum.diffsum[GRN] =
00518               myAmbSum.diffsum[BLU] = 0;
00519               myAmbSum.nsamps = 0;
00520               asump = &myAmbSum;
00521        }
00522                                    /* initialize value-squared map */
00523        if (val2map == NULL) {
00524               val2map = cprev;     /* OK to reuse at this point */
00525               n = (asump == NULL) ? hres*vres : 0;
00526               while (n--)
00527                      if (sbuffer[n])
00528                             setcolor(val2map[n],
00529                             colval(cbuffer[n],RED)*colval(cbuffer[n],RED),
00530                             colval(cbuffer[n],GRN)*colval(cbuffer[n],GRN),
00531                             colval(cbuffer[n],BLU)*colval(cbuffer[n],BLU));
00532                      else
00533                             setcolor(val2map[n], 0., 0., 0.);
00534        }
00535                                    /* compute conspicuity */
00536        if (!silent) {
00537               printf("\tComputing conspicuity map\n");
00538               fflush(stdout);
00539        }
00540        conspicuity();
00541        csp_cnt++;
00542 #if 0
00543 if (pass == 1) {
00544        char   fnm[256];
00545        sprintf(fnm, vval(BASENAME), fcur);
00546        strcat(fnm, "_incmap.pic");
00547        write_map(cerrmap, fnm);
00548 }
00549 #endif
00550                                    /* get ray start time */
00551        rtime_start = getTime();
00552        ctime_used += rtime_start - time_start;
00553        if (timed && rtime_start >= frm_stop)
00554               return(0);           /* error done but out of time */
00555        if (rtime_used <= FTINY) {
00556               if (quickstart)
00557                      rays_todo = 1000;
00558               else
00559                      rays_todo = hres*vres;
00560        } else {
00561               rays_todo = (long)((frm_stop - rtime_start) *
00562                                    ray_cnt / rtime_used);
00563               if (rays_todo < 1000)
00564                      return(0);    /* let's call it a frame */
00565        }
00566                                    /* set higher rendering quality */
00567        if (twolevels && curparams != &hirendparams) {
00568               ray_restore(curparams = &hirendparams);
00569               if (nprocs > 1) {    /* need to update children */
00570                      if (!silent) {
00571                             printf("\tRestarting %d processes\n", nprocs);
00572                             fflush(stdout);
00573                      }
00574                      ray_pclose(0);
00575                      ray_popen(nprocs);
00576               }
00577        }
00578                                    /* compute refinement rays */
00579        if (!silent) {
00580               printf("\tRefinement pass %d...",
00581                             pass+1); /*, rays_todo); */
00582               fflush(stdout);
00583        }
00584        if (asump != NULL)          /* flag low-quality samples */
00585               for (n = hres*vres; n--; )
00586                      if (sbuffer[n])
00587                             abuffer[n] = ALOWQ;
00588                                    /* trace those rays */
00589        nr = refine_rays(rays_todo);
00590        if (!silent)
00591               printf("traced %ld HQ rays\n", nr);
00592        if (nr <= 0)
00593               return(0);
00594                                    /* update timing stats */
00595        while (ray_cnt >= 1L<<20) {
00596               ray_cnt >>= 1;
00597               rtime_used *= .5;
00598        }
00599        ray_cnt += nr;
00600        time_done = getTime();
00601        rtime_used += time_done - rtime_start;
00602        if (!timed && time_done > frm_stop)
00603               frm_stop = time_done;
00604                                    /* update ambient value */
00605        if (asump != NULL && asump->nsamps >= 1000) {
00606               double sf = 1./(double)asump->nsamps;
00607               for (n = 3; n--; ) {
00608                      asump->diffsum[n] *= sf;
00609                      asump->diffsum[n] += colval(lorendparams.ambval,n);
00610                      if (asump->diffsum[n] < 0) asump->diffsum[n] = 0;
00611               }
00612               setcolor(lorendparams.ambval,
00613                             asump->diffsum[RED],
00614                             asump->diffsum[GRN],
00615                             asump->diffsum[BLU]);
00616               if (!silent)
00617                      printf("\tUpdated parameter: -av %f %f %f\n",
00618                                    asump->diffsum[RED],
00619                                    asump->diffsum[GRN],
00620                                    asump->diffsum[BLU]);
00621               asump = NULL;
00622        }
00623        return(1);
00624 nomore:
00625                                    /* make sure error map is updated */
00626        if ((fcur == fbeg) | (pass > 1))
00627               comp_frame_error();
00628        return(0);
00629 }