ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/px/pcond3.c
Revision: 3.1
Committed: Thu Oct 3 16:52:50 1996 UTC (27 years, 7 months ago) by greg
Content type: text/plain
Branch: MAIN
Log Message:
Initial revision

File Contents

# User Rev Content
1 greg 3.1 /* Copyright (c) 1996 Regents of the University of California */
2    
3     #ifndef lint
4     static char SCCSid[] = "$SunId$ LBL";
5     #endif
6    
7     /*
8     * Routines for computing and applying brightness mapping.
9     */
10    
11     #include "pcond.h"
12    
13    
14     #define CVRATIO 0.025 /* fraction of pixels allowed > env. */
15    
16     #define BotMesopic 5.62e-3 /* top of scotopic range */
17     #define TopMesopic 5.62 /* bottom of photopic range */
18    
19     #define exp10(x) exp(2.302585093*(x))
20    
21     int modhist[HISTRES]; /* modified histogram */
22     float cumf[HISTRES+1]; /* cumulative distribution function */
23    
24    
25     mkcumf() /* make cumulative distribution function */
26     {
27     register int i;
28     register long sum;
29    
30     cumf[0] = 0.;
31     sum = modhist[0];
32     for (i = 1; i < HISTRES; i++) {
33     cumf[i] = (double)sum/histot;
34     sum += modhist[i];
35     }
36     cumf[HISTRES] = 1.;
37     }
38    
39    
40     double
41     cf(b) /* return cumulative function at b */
42     double b;
43     {
44     double x;
45     register int i;
46    
47     i = x = HISTRES*(b - bwmin)/(bwmax - bwmin);
48     x -= (double)i;
49     return(cumf[i]*(1.-x) + cumf[i+1]*x);
50     }
51    
52    
53     double
54     BLw(Lw) /* map world luminance to display brightness */
55     double Lw;
56     {
57     double b;
58    
59     if (Lw <= LMIN || (b = Bl(Lw)) <= bwmin+FTINY)
60     return(Bldmin);
61     if (b >= bwmax-FTINY)
62     return(Bldmax);
63     return(Bldmin + cf(Bl(Lw))*(Bldmax-Bldmin));
64     }
65    
66    
67     double
68     htcontrs(La) /* human threshold contrast sensitivity, dL(La) */
69     double La;
70     {
71     double l10La, l10dL;
72     /* formula taken from Ferwerda et al. [SG96] */
73     if (La < 1.148e-4)
74     return(1.38e-3);
75     l10La = log10(La);
76     if (l10La < -1.44) /* rod response regime */
77     l10dL = pow(.405*l10La + 1.6, 2.18) - 2.86;
78     else if (l10La < -.0184)
79     l10dL = l10La - .395;
80     else if (l10La < 1.9) /* cone response regime */
81     l10dL = pow(.249*l10La + .65, 2.7) - .72;
82     else
83     l10dL = l10La - 1.255;
84    
85     return(exp10(l10dL));
86     }
87    
88    
89     double
90     clampf(Lw) /* derivative clamping function */
91     double Lw;
92     {
93     double bLw, ratio;
94    
95     bLw = BLw(Lw); /* apply current brightness map */
96     ratio = what2do&DO_HSENS ? htcontrs(Lb(bLw))/htcontrs(Lw) : Lb(bLw)/Lw;
97     return(ratio/(Lb1(bLw)*(Bldmax-Bldmin)*Bl1(Lw)));
98     }
99    
100    
101     int
102     shiftdir(bw) /* compute shift direction for histogram */
103     double bw;
104     {
105     if (what2do&DO_HSENS && cf(bw) - (bw - bwmin)/(Bldmax - bwmin))
106     return(1);
107     return(-1);
108     }
109    
110    
111     int
112     mkbrmap() /* make dynamic range map */
113     {
114     int hdiffs[HISTRES], above, below;
115     double T, b, s;
116     int maxd, maxi, sd;
117     register int i;
118     /* copy initial histogram */
119     for (i = 0; i < HISTRES; i++)
120     modhist[i] = bwhist[i];
121     T = histot * (bwmax - bwmin) / HISTRES;
122     s = (bwmax - bwmin)/HISTRES;
123     /* loop until satisfactory */
124     for ( ; ; ) {
125     mkcumf(); /* sync brightness mapping */
126     above = below = 0; /* compute visibility overflow */
127     for (i = 0, b = bwmin + .5*s; i < HISTRES; i++, b += s) {
128     hdiffs[i] = modhist[i] - (int)(T*clampf(Lb(b)) + .5);
129     if (hdiffs[i] > 0) above += hdiffs[i];
130     else below -= hdiffs[i];
131     }
132     if (above <= histot*CVRATIO)
133     break; /* close enough */
134     if (above-below >= 0)
135     return(-1); /* Houston, we have a problem.... */
136     /* original looped here as well (BEGIN_L2) */
137     maxd = 0; /* find largest overvis */
138     for (i = 0; i < HISTRES; i++)
139     if (hdiffs[i] > maxd)
140     maxd = hdiffs[maxi=i];
141     /* broke loop here when (maxd == 0) (BREAK_L2) */
142     for (sd = shiftdir((maxi+.5)/HISTRES*(bwmax-bwmin)+bwmin);
143     hdiffs[maxi] == maxd; sd = -sd)
144     for (i = maxi+sd; i >= 0 & i < HISTRES; i += sd)
145     if (hdiffs[i] < 0) {
146     if (hdiffs[i] <= -maxd) {
147     modhist[i] += maxd;
148     modhist[maxi] -= maxd;
149     hdiffs[i] += maxd;
150     hdiffs[maxi] = 0;
151     } else {
152     modhist[maxi] += hdiffs[i];
153     modhist[i] -= hdiffs[i];
154     hdiffs[maxi] += hdiffs[i];
155     hdiffs[i] = 0;
156     }
157     break;
158     }
159     /* (END_L2) */
160     }
161     return(0);
162     }
163    
164    
165     scotscan(scan, xres) /* apply scotopic color sensitivity loss */
166     COLOR *scan;
167     int xres;
168     {
169     COLOR ctmp;
170     double incolor, b, Lw;
171     register int i;
172    
173     for (i = 0; i < xres; i++) {
174     Lw = plum(scan[i]);
175     if (Lw >= TopMesopic)
176     incolor = 1.;
177     else if (Lw <= BotMesopic)
178     incolor = 0.;
179     else
180     incolor = (Lw - BotMesopic) /
181     (TopMesopic - BotMesopic);
182     if (incolor < 1.-FTINY) {
183     if (incolor <= FTINY)
184     setcolor(scan[i], 0., 0., 0.);
185     else
186     scalecolor(scan[i], incolor);
187     b = (1.-incolor)*slum(scan[i])*inpexp/SWNORM;
188     if (lumf == rgblum) b /= WHTEFFICACY;
189     setcolor(ctmp, b, b, b);
190     addcolor(scan[i], ctmp);
191     }
192     }
193     }
194    
195    
196     mapscan(scan, xres) /* apply tone mapping operator to scanline */
197     COLOR *scan;
198     int xres;
199     {
200     double mult, Lw, b;
201     register int i;
202    
203     for (i = 0; i < xres; i++) {
204     Lw = plum(scan[i]);
205     if (Lw < LMIN) {
206     setcolor(scan[i], 0., 0., 0.);
207     continue;
208     }
209     b = BLw(Lw);
210     mult = (Lb(b) - ldmin)/(ldmax - ldmin) / (Lw*inpexp);
211     if (lumf == rgblum) mult *= WHTEFFICACY;
212     scalecolor(scan[i], mult);
213     }
214     }
215    
216    
217     #ifdef DEBUG
218     doplots() /* generate debugging plots */
219     {
220     double T, b, s;
221     FILE *fp;
222     char fname[128];
223     register int i;
224    
225     T = histot * (bwmax - bwmin) / HISTRES;
226     s = (bwmax - bwmin)/HISTRES;
227    
228     sprintf(fname, "%s_hist.plt", infn);
229     if ((fp = fopen(fname, "w")) == NULL)
230     syserror(fname);
231     fputs("include=curve.plt\n", fp);
232     fputs("title=\"Brightness Frequency Distribution\"\n", fp);
233     fprintf(fp, "subtitle=%s\n", infn);
234     fputs("ymin=0\n", fp);
235     fputs("xlabel=\"Perceptual Brightness B(Lw)\"\n", fp);
236     fputs("ylabel=\"Frequency Count\"\n", fp);
237     fputs("Alabel=\"Histogram\"\n", fp);
238     fputs("Alintype=0\n", fp);
239     fputs("Blabel=\"Envelope\"\n", fp);
240     fputs("Bsymsize=0\n", fp);
241     fputs("Adata=\n", fp);
242     for (i = 0, b = bwmin + .5*s; i < HISTRES; i++, b += s)
243     fprintf(fp, "\t%f %d\n", b, modhist[i]);
244     fputs(";\nBdata=\n", fp);
245     for (i = 0, b = bwmin + .5*s; i < HISTRES; i++, b += s)
246     fprintf(fp, "\t%f %f\n", b, T*clampf(Lb(b)));
247     fputs(";\n", fp);
248     fclose(fp);
249     }
250     #endif