00001 #include <stdio.h>
00002 #include <stdlib.h>
00003
00004 #include "sdc_despike_src.h"
00005 #include "fmedian_src.h"
00006 #include "idl_export.h"
00007
00008 #define DEBUG 0
00009 #define BLANK 0x80000000
00010 #define MISSING BLANK
00011
00012 #define DPRINTF(a) {if (DEBUG) printf a;}
00013 #define PRINTI(var) DPRINTF(("%20s= %ld\n",#var,(long)var));
00014 #define PRINTF(var) DPRINTF(("%20s= %f\n",#var,var));
00015 #define PRINTX(var) DPRINTF(("%20s= x%llx\n",#var,(unsigned long long)var))
00016
00017
00018 #define MALLOC(dest,num) \
00019 {dest = malloc((num) * sizeof(*dest)); \
00020 if ( ! dest ) { \
00021 printf("malloc error for " #dest " in sdc_despike\n"); return 1; } \
00022 }
00023
00024
00025 int pre_spike(int loc,int *locs, int last)
00026 {
00027 int spikeno;
00028 for (spikeno=0; spikeno<last; spikeno++) if (locs[spikeno] == loc) return 1;
00029 return 0;
00030 }
00031
00032 SDC_DESPIKE_SIG
00033 {
00034 int xi,yi;
00035 int loc;
00036 int badblobix;
00037 int blobbed = 0;
00038
00039 int free_mask = 0;
00040 int free_kernel = 0;
00041
00042 int *locs;
00043 int *olds;
00044 int *news;
00045
00046 int ksz = kernel_size;
00047
00048 int *median;
00049 int *median_workspace;
00050
00051 int primary_spike;
00052 int spike;
00053
00054 int fill;
00055
00056 int *restore_val;
00057 char *restore_mask;
00058
00059 DPRINTF(("sdc_despike_src() called\n"));
00060 PRINTX(image);
00061 PRINTX(mask);
00062 PRINTI(nx);
00063 PRINTI(ny);
00064 PRINTI(neighbour);
00065 PRINTX(kernel);
00066 PRINTI(kernel_size);
00067 PRINTI(xbox);
00068 PRINTI(ybox);
00069 PRINTI(max_var_low);
00070 PRINTF(max_factor_hi);
00071 PRINTI(limit);
00072 PRINTX(badblobs);
00073 PRINTI(sizeofbads);
00074 PRINTX(nspikes);
00075 PRINTX(*oldvalues);
00076 PRINTX(*spikelocs);
00077 PRINTX(*newvalues);
00078
00079
00080 if (mask==0) {
00081 free_mask = 1;
00082 MALLOC(mask,nx * ny);
00083 for (loc=0; loc< nx*ny; loc++) mask[loc] = 1;
00084 DPRINTF(("Generated fake mask\n"));
00085 }
00086
00087
00088
00089 MALLOC(restore_val, nx * ny);
00090 MALLOC(restore_mask, nx * ny);
00091 for (loc=0; loc < nx * ny; loc++) {
00092 restore_val[loc] = image[loc];
00093 restore_mask[loc] = ( image[loc]==MISSING || !mask[loc] );
00094 }
00095
00096
00097 if ( !ksz || !kernel) {
00098 int i;
00099
00100 ksz = 3;
00101 MALLOC(kernel, ksz * ksz);
00102 free_kernel=1;
00103 for (i=0; i < ksz*ksz; kernel[i++] = 0);
00104
00105 kernel[1 + 0*3]=1;
00106 kernel[1 + 2*3]=1;
00107 kernel[0 + 1*3]=1;
00108 kernel[2 + 1*3]=1;
00109 }
00110
00111
00112 MALLOC(*spikelocs, nx * ny); locs = *spikelocs;
00113 MALLOC(*oldvalues, nx * ny); olds = *oldvalues;
00114 MALLOC(*newvalues, nx * ny); news = *newvalues;
00115
00116
00117 MALLOC(median, nx * ny);
00118 MALLOC(median_workspace, xbox * ybox);
00119
00120
00121
00122
00123 DPRINTF(("Blobbing - flag as MISSING but don't record\n"));
00124
00125 badblobix=0;
00126 while (badblobix<sizeofbads) {
00127 int nperim = badblobs[ badblobix++ ];
00128 int npix;
00129 badblobix += nperim;
00130 npix = badblobs[ badblobix++ ];
00131
00132 while (npix--) {
00133 int loc = badblobs[ badblobix++ ];
00134 image[loc]=MISSING;
00135 blobbed++;
00136 }
00137 }
00138 DPRINTF(("Blobbed: %d\n",blobbed));
00139 loc = nx*ny - 1;
00140
00141 FMEDIAN_CALL(IDL_LONG,image,median,median_workspace,nx,ny,xbox,ybox,
00142 1, MISSING, 0);
00143
00144
00145
00146
00147
00148 #define HANDLE_SPIKE(spike,loc,locs,olds,image) \
00149 { \
00150 locs[spike] = loc; \
00151 olds[spike] = image[loc]; \
00152 image[loc] = MISSING; \
00153 spike++; \
00154 }
00155
00156 spike=0;
00157
00158 for (yi=0; yi<ny; yi++) {
00159 for (xi=0; xi<nx; xi++) {
00160 loc = xi + yi*nx;
00161 if (mask[loc] && image[loc] != MISSING) {
00162 if (image[loc] < limit) {
00163 if ( (image[loc]-median[loc]) > max_var_low ) {
00164 HANDLE_SPIKE(spike,loc,locs,olds,image);
00165 DPRINTF(("HANDLED (%d,%d)\n",xi,yi));
00166 }
00167 } else {
00168 float med = median[loc] ? median[loc] : 1.0;
00169 if ( image[loc]/med > max_factor_hi) {
00170 HANDLE_SPIKE(spike,loc,locs,olds,image);
00171 DPRINTF(("HANDLED (%d,%d)\n",xi,yi));
00172 }
00173 }
00174 }
00175 }
00176 }
00177 DPRINTF(("Main algorithm done\n"));
00178
00179 DPRINTF(("Primary spikes (no neighbour): %d\n",spike));
00180 primary_spike = spike;
00181
00182
00183
00184
00185
00186 while (neighbour--) {
00187 int midk = ksz/2;
00188
00189
00190
00191
00192
00193 int last_spike = spike;
00194
00195
00196
00197 for (yi=0; yi<ny; yi++) {
00198 for (xi=0; xi<nx; xi++) {
00199
00200
00201
00202 int max_xi = MIN2(nx, xi-midk+ksz);
00203
00204
00205
00206 int max_kern_xi = ksz - ((xi-midk+ksz) - max_xi);
00207
00208
00209 int min_xi = MAX2( 0, xi-midk);
00210
00211
00212
00213 int min_kern_xi = min_xi - (xi-midk);
00214
00215
00216
00217 int max_yi = MIN2(ny, yi-midk+ksz);
00218 int max_kern_yi = ksz - ((yi-midk+ksz) - max_yi);
00219 int min_yi = MAX2( 0, yi-midk);
00220 int min_kern_yi = min_yi - (yi-midk);
00221
00222 int kern_xi,kern_yi;
00223
00224 loc = xi + nx*yi;
00225
00226
00227 if (image[loc] == MISSING || !mask[loc]) {
00228 char *why = mask[loc] ? "MISSING" : "MASKED";
00229 DPRINTF(("(%d,%d; %d) already %s - skipping\n",xi,yi,loc,why));
00230 continue;
00231 }
00232
00233
00234 for (kern_yi=min_kern_yi; kern_yi<max_kern_yi; kern_yi++) {
00235 for (kern_xi=min_kern_xi; kern_xi<max_kern_xi; kern_xi++) {
00236
00237 if (kernel[kern_xi + ksz*kern_yi]) {
00238
00239
00240
00241
00242 int neighb_xi = (xi + kern_xi - midk);
00243 int neighb_yi = (yi + kern_yi - midk);
00244 int neighb_loc = neighb_xi + nx * neighb_yi;
00245
00246 if (image[neighb_loc] == MISSING) {
00247 char *what = "but not prev-round spike";
00248 DPRINTF(("(%d,%d; %d) neighb. (%d,%d; %d) is MISSING ",
00249 xi,yi,loc,neighb_xi,neighb_yi,neighb_loc));
00250 if (pre_spike(neighb_loc,locs,last_spike)) {
00251 what = "and a last-round spike";
00252 HANDLE_SPIKE(spike,loc,locs,olds,image);
00253 goto next_image_pixel;
00254 }
00255 DPRINTF((" - %s\n",what));
00256 }
00257 }
00258 }
00259 }
00260 next_image_pixel: ;
00261 }
00262 }
00263 DPRINTF(("Neighbour iteration done, flagged %d\n",spike-last_spike));
00264 }
00265 DPRINTF(("Neighbouring done, total flagged %d\n",spike-primary_spike));
00266
00267 *nspikes = spike;
00268
00269
00270
00271 fill=1;
00272 while (fill) {
00273 fill=0;
00274
00275
00276 FMEDIAN_CALL(IDL_LONG,image,median,median_workspace,nx,ny,xbox,ybox,
00277 1,MISSING,0);
00278
00279
00280 for (loc=0; loc<nx*ny; loc++) {
00281
00282 if (image[loc] == MISSING) {
00283 if (median[loc] != MISSING) image[loc] = median[loc];
00284 else fill=1;
00285 }
00286 }
00287 }
00288 DPRINTF(("\nFilled\n"));
00289
00290
00291 for (loc=0; loc < nx*ny; loc++) {
00292 if (restore_mask[loc]) image[loc] = restore_val[loc];
00293 }
00294
00295
00296 if (free_mask) free(mask);
00297 if (free_kernel) free(kernel);
00298 free(restore_val);
00299 free(restore_mask);
00300 free(median);
00301 free(median_workspace);
00302
00303
00304 for (spike=0; spike<*nspikes; spike++) {
00305 loc = locs[spike];
00306 news[spike] = image[loc];
00307 }
00308
00309
00310 return 0;
00311 }