ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/px/pcond3.c
Revision: 3.10
Committed: Thu Mar 12 15:47:34 1998 UTC (26 years, 1 month ago) by gwlarson
Content type: text/plain
Branch: MAIN
Changes since 3.9: +70 -4 lines
Log Message:
added -I option for precomputed histogram

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