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.3 by greg, Wed Apr 16 20:28:03 1997 UTC vs.
Revision 3.15 by greg, Thu Jul 22 17:48:52 2004 UTC

# Line 1 | Line 1
1 /* Copyright (c) 1997 Regents of the University of California */
2
1   #ifndef lint
2 < static char SCCSid[] = "$SunId$ LBL";
2 > static const char       RCSid[] = "$Id$";
3   #endif
6
4   /*
5   * Tone mapping functions.
6   * See tonemap.h for detailed function descriptions.
7 + * Added von Kries white-balance calculations 10/01 (GW).
8 + *
9 + * Externals declared in tonemap.h
10   */
11  
12 + #include "copyright.h"
13 +
14   #include        <stdio.h>
15   #include        <math.h>
16   #include        "tmprivat.h"
# Line 18 | Line 20 | static char SCCSid[] = "$SunId$ LBL";
20  
21   struct tmStruct *tmTop = NULL;          /* current tone mapping stack */
22  
23 +                                        /* our list of conversion packages */
24 + struct tmPackage        *tmPkg[TM_MAXPKG];
25 + int     tmNumPkgs = 0;                  /* number of registered packages */
26  
27 < int
28 < tmErrorReturn(func, err)                /* error return (with message) */
24 < char    *func;
25 < int     err;
26 < {
27 <        if (tmTop != NULL && tmTop->flags & TM_F_NOSTDERR)
28 <                return(err);
29 <        fputs(func, stderr);
30 <        fputs(": ", stderr);
31 <        fputs(tmErrorMessage[err], stderr);
32 <        fputs("!\n", stderr);
33 <        return(err);
34 < }
27 > int     tmLastError;                    /* last error incurred by library */
28 > char    *tmLastFunction;                /* error-generating function name */
29  
30  
31   struct tmStruct *
# Line 40 | Line 34 | int    flags;
34   RGBPRIMP        monpri;
35   double  gamval;
36   {
43        static char     funcName[] = "tmInit";
37          COLORMAT        cmat;
38          register struct tmStruct        *tmnew;
39          register int    i;
# Line 50 | Line 43 | double gamval;
43                  return(NULL);
44  
45          tmnew->flags = flags & ~TM_F_UNIMPL;
46 +        if (tmnew->flags & TM_F_BW)
47 +                tmnew->flags &= ~TM_F_MESOPIC;
48                                                  /* set monitor transform */
49          if (monpri == NULL || monpri == stdprims || tmnew->flags & TM_F_BW) {
50                  tmnew->monpri = stdprims;
# Line 57 | Line 52 | double gamval;
52                  tmnew->clf[GRN] = rgb2xyzmat[1][1];
53                  tmnew->clf[BLU] = rgb2xyzmat[1][2];
54          } else {
55 <                comprgb2xyzmat(cmat, tmnew->monpri=monpri);
55 >                comprgb2xyzWBmat(cmat, tmnew->monpri=monpri);
56                  tmnew->clf[RED] = cmat[1][0];
57                  tmnew->clf[GRN] = cmat[1][1];
58                  tmnew->clf[BLU] = cmat[1][2];
59          }
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;
60                                                  /* set gamma value */
61          if (gamval < MINGAM)
62                  tmnew->mongam = DEFGAM;
63          else
64                  tmnew->mongam = gamval;
65 <        for (i = TM_GAMTSZ; i--; )
66 <                tmnew->gamb[i] = 256.*pow((i+.5)/TM_GAMTSZ, 1./tmnew->mongam);
65 >                                                /* set color divisors */
66 >        for (i = 0; i < 3; i++)
67 >                tmnew->cdiv[i] = 256.*pow(tmnew->clf[i], 1./tmnew->mongam);
68 >
69                                                  /* set input transform */
70          tmnew->inppri = tmnew->monpri;
71          tmnew->cmat[0][0] = tmnew->cmat[1][1] = tmnew->cmat[2][2] =
72                          tmnew->inpsf = WHTEFFICACY;
80        tmnew->inpsfb = TM_BRTSCALE*log(tmnew->inpsf) + .5;
73          tmnew->cmat[0][1] = tmnew->cmat[0][2] = tmnew->cmat[1][0] =
74          tmnew->cmat[1][2] = tmnew->cmat[2][0] = tmnew->cmat[2][1] = 0.;
75 <        tmnew->flags &= ~TM_F_NEEDMAT;
84 <        tmnew->brmin = tmnew->brmax = 0;
75 >        tmnew->hbrmin = 10; tmnew->hbrmax = -10;
76          tmnew->histo = NULL;
77 +        tmnew->mbrmin = 10; tmnew->mbrmax = -10;
78          tmnew->lumap = NULL;
79 <        tmnew->tmprev = NULL;
80 <
81 <        tmnew->flags |= TM_F_INITED;
82 <                                                /* make it current */
79 >                                                /* zero private data */
80 >        for (i = TM_MAXPKG; i--; )
81 >                tmnew->pd[i] = NULL;
82 >                                                /* make tmnew current */
83          tmnew->tmprev = tmTop;
84          return(tmTop = tmnew);
85   }
# Line 110 | Line 102 | double sf;
102                  returnOK;
103          tmTop->inppri = pri;                    /* let's set it */
104          tmTop->inpsf = sf;
113        tmTop->inpsfb = TM_BRTSCALE*log(sf) + (sf>=1. ? .5 : -.5);
105  
106          if (tmTop->flags & TM_F_BW) {           /* color doesn't matter */
107                  tmTop->monpri = tmTop->inppri;          /* eliminate xform */
108                  if (tmTop->inppri == TM_XYZPRIM) {
109                          tmTop->clf[CIEX] = tmTop->clf[CIEZ] = 0.;
110                          tmTop->clf[CIEY] = 1.;
120                        tmTop->clfb[CIEX] = tmTop->clfb[CIEZ] = 0;
121                        tmTop->clfb[CIEY] = 255;
111                  } else {
112 <                        comprgb2xyzmat(tmTop->cmat, tmTop->monpri);
112 >                        comprgb2xyzWBmat(tmTop->cmat, tmTop->monpri);
113                          tmTop->clf[RED] = tmTop->cmat[1][0];
114                          tmTop->clf[GRN] = tmTop->cmat[1][1];
115                          tmTop->clf[BLU] = tmTop->cmat[1][2];
# Line 131 | Line 120 | double sf;
120                  tmTop->cmat[1][2] = tmTop->cmat[2][0] = tmTop->cmat[2][1] = 0.;
121  
122          } else if (tmTop->inppri == TM_XYZPRIM) /* input is XYZ */
123 <                compxyz2rgbmat(tmTop->cmat, tmTop->monpri);
123 >                compxyz2rgbWBmat(tmTop->cmat, tmTop->monpri);
124  
125          else {                                  /* input is RGB */
126                  if (tmTop->inppri != tmTop->monpri &&
127                                  PRIMEQ(tmTop->inppri, tmTop->monpri))
128                          tmTop->inppri = tmTop->monpri;  /* no xform */
129 <                comprgb2rgbmat(tmTop->cmat, tmTop->inppri, tmTop->monpri);
129 >                comprgb2rgbWBmat(tmTop->cmat, tmTop->inppri, tmTop->monpri);
130          }
131          for (i = 0; i < 3; i++)
132                  for (j = 0; j < 3; j++)
133                          tmTop->cmat[i][j] *= tmTop->inpsf;
134 <        if (tmTop->inppri != tmTop->monpri)
135 <                tmTop->flags |= TM_F_NEEDMAT;
136 <        else
137 <                tmTop->flags &= ~TM_F_NEEDMAT;
134 >                                                /* set color divisors */
135 >        for (i = 0; i < 3; i++)
136 >                if (tmTop->clf[i] > .001)
137 >                        tmTop->cdiv[i] =
138 >                                256.*pow(tmTop->clf[i], 1./tmTop->mongam);
139 >                else
140 >                        tmTop->cdiv[i] = 1;
141 >                                                /* notify packages */
142 >        for (i = tmNumPkgs; i--; )
143 >                if (tmTop->pd[i] != NULL && tmPkg[i]->NewSpace != NULL)
144 >                        (*tmPkg[i]->NewSpace)(tmTop);
145          returnOK;
146   }
147  
# Line 155 | Line 151 | tmClearHisto()                 /* clear current histogram */
151   {
152          if (tmTop == NULL || tmTop->histo == NULL)
153                  return;
154 <        free((char *)tmTop->histo);
154 >        free((MEM_PTR)tmTop->histo);
155          tmTop->histo = NULL;
156   }
157  
# Line 168 | Line 164 | COLOR  *scan;
164   int     len;
165   {
166          static char     funcName[] = "tmCvColors";
167 +        static COLOR    csmall = {.5*MINLUM, .5*MINLUM, .5*MINLUM};
168          COLOR   cmon;
169          double  lum, slum;
170          register double d;
# Line 175 | Line 172 | int    len;
172  
173          if (tmTop == NULL)
174                  returnErr(TM_E_TMINVAL);
175 <        if (ls == NULL | scan == NULL | len <= 0)
175 >        if ((ls == NULL) | (scan == NULL) | (len < 0))
176                  returnErr(TM_E_ILLEGAL);
177          for (i = len; i--; ) {
178 <                if (tmTop->flags & TM_F_NEEDMAT)        /* get monitor RGB */
178 >                if (tmNeedMatrix(tmTop)) {              /* get monitor RGB */
179                          colortrans(cmon, tmTop->cmat, scan[i]);
180 <                else {
180 >                } else {
181                          cmon[RED] = tmTop->inpsf*scan[i][RED];
182                          cmon[GRN] = tmTop->inpsf*scan[i][GRN];
183                          cmon[BLU] = tmTop->inpsf*scan[i][BLU];
# Line 190 | Line 187 | int    len;
187                          tmTop->clf[GRN]*cmon[GRN] +
188                          tmTop->clf[BLU]*cmon[BLU] ;
189                                                          /* check range */
190 <                if (clipgamut(cmon, lum, CGAMUT_LOWER, cblack, cwhite))
190 >                if (clipgamut(cmon, lum, CGAMUT_LOWER, csmall, cwhite))
191                          lum =   tmTop->clf[RED]*cmon[RED] +
192                                  tmTop->clf[GRN]*cmon[GRN] +
193                                  tmTop->clf[BLU]*cmon[BLU] ;
# Line 223 | Line 220 | int    len;
220                          cmon[RED] = cmon[GRN] = cmon[BLU] = lum;
221                  }
222                  d = tmTop->clf[RED]*cmon[RED]/lum;
223 <                /* cs[3*i  ] = d>.999 ? 255 : 256.*pow(d, 1./tmTop->mongam); */
224 <                cs[3*i  ] = d>.999 ? 255 : tmTop->gamb[(int)(d*TM_GAMTSZ)];
223 >                cs[3*i  ] = d>=.999 ? 255 :
224 >                                (int)(256.*pow(d, 1./tmTop->mongam));
225                  d = tmTop->clf[GRN]*cmon[GRN]/lum;
226 <                /* cs[3*i+1] = d>.999 ? 255 : 256.*pow(d, 1./tmTop->mongam); */
227 <                cs[3*i+1] = d>.999 ? 255 : tmTop->gamb[(int)(d*TM_GAMTSZ)];
226 >                cs[3*i+1] = d>=.999 ? 255 :
227 >                                (int)(256.*pow(d, 1./tmTop->mongam));
228                  d = tmTop->clf[BLU]*cmon[BLU]/lum;
229 <                /* cs[3*i+2] = d>.999 ? 255 : 256.*pow(d, 1./tmTop->mongam); */
230 <                cs[3*i+2] = d>.999 ? 255 : tmTop->gamb[(int)(d*TM_GAMTSZ)];
229 >                cs[3*i+2] = d>=.999 ? 255 :
230 >                                (int)(256.*pow(d, 1./tmTop->mongam));
231          }
232          returnOK;
233   }
234  
235  
236   int
237 + tmCvGrays(ls, scan, len)                /* convert float gray values */
238 + TMbright        *ls;
239 + float   *scan;
240 + int     len;
241 + {
242 +        static char     funcName[] = "tmCvGrays";
243 +        register double d;
244 +        register int    i;
245 +
246 +        if (tmTop == NULL)
247 +                returnErr(TM_E_TMINVAL);
248 +        if ((ls == NULL) | (scan == NULL) | (len < 0))
249 +                returnErr(TM_E_ILLEGAL);
250 +        for (i = len; i--; )
251 +                if (scan[i] <= TM_NOLUM) {
252 +                        ls[i] = TM_NOBRT;               /* bogus value */
253 +                } else {
254 +                        d = TM_BRTSCALE*log(scan[i]);   /* encode it */
255 +                        ls[i] = d>0. ? (int)(d+.5) : (int)(d-.5);
256 +                }
257 +        returnOK;
258 + }
259 +
260 +
261 + int
262   tmAddHisto(ls, len, wt)                 /* add values to histogram */
263   register TMbright       *ls;
264   int     len;
265   int     wt;
266   {
267          static char     funcName[] = "tmAddHisto";
268 <        int     sum, oldorig, oldlen, horig, hlen;
268 >        int     oldorig=0, oldlen, horig, hlen;
269          register int    i, j;
270  
249        if (len <= 0)
250                returnErr(TM_E_ILLEGAL);
271          if (tmTop == NULL)
272                  returnErr(TM_E_TMINVAL);
273 +        if (len < 0)
274 +                returnErr(TM_E_ILLEGAL);
275 +        if (len == 0)
276 +                returnOK;
277                                                  /* first, grow limits */
278          if (tmTop->histo == NULL) {
279                  for (i = len; i-- && ls[i] < MINBRT; )
280                          ;
281                  if (i < 0)
282                          returnOK;
283 <                tmTop->brmin = tmTop->brmax = ls[i];
283 >                tmTop->hbrmin = tmTop->hbrmax = ls[i];
284                  oldlen = 0;
285          } else {
286 <                oldorig = (tmTop->brmin-MINBRT)/HISTEP;
287 <                oldlen = (tmTop->brmax-MINBRT)/HISTEP + 1 - oldorig;
286 >                oldorig = (tmTop->hbrmin-MINBRT)/HISTEP;
287 >                oldlen = (tmTop->hbrmax-MINBRT)/HISTEP + 1 - oldorig;
288          }
289          for (i = len; i--; ) {
290                  if ((j = ls[i]) < MINBRT)
291                          continue;
292 <                if (j < tmTop->brmin)
293 <                        tmTop->brmin = j;
294 <                else if (j > tmTop->brmax)
295 <                        tmTop->brmax = j;
292 >                if (j < tmTop->hbrmin)
293 >                        tmTop->hbrmin = j;
294 >                else if (j > tmTop->hbrmax)
295 >                        tmTop->hbrmax = j;
296          }
297 <        horig = (tmTop->brmin-MINBRT)/HISTEP;
298 <        hlen = (tmTop->brmax-MINBRT)/HISTEP + 1 - horig;
297 >        horig = (tmTop->hbrmin-MINBRT)/HISTEP;
298 >        hlen = (tmTop->hbrmax-MINBRT)/HISTEP + 1 - horig;
299          if (hlen > oldlen) {                    /* (re)allocate histogram */
300                  register int    *newhist = (int *)calloc(hlen, sizeof(int));
301                  if (newhist == NULL)
# Line 279 | Line 303 | int    wt;
303                  if (oldlen) {                   /* copy and free old */
304                          for (i = oldlen, j = i+oldorig-horig; i; )
305                                  newhist[--j] = tmTop->histo[--i];
306 <                        free((char *)tmTop->histo);
306 >                        free((MEM_PTR)tmTop->histo);
307                  }
308                  tmTop->histo = newhist;
285                if (tmTop->lumap != NULL) {     /* invalid tone map */
286                        free((char *)tmTop->lumap);
287                        tmTop->lumap = NULL;
288                }
309          }
310          if (wt == 0)
311                  returnOK;
# Line 318 | Line 338 | double La;
338   }
339  
340  
341 + static int
342 + tmNewMap()
343 + {
344 +        if (tmTop->lumap != NULL && (tmTop->mbrmax - tmTop->mbrmin) !=
345 +                                        (tmTop->hbrmax - tmTop->hbrmin)) {
346 +                free((MEM_PTR)tmTop->lumap);
347 +                tmTop->lumap = NULL;
348 +        }
349 +        tmTop->mbrmin = tmTop->hbrmin;
350 +        tmTop->mbrmax = tmTop->hbrmax;
351 +        if (tmTop->mbrmin > tmTop->mbrmax)
352 +                return 0;
353 +        if (tmTop->lumap == NULL)
354 +                tmTop->lumap = (unsigned short *)malloc(sizeof(unsigned short)*
355 +                                        (tmTop->mbrmax-tmTop->mbrmin+1));
356 +        return(tmTop->lumap != NULL);
357 + }
358 +
359 +
360   int
361 + tmFixedMapping(expmult, gamval)
362 + double  expmult;
363 + double  gamval;
364 + {
365 +        static char     funcName[] = "tmFixedMapping";
366 +        double          d;
367 +        register int    i;
368 +        
369 +        if (!tmNewMap())
370 +                returnErr(TM_E_NOMEM);
371 +        if (expmult <= .0)
372 +                expmult = 1.;
373 +        if (gamval < MINGAM)
374 +                gamval = tmTop->mongam;
375 +        d = log(expmult/tmTop->inpsf);
376 +        for (i = tmTop->mbrmax-tmTop->mbrmin+1; i--; )
377 +                tmTop->lumap[i] = 256. * exp(
378 +                        ( d + (tmTop->mbrmin+i)*(1./TM_BRTSCALE) )
379 +                        / gamval );
380 +        returnOK;
381 + }
382 +
383 +
384 + int
385   tmComputeMapping(gamval, Lddyn, Ldmax)
386   double  gamval;
387   double  Lddyn;
# Line 327 | Line 390 | double Ldmax;
390          static char     funcName[] = "tmComputeMapping";
391          int     *histo;
392          float   *cumf;
393 <        int     brt0, histlen, histot, threshold, ceiling, trimmings;
393 >        int     brt0, histlen, threshold, ceiling, trimmings;
394          double  logLddyn, Ldmin, Ldavg, Lwavg, Tr, Lw, Ld;
395 <        int4    sum;
395 >        int32   histot;
396 >        double  sum;
397          register double d;
398          register int    i, j;
399  
# Line 343 | Line 407 | double Ldmax;
407          Ldmin = Ldmax/Lddyn;
408          logLddyn = log(Lddyn);
409          Ldavg = sqrt(Ldmax*Ldmin);
410 <        i = (tmTop->brmin-MINBRT)/HISTEP;
410 >        i = (tmTop->hbrmin-MINBRT)/HISTEP;
411          brt0 = MINBRT + HISTEP/2 + i*HISTEP;
412 <        histlen = (tmTop->brmax-MINBRT)/HISTEP + 1 - i;
412 >        histlen = (tmTop->hbrmax-MINBRT)/HISTEP + 1 - i;
413                                          /* histogram total and mean */
414          histot = 0; sum = 0;
415          j = brt0 + histlen*HISTEP;
# Line 353 | Line 417 | double Ldmax;
417                  histot += tmTop->histo[i];
418                  sum += (j -= HISTEP) * tmTop->histo[i];
419          }
420 <        threshold = histot*.025 + .5;
420 >        threshold = histot*0.005 + .5;
421          if (threshold < 4)
422                  returnErr(TM_E_TMFAIL);
423          Lwavg = tmLuminance( (double)sum / histot );
424 <        if (!(tmTop->flags & TM_F_LINEAR)) {    /* clamp histogram */
425 <                histo = (int *)malloc(histlen*sizeof(int));
426 <                cumf = (float *)malloc((histlen+1)*sizeof(float));
427 <                if (histo == NULL | cumf == NULL)
428 <                        returnErr(TM_E_NOMEM);
429 <                for (i = histlen; i--; )        /* make malleable copy */
430 <                        histo[i] = tmTop->histo[i];
431 <                do {                            /* iterate to solution */
432 <                        sum = 0;                /* cumulative probability */
433 <                        for (i = 0; i < histlen; i++) {
434 <                                cumf[i] = (double)sum/histot;
435 <                                sum += histo[i];
424 >                                        /* allocate space for mapping */
425 >        if (!tmNewMap())
426 >                returnErr(TM_E_NOMEM);
427 >                                        /* use linear tone mapping? */
428 >        if (tmTop->flags & TM_F_LINEAR)
429 >                goto linearmap;
430 >                                        /* clamp histogram */
431 >        histo = (int *)malloc(histlen*sizeof(int));
432 >        cumf = (float *)malloc((histlen+2)*sizeof(float));
433 >        if ((histo == NULL) | (cumf == NULL))
434 >                returnErr(TM_E_NOMEM);
435 >        cumf[histlen+1] = 1.;           /* guard for assignment code */
436 >        for (i = histlen; i--; )        /* make malleable copy */
437 >                histo[i] = tmTop->histo[i];
438 >        do {                            /* iterate to solution */
439 >                sum = 0;                /* cumulative probability */
440 >                for (i = 0; i < histlen; i++) {
441 >                        cumf[i] = (double)sum/histot;
442 >                        sum += histo[i];
443 >                }
444 >                cumf[histlen] = 1.;
445 >                Tr = histot * (double)(tmTop->hbrmax - tmTop->hbrmin) /
446 >                        ((double)histlen*TM_BRTSCALE) / logLddyn;
447 >                ceiling = Tr + 1.;
448 >                trimmings = 0;          /* clip to envelope */
449 >                for (i = histlen; i--; ) {
450 >                        if (tmTop->flags & TM_F_HCONTR) {
451 >                                Lw = tmLuminance(brt0 + i*HISTEP);
452 >                                Ld = Ldmin * exp( logLddyn *
453 >                                        .5*(cumf[i]+cumf[i+1]) );
454 >                                ceiling = Tr * (htcontrs(Ld) * Lw) /
455 >                                        (htcontrs(Lw) * Ld) + 1.;
456                          }
457 <                        cumf[i] = 1.;
458 <                        Tr = histot * (double)(tmTop->brmax - tmTop->brmin) /
459 <                                ((double)histlen*TM_BRTSCALE) / logLddyn;
376 <                        ceiling = Tr + 1.;
377 <                        trimmings = 0;                  /* clip to envelope */
378 <                        for (i = histlen; i--; ) {
379 <                                if (tmTop->flags & TM_F_HCONTR) {
380 <                                        Lw = tmLuminance(brt0 + i*HISTEP);
381 <                                        Ld = Ldmin * exp( logLddyn *
382 <                                                .5*(cumf[i]+cumf[i+1]) );
383 <                                        ceiling = Tr * (htcontrs(Ld) * Lw) /
384 <                                                (htcontrs(Lw) * Ld) + 1.;
385 <                                }
386 <                                if (histo[i] > ceiling) {
387 <                                        trimmings += histo[i] - ceiling;
388 <                                        histo[i] = ceiling;
389 <                                }
457 >                        if (histo[i] > ceiling) {
458 >                                trimmings += histo[i] - ceiling;
459 >                                histo[i] = ceiling;
460                          }
391                } while ((histot -= trimmings) > threshold &&
392                                                trimmings > threshold);
393        }
394                                                /* allocate luminance map */
395        if (tmTop->lumap == NULL) {
396                tmTop->lumap = (unsigned short *)malloc(
397                        (tmTop->brmax-tmTop->brmin+1)*sizeof(unsigned short) );
398                if (tmTop->lumap == NULL)
399                        returnErr(TM_E_NOMEM);
400        }
401        if (tmTop->flags & TM_F_LINEAR || histot <= threshold) {
402                                                /* linear tone mapping */
403                if (tmTop->flags & TM_F_HCONTR)
404                        d = htcontrs(Ldavg) / htcontrs(Lwavg);
405                else
406                        d = Ldavg / Lwavg;
407                d = log(d/Ldmax);
408                for (i = tmTop->brmax-tmTop->brmin+1; i--; )
409                        tmTop->lumap[i] = 256. * exp(
410                                ( d + (tmTop->brmin+i)/(double)TM_BRTSCALE )
411                                / gamval );
412        } else {
413                                                /* histogram adjustment */
414                for (i = tmTop->brmax-tmTop->brmin+1; i--; ) {
415                        j = d = (double)i/(tmTop->brmax-tmTop->brmin)*histlen;
416                        d -= (double)j;
417                        Ld = Ldmin*exp(logLddyn*((1.-d)*cumf[j]+d*cumf[j+1]));
418                        d = (Ld - Ldmin)/(Ldmax - Ldmin);
419                        tmTop->lumap[i] = 256.*pow(d, 1./gamval);
461                  }
462 +                                        /* check if we're out of data */
463 +                if ((histot -= trimmings) <= threshold) {
464 +                        free((MEM_PTR)histo);
465 +                        free((MEM_PTR)cumf);
466 +                        goto linearmap;
467 +                }
468 +        } while (trimmings > threshold);
469 +                                        /* assign tone-mapping */
470 +        for (i = tmTop->mbrmax-tmTop->mbrmin+1; i--; ) {
471 +                j = d = (double)i/(tmTop->mbrmax-tmTop->mbrmin)*histlen;
472 +                d -= (double)j;
473 +                Ld = Ldmin*exp(logLddyn*((1.-d)*cumf[j]+d*cumf[j+1]));
474 +                d = (Ld - Ldmin)/(Ldmax - Ldmin);
475 +                tmTop->lumap[i] = 256.*pow(d, 1./gamval);
476          }
477 <        if (!(tmTop->flags & TM_F_LINEAR)) {
478 <                free((char *)histo);
424 <                free((char *)cumf);
425 <        }
477 >        free((MEM_PTR)histo);           /* clean up and return */
478 >        free((MEM_PTR)cumf);
479          returnOK;
480 + linearmap:                              /* linear tone-mapping */
481 +        if (tmTop->flags & TM_F_HCONTR)
482 +                d = htcontrs(Ldavg) / htcontrs(Lwavg);
483 +        else
484 +                d = Ldavg / Lwavg;
485 +        return(tmFixedMapping(tmTop->inpsf*d/Ldmax, gamval));
486   }
487  
488  
# Line 435 | Line 494 | register BYTE  *cs;
494   int     len;
495   {
496          static char     funcName[] = "tmMapPixels";
497 <        int     rdiv, gdiv, bdiv;
439 <        register int    li, pv;
497 >        register int32  li, pv;
498  
499          if (tmTop == NULL || tmTop->lumap == NULL)
500                  returnErr(TM_E_TMINVAL);
501 <        if (ps == NULL | ls == NULL | len <= 0)
501 >        if ((ps == NULL) | (ls == NULL) | (len < 0))
502                  returnErr(TM_E_ILLEGAL);
445        rdiv = tmTop->gamb[((int4)TM_GAMTSZ*tmTop->clfb[RED])>>8];
446        gdiv = tmTop->gamb[((int4)TM_GAMTSZ*tmTop->clfb[GRN])>>8];
447        bdiv = tmTop->gamb[((int4)TM_GAMTSZ*tmTop->clfb[BLU])>>8];
503          while (len--) {
504 <                if ((li = *ls++) < tmTop->brmin)
505 <                        li = tmTop->brmin;
506 <                else if (li > tmTop->brmax)
507 <                        li = tmTop->brmax;
508 <                li = tmTop->lumap[li - tmTop->brmin];
504 >                if ((li = *ls++) < tmTop->mbrmin) {
505 >                        li = 0;
506 >                } else {
507 >                        if (li > tmTop->mbrmax)
508 >                                li = tmTop->mbrmax;
509 >                        li = tmTop->lumap[li - tmTop->mbrmin];
510 >                }
511                  if (cs == TM_NOCHROM)
512                          *ps++ = li>255 ? 255 : li;
513                  else {
514 <                        pv = *cs++ * li / rdiv;
514 >                        pv = *cs++ * li / tmTop->cdiv[RED];
515                          *ps++ = pv>255 ? 255 : pv;
516 <                        pv = *cs++ * li / gdiv;
516 >                        pv = *cs++ * li / tmTop->cdiv[GRN];
517                          *ps++ = pv>255 ? 255 : pv;
518 <                        pv = *cs++ * li / bdiv;
518 >                        pv = *cs++ * li / tmTop->cdiv[BLU];
519                          *ps++ = pv>255 ? 255 : pv;
520                  }
521          }
# Line 483 | Line 540 | register struct tmStruct       *tms;
540   {
541          register struct tmStruct        *tms2;
542                                          /* special cases first */
543 <        if (tms == NULL | tmTop == NULL)
543 >        if ((tms == NULL) | (tmTop == NULL))
544                  return(0);
545          if (tms == tmTop) {
546                  tmTop = tms->tmprev;
# Line 514 | Line 571 | tmDup()                                /* duplicate top tone mapping */
571                  return(NULL);
572          *tmnew = *tmTop;                /* copy everything */
573          if (tmnew->histo != NULL) {     /* duplicate histogram */
574 <                len = (tmnew->brmax-MINBRT)/HISTEP + 1 -
575 <                                (tmnew->brmin-MINBRT)/HISTEP;
574 >                len = (tmnew->hbrmax-MINBRT)/HISTEP + 1 -
575 >                                (tmnew->hbrmin-MINBRT)/HISTEP;
576                  tmnew->histo = (int *)malloc(len*sizeof(int));
577                  if (tmnew->histo != NULL)
578                          for (i = len; i--; )
579                                  tmnew->histo[i] = tmTop->histo[i];
580          }
581          if (tmnew->lumap != NULL) {     /* duplicate luminance mapping */
582 <                len = tmnew->brmax-tmnew->brmin+1;
582 >                len = tmnew->mbrmax-tmnew->mbrmin+1;
583                  tmnew->lumap = (unsigned short *)malloc(
584                                                  len*sizeof(unsigned short) );
585                  if (tmnew->lumap != NULL)
586                          for (i = len; i--; )
587                                  tmnew->lumap[i] = tmTop->lumap[i];
588          }
589 +                                        /* clear package data */
590 +        for (i = tmNumPkgs; i--; )
591 +                tmnew->pd[i] = NULL;
592          tmnew->tmprev = tmTop;          /* make copy current */
593          return(tmTop = tmnew);
594   }
# Line 540 | Line 600 | register struct tmStruct       *tms;
600   {
601          static char     funcName[] = "tmPush";
602                                          /* check validity */
603 <        if (tms == NULL || !(tms->flags & TM_F_INITED))
603 >        if (tms == NULL)
604                  returnErr(TM_E_ILLEGAL);
605          if (tms == tmTop)               /* check necessity */
606                  returnOK;
# Line 557 | Line 617 | void
617   tmDone(tms)                     /* done with tone mapping -- destroy it */
618   register struct tmStruct        *tms;
619   {
620 +        register int    i;
621                                          /* NULL arg. is equiv. to tmTop */
622          if (tms == NULL && (tms = tmTop) == NULL)
623                  return;
# Line 564 | Line 625 | register struct tmStruct       *tms;
625          (void)tmPull(tms);
626                                          /* free tables */
627          if (tms->histo != NULL)
628 <                free((char *)tms->histo);
628 >                free((MEM_PTR)tms->histo);
629          if (tms->lumap != NULL)
630 <                free((char *)tms->lumap);
631 <        tms->flags = 0;
632 <        free((char *)tms);              /* free basic structure */
630 >                free((MEM_PTR)tms->lumap);
631 >                                        /* free private data */
632 >        for (i = tmNumPkgs; i--; )
633 >                if (tms->pd[i] != NULL)
634 >                        (*tmPkg[i]->Free)(tms->pd[i]);
635 >        free((MEM_PTR)tms);             /* free basic structure */
636 > }
637 >
638 > /******************** Shared but Private library routines *********************/
639 >
640 > BYTE    tmMesofact[BMESUPPER-BMESLOWER];
641 >
642 > void
643 > tmMkMesofact()                          /* build mesopic lookup factor table */
644 > {
645 >        register int    i;
646 >
647 >        if (tmMesofact[BMESUPPER-BMESLOWER-1])
648 >                return;
649 >
650 >        for (i = BMESLOWER; i < BMESUPPER; i++)
651 >                tmMesofact[i-BMESLOWER] = 256. *
652 >                                (tmLuminance(i) - LMESLOWER) /
653 >                                (LMESUPPER - LMESLOWER);
654 > }
655 >
656 >
657 > int
658 > tmErrorReturn(func, err)                /* error return (with message) */
659 > char    *func;
660 > int     err;
661 > {
662 >        tmLastFunction = func;
663 >        tmLastError = err;
664 >        if (tmTop != NULL && tmTop->flags & TM_F_NOSTDERR)
665 >                return(err);
666 >        fputs(func, stderr);
667 >        fputs(": ", stderr);
668 >        fputs(tmErrorMessage[err], stderr);
669 >        fputs("!\n", stderr);
670 >        return(err);
671   }

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines