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 } |
