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

# User Rev Content
1 greg 3.7 /* Copyright (c) 1997 Regents of the University of California */
2 greg 3.1
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 greg 3.5 #define CVRATIO 0.025 /* fraction of samples allowed > env. */
15 greg 3.1
16 gwlarson 3.10 #define LN_10 2.30258509299404568402
17     #define exp10(x) exp(LN_10*(x))
18 greg 3.1
19 greg 3.5 float modhist[HISTRES]; /* modified histogram */
20     double mhistot; /* modified histogram total */
21 greg 3.1 float cumf[HISTRES+1]; /* cumulative distribution function */
22    
23    
24 greg 3.8 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 gwlarson 3.10 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 greg 3.8 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 gwlarson 3.10 /* check for precalculated histogram */
166     if (what2do&DO_PREHIST)
167     return;
168 greg 3.8 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 greg 3.9 lwmax *= 1.01;
177     if (lwmax > LMAX)
178     lwmax = LMAX;
179 greg 3.8 bwmax = Bl(lwmax);
180 greg 3.9 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 greg 3.8 /* (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 gwlarson 3.10 bwavg += w*b;
202 greg 3.8 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 gwlarson 3.10 bwavg += w*b;
217 greg 3.8 bwhist[bwhi(b)] += w;
218     histot += w;
219     }
220     }
221     bwavg /= histot;
222 greg 3.9 if (lwmin > LMIN+FTINY) { /* add false samples at bottom */
223     bwhist[1] *= 0.5;
224     bwhist[0] += bwhist[1];
225     }
226 greg 3.8 }
227    
228    
229 greg 3.1 mkcumf() /* make cumulative distribution function */
230     {
231     register int i;
232 greg 3.5 register double sum;
233 greg 3.1
234 greg 3.5 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 greg 3.1 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 greg 3.4 return(Bldmin + cf(b)*(Bldmax-Bldmin));
271 greg 3.1 }
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 greg 3.5 double ceiling, trimmings;
313 greg 3.1 register int i;
314     /* copy initial histogram */
315 greg 3.5 bcopy((char *)bwhist, (char *)modhist, sizeof(modhist));
316 greg 3.1 s = (bwmax - bwmin)/HISTRES;
317     /* loop until satisfactory */
318 greg 3.5 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 greg 3.1 for (i = 0, b = bwmin + .5*s; i < HISTRES; i++, b += s) {
325 greg 3.5 ceiling = T*clampf(Lb(b));
326     if (modhist[i] > ceiling) {
327     trimmings += modhist[i] - ceiling;
328     modhist[i] = ceiling;
329     }
330 greg 3.1 }
331 greg 3.5 } while (trimmings > histot*CVRATIO);
332    
333     return(0); /* we got it */
334 greg 3.1 }
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 greg 3.2 b = (1.-incolor)*slum(scan[i])*inpexp/SWNORM;
356     if (lumf == rgblum) b /= WHTEFFICACY;
357     setcolor(ctmp, b, b, b);
358 greg 3.1 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 greg 3.4 }
386     }
387    
388    
389     putmapping(fp) /* put out mapping function */
390     FILE *fp;
391     {
392     double b, s;
393     register int i;
394 greg 3.7 double wlum, sf, dlum;
395 greg 3.4
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 greg 3.7 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 greg 3.4 fprintf(fp, "%e %e\n", wlum, Lb(BLw(wlum)));
408 greg 3.1 }
409     }