Mercurial > hg > wm
comparison Meerwald-dir/dwt.c @ 24:9f20bce6184e v0.7
move directories, support netpbm 11
author | Peter Meerwald-Stadler <pmeerw@pmeerw.net> |
---|---|
date | Fri, 20 Dec 2024 13:08:59 +0100 |
parents | Meerwald/dwt.c@1906e659edd0 |
children |
comparison
equal
deleted
inserted
replaced
23:71dd4b96221b | 24:9f20bce6184e |
---|---|
1 #include "wm.h" | |
2 #include "dwt.h" | |
3 | |
4 char filter_file[MAXPATHLEN] = ""; | |
5 AllFilters dwt_allfilters; | |
6 FilterGH *dwt_filters = NULL; | |
7 int dwt_method; | |
8 int dwt_cols; | |
9 int dwt_rows; | |
10 int dwt_levels; | |
11 int dwt_filter; | |
12 | |
13 void init_dwt(int cols, int rows, const char *filter_name, int filter, int level, int method) { | |
14 int i; | |
15 | |
16 if (strcmp(filter_file, filter_name)) { | |
17 if (filter_name) | |
18 strcpy(filter_file, filter_name); | |
19 else | |
20 strcpy(filter_file, "filter.dat"); | |
21 | |
22 /* memory leak here - there is no function unload_filters() */ | |
23 dwt_allfilters = load_filters(filter_file); | |
24 | |
25 if (!dwt_allfilters) { | |
26 fprintf(stderr, "init_dwt(): unable to open filter definition file %s\n", filter_file); | |
27 return; | |
28 } | |
29 } | |
30 | |
31 #ifdef DEBUG | |
32 if (level <= 0 || level > rint(log(MIN(cols, rows))/log(2.0)) - 2) { | |
33 fprintf(stderr, "init_dwt(): level parameter does not match image width/height\n"); | |
34 return; | |
35 } | |
36 #endif | |
37 | |
38 if (dwt_filters && level != dwt_levels) { | |
39 free(dwt_filters); | |
40 dwt_filters = NULL; | |
41 } | |
42 | |
43 dwt_levels = level; | |
44 | |
45 if (!dwt_filters) | |
46 dwt_filters = calloc(level + 1, sizeof(FilterGH)); | |
47 | |
48 for (i = 0; i < level + 1; i++) | |
49 dwt_filters[i] = (dwt_allfilters->filter)[filter]; | |
50 | |
51 dwt_filter = filter; | |
52 dwt_method = method; | |
53 dwt_cols = cols; | |
54 dwt_rows = rows; | |
55 } | |
56 | |
57 Image_tree fdwt(gray **pixels) { | |
58 Image image; | |
59 Image_tree tree; | |
60 int i, j; | |
61 | |
62 image = new_image(dwt_cols, dwt_rows); | |
63 | |
64 for (i = 0; i < dwt_rows; i++) | |
65 for (j = 0; j < dwt_cols; j++) | |
66 set_pixel(image, j, i, pixels[i][j]); | |
67 | |
68 tree = wavelettransform(image, dwt_levels, dwt_filters, dwt_method); | |
69 free_image(image); | |
70 | |
71 return tree; | |
72 } | |
73 | |
74 Image_tree fdwt_wp(gray **pixels) { | |
75 Image image; | |
76 Image_tree tree; | |
77 int i, j; | |
78 | |
79 image = new_image(dwt_cols, dwt_rows); | |
80 | |
81 for (i = 0; i < dwt_rows; i++) | |
82 for (j = 0; j < dwt_cols; j++) | |
83 set_pixel(image, j, i, pixels[i][j]); | |
84 | |
85 tree = wavelettransform_wp(image, dwt_levels, dwt_filters, dwt_method); | |
86 free_image(image); | |
87 | |
88 return tree; | |
89 } | |
90 | |
91 void idwt(Image_tree dwts, gray **pixels) { | |
92 Image image; | |
93 int i, j; | |
94 | |
95 image = inv_transform(dwts, dwt_filters, dwt_method + 1); | |
96 | |
97 for (i = 0; i < dwt_rows; i++) | |
98 for (j = 0; j < dwt_cols; j++) | |
99 pixels[i][j] = PIXELRANGE((int) (get_pixel(image, j, i) + 0.5)); | |
100 | |
101 free_image(image); | |
102 } | |
103 | |
104 void idwt_wp(Image_tree dwts, gray **pixels) { | |
105 Image image; | |
106 int i, j; | |
107 | |
108 image = inv_transform(dwts, dwt_filters, dwt_method + 1); | |
109 | |
110 for (i = 0; i < dwt_rows; i++) | |
111 for (j = 0; j < dwt_cols; j++) | |
112 pixels[i][j] = PIXELRANGE((int) (get_pixel(image, j, i) + 0.5)); | |
113 | |
114 free_image(image); | |
115 } | |
116 | |
117 int gen_pollen_filter(double *filter, double alpha, double beta, int which) { | |
118 int i, j, k, filterlength; | |
119 double tf[6]; | |
120 | |
121 /* parameter alpha, beta have to be in range -Pi .. Pi */ | |
122 if (alpha < -M_PI || alpha >= M_PI) { | |
123 fprintf(stderr, "alpha %f out of range\n", alpha); | |
124 return -1; | |
125 } | |
126 | |
127 if (beta < -M_PI || beta >= M_PI) { | |
128 fprintf(stderr, "beta %f out of range\n", beta); | |
129 return -1; | |
130 } | |
131 | |
132 /* generate Pollen filter coefficients, see http://www.dfw.net/~cody for details */ | |
133 tf[0] = ((1.0 + cos(alpha) + sin(alpha)) * (1.0 - cos(beta) - sin(beta)) + 2.0 * sin(beta) * cos(alpha)) / 4.0; | |
134 tf[1] = ((1.0 - cos(alpha) + sin(alpha)) * (1.0 + cos(beta) - sin(beta)) - 2.0 * sin(beta) * cos(alpha)) / 4.0; | |
135 tf[2] = (1.0 + cos(alpha - beta) + sin(alpha - beta)) / 2.0; | |
136 tf[3] = (1.0 + cos(alpha - beta) - sin(alpha - beta)) / 2.0; | |
137 tf[4] = 1.0 - tf[0] - tf[2]; | |
138 tf[5] = 1.0 - tf[1] - tf[3]; | |
139 | |
140 /* set close-to-zero filter coefficients to zero */ | |
141 for (i = 0; i < 6; i++) | |
142 if (fabs(tf[i]) < 1.0e-15) tf[i] = 0.0; | |
143 | |
144 /* find the first non-zero wavelet coefficient */ | |
145 i = 0; | |
146 while (tf[i] == 0.0) i++; | |
147 | |
148 /* find the last non-zero wavelet coefficient */ | |
149 j = 5; | |
150 while (tf[j] == 0.0) j--; | |
151 | |
152 filterlength = j - i + 1; | |
153 for (k = 0; k < filterlength; k++) | |
154 switch (which) { | |
155 case FILTERH: | |
156 filter[k] = tf[j--] / 2.0; | |
157 break; | |
158 case FILTERG: | |
159 filter[k] = (double) (((i & 0x01) * 2) - 1) * tf[i] / 2.0; | |
160 i++; | |
161 break; | |
162 case FILTERHi: | |
163 filter[k] = tf[j--]; | |
164 break; | |
165 case FILTERGi: | |
166 filter[k] = (double) (((i & 0x01) * 2) - 1) * tf[i]; | |
167 i++; | |
168 break; | |
169 default: | |
170 return -1; | |
171 } | |
172 | |
173 while (k < 6) | |
174 filter[k++] = 0.0; | |
175 | |
176 return filterlength; | |
177 } | |
178 | |
179 void dwt_pollen_filter(double alpha, double beta) { | |
180 FilterGH filter; | |
181 int i; | |
182 | |
183 filter = malloc(sizeof(struct FilterGHStruct)); | |
184 #ifdef DEBUG | |
185 if (!filter) { | |
186 fprintf(stderr, "dwt_pollen_filter(): malloc failed()\n"); | |
187 return; | |
188 } | |
189 #endif | |
190 | |
191 filter->type = FTOther; | |
192 filter->name = "pollen"; | |
193 | |
194 filter->g = new_filter(6); | |
195 filter->g->type = FTSymm; | |
196 filter->g->hipass = 1; | |
197 filter->g->len = gen_pollen_filter(filter->g->data, alpha, beta, FILTERG); | |
198 filter->g->start = -filter->g->len / 2; | |
199 filter->g->end = filter->g->len / 2 - 1; | |
200 | |
201 filter->h = new_filter(6); | |
202 filter->h->type = FTSymm; | |
203 filter->h->hipass = 0; | |
204 filter->h->len = gen_pollen_filter(filter->h->data, alpha, beta, FILTERH); | |
205 filter->h->start = -filter->h->len / 2; | |
206 filter->h->end = filter->h->len / 2 - 1; | |
207 | |
208 filter->gi = new_filter(6); | |
209 filter->gi->type = FTSymm; | |
210 filter->gi->hipass = 1; | |
211 filter->gi->len = gen_pollen_filter(filter->gi->data, alpha, beta, FILTERGi); | |
212 filter->gi->start = -filter->gi->len / 2; | |
213 filter->gi->end = filter->gi->len / 2 - 1; | |
214 | |
215 filter->hi = new_filter(6); | |
216 filter->hi->type = FTSymm; | |
217 filter->hi->hipass = 0; | |
218 filter->hi->len = gen_pollen_filter(filter->hi->data, alpha, beta, FILTERHi); | |
219 filter->hi->start = -filter->hi->len / 2; | |
220 filter->hi->end = filter->hi->len / 2 - 1; | |
221 | |
222 #ifdef DEBUG | |
223 if (dwt_levels <= 0) { | |
224 fprintf(stderr, "dwt_pollen_filter(): level invalid - set to zero\n"); | |
225 return; | |
226 } | |
227 #endif | |
228 | |
229 #ifdef DEBUG | |
230 if (!dwt_filters) { | |
231 fprintf(stderr, "dwt_pollen_filter(): wm_dwt not initialized, call init_dwt() first\n"); | |
232 return; | |
233 } | |
234 #endif | |
235 | |
236 for (i = 0; i < dwt_levels + 1; i++) | |
237 dwt_filters[i] = filter; | |
238 } | |
239 | |
240 int gen_param_filter(double *filter, int n, double alpha[], int which) { | |
241 int i, j, k, filterlength; | |
242 double *tf, *t; | |
243 | |
244 tf = malloc(2 * (n + 1) * sizeof(double)); | |
245 t = malloc(2 * (n + 1) * sizeof(double)); | |
246 if (!tf) { | |
247 fprintf(stderr, "gen_param_filter(): malloc() failed\n"); | |
248 return -1; | |
249 } | |
250 | |
251 tf[0] = 1.0 / sqrt(2.0); | |
252 tf[1] = 1.0 / sqrt(2.0); | |
253 | |
254 for (k = 0; k < n; k++) { | |
255 for (i = 0; i < 2 * (k + 2); i++) { | |
256 | |
257 #define H(X) (((X) < 0 || (X) >= 2 * (k + 1)) ? 0.0 : tf[X]) | |
258 | |
259 t[i] = 0.5 * (H(i - 2) + H(i) + | |
260 cos(alpha[k]) * (H(i - 2) - H(i)) + | |
261 (i & 1 ? -1.0 : 1.0) * sin(alpha[k]) * (H(2 * (k + 2) - i - 1) - H(2 * (k + 2) - i - 3))); | |
262 } | |
263 for (i = 0; i < 2 * (k + 2); i++) tf[i] = t[i]; | |
264 } | |
265 | |
266 /* set close-to-zero filter coefficients to zero */ | |
267 for (i = 0; i < 2 * (n + 1) ; i++) | |
268 if (fabs(tf[i]) < 1.0e-15) tf[i] = 0.0; | |
269 | |
270 /* find the first non-zero wavelet coefficient */ | |
271 i = 0; | |
272 while (tf[i] == 0.0) i++; | |
273 | |
274 /* find the last non-zero wavelet coefficient */ | |
275 j = 2 * (n + 1) - 1; | |
276 while (tf[j] == 0.0) j--; | |
277 | |
278 filterlength = j - i + 1; | |
279 for (k = 0; k < filterlength; k++) | |
280 switch (which) { | |
281 case FILTERG: | |
282 case FILTERGi: | |
283 filter[k] = (double) ((((i+1) & 0x01) * 2) - 1) * tf[i]; | |
284 i++; | |
285 break; | |
286 case FILTERH: | |
287 case FILTERHi: | |
288 filter[k] = tf[j--]; | |
289 break; | |
290 default: | |
291 return -1; | |
292 } | |
293 | |
294 while (k < 2 * (n + 1)) | |
295 filter[k++] = 0.0; | |
296 | |
297 return filterlength; | |
298 } | |
299 | |
300 void dwt_param_filter(double alpha[], int param_len[]) { | |
301 FilterGH filter; | |
302 int i; | |
303 int param_len_sum = 0; | |
304 | |
305 #ifdef DEBUG | |
306 if (dwt_levels <= 0) { | |
307 fprintf(stderr, "dwt_param_filter(): level invalid - set to zero\n"); | |
308 return; | |
309 } | |
310 #endif | |
311 | |
312 #ifdef DEBUG | |
313 if (!dwt_filters) { | |
314 fprintf(stderr, "dwt_param_filter(): wm_dwt not initialized, call init_dwt() first\n"); | |
315 return; | |
316 } | |
317 #endif | |
318 | |
319 | |
320 for (i = 0; i < dwt_levels + 1; i++) { | |
321 | |
322 filter = malloc(sizeof(struct FilterGHStruct)); | |
323 #ifdef DEBUG | |
324 if (!filter) { | |
325 fprintf(stderr, "dwt_param_filter(): malloc failed()\n"); | |
326 return; | |
327 } | |
328 #endif | |
329 | |
330 filter->type = FTOrtho; | |
331 filter->name = "param"; | |
332 | |
333 filter->g = new_filter(2 * (param_len[i] + 1)); | |
334 filter->g->type = FTSymm; | |
335 filter->g->hipass = 1; | |
336 filter->g->len = gen_param_filter(filter->g->data, | |
337 param_len[i], &alpha[param_len_sum], | |
338 FILTERG); | |
339 filter->g->start = -filter->g->len / 2; | |
340 filter->g->end = filter->g->len / 2 - 1; | |
341 | |
342 filter->h = new_filter(2 * (param_len[i] + 1)); | |
343 filter->h->type = FTSymm; | |
344 filter->h->hipass = 0; | |
345 filter->h->len = gen_param_filter(filter->h->data, | |
346 param_len[i], &alpha[param_len_sum], | |
347 FILTERH); | |
348 filter->h->start = -filter->h->len / 2; | |
349 filter->h->end = filter->h->len / 2 - 1; | |
350 | |
351 filter->gi = 0; | |
352 filter->hi = 0; | |
353 | |
354 dwt_filters[i] = filter; | |
355 | |
356 param_len_sum += param_len[i]; | |
357 } | |
358 } | |
359 | |
360 void done_dwt() { | |
361 } |