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

# Content
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