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.4 by greg, Fri Apr 18 13:59:43 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 +
26   int
27   tmErrorReturn(func, err)                /* error return (with message) */
28   char    *func;
29   int     err;
30   {
31 <        if (tmTop != NULL && tmTop->flags & TM_F_NOERRS)
31 >        if (tmTop != NULL && tmTop->flags & TM_F_NOSTDERR)
32                  return(err);
33          fputs(func, stderr);
34          fputs(": ", stderr);
# Line 62 | Line 66 | double gamval;
66                  tmnew->clf[GRN] = cmat[1][1];
67                  tmnew->clf[BLU] = cmat[1][2];
68          }
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;
69                                                  /* set gamma value */
70          if (gamval < MINGAM)
71                  tmnew->mongam = DEFGAM;
72          else
73                  tmnew->mongam = gamval;
74 <        for (i = TM_GAMTSZ; i--; )
75 <                tmnew->gamb[i] = 256.*pow((i+.5)/TM_GAMTSZ, 1./tmnew->mongam);
74 >                                                /* set color divisors */
75 >        for (i = 0; i < 3; i++)
76 >                tmnew->cdiv[i] = 256.*pow(tmnew->clf[i], 1./tmnew->mongam);
77 >
78                                                  /* set input transform */
79          tmnew->inppri = tmnew->monpri;
80          tmnew->cmat[0][0] = tmnew->cmat[1][1] = tmnew->cmat[2][2] =
81                          tmnew->inpsf = WHTEFFICACY;
80        tmnew->inpsfb = TM_BRTSCALE*log(tmnew->inpsf) + .5;
82          tmnew->cmat[0][1] = tmnew->cmat[0][2] = tmnew->cmat[1][0] =
83          tmnew->cmat[1][2] = tmnew->cmat[2][0] = tmnew->cmat[2][1] = 0.;
83        tmnew->flags &= ~TM_F_NEEDMAT;
84          tmnew->brmin = tmnew->brmax = 0;
85          tmnew->histo = NULL;
86          tmnew->lumap = NULL;
87 <        tmnew->tmprev = NULL;
88 <
89 <        tmnew->flags |= TM_F_INITED;
90 <                                                /* make it current */
87 >                                                /* zero private data */
88 >        for (i = TM_MAXPKG; i--; )
89 >                tmnew->pd[i] = NULL;
90 >                                                /* make tmnew current */
91          tmnew->tmprev = tmTop;
92          return(tmTop = tmnew);
93   }
# Line 110 | Line 110 | double sf;
110                  returnOK;
111          tmTop->inppri = pri;                    /* let's set it */
112          tmTop->inpsf = sf;
113        tmTop->inpsfb = TM_BRTSCALE*log(sf) + (sf>=1. ? .5 : -.5);
113  
114          if (tmTop->flags & TM_F_BW) {           /* color doesn't matter */
115                  tmTop->monpri = tmTop->inppri;          /* eliminate xform */
116                  if (tmTop->inppri == TM_XYZPRIM) {
117                          tmTop->clf[CIEX] = tmTop->clf[CIEZ] = 0.;
118                          tmTop->clf[CIEY] = 1.;
120                        tmTop->clfb[CIEX] = tmTop->clfb[CIEZ] = 0;
121                        tmTop->clfb[CIEY] = 255;
119                  } else {
120                          comprgb2xyzmat(tmTop->cmat, tmTop->monpri);
121                          tmTop->clf[RED] = tmTop->cmat[1][0];
# Line 142 | Line 139 | double sf;
139          for (i = 0; i < 3; i++)
140                  for (j = 0; j < 3; j++)
141                          tmTop->cmat[i][j] *= tmTop->inpsf;
142 <        if (tmTop->inppri != tmTop->monpri)
143 <                tmTop->flags |= TM_F_NEEDMAT;
144 <        else
145 <                tmTop->flags &= ~TM_F_NEEDMAT;
142 >                                                /* set color divisors */
143 >        for (i = 0; i < 3; i++)
144 >                if (tmTop->clf[i] > .001)
145 >                        tmTop->cdiv[i] =
146 >                                256.*pow(tmTop->clf[i], 1./tmTop->mongam);
147 >                else
148 >                        tmTop->cdiv[i] = 1;
149 >                                                /* notify packages */
150 >        for (i = tmNumPkgs; i--; )
151 >                if (tmTop->pd[i] != NULL && tmPkg[i]->NewSpace != NULL)
152 >                        (*tmPkg[i]->NewSpace)(tmTop);
153          returnOK;
154   }
155  
# Line 155 | Line 159 | tmClearHisto()                 /* clear current histogram */
159   {
160          if (tmTop == NULL || tmTop->histo == NULL)
161                  return;
162 <        free((char *)tmTop->histo);
162 >        free((MEM_PTR)tmTop->histo);
163          tmTop->histo = NULL;
164   }
165  
# Line 168 | Line 172 | COLOR  *scan;
172   int     len;
173   {
174          static char     funcName[] = "tmCvColors";
175 +        static COLOR    csmall = {1e-6, 1e-6, 1e-6};
176          COLOR   cmon;
177          double  lum, slum;
178          register double d;
# Line 178 | Line 183 | int    len;
183          if (ls == NULL | scan == NULL | len <= 0)
184                  returnErr(TM_E_ILLEGAL);
185          for (i = len; i--; ) {
186 <                if (tmTop->flags & TM_F_NEEDMAT)        /* get monitor RGB */
186 >                if (tmNeedMatrix(tmTop))                /* get monitor RGB */
187                          colortrans(cmon, tmTop->cmat, scan[i]);
188                  else {
189                          cmon[RED] = tmTop->inpsf*scan[i][RED];
# Line 190 | Line 195 | int    len;
195                          tmTop->clf[GRN]*cmon[GRN] +
196                          tmTop->clf[BLU]*cmon[BLU] ;
197                                                          /* check range */
198 <                if (clipgamut(cmon, lum, CGAMUT_LOWER, cblack, cwhite))
198 >                if (clipgamut(cmon, lum, CGAMUT_LOWER, csmall, cwhite))
199                          lum =   tmTop->clf[RED]*cmon[RED] +
200                                  tmTop->clf[GRN]*cmon[GRN] +
201                                  tmTop->clf[BLU]*cmon[BLU] ;
# Line 223 | Line 228 | int    len;
228                          cmon[RED] = cmon[GRN] = cmon[BLU] = lum;
229                  }
230                  d = tmTop->clf[RED]*cmon[RED]/lum;
231 <                /* cs[3*i  ] = d>.999 ? 255 : 256.*pow(d, 1./tmTop->mongam); */
232 <                cs[3*i  ] = d>.999 ? 255 : tmTop->gamb[(int)(d*TM_GAMTSZ)];
231 >                cs[3*i  ] = d>=.999 ? 255 :
232 >                                (int)(256.*pow(d, 1./tmTop->mongam));
233                  d = tmTop->clf[GRN]*cmon[GRN]/lum;
234 <                /* cs[3*i+1] = d>.999 ? 255 : 256.*pow(d, 1./tmTop->mongam); */
235 <                cs[3*i+1] = d>.999 ? 255 : tmTop->gamb[(int)(d*TM_GAMTSZ)];
234 >                cs[3*i+1] = d>=.999 ? 255 :
235 >                                (int)(256.*pow(d, 1./tmTop->mongam));
236                  d = tmTop->clf[BLU]*cmon[BLU]/lum;
237 <                /* cs[3*i+2] = d>.999 ? 255 : 256.*pow(d, 1./tmTop->mongam); */
238 <                cs[3*i+2] = d>.999 ? 255 : tmTop->gamb[(int)(d*TM_GAMTSZ)];
237 >                cs[3*i+2] = d>=.999 ? 255 :
238 >                                (int)(256.*pow(d, 1./tmTop->mongam));
239          }
240          returnOK;
241   }
# Line 277 | Line 282 | int    wt;
282                  if (newhist == NULL)
283                          returnErr(TM_E_NOMEM);
284                  if (oldlen) {                   /* copy and free old */
285 <                        for (i = oldlen, j = i+oldorig-horig; i--; )
286 <                                newhist[--j] = tmTop->histo[i];
287 <                        free((char *)tmTop->histo);
285 >                        for (i = oldlen, j = i+oldorig-horig; i; )
286 >                                newhist[--j] = tmTop->histo[--i];
287 >                        free((MEM_PTR)tmTop->histo);
288                  }
289                  tmTop->histo = newhist;
290                  if (tmTop->lumap != NULL) {     /* invalid tone map */
291 <                        free((char *)tmTop->lumap);
291 >                        free((MEM_PTR)tmTop->lumap);
292                          tmTop->lumap = NULL;
293                  }
294          }
# Line 346 | Line 351 | double Ldmax;
351          i = (tmTop->brmin-MINBRT)/HISTEP;
352          brt0 = MINBRT + HISTEP/2 + i*HISTEP;
353          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);
354                                          /* histogram total and mean */
355          histot = 0; sum = 0;
356          j = brt0 + histlen*HISTEP;
357          for (i = histlen; i--; ) {
358 <                histot += (histo[i] = tmTop->histo[i]);
359 <                sum += (j -= HISTEP) * histo[i];
358 >                histot += tmTop->histo[i];
359 >                sum += (j -= HISTEP) * tmTop->histo[i];
360          }
361          threshold = histot*.025 + .5;
362          if (threshold < 4)
363                  returnErr(TM_E_TMFAIL);
364          Lwavg = tmLuminance( (double)sum / histot );
365 <        do {                            /* iterate to solution */
366 <                sum = 0;                /* compute cumulative probability */
367 <                for (i = 0; i < histlen; i++) {
368 <                        cumf[i] = (double)sum/histot;
369 <                        sum += histo[i];
370 <                }
371 <                cumf[i] = 1.;
372 <                Tr = histot * (double)(tmTop->brmax - tmTop->brmin) /
365 >        if (!(tmTop->flags & TM_F_LINEAR)) {    /* clamp histogram */
366 >                histo = (int *)malloc(histlen*sizeof(int));
367 >                cumf = (float *)malloc((histlen+1)*sizeof(float));
368 >                if (histo == NULL | cumf == NULL)
369 >                        returnErr(TM_E_NOMEM);
370 >                for (i = histlen; i--; )        /* make malleable copy */
371 >                        histo[i] = tmTop->histo[i];
372 >                do {                            /* iterate to solution */
373 >                        sum = 0;                /* cumulative probability */
374 >                        for (i = 0; i < histlen; i++) {
375 >                                cumf[i] = (double)sum/histot;
376 >                                sum += histo[i];
377 >                        }
378 >                        cumf[i] = 1.;
379 >                        Tr = histot * (double)(tmTop->brmax - tmTop->brmin) /
380                                  ((double)histlen*TM_BRTSCALE) / logLddyn;
381 <                ceiling = Tr + 1.;
382 <                trimmings = 0;                  /* clip to envelope */
383 <                for (i = histlen; i--; ) {
384 <                        if (tmTop->flags & TM_F_HCONTR) {
385 <                                Lw = tmLuminance(brt0 + i*HISTEP);
386 <                                Ld = Ldmin * exp( logLddyn *
381 >                        ceiling = Tr + 1.;
382 >                        trimmings = 0;                  /* clip to envelope */
383 >                        for (i = histlen; i--; ) {
384 >                                if (tmTop->flags & TM_F_HCONTR) {
385 >                                        Lw = tmLuminance(brt0 + i*HISTEP);
386 >                                        Ld = Ldmin * exp( logLddyn *
387                                                  .5*(cumf[i]+cumf[i+1]) );
388 <                                ceiling = Tr * (htcontrs(Ld) * Lw) /
388 >                                        ceiling = Tr * (htcontrs(Ld) * Lw) /
389                                                  (htcontrs(Lw) * Ld) + 1.;
390 +                                }
391 +                                if (histo[i] > ceiling) {
392 +                                        trimmings += histo[i] - ceiling;
393 +                                        histo[i] = ceiling;
394 +                                }
395                          }
396 <                        if (histo[i] > ceiling) {
397 <                                trimmings += histo[i] - ceiling;
398 <                                histo[i] = ceiling;
399 <                        }
400 <                }
389 <        } while ((histot -= trimmings) > threshold && trimmings > threshold);
390 <
391 <        if (tmTop->lumap == NULL) {             /* allocate luminance map */
396 >                } while ((histot -= trimmings) > threshold &&
397 >                                                trimmings > threshold);
398 >        }
399 >                                                /* allocate luminance map */
400 >        if (tmTop->lumap == NULL) {
401                  tmTop->lumap = (unsigned short *)malloc(
402                          (tmTop->brmax-tmTop->brmin+1)*sizeof(unsigned short) );
403                  if (tmTop->lumap == NULL)
# Line 415 | Line 424 | double Ldmax;
424                          tmTop->lumap[i] = 256.*pow(d, 1./gamval);
425                  }
426          }
427 <        free((char *)histo);
428 <        free((char *)cumf);
427 >        if (!(tmTop->flags & TM_F_LINEAR)) {
428 >                free((MEM_PTR)histo);
429 >                free((MEM_PTR)cumf);
430 >        }
431          returnOK;
432   }
433  
# Line 429 | Line 440 | register BYTE  *cs;
440   int     len;
441   {
442          static char     funcName[] = "tmMapPixels";
443 <        int     rdiv, gdiv, bdiv;
433 <        register int    li, pv;
443 >        register int4   li, pv;
444  
445          if (tmTop == NULL || tmTop->lumap == NULL)
446                  returnErr(TM_E_TMINVAL);
447          if (ps == NULL | ls == NULL | len <= 0)
448                  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];
449          while (len--) {
450                  if ((li = *ls++) < tmTop->brmin)
451                          li = tmTop->brmin;
# Line 448 | Line 455 | int    len;
455                  if (cs == TM_NOCHROM)
456                          *ps++ = li>255 ? 255 : li;
457                  else {
458 <                        pv = *cs++ * li / rdiv;
458 >                        pv = *cs++ * li / tmTop->cdiv[RED];
459                          *ps++ = pv>255 ? 255 : pv;
460 <                        pv = *cs++ * li / gdiv;
460 >                        pv = *cs++ * li / tmTop->cdiv[GRN];
461                          *ps++ = pv>255 ? 255 : pv;
462 <                        pv = *cs++ * li / bdiv;
462 >                        pv = *cs++ * li / tmTop->cdiv[BLU];
463                          *ps++ = pv>255 ? 255 : pv;
464                  }
465          }
# Line 494 | Line 501 | register struct tmStruct       *tms;
501   }
502  
503  
504 + struct tmStruct *
505 + tmDup()                         /* duplicate top tone mapping */
506 + {
507 +        int     len;
508 +        register int    i;
509 +        register struct tmStruct        *tmnew;
510 +
511 +        if (tmTop == NULL)              /* anything to duplicate? */
512 +                return(NULL);
513 +        tmnew = (struct tmStruct *)malloc(sizeof(struct tmStruct));
514 +        if (tmnew == NULL)
515 +                return(NULL);
516 +        *tmnew = *tmTop;                /* copy everything */
517 +        if (tmnew->histo != NULL) {     /* duplicate histogram */
518 +                len = (tmnew->brmax-MINBRT)/HISTEP + 1 -
519 +                                (tmnew->brmin-MINBRT)/HISTEP;
520 +                tmnew->histo = (int *)malloc(len*sizeof(int));
521 +                if (tmnew->histo != NULL)
522 +                        for (i = len; i--; )
523 +                                tmnew->histo[i] = tmTop->histo[i];
524 +        }
525 +        if (tmnew->lumap != NULL) {     /* duplicate luminance mapping */
526 +                len = tmnew->brmax-tmnew->brmin+1;
527 +                tmnew->lumap = (unsigned short *)malloc(
528 +                                                len*sizeof(unsigned short) );
529 +                if (tmnew->lumap != NULL)
530 +                        for (i = len; i--; )
531 +                                tmnew->lumap[i] = tmTop->lumap[i];
532 +        }
533 +                                        /* clear package data */
534 +        for (i = tmNumPkgs; i--; )
535 +                tmnew->pd[i] = NULL;
536 +        tmnew->tmprev = tmTop;          /* make copy current */
537 +        return(tmTop = tmnew);
538 + }
539 +
540 +
541   int
542   tmPush(tms)                     /* push tone mapping on top of stack */
543   register struct tmStruct        *tms;
544   {
545          static char     funcName[] = "tmPush";
546                                          /* check validity */
547 <        if (tms == NULL || !(tms->flags & TM_F_INITED))
547 >        if (tms == NULL)
548                  returnErr(TM_E_ILLEGAL);
549          if (tms == tmTop)               /* check necessity */
550                  returnOK;
# Line 517 | Line 561 | void
561   tmDone(tms)                     /* done with tone mapping -- destroy it */
562   register struct tmStruct        *tms;
563   {
564 +        register int    i;
565                                          /* NULL arg. is equiv. to tmTop */
566          if (tms == NULL && (tms = tmTop) == NULL)
567                  return;
# Line 524 | Line 569 | register struct tmStruct       *tms;
569          (void)tmPull(tms);
570                                          /* free tables */
571          if (tms->histo != NULL)
572 <                free((char *)tms->histo);
572 >                free((MEM_PTR)tms->histo);
573          if (tms->lumap != NULL)
574 <                free((char *)tms->lumap);
575 <        tms->flags = 0;
576 <        free((char *)tms);              /* free basic structure */
574 >                free((MEM_PTR)tms->lumap);
575 >                                        /* free private data */
576 >        for (i = tmNumPkgs; i--; )
577 >                if (tms->pd[i] != NULL)
578 >                        (*tmPkg[i]->Free)(tms->pd[i]);
579 >        free((MEM_PTR)tms);             /* free basic structure */
580   }

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines