ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/px/pcond3.c
Revision: 3.9
Committed: Fri Apr 11 18:34:39 1997 UTC (27 years ago) by greg
Content type: text/plain
Branch: MAIN
Changes since 3.8: +14 -5 lines
Log Message:
added an extra histogram bin at lower limit to avoid clipping

File Contents

# Content
1 /* Copyright (c) 1997 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 samples allowed > env. */
15
16 #define exp10(x) exp(2.302585093*(x))
17
18 float modhist[HISTRES]; /* modified histogram */
19 double mhistot; /* modified histogram total */
20 float cumf[HISTRES+1]; /* cumulative distribution function */
21
22
23 getfixations(fp) /* load fixation history list */
24 FILE *fp;
25 {
26 #define FIXHUNK 128
27 RESOLU fvres;
28 int pos[2];
29 register int px, py, i;
30 /* initialize our resolution struct */
31 if ((fvres.or=inpres.or)&YMAJOR) {
32 fvres.xr = fvxr;
33 fvres.yr = fvyr;
34 } else {
35 fvres.xr = fvyr;
36 fvres.yr = fvxr;
37 }
38 /* read each picture position */
39 while (fscanf(fp, "%d %d", &pos[0], &pos[1]) == 2) {
40 /* convert to closest index in foveal image */
41 loc2pix(pos, &fvres,
42 (pos[0]+.5)/inpres.xr, (pos[1]+.5)/inpres.yr);
43 /* include nine neighborhood samples */
44 for (px = pos[0]-1; px <= pos[0]+1; px++) {
45 if (px < 0 || px >= fvxr)
46 continue;
47 for (py = pos[1]-1; py <= pos[1]+1; py++) {
48 if (py < 0 || py >= fvyr)
49 continue;
50 for (i = nfixations; i-- > 0; )
51 if (fixlst[i][0] == px &&
52 fixlst[i][1] == py)
53 break;
54 if (i >= 0)
55 continue; /* already there */
56 if (nfixations % FIXHUNK == 0) {
57 if (nfixations)
58 fixlst = (short (*)[2])
59 realloc((char *)fixlst,
60 (nfixations+FIXHUNK)*
61 2*sizeof(short));
62 else
63 fixlst = (short (*)[2])malloc(
64 FIXHUNK*2*sizeof(short)
65 );
66 if (fixlst == NULL)
67 syserror("malloc");
68 }
69 fixlst[nfixations][0] = px;
70 fixlst[nfixations][1] = py;
71 nfixations++;
72 }
73 }
74 }
75 if (!feof(fp)) {
76 fprintf(stderr, "%s: format error reading fixation data\n",
77 progname);
78 exit(1);
79 }
80 #undef FIXHUNK
81 }
82
83
84 double
85 centprob(x, y) /* center-weighting probability function */
86 int x, y;
87 {
88 double xr, yr, p;
89 /* paraboloid, 0 at 90 degrees from center */
90 xr = (x - .5*(fvxr-1))/90.; /* 180 degree fisheye has fv?r == 90 */
91 yr = (y - .5*(fvyr-1))/90.;
92 p = 1. - xr*xr - yr*yr;
93 return(p < 0. ? 0. : p);
94 }
95
96
97 comphist() /* create foveal sampling histogram */
98 {
99 double l, b, w, lwmin, lwmax;
100 register int x, y;
101
102 lwmin = 1e10; /* find extrema */
103 lwmax = 0.;
104 for (y = 0; y < fvyr; y++)
105 for (x = 0; x < fvxr; x++) {
106 l = plum(fovscan(y)[x]);
107 if (l < lwmin) lwmin = l;
108 if (l > lwmax) lwmax = l;
109 }
110 lwmax *= 1.01;
111 if (lwmax > LMAX)
112 lwmax = LMAX;
113 bwmax = Bl(lwmax);
114 if (lwmin < LMIN) {
115 lwmin = LMIN;
116 bwmin = Bl(LMIN);
117 } else { /* duplicate bottom bin */
118 bwmin = bwmax - (bwmax-Bl(lwmin))*HISTRES/(HISTRES-1);
119 lwmin = Lb(bwmin);
120 }
121 /* (re)compute histogram */
122 bwavg = 0.;
123 histot = 0.;
124 for (x = 0; x < HISTRES; x++)
125 bwhist[x] = 0.;
126 /* global average */
127 if (!(what2do&DO_FIXHIST) || fixfrac < 1.-FTINY)
128 for (y = 0; y < fvyr; y++)
129 for (x = 0; x < fvxr; x++) {
130 l = plum(fovscan(y)[x]);
131 if (l < lwmin) continue;
132 if (l > lwmax) continue;
133 b = Bl(l);
134 bwavg += b;
135 w = what2do&DO_CWEIGHT ? centprob(x,y) : 1.;
136 bwhist[bwhi(b)] += w;
137 histot += w;
138 }
139 /* average fixation points */
140 if (what2do&DO_FIXHIST && nfixations > 0) {
141 if (histot > FTINY)
142 w = fixfrac/(1.-fixfrac)*histot/nfixations;
143 else
144 w = 1.;
145 for (x = 0; x < nfixations; x++) {
146 l = plum(fovscan(fixlst[x][1])[fixlst[x][0]]);
147 if (l < lwmin) continue;
148 if (l > lwmax) continue;
149 b = Bl(l);
150 bwavg += b;
151 bwhist[bwhi(b)] += w;
152 histot += w;
153 }
154 }
155 bwavg /= histot;
156 if (lwmin > LMIN+FTINY) { /* add false samples at bottom */
157 bwhist[1] *= 0.5;
158 bwhist[0] += bwhist[1];
159 }
160 }
161
162
163 mkcumf() /* make cumulative distribution function */
164 {
165 register int i;
166 register double sum;
167
168 mhistot = 0.; /* compute modified total */
169 for (i = 0; i < HISTRES; i++)
170 mhistot += modhist[i];
171
172 sum = 0.; /* compute cumulative function */
173 for (i = 0; i < HISTRES; i++) {
174 cumf[i] = sum/mhistot;
175 sum += modhist[i];
176 }
177 cumf[HISTRES] = 1.;
178 }
179
180
181 double
182 cf(b) /* return cumulative function at b */
183 double b;
184 {
185 double x;
186 register int i;
187
188 i = x = HISTRES*(b - bwmin)/(bwmax - bwmin);
189 x -= (double)i;
190 return(cumf[i]*(1.-x) + cumf[i+1]*x);
191 }
192
193
194 double
195 BLw(Lw) /* map world luminance to display brightness */
196 double Lw;
197 {
198 double b;
199
200 if (Lw <= LMIN || (b = Bl(Lw)) <= bwmin+FTINY)
201 return(Bldmin);
202 if (b >= bwmax-FTINY)
203 return(Bldmax);
204 return(Bldmin + cf(b)*(Bldmax-Bldmin));
205 }
206
207
208 double
209 htcontrs(La) /* human threshold contrast sensitivity, dL(La) */
210 double La;
211 {
212 double l10La, l10dL;
213 /* formula taken from Ferwerda et al. [SG96] */
214 if (La < 1.148e-4)
215 return(1.38e-3);
216 l10La = log10(La);
217 if (l10La < -1.44) /* rod response regime */
218 l10dL = pow(.405*l10La + 1.6, 2.18) - 2.86;
219 else if (l10La < -.0184)
220 l10dL = l10La - .395;
221 else if (l10La < 1.9) /* cone response regime */
222 l10dL = pow(.249*l10La + .65, 2.7) - .72;
223 else
224 l10dL = l10La - 1.255;
225
226 return(exp10(l10dL));
227 }
228
229
230 double
231 clampf(Lw) /* derivative clamping function */
232 double Lw;
233 {
234 double bLw, ratio;
235
236 bLw = BLw(Lw); /* apply current brightness map */
237 ratio = what2do&DO_HSENS ? htcontrs(Lb(bLw))/htcontrs(Lw) : Lb(bLw)/Lw;
238 return(ratio/(Lb1(bLw)*(Bldmax-Bldmin)*Bl1(Lw)));
239 }
240
241
242 int
243 mkbrmap() /* make dynamic range map */
244 {
245 double T, b, s;
246 double ceiling, trimmings;
247 register int i;
248 /* copy initial histogram */
249 bcopy((char *)bwhist, (char *)modhist, sizeof(modhist));
250 s = (bwmax - bwmin)/HISTRES;
251 /* loop until satisfactory */
252 do {
253 mkcumf(); /* sync brightness mapping */
254 if (mhistot <= histot*CVRATIO)
255 return(-1); /* no compression needed! */
256 T = mhistot * (bwmax - bwmin) / HISTRES;
257 trimmings = 0.; /* clip to envelope */
258 for (i = 0, b = bwmin + .5*s; i < HISTRES; i++, b += s) {
259 ceiling = T*clampf(Lb(b));
260 if (modhist[i] > ceiling) {
261 trimmings += modhist[i] - ceiling;
262 modhist[i] = ceiling;
263 }
264 }
265 } while (trimmings > histot*CVRATIO);
266
267 return(0); /* we got it */
268 }
269
270
271 scotscan(scan, xres) /* apply scotopic color sensitivity loss */
272 COLOR *scan;
273 int xres;
274 {
275 COLOR ctmp;
276 double incolor, b, Lw;
277 register int i;
278
279 for (i = 0; i < xres; i++) {
280 Lw = plum(scan[i]);
281 if (Lw >= TopMesopic)
282 incolor = 1.;
283 else if (Lw <= BotMesopic)
284 incolor = 0.;
285 else
286 incolor = (Lw - BotMesopic) /
287 (TopMesopic - BotMesopic);
288 if (incolor < 1.-FTINY) {
289 b = (1.-incolor)*slum(scan[i])*inpexp/SWNORM;
290 if (lumf == rgblum) b /= WHTEFFICACY;
291 setcolor(ctmp, b, b, b);
292 if (incolor <= FTINY)
293 setcolor(scan[i], 0., 0., 0.);
294 else
295 scalecolor(scan[i], incolor);
296 addcolor(scan[i], ctmp);
297 }
298 }
299 }
300
301
302 mapscan(scan, xres) /* apply tone mapping operator to scanline */
303 COLOR *scan;
304 int xres;
305 {
306 double mult, Lw, b;
307 register int i;
308
309 for (i = 0; i < xres; i++) {
310 Lw = plum(scan[i]);
311 if (Lw < LMIN) {
312 setcolor(scan[i], 0., 0., 0.);
313 continue;
314 }
315 b = BLw(Lw);
316 mult = (Lb(b) - ldmin)/(ldmax - ldmin) / (Lw*inpexp);
317 if (lumf == rgblum) mult *= WHTEFFICACY;
318 scalecolor(scan[i], mult);
319 }
320 }
321
322
323 putmapping(fp) /* put out mapping function */
324 FILE *fp;
325 {
326 double b, s;
327 register int i;
328 double wlum, sf, dlum;
329
330 sf = scalef*inpexp;
331 if (lumf == cielum) sf *= WHTEFFICACY;
332 s = (bwmax - bwmin)/HISTRES;
333 for (i = 0, b = bwmin + .5*s; i < HISTRES; i++, b += s) {
334 wlum = Lb(b);
335 if (what2do&DO_LINEAR) {
336 dlum = sf*wlum;
337 if (dlum > ldmax) dlum = ldmax;
338 else if (dlum < ldmin) dlum = ldmin;
339 fprintf(fp, "%e %e\n", wlum, dlum);
340 } else
341 fprintf(fp, "%e %e\n", wlum, Lb(BLw(wlum)));
342 }
343 }