00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029 #ifdef HAVE_CONFIG_H
00030 #include <config.h>
00031 #endif
00032
00033
00034
00035
00036
00037
00038 #include "irplib_filter.h"
00039
00040 #include <assert.h>
00041
00042
00058
00059
00062
00063
00064
00065
00066 static void
00067 irplib_image_filter_double_double(double *, const double *,
00068 int, int, int,
00069 int, unsigned);
00070
00071 static void
00072 irplib_image_filter_double_float(double *, const float *,
00073 int, int, int,
00074 int, unsigned);
00075 static void
00076 irplib_image_filter_double_int(double *, const int *,
00077 int, int, int,
00078 int, unsigned);
00079
00080 static void
00081 irplib_image_filter_float_double(float *, const double *,
00082 int, int, int,
00083 int, unsigned);
00084
00085 static void
00086 irplib_image_filter_float_float(float *, const float *,
00087 int, int, int,
00088 int, unsigned);
00089 static void
00090 irplib_image_filter_float_int(float *, const int *,
00091 int, int, int,
00092 int, unsigned);
00093
00094 static void
00095 irplib_image_filter_int_double(int *, const double *,
00096 int, int, int,
00097 int, unsigned);
00098
00099 static void
00100 irplib_image_filter_int_float(int *, const float *,
00101 int, int, int,
00102 int, unsigned);
00103 static void
00104 irplib_image_filter_int_int(int *, const int *,
00105 int, int, int,
00106 int, unsigned);
00107
00108
00109
00110
00111
00112
00164
00165
00166 cpl_error_code irplib_image_filter(cpl_image * self, const cpl_image * other,
00167 int hsizex, int hsizey,
00168 irplib_filter_mode mode)
00169 {
00170
00171 int nx, ny;
00172 const irplib_filter_mode filter_mode = mode & ~IRPLIB_FILTER_BORDER_MODE;
00173 const irplib_filter_mode border_mode = mode & IRPLIB_FILTER_BORDER_MODE;
00174
00175 cpl_ensure_code(self != NULL, CPL_ERROR_NULL_INPUT);
00176 cpl_ensure_code(other != NULL, CPL_ERROR_NULL_INPUT);
00177
00178 cpl_ensure_code(self != other, CPL_ERROR_UNSUPPORTED_MODE);
00179
00180 cpl_ensure_code(cpl_image_get_data(self) != cpl_image_get_data_const(other),
00181 CPL_ERROR_UNSUPPORTED_MODE);
00182
00183 cpl_ensure_code(hsizex >= 0, CPL_ERROR_ILLEGAL_INPUT);
00184 cpl_ensure_code(hsizey >= 0, CPL_ERROR_ILLEGAL_INPUT);
00185 cpl_ensure_code(hsizex >= 0 || hsizey >= 0, CPL_ERROR_ILLEGAL_INPUT);
00186
00187 nx = cpl_image_get_size_x(other);
00188 ny = cpl_image_get_size_y(other);
00189
00190 cpl_ensure_code(2 * hsizex + 1 <= nx, CPL_ERROR_ACCESS_OUT_OF_RANGE);
00191 cpl_ensure_code(2 * hsizey + 1 <= ny, CPL_ERROR_ACCESS_OUT_OF_RANGE);
00192
00193 if (border_mode == IRPLIB_FILTER_BORDER_CROP) {
00194 cpl_ensure_code(cpl_image_get_size_x(self) == nx - 2 * hsizex,
00195 CPL_ERROR_INCOMPATIBLE_INPUT);
00196
00197 cpl_ensure_code(cpl_image_get_size_y(self) == ny - 2 * hsizex,
00198 CPL_ERROR_INCOMPATIBLE_INPUT);
00199
00200 } else {
00201 cpl_ensure_code(cpl_image_get_size_x(self) == nx,
00202 CPL_ERROR_INCOMPATIBLE_INPUT);
00203
00204 cpl_ensure_code(cpl_image_get_size_y(self) == ny,
00205 CPL_ERROR_INCOMPATIBLE_INPUT);
00206
00207 }
00208
00209 if (filter_mode == IRPLIB_FILTER_MEDIAN) {
00210
00211 cpl_ensure_code(cpl_image_get_type(self) == cpl_image_get_type(other),
00212 CPL_ERROR_TYPE_MISMATCH);
00213
00214 if (hsizex != 1 || hsizey != 1) {
00215 cpl_ensure_code(border_mode == IRPLIB_FILTER_BORDER_NOP,
00216 CPL_ERROR_UNSUPPORTED_MODE);
00217 }
00218
00219 switch (cpl_image_get_type(other)) {
00220 case CPL_TYPE_DOUBLE:
00221 irplib_image_filter_double(cpl_image_get_data_double(self),
00222 cpl_image_get_data_double_const(other),
00223 (unsigned)nx, (unsigned)ny,
00224 (unsigned)hsizex, (unsigned)hsizey,
00225 (unsigned)mode);
00226 break;
00227 case CPL_TYPE_FLOAT:
00228 irplib_image_filter_float(cpl_image_get_data_float(self),
00229 cpl_image_get_data_float_const(other),
00230 (unsigned)nx, (unsigned)ny,
00231 (unsigned)hsizex, (unsigned)hsizey,
00232 (unsigned)mode);
00233 break;
00234 case CPL_TYPE_INT:
00235 irplib_image_filter_int(cpl_image_get_data_int(self),
00236 cpl_image_get_data_int_const(other),
00237 (unsigned)nx, (unsigned)ny,
00238 (unsigned)hsizex, (unsigned)hsizey,
00239 (unsigned)mode);
00240 break;
00241 default:
00242
00243 assert( 0 );
00244 }
00245
00246 } else if (filter_mode == IRPLIB_FILTER_AVERAGE) {
00247
00248 cpl_ensure_code(border_mode == IRPLIB_FILTER_BORDER_FILTER,
00249 CPL_ERROR_UNSUPPORTED_MODE);
00250
00251 switch (cpl_image_get_type(self)) {
00252 case CPL_TYPE_DOUBLE: {
00253 switch (cpl_image_get_type(other)) {
00254 case CPL_TYPE_DOUBLE:
00255 irplib_image_filter_double_double(cpl_image_get_data_double(self),
00256 cpl_image_get_data_double_const(other),
00257 nx, ny,
00258 hsizex, hsizey,
00259 (unsigned)mode);
00260 break;
00261 case CPL_TYPE_FLOAT:
00262 irplib_image_filter_double_float(cpl_image_get_data_double(self),
00263 cpl_image_get_data_float_const(other),
00264 nx, ny,
00265 hsizex, hsizey,
00266 (unsigned)mode);
00267 break;
00268 case CPL_TYPE_INT:
00269 irplib_image_filter_double_int(cpl_image_get_data_double(self),
00270 cpl_image_get_data_int_const(other),
00271 nx, ny,
00272 hsizex, hsizey,
00273 (unsigned)mode);
00274 break;
00275 default:
00276
00277 assert( 0 );
00278 }
00279
00280 break;
00281 }
00282
00283 case CPL_TYPE_FLOAT: {
00284 switch (cpl_image_get_type(other)) {
00285 case CPL_TYPE_DOUBLE:
00286 irplib_image_filter_float_double(cpl_image_get_data_float(self),
00287 cpl_image_get_data_double_const(other),
00288 nx, ny,
00289 hsizex, hsizey,
00290 (unsigned)mode);
00291 break;
00292 case CPL_TYPE_FLOAT:
00293 irplib_image_filter_float_float(cpl_image_get_data_float(self),
00294 cpl_image_get_data_float_const(other),
00295 nx, ny,
00296 hsizex, hsizey,
00297 (unsigned)mode);
00298 break;
00299 case CPL_TYPE_INT:
00300 irplib_image_filter_float_int(cpl_image_get_data_float(self),
00301 cpl_image_get_data_int_const(other),
00302 nx, ny,
00303 hsizex, hsizey,
00304 (unsigned)mode);
00305 break;
00306 default:
00307
00308 assert( 0 );
00309 }
00310 break;
00311 }
00312
00313
00314 case CPL_TYPE_INT: {
00315 switch (cpl_image_get_type(other)) {
00316 case CPL_TYPE_DOUBLE:
00317 irplib_image_filter_int_double(cpl_image_get_data_int(self),
00318 cpl_image_get_data_double_const(other),
00319 nx, ny,
00320 hsizex, hsizey,
00321 (unsigned)mode);
00322 break;
00323 case CPL_TYPE_FLOAT:
00324 irplib_image_filter_int_float(cpl_image_get_data_int(self),
00325 cpl_image_get_data_float_const(other),
00326 nx, ny,
00327 hsizex, hsizey,
00328 (unsigned)mode);
00329 break;
00330 case CPL_TYPE_INT:
00331 irplib_image_filter_int_int(cpl_image_get_data_int(self),
00332 cpl_image_get_data_int_const(other),
00333 nx, ny,
00334 hsizex, hsizey,
00335 (unsigned)mode);
00336 break;
00337 default:
00338
00339 assert( 0 );
00340 }
00341 break;
00342 }
00343
00344 default:
00345
00346 assert( 0 );
00347 }
00348 } else {
00349 cpl_ensure_code(0, CPL_ERROR_UNSUPPORTED_MODE);
00350 }
00351
00352
00353 return CPL_ERROR_NONE;
00354
00355 }
00356
00359
00360
00361 #define CONCAT(a,b) a ## _ ## b
00362 #define CONCAT2X(a,b) CONCAT(a,b)
00363
00364 #define IN_TYPE double
00365 #define OUT_TYPE double
00366 #define ACCU_TYPE double
00367 #include "irplib_filter_body.c"
00368
00369 #define IN_TYPE float
00370 #define OUT_TYPE float
00371 #define ACCU_TYPE float
00372 #include "irplib_filter_body.c"
00373
00374 #define IN_TYPE int
00375 #define OUT_TYPE int
00376 #define ACCU_TYPE int
00377 #define ACCU_TYPE_IS_INT
00378 #include "irplib_filter_body.c"
00379
00380
00381 #define IN_TYPE double
00382 #define OUT_TYPE float
00383 #define ACCU_TYPE double
00384 #include "irplib_filter_body.c"
00385
00386 #define IN_TYPE double
00387 #define OUT_TYPE int
00388 #define ACCU_TYPE double
00389 #include "irplib_filter_body.c"
00390
00391 #define IN_TYPE float
00392 #define OUT_TYPE double
00393 #define ACCU_TYPE double
00394 #include "irplib_filter_body.c"
00395
00396 #define IN_TYPE float
00397 #define OUT_TYPE int
00398 #define ACCU_TYPE float
00399 #include "irplib_filter_body.c"
00400
00401
00402 #define IN_TYPE int
00403 #define OUT_TYPE double
00404 #define ACCU_TYPE double
00405 #include "irplib_filter_body.c"
00406
00407 #define IN_TYPE int
00408 #define OUT_TYPE float
00409 #define ACCU_TYPE float
00410 #include "irplib_filter_body.c"