00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020 #ifdef HAVE_CONFIG_H
00021 # include <config.h>
00022 #endif
00023
00024
00025
00026
00027
00028 #include <irplib_filter.h>
00029 #include <irplib_test.h>
00030
00031
00032 #include <math.h>
00033 #include <assert.h>
00034
00035
00036 #include <time.h>
00037
00038
00039 #include <string.h>
00040
00041
00042
00043
00044
00045 #ifndef BENCHSIZE
00046 #define BENCHSIZE 5
00047 #endif
00048
00049 #define assure(x) assert(x)
00050
00051 #ifdef bool
00052 #define mybool bool
00053 #else
00054 #define mybool unsigned char
00055 #endif
00056
00057 #ifdef true
00058 #define mytrue true
00059 #else
00060 #define mytrue 1
00061 #endif
00062
00063 #ifdef false
00064 #define myfalse false
00065 #else
00066 #define myfalse 0
00067 #endif
00068
00069
00070
00071
00072
00073 static void test_filter(void);
00074
00075 static void benchmark(irplib_filter_mode filter,
00076 irplib_filter_mode border_mode);
00077
00078 static double rand_gauss(void);
00079 static int test_irplib_image_filter_double(unsigned, unsigned, unsigned,
00080 unsigned, unsigned, unsigned,
00081 unsigned);
00082 static int test_irplib_image_filter_float(unsigned, unsigned, unsigned,
00083 unsigned, unsigned, unsigned,
00084 unsigned);
00085 static int test_irplib_image_filter_int(unsigned, unsigned, unsigned,
00086 unsigned, unsigned, unsigned,
00087 unsigned);
00088
00089 static void test_irplib_image_filter(int, int,
00090 int, int,
00091 irplib_filter_mode,
00092 irplib_filter_mode);
00093
00094 #ifdef IRPLIB_FILTER_TEST_AVERAGE_FAST
00095
00096 static void
00097 image_filter_average_ref_double(double *, const double *,
00098 int, int, int,
00099 int, unsigned);
00100
00101
00102 static void
00103 image_filter_average_ref_float(float *, const float *,
00104 int, int, int,
00105 int, unsigned);
00106
00107 static void
00108 image_filter_average_ref_int(int *, const int *,
00109 int, int, int,
00110 int, unsigned);
00111
00112 #elif 1
00113
00114 static void
00115 image_filter_average_bf_double(double *, const double *,
00116 int, int, int,
00117 int, unsigned);
00118
00119 static void
00120 image_filter_average_bf_float(float *, const float *,
00121 int, int, int,
00122 int, unsigned);
00123
00124 static void
00125 image_filter_average_bf_int(int *, const int *,
00126 int, int, int,
00127 int, unsigned);
00128
00129 #else
00130 static cpl_error_code filter_average_bf(cpl_image *, const cpl_image *,
00131 unsigned, unsigned, unsigned);
00132
00133 #endif
00134
00135
00139
00140
00141
00145
00146
00147
00151
00152 int main(void)
00153 {
00154
00155 IRPLIB_TEST_INIT;
00156
00157 test_filter();
00158
00159 IRPLIB_TEST_END;
00160 }
00161
00162
00163
00167
00168 static void test_filter(void)
00169 {
00170 const irplib_filter_mode filter_mode[] = {IRPLIB_FILTER_AVERAGE,
00171 IRPLIB_FILTER_MEDIAN};
00172
00173 const irplib_filter_mode border_mode[] = {IRPLIB_FILTER_BORDER_NOP,
00174 IRPLIB_FILTER_BORDER_FILTER,
00175 IRPLIB_FILTER_BORDER_EXTRAPOL_OUT,
00176 IRPLIB_FILTER_BORDER_CROP,
00177 IRPLIB_FILTER_BORDER_COPY};
00178 const int dopix[] = {3, 8, 17, 32};
00179 const int dor[] = {0, 1, 2, 3, 4, 7};
00180
00181
00182 unsigned ifilt;
00183
00184 for (ifilt = 0;
00185 ifilt < sizeof(filter_mode)/sizeof(filter_mode[0]);
00186 ifilt++) {
00187
00188 unsigned ibord;
00189
00190 for (ibord = 0 ;
00191 ibord < sizeof(border_mode)/sizeof(border_mode[0]);
00192 ibord++) {
00193
00194 unsigned ix;
00195
00196 if (filter_mode[ifilt] == IRPLIB_FILTER_AVERAGE &&
00197 border_mode[ibord] != IRPLIB_FILTER_BORDER_FILTER) continue;
00198
00199 for (ix = 0; ix < sizeof(dopix)/sizeof(dopix[0]); ix++) {
00200 const int nx = dopix[ix];
00201 unsigned iy;
00202
00203 for (iy = 0; iy < sizeof(dopix)/sizeof(dopix[0]); iy++) {
00204 const int ny = dopix[iy];
00205 unsigned irx;
00206
00207 for (irx = 0; irx < sizeof(dor)/sizeof(dor[0]); irx++) {
00208 const int rx =
00209 2*dor[irx] + 1 >= nx ? (nx-1)/2 : dor[irx];
00210 unsigned iry;
00211
00212 for (iry = 0; iry < sizeof(dor)/sizeof(dor[0]); iry++) {
00213 const int ry =
00214 2*dor[iry] + 1 >= ny ? (ny-1)/2 : dor[iry];
00215
00216 if (filter_mode[ifilt] == IRPLIB_FILTER_MEDIAN &&
00217 border_mode[ibord] != IRPLIB_FILTER_BORDER_NOP &&
00218 !(rx == 1 && ry == 1)) {
00219
00220 continue;
00221 }
00222
00223 if (2*rx + 1 <= nx &&
00224 2*ry + 1 <= ny) {
00225 test_irplib_image_filter(nx, ny, rx, ry,
00226 filter_mode[ifilt],
00227 border_mode[ibord]);
00228 }
00229 }
00230 }
00231 }
00232 }
00233
00234 benchmark(filter_mode[ifilt], border_mode[ibord]);
00235 }
00236 }
00237 }
00238
00239 static void test_irplib_image_filter(int nx, int ny,
00240 int rx, int ry,
00241 irplib_filter_mode filter,
00242 irplib_filter_mode border_mode)
00243 {
00244 cpl_msg_debug(cpl_func,
00245 "Testing %dx%d image, "
00246 "%dx%d kernel, filter = %d, border = %d",
00247 nx, ny, rx, ry,
00248 filter, border_mode);
00249
00250
00251 {
00252 cpl_image * in = cpl_image_new(nx, ny, CPL_TYPE_FLOAT);
00253 cpl_image * out = cpl_image_new(nx, ny, CPL_TYPE_FLOAT);
00254
00255 assert( in != NULL);
00256 assert( out != NULL);
00257
00258 irplib_test_eq(irplib_image_filter(NULL, in, rx, ry,
00259 filter | border_mode),
00260 CPL_ERROR_NULL_INPUT);
00261
00262 cpl_error_reset();
00263
00264 irplib_test_eq(irplib_image_filter(out, NULL, rx, ry,
00265 filter | border_mode),
00266 CPL_ERROR_NULL_INPUT);
00267
00268 cpl_error_reset();
00269
00270 cpl_image_delete(in);
00271 cpl_image_delete(out);
00272 }
00273
00274
00275 irplib_test( !test_irplib_image_filter_double(nx, ny,
00276 rx, ry,
00277 filter | border_mode, 1, 1));
00278 irplib_test( !test_irplib_image_filter_float(nx, ny,
00279 rx, ry,
00280 filter | border_mode, 1, 1));
00281 irplib_test( !test_irplib_image_filter_int(nx, ny,
00282 rx, ry,
00283 filter | border_mode, 1, 1));
00284 return;
00285 }
00286
00287 static
00288 void benchmark(irplib_filter_mode filter,
00289 irplib_filter_mode border_mode)
00290 {
00291 irplib_filter_mode mode = filter | border_mode;
00292
00293 irplib_test( !test_irplib_image_filter_float(BENCHSIZE, BENCHSIZE, 1, 1,
00294 mode, 100, 3));
00295 irplib_test( !test_irplib_image_filter_double(BENCHSIZE, BENCHSIZE, 1, 1,
00296 mode, 100, 3));
00297 irplib_test( !test_irplib_image_filter_int(BENCHSIZE, BENCHSIZE, 1, 1,
00298 mode, 100, 3));
00299
00300 if (border_mode == IRPLIB_FILTER_BORDER_NOP) {
00301
00302 irplib_test( !test_irplib_image_filter_float(BENCHSIZE, BENCHSIZE, 2, 2,
00303 mode, 20, 3));
00304 irplib_test( !test_irplib_image_filter_double(BENCHSIZE, BENCHSIZE, 2, 2,
00305 mode, 20, 3));
00306 irplib_test( !test_irplib_image_filter_int(BENCHSIZE, BENCHSIZE, 2, 2,
00307 mode, 20, 3));
00308
00309 if (filter == IRPLIB_FILTER_AVERAGE) {
00310
00311 irplib_test( !test_irplib_image_filter_float(BENCHSIZE, BENCHSIZE, 14, 14,
00312 mode, 20, 3));
00313 irplib_test( !test_irplib_image_filter_double(BENCHSIZE, BENCHSIZE, 14, 14,
00314 mode, 20, 3));
00315 irplib_test( !test_irplib_image_filter_int(BENCHSIZE, BENCHSIZE, 14, 14,
00316 mode, 20, 3));
00317 }
00318 }
00319
00320 return;
00321 }
00322
00323
00324 static
00325 double rand_gauss(void)
00326 {
00327 static double V1, V2, S;
00328 static int phase = 0;
00329 double X;
00330
00331 if(phase == 0) {
00332 do {
00333 double U1 = (double)rand() / RAND_MAX;
00334 double U2 = (double)rand() / RAND_MAX;
00335
00336 V1 = 2 * U1 - 1;
00337 V2 = 2 * U2 - 1;
00338 S = V1 * V1 + V2 * V2;
00339 } while(S >= 1 || S == 0);
00340
00341 X = V1 * sqrt(-2 * log(S) / S);
00342 } else
00343 X = V2 * sqrt(-2 * log(S) / S);
00344
00345 phase = 1 - phase;
00346
00347 return X;
00348 }
00349
00350 #if 0
00351 static cpl_error_code filter_average_bf(cpl_image * self,
00352 const cpl_image * other,
00353 unsigned hsizex, unsigned hsizey,
00354 unsigned mode)
00355 {
00356
00357 const int nx = cpl_image_get_size_x(self);
00358 const int ny = cpl_image_get_size_y(self);
00359 cpl_matrix * kernel = cpl_matrix_new(1+2*hsizex, 1+2*hsizey);
00360 cpl_image * copy;
00361 cpl_errorstate prevstate = cpl_errorstate_get();
00362
00363 cpl_matrix_fill(kernel, 1.0);
00364
00365 copy = cpl_image_filter_linear(other, kernel);
00366
00367 if (cpl_error_get_code()) {
00368 cpl_errorstate_dump(prevstate, CPL_FALSE, NULL);
00369 }
00370
00371 assert(copy != NULL);
00372
00373 assert(cpl_image_get_type(copy) == cpl_image_get_type(self));
00374 assert(cpl_image_get_size_x(copy) == nx);
00375 assert(cpl_image_get_size_y(copy) == ny);
00376
00377 assert((mode & ~IRPLIB_FILTER_BORDER_MODE) == IRPLIB_FILTER_AVERAGE);
00378
00379 switch (cpl_image_get_type(self)) {
00380 case CPL_TYPE_DOUBLE: {
00381 const double * sour = cpl_image_get_data_double_const(copy);
00382 double * dest = cpl_image_get_data_double(self);
00383
00384 (void)memcpy(dest, sour, nx*ny*sizeof(double));
00385
00386 break;
00387 }
00388
00389 case CPL_TYPE_FLOAT: {
00390 const float * sour = cpl_image_get_data_float_const(copy);
00391 float * dest = cpl_image_get_data_float(self);
00392
00393 (void)memcpy(dest, sour, nx*ny*sizeof(float));
00394
00395 break;
00396 }
00397 case CPL_TYPE_INT: {
00398 const int * sour = cpl_image_get_data_int_const(copy);
00399 int * dest = cpl_image_get_data_int(self);
00400
00401 (void)memcpy(dest, sour, nx*ny*sizeof(int));
00402
00403 break;
00404 }
00405 default:
00406
00407 assert( 0 );
00408 }
00409
00410 cpl_image_delete(copy);
00411
00412 return cpl_error_get_code();
00413
00414 }
00415
00416 #endif
00417
00418
00419
00420 #define CONCAT(a,b) a ## _ ## b
00421 #define CONCAT2X(a,b) CONCAT(a,b)
00422
00423 #define PIXEL_TYPE double
00424 #include "filter_median_type.c"
00425 #undef PIXEL_TYPE
00426
00427 #define PIXEL_TYPE float
00428 #include "filter_median_type.c"
00429 #undef PIXEL_TYPE
00430
00431 #define PIXEL_TYPE_IS_INT 1
00432 #define PIXEL_TYPE int
00433 #include "filter_median_type.c"
00434 #undef PIXEL_TYPE
00435 #undef PIXEL_TYPE_IS_INT