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