ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/common/tonemap.c
(Generate patch)

Comparing ray/src/common/tonemap.c (file contents):
Revision 3.1 by greg, Tue Apr 15 16:53:01 1997 UTC vs.
Revision 3.5 by gregl, Wed Nov 12 13:25:48 1997 UTC

# Line 18 | Line 18 | static char SCCSid[] = "$SunId$ LBL";
18  
19   struct tmStruct *tmTop = NULL;          /* current tone mapping stack */
20  
21 +                                        /* our list of conversion packages */
22 + struct tmPackage        *tmPkg[TM_MAXPKG];
23 + int     tmNumPkgs = 0;                  /* number of registered packages */
24  
25 + int     tmLastError;                    /* last error incurred by library */
26 + char    *tmLastFunction;                /* error-generating function name */
27 +
28 +
29   int
30   tmErrorReturn(func, err)                /* error return (with message) */
31   char    *func;
32   int     err;
33   {
34 <        if (tmTop != NULL && tmTop->flags & TM_F_NOERRS)
34 >        tmLastFunction = func;
35 >        tmLastError = err;
36 >        if (tmTop != NULL && tmTop->flags & TM_F_NOSTDERR)
37                  return(err);
38          fputs(func, stderr);
39          fputs(": ", stderr);
# Line 62 | Line 71 | double gamval;
71                  tmnew->clf[GRN] = cmat[1][1];
72                  tmnew->clf[BLU] = cmat[1][2];
73          }
65        tmnew->clfb[RED] = 256.*tmnew->clf[RED] + .5;
66        tmnew->clfb[GRN] = 256.*tmnew->clf[GRN] + .5;
67        tmnew->clfb[BLU] = 256.*tmnew->clf[BLU] + .5;
68        tmnew->clfb[EXP] = COLXS;
74                                                  /* set gamma value */
75          if (gamval < MINGAM)
76                  tmnew->mongam = DEFGAM;
77          else
78                  tmnew->mongam = gamval;
79 <        for (i = TM_GAMTSZ; i--; )
80 <                tmnew->gamb[i] = 256.*pow((i+.5)/TM_GAMTSZ, 1./tmnew->mongam);
79 >                                                /* set color divisors */
80 >        for (i = 0; i < 3; i++)
81 >                tmnew->cdiv[i] = 256.*pow(tmnew->clf[i], 1./tmnew->mongam);
82 >
83                                                  /* set input transform */
84          tmnew->inppri = tmnew->monpri;
85          tmnew->cmat[0][0] = tmnew->cmat[1][1] = tmnew->cmat[2][2] =
86                          tmnew->inpsf = WHTEFFICACY;
80        tmnew->inpsfb = TM_BRTSCALE*log(tmnew->inpsf) + .5;
87          tmnew->cmat[0][1] = tmnew->cmat[0][2] = tmnew->cmat[1][0] =
88          tmnew->cmat[1][2] = tmnew->cmat[2][0] = tmnew->cmat[2][1] = 0.;
83        tmnew->flags &= ~TM_F_NEEDMAT;
89          tmnew->brmin = tmnew->brmax = 0;
90          tmnew->histo = NULL;
91          tmnew->lumap = NULL;
92 <        tmnew->tmprev = NULL;
93 <
94 <        tmnew->flags |= TM_F_INITED;
95 <                                                /* make it current */
92 >                                                /* zero private data */
93 >        for (i = TM_MAXPKG; i--; )
94 >                tmnew->pd[i] = NULL;
95 >                                                /* make tmnew current */
96          tmnew->tmprev = tmTop;
97          return(tmTop = tmnew);
98   }
# Line 110 | Line 115 | double sf;
115                  returnOK;
116          tmTop->inppri = pri;                    /* let's set it */
117          tmTop->inpsf = sf;
113        tmTop->inpsfb = TM_BRTSCALE*log(sf) + (sf>=1. ? .5 : -.5);
118  
119          if (tmTop->flags & TM_F_BW) {           /* color doesn't matter */
120                  tmTop->monpri = tmTop->inppri;          /* eliminate xform */
121                  if (tmTop->inppri == TM_XYZPRIM) {
122                          tmTop->clf[CIEX] = tmTop->clf[CIEZ] = 0.;
123                          tmTop->clf[CIEY] = 1.;
120                        tmTop->clfb[CIEX] = tmTop->clfb[CIEZ] = 0;
121                        tmTop->clfb[CIEY] = 255;
124                  } else {
125                          comprgb2xyzmat(tmTop->cmat, tmTop->monpri);
126                          tmTop->clf[RED] = tmTop->cmat[1][0];
# Line 142 | Line 144 | double sf;
144          for (i = 0; i < 3; i++)
145                  for (j = 0; j < 3; j++)
146                          tmTop->cmat[i][j] *= tmTop->inpsf;
147 <        if (tmTop->inppri != tmTop->monpri)
148 <                tmTop->flags |= TM_F_NEEDMAT;
149 <        else
150 <                tmTop->flags &= ~TM_F_NEEDMAT;
147 >                                                /* set color divisors */
148 >        for (i = 0; i < 3; i++)
149 >                if (tmTop->clf[i] > .001)
150 >                        tmTop->cdiv[i] =
151 >                                256.*pow(tmTop->clf[i], 1./tmTop->mongam);
152 >                else
153 >                        tmTop->cdiv[i] = 1;
154 >                                                /* notify packages */
155 >        for (i = tmNumPkgs; i--; )
156 >                if (tmTop->pd[i] != NULL && tmPkg[i]->NewSpace != NULL)
157 >                        (*tmPkg[i]->NewSpace)(tmTop);
158          returnOK;
159   }
160  
# Line 155 | Line 164 | tmClearHisto()                 /* clear current histogram */
164   {
165          if (tmTop == NULL || tmTop->histo == NULL)
166                  return;
167 <        free((char *)tmTop->histo);
167 >        free((MEM_PTR)tmTop->histo);
168          tmTop->histo = NULL;
169   }
170  
# Line 168 | Line 177 | COLOR  *scan;
177   int     len;
178   {
179          static char     funcName[] = "tmCvColors";
180 +        static COLOR    csmall = {1e-6, 1e-6, 1e-6};
181          COLOR   cmon;
182          double  lum, slum;
183          register double d;
# Line 178 | Line 188 | int    len;
188          if (ls == NULL | scan == NULL | len <= 0)
189                  returnErr(TM_E_ILLEGAL);
190          for (i = len; i--; ) {
191 <                if (tmTop->flags & TM_F_NEEDMAT)        /* get monitor RGB */
191 >                if (tmNeedMatrix(tmTop))                /* get monitor RGB */
192                          colortrans(cmon, tmTop->cmat, scan[i]);
193                  else {
194                          cmon[RED] = tmTop->inpsf*scan[i][RED];
# Line 190 | Line 200 | int    len;
200                          tmTop->clf[GRN]*cmon[GRN] +
201                          tmTop->clf[BLU]*cmon[BLU] ;
202                                                          /* check range */
203 <                if (clipgamut(cmon, lum, CGAMUT_LOWER, cblack, cwhite))
203 >                if (clipgamut(cmon, lum, CGAMUT_LOWER, csmall, cwhite))
204                          lum =   tmTop->clf[RED]*cmon[RED] +
205                                  tmTop->clf[GRN]*cmon[GRN] +
206                                  tmTop->clf[BLU]*cmon[BLU] ;
# Line 223 | Line 233 | int    len;
233                          cmon[RED] = cmon[GRN] = cmon[BLU] = lum;
234                  }
235                  d = tmTop->clf[RED]*cmon[RED]/lum;
236 <                /* cs[3*i  ] = d>.999 ? 255 : 256.*pow(d, 1./tmTop->mongam); */
237 <                cs[3*i  ] = d>.999 ? 255 : tmTop->gamb[(int)(d*TM_GAMTSZ)];
236 >                cs[3*i  ] = d>=.999 ? 255 :
237 >                                (int)(256.*pow(d, 1./tmTop->mongam));
238                  d = tmTop->clf[GRN]*cmon[GRN]/lum;
239 <                /* cs[3*i+1] = d>.999 ? 255 : 256.*pow(d, 1./tmTop->mongam); */
240 <                cs[3*i+1] = d>.999 ? 255 : tmTop->gamb[(int)(d*TM_GAMTSZ)];
239 >                cs[3*i+1] = d>=.999 ? 255 :
240 >                                (int)(256.*pow(d, 1./tmTop->mongam));
241                  d = tmTop->clf[BLU]*cmon[BLU]/lum;
242 <                /* cs[3*i+2] = d>.999 ? 255 : 256.*pow(d, 1./tmTop->mongam); */
243 <                cs[3*i+2] = d>.999 ? 255 : tmTop->gamb[(int)(d*TM_GAMTSZ)];
242 >                cs[3*i+2] = d>=.999 ? 255 :
243 >                                (int)(256.*pow(d, 1./tmTop->mongam));
244          }
245          returnOK;
246   }
# Line 277 | Line 287 | int    wt;
287                  if (newhist == NULL)
288                          returnErr(TM_E_NOMEM);
289                  if (oldlen) {                   /* copy and free old */
290 <                        for (i = oldlen, j = i+oldorig-horig; i--; )
291 <                                newhist[--j] = tmTop->histo[i];
292 <                        free((char *)tmTop->histo);
290 >                        for (i = oldlen, j = i+oldorig-horig; i; )
291 >                                newhist[--j] = tmTop->histo[--i];
292 >                        free((MEM_PTR)tmTop->histo);
293                  }
294                  tmTop->histo = newhist;
295                  if (tmTop->lumap != NULL) {     /* invalid tone map */
296 <                        free((char *)tmTop->lumap);
296 >                        free((MEM_PTR)tmTop->lumap);
297                          tmTop->lumap = NULL;
298                  }
299          }
# Line 346 | Line 356 | double Ldmax;
356          i = (tmTop->brmin-MINBRT)/HISTEP;
357          brt0 = MINBRT + HISTEP/2 + i*HISTEP;
358          histlen = (tmTop->brmax-MINBRT)/HISTEP + 1 - i;
349                                        /* allocate temporary tables */
350        histo = (int *)malloc(histlen*sizeof(int));
351        cumf = (float *)malloc((histlen+1)*sizeof(float));
352        if (histo == NULL | cumf == NULL)
353                returnErr(TM_E_NOMEM);
359                                          /* histogram total and mean */
360          histot = 0; sum = 0;
361          j = brt0 + histlen*HISTEP;
362          for (i = histlen; i--; ) {
363 <                histot += (histo[i] = tmTop->histo[i]);
364 <                sum += (j -= HISTEP) * histo[i];
363 >                histot += tmTop->histo[i];
364 >                sum += (j -= HISTEP) * tmTop->histo[i];
365          }
366          threshold = histot*.025 + .5;
367          if (threshold < 4)
368                  returnErr(TM_E_TMFAIL);
369          Lwavg = tmLuminance( (double)sum / histot );
370 <        do {                            /* iterate to solution */
371 <                sum = 0;                /* compute cumulative probability */
372 <                for (i = 0; i < histlen; i++) {
373 <                        cumf[i] = (double)sum/histot;
374 <                        sum += histo[i];
375 <                }
376 <                cumf[i] = 1.;
377 <                Tr = histot * (double)(tmTop->brmax - tmTop->brmin) /
370 >        if (!(tmTop->flags & TM_F_LINEAR)) {    /* clamp histogram */
371 >                histo = (int *)malloc(histlen*sizeof(int));
372 >                cumf = (float *)malloc((histlen+1)*sizeof(float));
373 >                if (histo == NULL | cumf == NULL)
374 >                        returnErr(TM_E_NOMEM);
375 >                for (i = histlen; i--; )        /* make malleable copy */
376 >                        histo[i] = tmTop->histo[i];
377 >                do {                            /* iterate to solution */
378 >                        sum = 0;                /* cumulative probability */
379 >                        for (i = 0; i < histlen; i++) {
380 >                                cumf[i] = (double)sum/histot;
381 >                                sum += histo[i];
382 >                        }
383 >                        cumf[i] = 1.;
384 >                        Tr = histot * (double)(tmTop->brmax - tmTop->brmin) /
385                                  ((double)histlen*TM_BRTSCALE) / logLddyn;
386 <                ceiling = Tr + 1.;
387 <                trimmings = 0;                  /* clip to envelope */
388 <                for (i = histlen; i--; ) {
389 <                        if (tmTop->flags & TM_F_HCONTR) {
390 <                                Lw = tmLuminance(brt0 + i*HISTEP);
391 <                                Ld = Ldmin * exp( logLddyn *
386 >                        ceiling = Tr + 1.;
387 >                        trimmings = 0;                  /* clip to envelope */
388 >                        for (i = histlen; i--; ) {
389 >                                if (tmTop->flags & TM_F_HCONTR) {
390 >                                        Lw = tmLuminance(brt0 + i*HISTEP);
391 >                                        Ld = Ldmin * exp( logLddyn *
392                                                  .5*(cumf[i]+cumf[i+1]) );
393 <                                ceiling = Tr * (htcontrs(Ld) * Lw) /
393 >                                        ceiling = Tr * (htcontrs(Ld) * Lw) /
394                                                  (htcontrs(Lw) * Ld) + 1.;
395 +                                }
396 +                                if (histo[i] > ceiling) {
397 +                                        trimmings += histo[i] - ceiling;
398 +                                        histo[i] = ceiling;
399 +                                }
400                          }
401 <                        if (histo[i] > ceiling) {
402 <                                trimmings += histo[i] - ceiling;
403 <                                histo[i] = ceiling;
404 <                        }
405 <                }
389 <        } while ((histot -= trimmings) > threshold && trimmings > threshold);
390 <
391 <        if (tmTop->lumap == NULL) {             /* allocate luminance map */
401 >                } while ((histot -= trimmings) > threshold &&
402 >                                                trimmings > threshold);
403 >        }
404 >                                                /* allocate luminance map */
405 >        if (tmTop->lumap == NULL) {
406                  tmTop->lumap = (unsigned short *)malloc(
407                          (tmTop->brmax-tmTop->brmin+1)*sizeof(unsigned short) );
408                  if (tmTop->lumap == NULL)
# Line 415 | Line 429 | double Ldmax;
429                          tmTop->lumap[i] = 256.*pow(d, 1./gamval);
430                  }
431          }
432 <        free((char *)histo);
433 <        free((char *)cumf);
432 >        if (!(tmTop->flags & TM_F_LINEAR)) {
433 >                free((MEM_PTR)histo);
434 >                free((MEM_PTR)cumf);
435 >        }
436          returnOK;
437   }
438  
# Line 429 | Line 445 | register BYTE  *cs;
445   int     len;
446   {
447          static char     funcName[] = "tmMapPixels";
448 <        int     rdiv, gdiv, bdiv;
433 <        register int    li, pv;
448 >        register int4   li, pv;
449  
450          if (tmTop == NULL || tmTop->lumap == NULL)
451                  returnErr(TM_E_TMINVAL);
452          if (ps == NULL | ls == NULL | len <= 0)
453                  returnErr(TM_E_ILLEGAL);
439        rdiv = tmTop->gamb[((int4)TM_GAMTSZ*tmTop->clfb[RED])>>8];
440        gdiv = tmTop->gamb[((int4)TM_GAMTSZ*tmTop->clfb[GRN])>>8];
441        bdiv = tmTop->gamb[((int4)TM_GAMTSZ*tmTop->clfb[BLU])>>8];
454          while (len--) {
455                  if ((li = *ls++) < tmTop->brmin)
456                          li = tmTop->brmin;
# Line 448 | Line 460 | int    len;
460                  if (cs == TM_NOCHROM)
461                          *ps++ = li>255 ? 255 : li;
462                  else {
463 <                        pv = *cs++ * li / rdiv;
463 >                        pv = *cs++ * li / tmTop->cdiv[RED];
464                          *ps++ = pv>255 ? 255 : pv;
465 <                        pv = *cs++ * li / gdiv;
465 >                        pv = *cs++ * li / tmTop->cdiv[GRN];
466                          *ps++ = pv>255 ? 255 : pv;
467 <                        pv = *cs++ * li / bdiv;
467 >                        pv = *cs++ * li / tmTop->cdiv[BLU];
468                          *ps++ = pv>255 ? 255 : pv;
469                  }
470          }
# Line 494 | Line 506 | register struct tmStruct       *tms;
506   }
507  
508  
509 + struct tmStruct *
510 + tmDup()                         /* duplicate top tone mapping */
511 + {
512 +        int     len;
513 +        register int    i;
514 +        register struct tmStruct        *tmnew;
515 +
516 +        if (tmTop == NULL)              /* anything to duplicate? */
517 +                return(NULL);
518 +        tmnew = (struct tmStruct *)malloc(sizeof(struct tmStruct));
519 +        if (tmnew == NULL)
520 +                return(NULL);
521 +        *tmnew = *tmTop;                /* copy everything */
522 +        if (tmnew->histo != NULL) {     /* duplicate histogram */
523 +                len = (tmnew->brmax-MINBRT)/HISTEP + 1 -
524 +                                (tmnew->brmin-MINBRT)/HISTEP;
525 +                tmnew->histo = (int *)malloc(len*sizeof(int));
526 +                if (tmnew->histo != NULL)
527 +                        for (i = len; i--; )
528 +                                tmnew->histo[i] = tmTop->histo[i];
529 +        }
530 +        if (tmnew->lumap != NULL) {     /* duplicate luminance mapping */
531 +                len = tmnew->brmax-tmnew->brmin+1;
532 +                tmnew->lumap = (unsigned short *)malloc(
533 +                                                len*sizeof(unsigned short) );
534 +                if (tmnew->lumap != NULL)
535 +                        for (i = len; i--; )
536 +                                tmnew->lumap[i] = tmTop->lumap[i];
537 +        }
538 +                                        /* clear package data */
539 +        for (i = tmNumPkgs; i--; )
540 +                tmnew->pd[i] = NULL;
541 +        tmnew->tmprev = tmTop;          /* make copy current */
542 +        return(tmTop = tmnew);
543 + }
544 +
545 +
546   int
547   tmPush(tms)                     /* push tone mapping on top of stack */
548   register struct tmStruct        *tms;
549   {
550          static char     funcName[] = "tmPush";
551                                          /* check validity */
552 <        if (tms == NULL || !(tms->flags & TM_F_INITED))
552 >        if (tms == NULL)
553                  returnErr(TM_E_ILLEGAL);
554          if (tms == tmTop)               /* check necessity */
555                  returnOK;
# Line 517 | Line 566 | void
566   tmDone(tms)                     /* done with tone mapping -- destroy it */
567   register struct tmStruct        *tms;
568   {
569 +        register int    i;
570                                          /* NULL arg. is equiv. to tmTop */
571          if (tms == NULL && (tms = tmTop) == NULL)
572                  return;
# Line 524 | Line 574 | register struct tmStruct       *tms;
574          (void)tmPull(tms);
575                                          /* free tables */
576          if (tms->histo != NULL)
577 <                free((char *)tms->histo);
577 >                free((MEM_PTR)tms->histo);
578          if (tms->lumap != NULL)
579 <                free((char *)tms->lumap);
580 <        tms->flags = 0;
581 <        free((char *)tms);              /* free basic structure */
579 >                free((MEM_PTR)tms->lumap);
580 >                                        /* free private data */
581 >        for (i = tmNumPkgs; i--; )
582 >                if (tms->pd[i] != NULL)
583 >                        (*tmPkg[i]->Free)(tms->pd[i]);
584 >        free((MEM_PTR)tms);             /* free basic structure */
585   }

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines