ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/px/pf3.c
Revision: 2.11
Committed: Fri Jul 16 11:32:06 1993 UTC (30 years, 9 months ago) by greg
Content type: text/plain
Branch: MAIN
Changes since 2.10: +7 -4 lines
Log Message:
improved handling of zero exclusive average in pickfilt()

File Contents

# Content
1 /* Copyright (c) 1993 Regents of the University of California */
2
3 #ifndef lint
4 static char SCCSid[] = "$SunId$ LBL";
5 #endif
6
7 /*
8 * pf3.c - routines for gaussian and box filtering
9 *
10 * 8/13/86
11 */
12
13 #include "standard.h"
14
15 #include "color.h"
16
17 #define TEPS 0.2 /* threshold proximity goal */
18 #define REPS 0.1 /* radius proximity goal */
19
20 extern double CHECKRAD; /* radius over which gaussian is summed */
21
22 extern double rad; /* output pixel radius for filtering */
23
24 extern double thresh; /* maximum contribution for subpixel */
25
26 extern int nrows; /* number of rows for output */
27 extern int ncols; /* number of columns for output */
28
29 extern int xres, yres; /* resolution of input */
30
31 extern double x_c, y_r; /* conversion factors */
32
33 extern int xrad; /* x search radius */
34 extern int yrad; /* y search radius */
35 extern int xbrad; /* x box size */
36 extern int ybrad; /* y box size */
37
38 extern int barsize; /* size of input scan bar */
39 extern COLOR **scanin; /* input scan bar */
40 extern COLOR *scanout; /* output scan line */
41 extern COLOR **scoutbar; /* output scan bar (if thresh > 0) */
42 extern float **greybar; /* grey-averaged input values */
43 extern int obarsize; /* size of output scan bar */
44 extern int orad; /* output window radius */
45
46 extern char *progname;
47
48 float *gausstable; /* gauss lookup table */
49
50 float *ringsum; /* sum of ring values */
51 short *ringwt; /* weight (count) of ring values */
52 short *ringndx; /* ring index table */
53 float *warr; /* array of pixel weights */
54
55 double pickfilt();
56
57 #define lookgauss(x) gausstable[(int)(10.*(x)+.5)]
58
59
60 initmask() /* initialize gaussian lookup table */
61 {
62 int gtabsiz;
63 double gaussN;
64 double d;
65 register int x;
66
67 gtabsiz = 150*CHECKRAD;
68 gausstable = (float *)malloc(gtabsiz*sizeof(float));
69 if (gausstable == NULL)
70 goto memerr;
71 d = x_c*y_r*0.25/(rad*rad);
72 gausstable[0] = exp(-d)/sqrt(d);
73 for (x = 1; x < gtabsiz; x++)
74 if ((gausstable[x] = exp(-x*0.1)/sqrt(x*0.1)) > gausstable[0])
75 gausstable[x] = gausstable[0];
76 if (obarsize == 0)
77 return;
78 /* compute integral of filter */
79 gaussN = PI*sqrt(d)*exp(-d); /* plateau */
80 for (d = sqrt(d)+0.05; d <= 1.25*CHECKRAD; d += 0.1)
81 gaussN += 0.1*2.0*PI*exp(-d*d);
82 /* normalize filter */
83 gaussN = x_c*y_r/(rad*rad*gaussN);
84 for (x = 0; x < gtabsiz; x++)
85 gausstable[x] *= gaussN;
86 /* create ring averages table */
87 ringndx = (short *)malloc((2*orad*orad+1)*sizeof(short));
88 if (ringndx == NULL)
89 goto memerr;
90 for (x = 2*orad*orad+1; --x > orad*orad; )
91 ringndx[x] = -1;
92 do
93 ringndx[x] = sqrt((double)x);
94 while (x--);
95 ringsum = (float *)malloc((orad+1)*sizeof(float));
96 ringwt = (short *)malloc((orad+1)*sizeof(short));
97 warr = (float *)malloc(obarsize*obarsize*sizeof(float));
98 if (ringsum == NULL | ringwt == 0 | warr == NULL)
99 goto memerr;
100 return;
101 memerr:
102 fprintf(stderr, "%s: out of memory in initmask\n", progname);
103 quit(1);
104 }
105
106
107 dobox(csum, xcent, ycent, c, r) /* simple box filter */
108 COLOR csum;
109 int xcent, ycent;
110 int c, r;
111 {
112 int wsum;
113 double d;
114 int y;
115 register int x;
116 register COLOR *scan;
117
118 wsum = 0;
119 setcolor(csum, 0.0, 0.0, 0.0);
120 for (y = ycent+1-ybrad; y <= ycent+ybrad; y++) {
121 if (y < 0) continue;
122 if (y >= yres) break;
123 d = y_r < 1.0 ? y_r*y - r : (double)(y - ycent);
124 if (d < -0.5) continue;
125 if (d >= 0.5) break;
126 scan = scanin[y%barsize];
127 for (x = xcent+1-xbrad; x <= xcent+xbrad; x++) {
128 if (x < 0) continue;
129 if (x >= xres) break;
130 d = x_c < 1.0 ? x_c*x - c : (double)(x - xcent);
131 if (d < -0.5) continue;
132 if (d >= 0.5) break;
133 wsum++;
134 addcolor(csum, scan[x]);
135 }
136 }
137 if (wsum > 1)
138 scalecolor(csum, 1.0/wsum);
139 }
140
141
142 dogauss(csum, xcent, ycent, c, r) /* gaussian filter */
143 COLOR csum;
144 int xcent, ycent;
145 int c, r;
146 {
147 double dy, dx, weight, wsum;
148 COLOR ctmp;
149 int y;
150 register int x;
151 register COLOR *scan;
152
153 wsum = FTINY;
154 setcolor(csum, 0.0, 0.0, 0.0);
155 for (y = ycent-yrad; y <= ycent+yrad; y++) {
156 if (y < 0) continue;
157 if (y >= yres) break;
158 dy = (y_r*(y+.5) - (r+.5))/rad;
159 scan = scanin[y%barsize];
160 for (x = xcent-xrad; x <= xcent+xrad; x++) {
161 if (x < 0) continue;
162 if (x >= xres) break;
163 dx = (x_c*(x+.5) - (c+.5))/rad;
164 weight = lookgauss(dx*dx + dy*dy);
165 wsum += weight;
166 copycolor(ctmp, scan[x]);
167 scalecolor(ctmp, weight);
168 addcolor(csum, ctmp);
169 }
170 }
171 scalecolor(csum, 1.0/wsum);
172 }
173
174
175 dothresh(xcent, ycent, ccent, rcent) /* gaussian threshold filter */
176 int xcent, ycent;
177 int ccent, rcent;
178 {
179 double d;
180 int r, y;
181 register int c, x;
182 register float *gscan;
183 #define pval gscan
184 /* compute ring sums */
185 bzero((char *)ringsum, (orad+1)*sizeof(float));
186 bzero((char *)ringwt, (orad+1)*sizeof(short));
187 for (r = -orad; r <= orad; r++) {
188 if (rcent+r < 0) continue;
189 if (rcent+r >= nrows) break;
190 gscan = greybar[(rcent+r)%obarsize];
191 for (c = -orad; c <= orad; c++) {
192 if (ccent+c < 0) continue;
193 if (ccent+c >= ncols) break;
194 x = ringndx[c*c + r*r];
195 if (x < 0) continue;
196 ringsum[x] += gscan[ccent+c];
197 ringwt[x]++;
198 }
199 }
200 /* filter each subpixel */
201 for (y = ycent+1-ybrad; y <= ycent+ybrad; y++) {
202 if (y < 0) continue;
203 if (y >= yres) break;
204 d = y_r < 1.0 ? y_r*y - rcent : (double)(y - ycent);
205 if (d < -0.5) continue;
206 if (d >= 0.5) break;
207 for (x = xcent+1-xbrad; x <= xcent+xbrad; x++) {
208 if (x < 0) continue;
209 if (x >= xres) break;
210 d = x_c < 1.0 ? x_c*x - ccent : (double)(x - xcent);
211 if (d < -0.5) continue;
212 if (d >= 0.5) break;
213 pval = scanin[y%barsize][x];
214 sumans(x, y, rcent, ccent, pickfilt(bright(pval)));
215 }
216 }
217 #undef pval
218 }
219
220
221 double
222 pickfilt(p0) /* find filter multiplier for p0 */
223 double p0;
224 {
225 double m = 1.0;
226 double t, num, denom, avg, wsum;
227 double mlimit[2];
228 int ilimit = 4/TEPS;
229 register int i;
230 /* iterative search for m */
231 mlimit[0] = 1.0; mlimit[1] = orad/rad/CHECKRAD;
232 do {
233 /* compute grey weighted average */
234 i = 1.25*CHECKRAD*rad*m + .5;
235 if (i > orad) i = orad;
236 avg = wsum = 0.0;
237 while (i--) {
238 t = (i+.5)/(m*rad);
239 t = lookgauss(t*t);
240 avg += t*ringsum[i];
241 wsum += t*ringwt[i];
242 }
243 if (avg < 1e-20) /* zero inclusive average */
244 return(1.0);
245 avg /= wsum;
246 /* check threshold */
247 denom = m*m/gausstable[0] - p0/avg;
248 if (denom <= FTINY) { /* zero exclusive average */
249 if (m >= mlimit[1]-REPS)
250 break;
251 m = mlimit[1];
252 continue;
253 }
254 num = p0/avg - 1.0;
255 if (num < 0.0) num = -num;
256 t = num/denom;
257 if (t <= thresh) {
258 if (m <= mlimit[0]+REPS || (thresh-t)/thresh <= TEPS)
259 break;
260 } else {
261 if (m >= mlimit[1]-REPS || (t-thresh)/thresh <= TEPS)
262 break;
263 }
264 t = m; /* remember current m */
265 /* next guesstimate */
266 m = sqrt(gausstable[0]*(num/thresh + p0/avg));
267 if (m < t) { /* bound it */
268 if (m <= mlimit[0]+FTINY)
269 m = 0.5*(mlimit[0] + t);
270 mlimit[1] = t;
271 } else {
272 if (m >= mlimit[1]-FTINY)
273 m = 0.5*(mlimit[1] + t);
274 mlimit[0] = t;
275 }
276 } while (--ilimit > 0);
277 return(m);
278 }
279
280
281 sumans(px, py, rcent, ccent, m) /* sum input pixel to output */
282 int px, py;
283 int rcent, ccent;
284 double m;
285 {
286 double dy, dx;
287 COLOR pval, ctmp;
288 int ksiz, r;
289 double pc, pr, norm;
290 register int i, c;
291 register COLOR *scan;
292
293 copycolor(pval, scanin[py%barsize][px]);
294 pc = x_c*(px+.5);
295 pr = y_r*(py+.5);
296 ksiz = CHECKRAD*m*rad + 1;
297 if (ksiz > orad) ksiz = orad;
298 /* compute normalization */
299 norm = 0.0;
300 i = 0;
301 for (r = rcent-ksiz; r <= rcent+ksiz; r++) {
302 if (r < 0) continue;
303 if (r >= nrows) break;
304 dy = (pr - (r+.5))/(m*rad);
305 for (c = ccent-ksiz; c <= ccent+ksiz; c++) {
306 if (c < 0) continue;
307 if (c >= ncols) break;
308 dx = (pc - (c+.5))/(m*rad);
309 norm += warr[i++] = lookgauss(dx*dx + dy*dy);
310 }
311 }
312 norm = 1.0/norm;
313 if (x_c < 1.0) norm *= x_c;
314 if (y_r < 1.0) norm *= y_r;
315 /* sum pixels */
316 i = 0;
317 for (r = rcent-ksiz; r <= rcent+ksiz; r++) {
318 if (r < 0) continue;
319 if (r >= nrows) break;
320 scan = scoutbar[r%obarsize];
321 for (c = ccent-ksiz; c <= ccent+ksiz; c++) {
322 if (c < 0) continue;
323 if (c >= ncols) break;
324 copycolor(ctmp, pval);
325 dx = norm*warr[i++];
326 scalecolor(ctmp, dx);
327 addcolor(scan[c], ctmp);
328 }
329 }
330 }