From f6cee4785f35166482e0cd9af936aba97636bf4e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Igor=20Podgain=C3=B5i?= Date: Mon, 24 Jun 2024 17:28:45 +0200 Subject: [PATCH 1/2] Refactor Gaussian blur API - Changed the filter context creation API: - More intuitive function and arguments names - Kernel size parameters added - Intermediate size now automatically deduced from the kernel size parameters - Changed the implementation API: - Unified separate kernel size APIs into one - Changed specification to allow future support for custom sigma values - Simplified the HAL handler - Modified unit tests and also added some new ones - Other miscellaneous refactoring --- adapters/opencv/kleidicv_hal.cpp | 44 +- benchmark/benchmark.cpp | 33 +- .../include/kleidicv/filters/gaussian_blur.h | 102 +- kleidicv/include/kleidicv/kleidicv.h | 161 +-- kleidicv/src/filters/gaussian_blur_api.cpp | 50 +- kleidicv/src/filters/gaussian_blur_neon.cpp | 91 +- kleidicv/src/filters/gaussian_blur_sc.h | 58 +- kleidicv/src/filters/gaussian_blur_sme2.cpp | 46 +- kleidicv/src/filters/gaussian_blur_sve2.cpp | 55 +- test/api/test_gaussian_blur.cpp | 945 +++++++++--------- 10 files changed, 700 insertions(+), 885 deletions(-) diff --git a/adapters/opencv/kleidicv_hal.cpp b/adapters/opencv/kleidicv_hal.cpp index c2fff2edf..1a90fd24c 100644 --- a/adapters/opencv/kleidicv_hal.cpp +++ b/adapters/opencv/kleidicv_hal.cpp @@ -247,8 +247,8 @@ int gaussian_blur_binomial(const uchar *src_data, size_t src_step, return CV_HAL_ERROR_NOT_IMPLEMENTED; } - if ((margin_left != 0) || (margin_top != 0) || (margin_right != 0) || - (margin_bottom != 0)) { + if (margin_left != 0 || margin_top != 0 || margin_right != 0 || + margin_bottom != 0) { return CV_HAL_ERROR_NOT_IMPLEMENTED; } @@ -265,43 +265,19 @@ int gaussian_blur_binomial(const uchar *src_data, size_t src_step, return CV_HAL_ERROR_NOT_IMPLEMENTED; } - decltype(kleidicv_gaussian_blur_3x3_u8) impl{nullptr}; - if ((kernel_size == 3) && (width >= 3) && (height >= 3)) { - impl = kleidicv_gaussian_blur_3x3_u8; - } else if ((kernel_size == 5) && (width >= 5) && (height >= 5)) { - impl = kleidicv_gaussian_blur_5x5_u8; - } else if ((kernel_size == 7) && (width >= 7) && (height >= 7)) { - impl = kleidicv_gaussian_blur_7x7_u8; - } else if ((kernel_size == 15) && (width >= 15) && (height >= 15)) { - impl = kleidicv_gaussian_blur_15x15_u8; - } else { - return CV_HAL_ERROR_NOT_IMPLEMENTED; - } - kleidicv_filter_context_t *context; - size_t type_size = get_type_size(depth); - if (type_size == SIZE_MAX) { - return CV_HAL_ERROR_NOT_IMPLEMENTED; - } - - // widening - size_t intermediate_size = - (kernel_size == 15) ? 4 * type_size : 2 * type_size; - - kleidicv_rectangle_t image = { - .width = static_cast(width), - .height = static_cast(height)}; - if (kleidicv_error_t create_err = - kleidicv_filter_create(&context, cn, intermediate_size, image)) { + if (kleidicv_error_t create_err = kleidicv_filter_context_create( + &context, cn, kernel_size, kernel_size, static_cast(width), + static_cast(height))) { return convert_error(create_err); } - kleidicv_error_t blur_err = - impl(reinterpret_cast(src_data), src_step, - reinterpret_cast(dst_data), dst_step, width, height, cn, - kleidicv_border_type, context); + kleidicv_error_t blur_err = kleidicv_gaussian_blur_u8( + reinterpret_cast(src_data), src_step, + reinterpret_cast(dst_data), dst_step, width, height, cn, + kernel_size, kernel_size, 0.0, 0.0, kleidicv_border_type, context); - kleidicv_error_t release_err = kleidicv_filter_release(context); + kleidicv_error_t release_err = kleidicv_filter_context_release(context); return convert_error(blur_err ? blur_err : release_err); } diff --git a/benchmark/benchmark.cpp b/benchmark/benchmark.cpp index 1af3daece..bbf5bec00 100644 --- a/benchmark/benchmark.cpp +++ b/benchmark/benchmark.cpp @@ -224,45 +224,44 @@ static void resize_linear_4x4_f32(benchmark::State& state) { } BENCHMARK(resize_linear_4x4_f32); -template -static void gaussian_blur(Function f, benchmark::State& state) { +template +static void gaussian_blur(benchmark::State& state) { kleidicv_filter_context_t* context; - kleidicv_error_t err = - kleidicv_filter_create(&context, Channels, WideningMultiplier * sizeof(T), - kleidicv_rectangle_t{image_width, image_height}); + kleidicv_error_t err = kleidicv_filter_context_create( + &context, Channels, KernelSize, KernelSize, image_width, image_height); if (err != KLEIDICV_OK) { state.SkipWithError("Could not initialize Gaussian blur filter."); return; } - bench_functor(state, [f, context]() { - (void)f(get_source_buffer_a(), - image_width * Channels * sizeof(T), - get_destination_buffer(), - image_width * Channels * sizeof(T), image_width, image_height, - Channels, KLEIDICV_BORDER_TYPE_REFLECT, context); + bench_functor(state, [context]() { + (void)kleidicv_gaussian_blur_u8( + get_source_buffer_a(), image_width * Channels * sizeof(T), + get_destination_buffer(), + image_width * Channels * sizeof(T), image_width, image_height, Channels, + KernelSize, KernelSize, 0.0, 0.0, KLEIDICV_BORDER_TYPE_REFLECT, + context); }); - (void)kleidicv_filter_release(context); + (void)kleidicv_filter_context_release(context); } static void gaussian_blur_7x7_u8_1ch(benchmark::State& state) { - gaussian_blur(kleidicv_gaussian_blur_7x7_u8, state); + gaussian_blur(state); } BENCHMARK(gaussian_blur_7x7_u8_1ch); static void gaussian_blur_7x7_u8_3ch(benchmark::State& state) { - gaussian_blur(kleidicv_gaussian_blur_7x7_u8, state); + gaussian_blur(state); } BENCHMARK(gaussian_blur_7x7_u8_3ch); static void gaussian_blur_15x15_u8_1ch(benchmark::State& state) { - gaussian_blur(kleidicv_gaussian_blur_15x15_u8, state); + gaussian_blur(state); } BENCHMARK(gaussian_blur_15x15_u8_1ch); static void gaussian_blur_15x15_u8_3ch(benchmark::State& state) { - gaussian_blur(kleidicv_gaussian_blur_15x15_u8, state); + gaussian_blur(state); } BENCHMARK(gaussian_blur_15x15_u8_3ch); diff --git a/kleidicv/include/kleidicv/filters/gaussian_blur.h b/kleidicv/include/kleidicv/filters/gaussian_blur.h index d14f75e43..eee58e7d0 100644 --- a/kleidicv/include/kleidicv/filters/gaussian_blur.h +++ b/kleidicv/include/kleidicv/filters/gaussian_blur.h @@ -12,97 +12,37 @@ namespace kleidicv { namespace neon { -kleidicv_error_t gaussian_blur_3x3_u8(const uint8_t *src, size_t src_stride, - uint8_t *dst, size_t dst_stride, - size_t width, size_t height, - size_t channels, - kleidicv_border_type_t border_type, - kleidicv_filter_context_t *context); - -kleidicv_error_t gaussian_blur_5x5_u8(const uint8_t *src, size_t src_stride, - uint8_t *dst, size_t dst_stride, - size_t width, size_t height, - size_t channels, - kleidicv_border_type_t border_type, - kleidicv_filter_context_t *context); - -kleidicv_error_t gaussian_blur_7x7_u8(const uint8_t *src, size_t src_stride, - uint8_t *dst, size_t dst_stride, - size_t width, size_t height, - size_t channels, - kleidicv_border_type_t border_type, - kleidicv_filter_context_t *context); - -kleidicv_error_t gaussian_blur_15x15_u8(const uint8_t *src, size_t src_stride, - uint8_t *dst, size_t dst_stride, - size_t width, size_t height, - size_t channels, - kleidicv_border_type_t border_type, - kleidicv_filter_context_t *context); +kleidicv_error_t gaussian_blur_u8(const uint8_t *src, size_t src_stride, + uint8_t *dst, size_t dst_stride, size_t width, + size_t height, size_t channels, + size_t kernel_width, size_t kernel_height, + float sigma_x, float sigma_y, + kleidicv_border_type_t border_type, + kleidicv_filter_context_t *context); } // namespace neon namespace sve2 { -kleidicv_error_t gaussian_blur_3x3_u8(const uint8_t *src, size_t src_stride, - uint8_t *dst, size_t dst_stride, - size_t width, size_t height, - size_t channels, - kleidicv_border_type_t border_type, - kleidicv_filter_context_t *context); - -kleidicv_error_t gaussian_blur_5x5_u8(const uint8_t *src, size_t src_stride, - uint8_t *dst, size_t dst_stride, - size_t width, size_t height, - size_t channels, - kleidicv_border_type_t border_type, - kleidicv_filter_context_t *context); - -kleidicv_error_t gaussian_blur_7x7_u8(const uint8_t *src, size_t src_stride, - uint8_t *dst, size_t dst_stride, - size_t width, size_t height, - size_t channels, - kleidicv_border_type_t border_type, - kleidicv_filter_context_t *context); - -kleidicv_error_t gaussian_blur_15x15_u8(const uint8_t *src, size_t src_stride, - uint8_t *dst, size_t dst_stride, - size_t width, size_t height, - size_t channels, - kleidicv_border_type_t border_type, - kleidicv_filter_context_t *context); +kleidicv_error_t gaussian_blur_u8(const uint8_t *src, size_t src_stride, + uint8_t *dst, size_t dst_stride, size_t width, + size_t height, size_t channels, + size_t kernel_width, size_t kernel_height, + float sigma_x, float sigma_y, + kleidicv_border_type_t border_type, + kleidicv_filter_context_t *context); } // namespace sve2 namespace sme2 { -kleidicv_error_t gaussian_blur_3x3_u8(const uint8_t *src, size_t src_stride, - uint8_t *dst, size_t dst_stride, - size_t width, size_t height, - size_t channels, - kleidicv_border_type_t border_type, - kleidicv_filter_context_t *context); - -kleidicv_error_t gaussian_blur_5x5_u8(const uint8_t *src, size_t src_stride, - uint8_t *dst, size_t dst_stride, - size_t width, size_t height, - size_t channels, - kleidicv_border_type_t border_type, - kleidicv_filter_context_t *context); - -kleidicv_error_t gaussian_blur_7x7_u8(const uint8_t *src, size_t src_stride, - uint8_t *dst, size_t dst_stride, - size_t width, size_t height, - size_t channels, - kleidicv_border_type_t border_type, - kleidicv_filter_context_t *context); - -kleidicv_error_t gaussian_blur_15x15_u8(const uint8_t *src, size_t src_stride, - uint8_t *dst, size_t dst_stride, - size_t width, size_t height, - size_t channels, - kleidicv_border_type_t border_type, - kleidicv_filter_context_t *context); +kleidicv_error_t gaussian_blur_u8(const uint8_t *src, size_t src_stride, + uint8_t *dst, size_t dst_stride, size_t width, + size_t height, size_t channels, + size_t kernel_width, size_t kernel_height, + float sigma_x, float sigma_y, + kleidicv_border_type_t border_type, + kleidicv_filter_context_t *context); } // namespace sme2 diff --git a/kleidicv/include/kleidicv/kleidicv.h b/kleidicv/include/kleidicv/kleidicv.h index b74a3aa2f..06be5ca8f 100644 --- a/kleidicv/include/kleidicv/kleidicv.h +++ b/kleidicv/include/kleidicv/kleidicv.h @@ -1163,130 +1163,79 @@ KLEIDICV_API_DECLARATION(kleidicv_canny_u8, const uint8_t *src, /// /// Before a Gaussian blur operation, this initialization is needed. /// After the operation is finished, the context needs to be released -/// using @ref kleidicv_filter_release. -/// -/// @param context Pointer where to return the created context's address. -/// @param channels Number of channels in the data. Must be not more than -/// @ref KLEIDICV_MAXIMUM_CHANNEL_COUNT. -/// @param intermediate_size Size of an intermediate buffer element in bytes. -/// The element must be large enough to fit values of -/// the intermediate type used internally by the -/// Gaussian blur operation. -/// @param image Image dimensions. Its size must not be more than -/// @ref KLEIDICV_MAX_IMAGE_PIXELS. -/// -kleidicv_error_t kleidicv_filter_create(kleidicv_filter_context_t **context, - size_t channels, - size_t intermediate_size, - kleidicv_rectangle_t image); +/// using @ref kleidicv_filter_context_release. +/// +/// @param context Pointer where to return the created context's +/// address. +/// @param max_channels Maximum number of channels in the data. Must not be +/// more than @ref KLEIDICV_MAXIMUM_CHANNEL_COUNT. +/// @param max_kernel_width Maximum width of the Gaussian blur kernel. +/// @param max_kernel_height Maximum height of the Gaussian blur kernel. +/// @param max_image_width Maximum image width. max_image_width * +/// max_image_height must not be more than @ref +/// KLEIDICV_MAX_IMAGE_PIXELS. +/// @param max_image_height Maximum image height. max_image_width * +/// max_image_height must not be more than @ref +/// KLEIDICV_MAX_IMAGE_PIXELS. +/// +kleidicv_error_t kleidicv_filter_context_create( + kleidicv_filter_context_t **context, size_t max_channels, + size_t max_kernel_width, size_t max_kernel_height, size_t max_image_width, + size_t max_image_height); /// Releases a filter context that was previously created using @ref -/// kleidicv_filter_create. +/// kleidicv_filter_context_create. /// /// @param context Pointer to filter context. Must not be nullptr. /// -kleidicv_error_t kleidicv_filter_release(kleidicv_filter_context_t *context); +kleidicv_error_t kleidicv_filter_context_release( + kleidicv_filter_context_t *context); -/// Convolves the source image with the specified Gaussian kernel. +/// Applies Gaussian blur to the source image using the specified parameters. /// In-place filtering is not supported. /// -/// 3x3 Gaussian Blur filter for uint8_t types: -/// ``` -/// [ 1, 2, 1 ] -/// 1/16 * [ 2, 4, 2 ] -/// [ 1, 2, 1 ] -/// ``` -/// 5x5 Gaussian Blur filter for uint8_t types: -/// ``` -/// [ 1, 4, 6, 4, 1 ] -/// [ 4, 16, 24, 16, 4 ] -/// 1/256 * [ 6, 24, 36, 24, 6 ] -/// [ 4, 16, 24, 16, 4 ] -/// [ 1, 4, 6, 4, 1 ] -/// ``` -/// 7x7 Gaussian Blur filter for uint8_t types: -/// ``` -/// [ 4, 14, 28, 36, 28, 14, 4 ] -/// [ 14, 49, 98, 126, 98, 49, 14 ] -/// [ 28, 98, 196, 252, 196, 98, 28 ] -/// 1/4096 * [ 36, 126, 252, 324, 252, 126, 36 ] -/// [ 28, 98, 196, 252, 196, 98, 28 ] -/// [ 14, 49, 98, 126, 98, 49, 14 ] -/// [ 4, 14, 28, 36, 28, 14, 4 ] -/// ``` -/// 15x15 Gaussian Blur filter for uint8_t types: -/// ``` -/// [ 16, 44, 100, 192 ... 192, 100, 44, 16 ] -/// [ 44, 121, 275, 528 ... 528, 275, 121, 44 ] -/// [ 100, 275, 625, 1200 ... 1200, 625, 275, 100 ] -/// [ 192, 528, 1200, 2304 ... 2304, 1200, 528, 192 ] -/// 1/1048576 * [ | | | | ... | | | | ] -/// [ 192, 528, 1200, 2304 ... 2304, 1200, 528, 192 ] -/// [ 100, 275, 625, 1200 ... 1200, 625, 275, 100 ] -/// [ 44, 121, 275, 528 ... 528, 275, 121, 44 ] -/// [ 16, 44, 100, 192 ... 192, 100, 44, 16 ] -/// ``` -/// -/// Width and height are the same for the source and for the destination. Number -/// of elements is limited to @ref KLEIDICV_MAX_IMAGE_PIXELS. +/// Width and height are assumed to be the same for the source and for the +/// destination. The number of elements is limited to @ref +/// KLEIDICV_MAX_IMAGE_PIXELS. /// /// Usage: \n /// Before using this function, a context must be created using -/// kleidicv_filter_create, and after finished, it has to be released -/// using kleidicv_filter_release. The context must be created with the same -/// image dimensions as width and height parameters, with sizeof(uint8) as -/// size_type, and with the channel number of the data as channels. \n -/// Note, from the border types only these are supported: \n +/// kleidicv_filter_context_create, and after finished, it has to be released +/// using kleidicv_filter_context_release. Please ensure that your filter +/// context parameters are large enough, otherwise this API will return with an +/// error. \n Note, from the border types only these are supported: \n /// - @ref KLEIDICV_BORDER_TYPE_REPLICATE \n /// - @ref KLEIDICV_BORDER_TYPE_REFLECT \n /// - @ref KLEIDICV_BORDER_TYPE_WRAP \n /// - @ref KLEIDICV_BORDER_TYPE_REVERSE /// -/// @param src Pointer to the source data. Must be non-null. -/// @param src_stride Distance in bytes from the start of one row to the -/// start of the next row in the source data. Must be a -/// multiple of sizeof(type) and no less than width * -/// sizeof(type) * channels, except for single-row images. -/// @param dst Pointer to the destination data. Must be non-null. -/// @param dst_stride Distance in bytes from the start of one row to the -/// start of the next row in the destination data. Must be a -/// multiple of sizeof(type) and no less than width * -/// sizeof(type) * channels, except for single-row images. -/// @param width Number of columns in the data. (One column consists of -/// 'channels' number of elements.) -/// @param height Number of rows in the data. -/// @param channels Number of channels in the data. Must be not more than -/// @ref KLEIDICV_MAXIMUM_CHANNEL_COUNT. -/// @param border_type Way of handling the border. -/// @param context Pointer to filter context. -/// -KLEIDICV_API_DECLARATION(kleidicv_gaussian_blur_3x3_u8, const uint8_t *src, - size_t src_stride, uint8_t *dst, size_t dst_stride, - size_t width, size_t height, size_t channels, - kleidicv_border_type_t border_type, - kleidicv_filter_context_t *context); - -/// @copydoc kleidicv_gaussian_blur_3x3_u8 -/// -KLEIDICV_API_DECLARATION(kleidicv_gaussian_blur_5x5_u8, const uint8_t *src, - size_t src_stride, uint8_t *dst, size_t dst_stride, - size_t width, size_t height, size_t channels, - kleidicv_border_type_t border_type, - kleidicv_filter_context_t *context); - -/// @copydoc kleidicv_gaussian_blur_3x3_u8 -/// -KLEIDICV_API_DECLARATION(kleidicv_gaussian_blur_7x7_u8, const uint8_t *src, - size_t src_stride, uint8_t *dst, size_t dst_stride, - size_t width, size_t height, size_t channels, - kleidicv_border_type_t border_type, - kleidicv_filter_context_t *context); - -/// @copydoc kleidicv_gaussian_blur_3x3_u8 -/// -KLEIDICV_API_DECLARATION(kleidicv_gaussian_blur_15x15_u8, const uint8_t *src, +/// @param src Pointer to the source data. Must be non-null. +/// @param src_stride Distance in bytes from the start of one row to the +/// start of the next row in the source data. Must be a +/// multiple of sizeof(type) and no less than width * +/// sizeof(type) * channels, except for single-row images. +/// @param dst Pointer to the destination data. Must be non-null. +/// @param dst_stride Distance in bytes from the start of one row to the +/// start of the next row in the destination data. Must be +/// a multiple of sizeof(type) and no less than width * +/// sizeof(type) * channels, except for single-row images. +/// @param width Number of columns in the data. (One column consists of +/// 'channels' number of elements.) +/// @param height Number of rows in the data. +/// @param channels Number of channels in the data. Must be not more than +/// @ref KLEIDICV_MAXIMUM_CHANNEL_COUNT. +/// @param kernel_width Width of the Gaussian kernel. +/// @param kernel_height Height of the Gaussian kernel. +/// @param sigma_x Horizontal sigma (standard deviation) value. +/// @param sigma_y Vertical sigma (standard deviation) value. +/// @param border_type Way of handling the border. +/// @param context Pointer to filter context. +/// +KLEIDICV_API_DECLARATION(kleidicv_gaussian_blur_u8, const uint8_t *src, size_t src_stride, uint8_t *dst, size_t dst_stride, size_t width, size_t height, size_t channels, + size_t kernel_width, size_t kernel_height, + float sigma_x, float sigma_y, kleidicv_border_type_t border_type, kleidicv_filter_context_t *context); diff --git a/kleidicv/src/filters/gaussian_blur_api.cpp b/kleidicv/src/filters/gaussian_blur_api.cpp index 6732e1d29..10fc41b6d 100644 --- a/kleidicv/src/filters/gaussian_blur_api.cpp +++ b/kleidicv/src/filters/gaussian_blur_api.cpp @@ -12,23 +12,29 @@ extern "C" { using KLEIDICV_TARGET_NAMESPACE::Rectangle; using KLEIDICV_TARGET_NAMESPACE::SeparableFilterWorkspace; -kleidicv_error_t kleidicv_filter_create(kleidicv_filter_context_t **context, - size_t channels, - size_t intermediate_size, - kleidicv_rectangle_t image) { +kleidicv_error_t kleidicv_filter_context_create( + kleidicv_filter_context_t **context, size_t max_channels, + size_t max_kernel_width, size_t max_kernel_height, size_t max_image_width, + size_t max_image_height) { CHECK_POINTERS(context); - CHECK_RECTANGLE_SIZE(image); - if (intermediate_size > KLEIDICV_MAXIMUM_TYPE_SIZE) { - return KLEIDICV_ERROR_RANGE; + if (max_kernel_width != max_kernel_height) { + return KLEIDICV_ERROR_NOT_IMPLEMENTED; } - if (channels > KLEIDICV_MAXIMUM_CHANNEL_COUNT) { + if (max_channels > KLEIDICV_MAXIMUM_CHANNEL_COUNT) { return KLEIDICV_ERROR_RANGE; } - auto workspace = SeparableFilterWorkspace::create(Rectangle{image}, channels, - intermediate_size); + CHECK_IMAGE_SIZE(max_image_width, max_image_height); + + // naive check because non-square kernels are not supported anyway + size_t intermediate_size = (max_kernel_width == 15 || max_kernel_height == 15) + ? sizeof(uint32_t) + : sizeof(uint16_t); + auto workspace = SeparableFilterWorkspace::create( + Rectangle{max_image_width, max_image_height}, max_channels, + intermediate_size); if (!workspace) { *context = nullptr; return KLEIDICV_ERROR_ALLOCATION; @@ -38,7 +44,8 @@ kleidicv_error_t kleidicv_filter_create(kleidicv_filter_context_t **context, return KLEIDICV_OK; } -kleidicv_error_t kleidicv_filter_release(kleidicv_filter_context_t *context) { +kleidicv_error_t kleidicv_filter_context_release( + kleidicv_filter_context_t *context) { CHECK_POINTERS(context); // Deliberately create and immediately destroy a unique_ptr to delete the @@ -53,21 +60,6 @@ kleidicv_error_t kleidicv_filter_release(kleidicv_filter_context_t *context) { } // extern "C" KLEIDICV_MULTIVERSION_C_API( - kleidicv_gaussian_blur_3x3_u8, &kleidicv::neon::gaussian_blur_3x3_u8, - KLEIDICV_SVE2_IMPL_IF(kleidicv::sve2::gaussian_blur_3x3_u8), - &kleidicv::sme2::gaussian_blur_3x3_u8); - -KLEIDICV_MULTIVERSION_C_API( - kleidicv_gaussian_blur_5x5_u8, &kleidicv::neon::gaussian_blur_5x5_u8, - KLEIDICV_SVE2_IMPL_IF(kleidicv::sve2::gaussian_blur_5x5_u8), - &kleidicv::sme2::gaussian_blur_5x5_u8); - -KLEIDICV_MULTIVERSION_C_API( - kleidicv_gaussian_blur_7x7_u8, &kleidicv::neon::gaussian_blur_7x7_u8, - KLEIDICV_SVE2_IMPL_IF(kleidicv::sve2::gaussian_blur_7x7_u8), - &kleidicv::sme2::gaussian_blur_7x7_u8); - -KLEIDICV_MULTIVERSION_C_API( - kleidicv_gaussian_blur_15x15_u8, &kleidicv::neon::gaussian_blur_15x15_u8, - KLEIDICV_SVE2_IMPL_IF(kleidicv::sve2::gaussian_blur_15x15_u8), - &kleidicv::sme2::gaussian_blur_15x15_u8); + kleidicv_gaussian_blur_u8, &kleidicv::neon::gaussian_blur_u8, + KLEIDICV_SVE2_IMPL_IF(kleidicv::sve2::gaussian_blur_u8), + &kleidicv::sme2::gaussian_blur_u8); diff --git a/kleidicv/src/filters/gaussian_blur_neon.cpp b/kleidicv/src/filters/gaussian_blur_neon.cpp index e54bb4665..71e492104 100644 --- a/kleidicv/src/filters/gaussian_blur_neon.cpp +++ b/kleidicv/src/filters/gaussian_blur_neon.cpp @@ -514,8 +514,6 @@ kleidicv_error_t discrete_gaussian_blur(const ScalarType *src, size_t height, size_t channels, kleidicv_border_type_t border_type, kleidicv_filter_context_t *context) { - using GaussianBlurFilterType = DiscreteGaussianBlur; - CHECK_POINTERS(context); CHECK_POINTER_AND_STRIDE(src, src_stride, height); CHECK_POINTER_AND_STRIDE(dst, dst_stride, height); @@ -529,25 +527,21 @@ kleidicv_error_t discrete_gaussian_blur(const ScalarType *src, return KLEIDICV_ERROR_RANGE; } - Rectangle rect{width, height}; - Rows src_rows{src, src_stride, channels}; - Rows dst_rows{dst, dst_stride, channels}; - auto *workspace = reinterpret_cast(context); if constexpr (KernelSize == 15) { - if (workspace->intermediate_size() != 4 * sizeof(ScalarType)) { + if (workspace->intermediate_size() < sizeof(uint32_t)) { return KLEIDICV_ERROR_CONTEXT_MISMATCH; } - } else if (workspace->intermediate_size() != 2 * sizeof(ScalarType)) { - return KLEIDICV_ERROR_CONTEXT_MISMATCH; } - if (workspace->channels() != channels) { + if (workspace->channels() < channels) { return KLEIDICV_ERROR_CONTEXT_MISMATCH; } - if (workspace->image_size() != rect) { + Rectangle rect{width, height}; + const Rectangle &context_rect = workspace->image_size(); + if (context_rect.width() < width || context_rect.height() < height) { return KLEIDICV_ERROR_CONTEXT_MISMATCH; } @@ -557,59 +551,50 @@ kleidicv_error_t discrete_gaussian_blur(const ScalarType *src, return KLEIDICV_ERROR_NOT_IMPLEMENTED; } + using GaussianBlurFilterType = DiscreteGaussianBlur; + GaussianBlurFilterType blur; SeparableFilter filter{blur}; + + Rows src_rows{src, src_stride, channels}; + Rows dst_rows{dst, dst_stride, channels}; workspace->process(rect, src_rows, dst_rows, channels, *fixed_border_type, filter); return KLEIDICV_OK; } -KLEIDICV_TARGET_FN_ATTRS -kleidicv_error_t gaussian_blur_3x3_u8(const uint8_t *src, size_t src_stride, - uint8_t *dst, size_t dst_stride, - size_t width, size_t height, - size_t channels, - kleidicv_border_type_t border_type, - kleidicv_filter_context_t *context) { - return discrete_gaussian_blur(src, src_stride, dst, dst_stride, - width, height, channels, - border_type, context); -} +#define KLEIDICV_GAUSSIAN_BLUR_WRAPPER(size, ...) \ + if (kernel_width == size) { \ + return discrete_gaussian_blur(__VA_ARGS__); \ + } -KLEIDICV_TARGET_FN_ATTRS -kleidicv_error_t gaussian_blur_5x5_u8(const uint8_t *src, size_t src_stride, - uint8_t *dst, size_t dst_stride, - size_t width, size_t height, - size_t channels, - kleidicv_border_type_t border_type, - kleidicv_filter_context_t *context) { - return discrete_gaussian_blur(src, src_stride, dst, dst_stride, - width, height, channels, - border_type, context); -} +#define KLEIDICV_GENERATE_GAUSSIAN_BLUR_WRAPPERS(...) \ + KLEIDICV_GAUSSIAN_BLUR_WRAPPER(3, __VA_ARGS__) \ + KLEIDICV_GAUSSIAN_BLUR_WRAPPER(5, __VA_ARGS__) \ + KLEIDICV_GAUSSIAN_BLUR_WRAPPER(7, __VA_ARGS__) \ + KLEIDICV_GAUSSIAN_BLUR_WRAPPER(15, __VA_ARGS__) KLEIDICV_TARGET_FN_ATTRS -kleidicv_error_t gaussian_blur_7x7_u8(const uint8_t *src, size_t src_stride, - uint8_t *dst, size_t dst_stride, - size_t width, size_t height, - size_t channels, - kleidicv_border_type_t border_type, - kleidicv_filter_context_t *context) { - return discrete_gaussian_blur(src, src_stride, dst, dst_stride, - width, height, channels, - border_type, context); -} +kleidicv_error_t gaussian_blur_u8(const uint8_t *src, size_t src_stride, + uint8_t *dst, size_t dst_stride, size_t width, + size_t height, size_t channels, + size_t kernel_width, size_t kernel_height, + float sigma_x, float sigma_y, + kleidicv_border_type_t border_type, + kleidicv_filter_context_t *context) { + if (kernel_width != kernel_height) { + return KLEIDICV_ERROR_NOT_IMPLEMENTED; + } -KLEIDICV_TARGET_FN_ATTRS -kleidicv_error_t gaussian_blur_15x15_u8(const uint8_t *src, size_t src_stride, - uint8_t *dst, size_t dst_stride, - size_t width, size_t height, - size_t channels, - kleidicv_border_type_t border_type, - kleidicv_filter_context_t *context) { - return discrete_gaussian_blur(src, src_stride, dst, dst_stride, - width, height, channels, - border_type, context); + if (sigma_x != 0.0 || sigma_y != 0.0) { + return KLEIDICV_ERROR_NOT_IMPLEMENTED; + } + + KLEIDICV_GENERATE_GAUSSIAN_BLUR_WRAPPERS(src, src_stride, dst, dst_stride, + width, height, channels, border_type, + context) + + return KLEIDICV_ERROR_NOT_IMPLEMENTED; } } // namespace kleidicv::neon diff --git a/kleidicv/src/filters/gaussian_blur_sc.h b/kleidicv/src/filters/gaussian_blur_sc.h index 96b8c5dc7..e9254564e 100644 --- a/kleidicv/src/filters/gaussian_blur_sc.h +++ b/kleidicv/src/filters/gaussian_blur_sc.h @@ -436,8 +436,6 @@ kleidicv_error_t discrete_gaussian_blur( size_t dst_stride, size_t width, size_t height, size_t channels, kleidicv_border_type_t border_type, kleidicv_filter_context_t *context) KLEIDICV_STREAMING_COMPATIBLE { - using GaussianBlurFilterType = DiscreteGaussianBlur; - CHECK_POINTERS(context); CHECK_POINTER_AND_STRIDE(src, src_stride, height); CHECK_POINTER_AND_STRIDE(dst, dst_stride, height); @@ -451,42 +449,74 @@ kleidicv_error_t discrete_gaussian_blur( return KLEIDICV_ERROR_RANGE; } - Rectangle rect{width, height}; - Rows src_rows{src, src_stride, channels}; - Rows dst_rows{dst, dst_stride, channels}; - auto *workspace = reinterpret_cast(context); if constexpr (KernelSize == 15) { - if (workspace->intermediate_size() != 4 * sizeof(ScalarType)) { + if (workspace->intermediate_size() < sizeof(uint32_t)) { return KLEIDICV_ERROR_CONTEXT_MISMATCH; } - } else if (workspace->intermediate_size() != 2 * sizeof(ScalarType)) { - return KLEIDICV_ERROR_CONTEXT_MISMATCH; } - if (workspace->channels() != channels) { + if (workspace->channels() < channels) { return KLEIDICV_ERROR_CONTEXT_MISMATCH; } - if (workspace->image_size() != rect) { + Rectangle rect{width, height}; + const Rectangle &context_rect = workspace->image_size(); + if (context_rect.width() < width || context_rect.height() < height) { return KLEIDICV_ERROR_CONTEXT_MISMATCH; } - GaussianBlurFilterType blur; - SeparableFilter filter{blur}; - auto fixed_border_type = get_fixed_border_type(border_type); if (!fixed_border_type) { return KLEIDICV_ERROR_NOT_IMPLEMENTED; } + using GaussianBlurFilterType = DiscreteGaussianBlur; + + GaussianBlurFilterType blur; + SeparableFilter filter{blur}; + + Rows src_rows{src, src_stride, channels}; + Rows dst_rows{dst, dst_stride, channels}; workspace->process(rect, src_rows, dst_rows, channels, *fixed_border_type, filter); return KLEIDICV_OK; } +#define KLEIDICV_GAUSSIAN_BLUR_WRAPPER(size, ...) \ + if (kernel_width == size) { \ + return discrete_gaussian_blur(__VA_ARGS__); \ + } + +#define KLEIDICV_GENERATE_GAUSSIAN_BLUR_WRAPPERS(...) \ + KLEIDICV_GAUSSIAN_BLUR_WRAPPER(3, __VA_ARGS__) \ + KLEIDICV_GAUSSIAN_BLUR_WRAPPER(5, __VA_ARGS__) \ + KLEIDICV_GAUSSIAN_BLUR_WRAPPER(7, __VA_ARGS__) \ + KLEIDICV_GAUSSIAN_BLUR_WRAPPER(15, __VA_ARGS__) + +kleidicv_error_t gaussian_blur_u8_entry( + const uint8_t *src, size_t src_stride, uint8_t *dst, size_t dst_stride, + size_t width, size_t height, size_t channels, size_t kernel_width, + size_t kernel_height, float sigma_x, float sigma_y, + kleidicv_border_type_t border_type, + kleidicv_filter_context_t *context) KLEIDICV_STREAMING_COMPATIBLE { + if (kernel_width != kernel_height) { + return KLEIDICV_ERROR_NOT_IMPLEMENTED; + } + + if (sigma_x != 0.0 || sigma_y != 0.0) { + return KLEIDICV_ERROR_NOT_IMPLEMENTED; + } + + KLEIDICV_GENERATE_GAUSSIAN_BLUR_WRAPPERS(src, src_stride, dst, dst_stride, + width, height, channels, border_type, + context) + + return KLEIDICV_ERROR_NOT_IMPLEMENTED; +} + } // namespace KLEIDICV_TARGET_NAMESPACE #endif // KLEIDICV_GAUSSIAN_BLUR_SC_H diff --git a/kleidicv/src/filters/gaussian_blur_sme2.cpp b/kleidicv/src/filters/gaussian_blur_sme2.cpp index ec9c6700e..a95a6c828 100644 --- a/kleidicv/src/filters/gaussian_blur_sme2.cpp +++ b/kleidicv/src/filters/gaussian_blur_sme2.cpp @@ -8,43 +8,15 @@ namespace kleidicv::sme2 { KLEIDICV_LOCALLY_STREAMING KLEIDICV_TARGET_FN_ATTRS kleidicv_error_t -gaussian_blur_3x3_u8(const uint8_t *src, size_t src_stride, uint8_t *dst, - size_t dst_stride, size_t width, size_t height, - size_t channels, kleidicv_border_type_t border_type, - kleidicv_filter_context_t *context) { - return discrete_gaussian_blur(src, src_stride, dst, dst_stride, - width, height, channels, - border_type, context); -} - -KLEIDICV_LOCALLY_STREAMING KLEIDICV_TARGET_FN_ATTRS kleidicv_error_t -gaussian_blur_5x5_u8(const uint8_t *src, size_t src_stride, uint8_t *dst, - size_t dst_stride, size_t width, size_t height, - size_t channels, kleidicv_border_type_t border_type, - kleidicv_filter_context_t *context) { - return discrete_gaussian_blur(src, src_stride, dst, dst_stride, - width, height, channels, - border_type, context); -} - -KLEIDICV_LOCALLY_STREAMING KLEIDICV_TARGET_FN_ATTRS kleidicv_error_t -gaussian_blur_7x7_u8(const uint8_t *src, size_t src_stride, uint8_t *dst, - size_t dst_stride, size_t width, size_t height, - size_t channels, kleidicv_border_type_t border_type, - kleidicv_filter_context_t *context) { - return discrete_gaussian_blur(src, src_stride, dst, dst_stride, - width, height, channels, - border_type, context); -} - -KLEIDICV_LOCALLY_STREAMING KLEIDICV_TARGET_FN_ATTRS kleidicv_error_t -gaussian_blur_15x15_u8(const uint8_t *src, size_t src_stride, uint8_t *dst, - size_t dst_stride, size_t width, size_t height, - size_t channels, kleidicv_border_type_t border_type, - kleidicv_filter_context_t *context) { - return discrete_gaussian_blur(src, src_stride, dst, dst_stride, - width, height, channels, - border_type, context); +gaussian_blur_u8(const uint8_t *src, size_t src_stride, uint8_t *dst, + size_t dst_stride, size_t width, size_t height, + size_t channels, size_t kernel_width, size_t kernel_height, + float sigma_x, float sigma_y, + kleidicv_border_type_t border_type, + kleidicv_filter_context_t *context) { + return gaussian_blur_u8_entry(src, src_stride, dst, dst_stride, width, height, + channels, kernel_width, kernel_height, sigma_x, + sigma_y, border_type, context); } } // namespace kleidicv::sme2 diff --git a/kleidicv/src/filters/gaussian_blur_sve2.cpp b/kleidicv/src/filters/gaussian_blur_sve2.cpp index 1e872e2f4..764faa00e 100644 --- a/kleidicv/src/filters/gaussian_blur_sve2.cpp +++ b/kleidicv/src/filters/gaussian_blur_sve2.cpp @@ -8,51 +8,16 @@ namespace kleidicv::sve2 { KLEIDICV_TARGET_FN_ATTRS -kleidicv_error_t gaussian_blur_3x3_u8(const uint8_t *src, size_t src_stride, - uint8_t *dst, size_t dst_stride, - size_t width, size_t height, - size_t channels, - kleidicv_border_type_t border_type, - kleidicv_filter_context_t *context) { - return discrete_gaussian_blur(src, src_stride, dst, dst_stride, - width, height, channels, - border_type, context); -} - -KLEIDICV_TARGET_FN_ATTRS -kleidicv_error_t gaussian_blur_5x5_u8(const uint8_t *src, size_t src_stride, - uint8_t *dst, size_t dst_stride, - size_t width, size_t height, - size_t channels, - kleidicv_border_type_t border_type, - kleidicv_filter_context_t *context) { - return discrete_gaussian_blur(src, src_stride, dst, dst_stride, - width, height, channels, - border_type, context); -} - -KLEIDICV_TARGET_FN_ATTRS -kleidicv_error_t gaussian_blur_7x7_u8(const uint8_t *src, size_t src_stride, - uint8_t *dst, size_t dst_stride, - size_t width, size_t height, - size_t channels, - kleidicv_border_type_t border_type, - kleidicv_filter_context_t *context) { - return discrete_gaussian_blur(src, src_stride, dst, dst_stride, - width, height, channels, - border_type, context); -} - -KLEIDICV_TARGET_FN_ATTRS -kleidicv_error_t gaussian_blur_15x15_u8(const uint8_t *src, size_t src_stride, - uint8_t *dst, size_t dst_stride, - size_t width, size_t height, - size_t channels, - kleidicv_border_type_t border_type, - kleidicv_filter_context_t *context) { - return discrete_gaussian_blur(src, src_stride, dst, dst_stride, - width, height, channels, - border_type, context); +kleidicv_error_t gaussian_blur_u8(const uint8_t *src, size_t src_stride, + uint8_t *dst, size_t dst_stride, size_t width, + size_t height, size_t channels, + size_t kernel_width, size_t kernel_height, + float sigma_x, float sigma_y, + kleidicv_border_type_t border_type, + kleidicv_filter_context_t *context) { + return gaussian_blur_u8_entry(src, src_stride, dst, dst_stride, width, height, + channels, kernel_width, kernel_height, sigma_x, + sigma_y, border_type, context); } } // namespace kleidicv::sve2 diff --git a/test/api/test_gaussian_blur.cpp b/test/api/test_gaussian_blur.cpp index ff9abc94e..a5bb1465d 100644 --- a/test/api/test_gaussian_blur.cpp +++ b/test/api/test_gaussian_blur.cpp @@ -11,14 +11,10 @@ #include "kleidicv/kleidicv.h" #include "test_config.h" -#define KLEIDICV_GAUSSIAN_BLUR(type, kernel_suffix, type_suffix) \ - KLEIDICV_API(gaussian_blur_##kernel_suffix, \ - kleidicv_gaussian_blur_##kernel_suffix##_##type_suffix, type) +#define KLEIDICV_GAUSSIAN_BLUR(type, type_suffix) \ + KLEIDICV_API(gaussian_blur, kleidicv_gaussian_blur_##type_suffix, type) -KLEIDICV_GAUSSIAN_BLUR(uint8_t, 3x3, u8); -KLEIDICV_GAUSSIAN_BLUR(uint8_t, 5x5, u8); -KLEIDICV_GAUSSIAN_BLUR(uint8_t, 7x7, u8); -KLEIDICV_GAUSSIAN_BLUR(uint8_t, 15x15, u8); +KLEIDICV_GAUSSIAN_BLUR(uint8_t, u8); // Implements KernelTestParams for Gaussian Blur operators. template @@ -104,32 +100,21 @@ class GaussianBlurTest : public test::KernelTest { test::Array2D *output, kleidicv_border_type_t border_type, kleidicv_border_values_t) override { - // NOLINTBEGIN(readability-avoid-nested-conditional-operator) - auto api = - KernelTestParams::kKernelSize == 3 ? gaussian_blur_3x3() - : KernelTestParams::kKernelSize == 5 ? gaussian_blur_5x5() - : KernelTestParams::kKernelSize == 7 ? gaussian_blur_7x7() - : gaussian_blur_15x15(); - // NOLINTEND(readability-avoid-nested-conditional-operator) - - size_t intermediate_size = 2 * sizeof(InputType); - if constexpr (KernelTestParams::kKernelSize == 15) { - intermediate_size = 4 * sizeof(InputType); - } - kleidicv_filter_context_t *context = nullptr; - auto ret = kleidicv_filter_create( - &context, input->channels(), intermediate_size, - kleidicv_rectangle_t{input->width() / input->channels(), - input->height()}); + auto ret = kleidicv_filter_context_create( + &context, input->channels(), KernelTestParams::kKernelSize, + KernelTestParams::kKernelSize, input->width() / input->channels(), + input->height()); if (ret != KLEIDICV_OK) { return ret; } - ret = api(input->data(), input->stride(), output->data(), output->stride(), - input->width() / input->channels(), input->height(), - input->channels(), border_type, context); - auto releaseRet = kleidicv_filter_release(context); + ret = gaussian_blur()( + input->data(), input->stride(), output->data(), output->stride(), + input->width() / input->channels(), input->height(), input->channels(), + KernelTestParams::kKernelSize, KernelTestParams::kKernelSize, 0.0, 0.0, + border_type, context); + auto releaseRet = kleidicv_filter_context_release(context); if (releaseRet != KLEIDICV_OK) { return releaseRet; } @@ -256,9 +241,8 @@ TYPED_TEST(GaussianBlur, UnsupportedBorderType3x3) { using KernelTestParams = GaussianBlurKernelTestParams; kleidicv_filter_context_t *context = nullptr; size_t validSize = KernelTestParams::kKernelSize - 1; - ASSERT_EQ(KLEIDICV_OK, - kleidicv_filter_create(&context, 1, 2 * sizeof(TypeParam), - kleidicv_rectangle_t{validSize, validSize})); + ASSERT_EQ(KLEIDICV_OK, kleidicv_filter_context_create(&context, 1, 3, 3, + validSize, validSize)); TypeParam src[1] = {}, dst[1]; for (kleidicv_border_type_t border : { KLEIDICV_BORDER_TYPE_CONSTANT, @@ -266,20 +250,19 @@ TYPED_TEST(GaussianBlur, UnsupportedBorderType3x3) { KLEIDICV_BORDER_TYPE_NONE, }) { EXPECT_EQ(KLEIDICV_ERROR_NOT_IMPLEMENTED, - gaussian_blur_3x3()(src, sizeof(TypeParam), dst, - sizeof(TypeParam), validSize, - validSize, 1, border, context)); + gaussian_blur()( + src, sizeof(TypeParam), dst, sizeof(TypeParam), validSize, + validSize, 1, 3, 3, 0.0, 0.0, border, context)); } - EXPECT_EQ(KLEIDICV_OK, kleidicv_filter_release(context)); + EXPECT_EQ(KLEIDICV_OK, kleidicv_filter_context_release(context)); } TYPED_TEST(GaussianBlur, UnsupportedBorderType5x5) { using KernelTestParams = GaussianBlurKernelTestParams; kleidicv_filter_context_t *context = nullptr; size_t validSize = KernelTestParams::kKernelSize - 1; - ASSERT_EQ(KLEIDICV_OK, - kleidicv_filter_create(&context, 1, 2 * sizeof(TypeParam), - kleidicv_rectangle_t{validSize, validSize})); + ASSERT_EQ(KLEIDICV_OK, kleidicv_filter_context_create(&context, 1, 5, 5, + validSize, validSize)); TypeParam src[1] = {}, dst[1]; for (kleidicv_border_type_t border : { KLEIDICV_BORDER_TYPE_CONSTANT, @@ -287,20 +270,19 @@ TYPED_TEST(GaussianBlur, UnsupportedBorderType5x5) { KLEIDICV_BORDER_TYPE_NONE, }) { EXPECT_EQ(KLEIDICV_ERROR_NOT_IMPLEMENTED, - gaussian_blur_5x5()(src, sizeof(TypeParam), dst, - sizeof(TypeParam), validSize, - validSize, 1, border, context)); + gaussian_blur()( + src, sizeof(TypeParam), dst, sizeof(TypeParam), validSize, + validSize, 1, 5, 5, 0.0, 0.0, border, context)); } - EXPECT_EQ(KLEIDICV_OK, kleidicv_filter_release(context)); + EXPECT_EQ(KLEIDICV_OK, kleidicv_filter_context_release(context)); } TYPED_TEST(GaussianBlur, UnsupportedBorderType7x7) { using KernelTestParams = GaussianBlurKernelTestParams; kleidicv_filter_context_t *context = nullptr; size_t validSize = KernelTestParams::kKernelSize - 1; - ASSERT_EQ(KLEIDICV_OK, - kleidicv_filter_create(&context, 1, 2 * sizeof(TypeParam), - kleidicv_rectangle_t{validSize, validSize})); + ASSERT_EQ(KLEIDICV_OK, kleidicv_filter_context_create(&context, 1, 7, 7, + validSize, validSize)); TypeParam src[1] = {}, dst[1]; for (kleidicv_border_type_t border : { KLEIDICV_BORDER_TYPE_CONSTANT, @@ -308,20 +290,19 @@ TYPED_TEST(GaussianBlur, UnsupportedBorderType7x7) { KLEIDICV_BORDER_TYPE_NONE, }) { EXPECT_EQ(KLEIDICV_ERROR_NOT_IMPLEMENTED, - gaussian_blur_7x7()(src, sizeof(TypeParam), dst, - sizeof(TypeParam), validSize, - validSize, 1, border, context)); + gaussian_blur()( + src, sizeof(TypeParam), dst, sizeof(TypeParam), validSize, + validSize, 1, 7, 7, 0.0, 0.0, border, context)); } - EXPECT_EQ(KLEIDICV_OK, kleidicv_filter_release(context)); + EXPECT_EQ(KLEIDICV_OK, kleidicv_filter_context_release(context)); } TYPED_TEST(GaussianBlur, UnsupportedBorderType15x15) { using KernelTestParams = GaussianBlurKernelTestParams; kleidicv_filter_context_t *context = nullptr; size_t validSize = KernelTestParams::kKernelSize - 1; - ASSERT_EQ(KLEIDICV_OK, - kleidicv_filter_create(&context, 1, 4 * sizeof(TypeParam), - kleidicv_rectangle_t{validSize, validSize})); + ASSERT_EQ(KLEIDICV_OK, kleidicv_filter_context_create(&context, 1, 15, 15, + validSize, validSize)); TypeParam src[1] = {}, dst[1]; for (kleidicv_border_type_t border : { KLEIDICV_BORDER_TYPE_CONSTANT, @@ -329,40 +310,96 @@ TYPED_TEST(GaussianBlur, UnsupportedBorderType15x15) { KLEIDICV_BORDER_TYPE_NONE, }) { EXPECT_EQ(KLEIDICV_ERROR_NOT_IMPLEMENTED, - gaussian_blur_15x15()(src, sizeof(TypeParam), dst, - sizeof(TypeParam), validSize, - validSize, 1, border, context)); + gaussian_blur()( + src, sizeof(TypeParam), dst, sizeof(TypeParam), validSize, + validSize, 1, 15, 15, 0.0, 0.0, border, context)); } - EXPECT_EQ(KLEIDICV_OK, kleidicv_filter_release(context)); + EXPECT_EQ(KLEIDICV_OK, kleidicv_filter_context_release(context)); +} + +TYPED_TEST(GaussianBlur, DifferentKernelSize) { + using KernelTestParams15x15 = GaussianBlurKernelTestParams; + kleidicv_filter_context_t *context = nullptr; + size_t validSize = KernelTestParams15x15::kKernelSize - 1; + ASSERT_EQ(KLEIDICV_OK, kleidicv_filter_context_create(&context, 1, 15, 15, + validSize, validSize)); + TypeParam src[1] = {}, dst[1]; + + EXPECT_EQ( + KLEIDICV_ERROR_NOT_IMPLEMENTED, + gaussian_blur()(src, sizeof(TypeParam), dst, sizeof(TypeParam), + validSize, validSize, 1, 5, 15, 0.0, 0.0, + KLEIDICV_BORDER_TYPE_REPLICATE, context)); + + EXPECT_EQ(KLEIDICV_OK, kleidicv_filter_context_release(context)); +} + +TYPED_TEST(GaussianBlur, NonZeroSigma) { + using KernelTestParams15x15 = GaussianBlurKernelTestParams; + kleidicv_filter_context_t *context = nullptr; + size_t validSize = KernelTestParams15x15::kKernelSize - 1; + ASSERT_EQ(KLEIDICV_OK, kleidicv_filter_context_create(&context, 1, 15, 15, + validSize, validSize)); + TypeParam src[1] = {}, dst[1]; + + EXPECT_EQ( + KLEIDICV_ERROR_NOT_IMPLEMENTED, + gaussian_blur()(src, sizeof(TypeParam), dst, sizeof(TypeParam), + validSize, validSize, 1, 15, 15, 1.23, 4.56, + KLEIDICV_BORDER_TYPE_REPLICATE, context)); + + EXPECT_EQ( + KLEIDICV_ERROR_NOT_IMPLEMENTED, + gaussian_blur()(src, sizeof(TypeParam), dst, sizeof(TypeParam), + validSize, validSize, 1, 15, 15, 1.23, 0.0, + KLEIDICV_BORDER_TYPE_REPLICATE, context)); + + EXPECT_EQ( + KLEIDICV_ERROR_NOT_IMPLEMENTED, + gaussian_blur()(src, sizeof(TypeParam), dst, sizeof(TypeParam), + validSize, validSize, 1, 15, 15, 0.0, 4.56, + KLEIDICV_BORDER_TYPE_REPLICATE, context)); + + EXPECT_EQ(KLEIDICV_OK, kleidicv_filter_context_release(context)); +} + +TYPED_TEST(GaussianBlur, UnsupportedKernelSize) { + using KernelTestParams15x15 = GaussianBlurKernelTestParams; + kleidicv_filter_context_t *context = nullptr; + size_t validSize = KernelTestParams15x15::kKernelSize - 1; + ASSERT_EQ(KLEIDICV_OK, kleidicv_filter_context_create(&context, 1, 15, 15, + validSize, validSize)); + TypeParam src[1] = {}, dst[1]; + + EXPECT_EQ( + KLEIDICV_ERROR_NOT_IMPLEMENTED, + gaussian_blur()(src, sizeof(TypeParam), dst, sizeof(TypeParam), + validSize, validSize, 1, 33, 33, 0.0, 0.0, + KLEIDICV_BORDER_TYPE_REPLICATE, context)); + + EXPECT_EQ(KLEIDICV_OK, kleidicv_filter_context_release(context)); } TYPED_TEST(GaussianBlur, NullPointer) { - using KernelTestParams3x3 = GaussianBlurKernelTestParams; - using KernelTestParams5x5 = GaussianBlurKernelTestParams; - using KernelTestParams7x7 = GaussianBlurKernelTestParams; using KernelTestParams15x15 = GaussianBlurKernelTestParams; kleidicv_filter_context_t *context = nullptr; - size_t validSize = KernelTestParams3x3::kKernelSize - 1; - ASSERT_EQ(KLEIDICV_OK, - kleidicv_filter_create(&context, 1, 2 * sizeof(TypeParam), - kleidicv_rectangle_t{validSize, validSize})); + size_t validSize = KernelTestParams15x15::kKernelSize - 1; + ASSERT_EQ(KLEIDICV_OK, kleidicv_filter_context_create(&context, 1, 15, 15, + validSize, validSize)); TypeParam src[1] = {}, dst[1]; - test::test_null_args(gaussian_blur_3x3(), src, sizeof(TypeParam), - dst, sizeof(TypeParam), validSize, validSize, 1, - KLEIDICV_BORDER_TYPE_REPLICATE, context); - validSize = KernelTestParams5x5::kKernelSize - 1; - test::test_null_args(gaussian_blur_5x5(), src, sizeof(TypeParam), - dst, sizeof(TypeParam), validSize, validSize, 1, - KLEIDICV_BORDER_TYPE_REPLICATE, context); - validSize = KernelTestParams7x7::kKernelSize - 1; - test::test_null_args(gaussian_blur_7x7(), src, sizeof(TypeParam), - dst, sizeof(TypeParam), validSize, validSize, 1, - KLEIDICV_BORDER_TYPE_REPLICATE, context); - validSize = KernelTestParams15x15::kKernelSize - 1; - test::test_null_args(gaussian_blur_15x15(), src, sizeof(TypeParam), - dst, sizeof(TypeParam), validSize, validSize, 1, - KLEIDICV_BORDER_TYPE_REPLICATE, context); - EXPECT_EQ(KLEIDICV_OK, kleidicv_filter_release(context)); + test::test_null_args(gaussian_blur(), src, sizeof(TypeParam), dst, + sizeof(TypeParam), validSize, validSize, 1, 3, 3, 0.0, + 0.0, KLEIDICV_BORDER_TYPE_REPLICATE, context); + test::test_null_args(gaussian_blur(), src, sizeof(TypeParam), dst, + sizeof(TypeParam), validSize, validSize, 1, 5, 5, 0.0, + 0.0, KLEIDICV_BORDER_TYPE_REPLICATE, context); + test::test_null_args(gaussian_blur(), src, sizeof(TypeParam), dst, + sizeof(TypeParam), validSize, validSize, 1, 7, 7, 0.0, + 0.0, KLEIDICV_BORDER_TYPE_REPLICATE, context); + test::test_null_args(gaussian_blur(), src, sizeof(TypeParam), dst, + sizeof(TypeParam), validSize, validSize, 1, 15, 15, 0.0, + 0.0, KLEIDICV_BORDER_TYPE_REPLICATE, context); + EXPECT_EQ(KLEIDICV_OK, kleidicv_filter_context_release(context)); } TYPED_TEST(GaussianBlur, Misalignment) { @@ -370,149 +407,130 @@ TYPED_TEST(GaussianBlur, Misalignment) { // misalignment impossible return; } - using KernelTestParams3x3 = GaussianBlurKernelTestParams; - using KernelTestParams5x5 = GaussianBlurKernelTestParams; - using KernelTestParams7x7 = GaussianBlurKernelTestParams; using KernelTestParams15x15 = GaussianBlurKernelTestParams; kleidicv_filter_context_t *context = nullptr; - size_t validSize = KernelTestParams3x3::kKernelSize - 1; - ASSERT_EQ(KLEIDICV_OK, - kleidicv_filter_create(&context, 1, 2 * sizeof(TypeParam), - kleidicv_rectangle_t{validSize, validSize})); + size_t validSize = KernelTestParams15x15::kKernelSize - 1; + ASSERT_EQ(KLEIDICV_OK, kleidicv_filter_context_create(&context, 1, 15, 15, + validSize, validSize)); TypeParam src[1] = {}, dst[1]; + EXPECT_EQ(KLEIDICV_ERROR_ALIGNMENT, - gaussian_blur_3x3()( + gaussian_blur()( src, sizeof(TypeParam) + 1, dst, sizeof(TypeParam), validSize, - validSize, 1, KLEIDICV_BORDER_TYPE_REPLICATE, context)); + validSize, 1, 3, 3, 0.0, 0.0, KLEIDICV_BORDER_TYPE_REPLICATE, + context)); EXPECT_EQ(KLEIDICV_ERROR_ALIGNMENT, - gaussian_blur_3x3()( + gaussian_blur()( src, sizeof(TypeParam), dst, sizeof(TypeParam) + 1, validSize, - validSize, 1, KLEIDICV_BORDER_TYPE_REPLICATE, context)); - validSize = KernelTestParams5x5::kKernelSize - 1; + validSize, 1, 3, 3, 0.0, 0.0, KLEIDICV_BORDER_TYPE_REPLICATE, + context)); + EXPECT_EQ(KLEIDICV_ERROR_ALIGNMENT, - gaussian_blur_5x5()( + gaussian_blur()( src, sizeof(TypeParam) + 1, dst, sizeof(TypeParam), validSize, - validSize, 1, KLEIDICV_BORDER_TYPE_REPLICATE, context)); + validSize, 1, 5, 5, 0.0, 0.0, KLEIDICV_BORDER_TYPE_REPLICATE, + context)); EXPECT_EQ(KLEIDICV_ERROR_ALIGNMENT, - gaussian_blur_5x5()( + gaussian_blur()( src, sizeof(TypeParam), dst, sizeof(TypeParam) + 1, validSize, - validSize, 1, KLEIDICV_BORDER_TYPE_REPLICATE, context)); - validSize = KernelTestParams7x7::kKernelSize - 1; + validSize, 1, 5, 5, 0.0, 0.0, KLEIDICV_BORDER_TYPE_REPLICATE, + context)); + EXPECT_EQ(KLEIDICV_ERROR_ALIGNMENT, - gaussian_blur_7x7()( + gaussian_blur()( src, sizeof(TypeParam) + 1, dst, sizeof(TypeParam), validSize, - validSize, 1, KLEIDICV_BORDER_TYPE_REPLICATE, context)); + validSize, 1, 7, 7, 0.0, 0.0, KLEIDICV_BORDER_TYPE_REPLICATE, + context)); EXPECT_EQ(KLEIDICV_ERROR_ALIGNMENT, - gaussian_blur_7x7()( + gaussian_blur()( src, sizeof(TypeParam), dst, sizeof(TypeParam) + 1, validSize, - validSize, 1, KLEIDICV_BORDER_TYPE_REPLICATE, context)); - validSize = KernelTestParams15x15::kKernelSize - 1; + validSize, 1, 7, 7, 0.0, 0.0, KLEIDICV_BORDER_TYPE_REPLICATE, + context)); + EXPECT_EQ(KLEIDICV_ERROR_ALIGNMENT, - gaussian_blur_15x15()( + gaussian_blur()( src, sizeof(TypeParam) + 1, dst, sizeof(TypeParam), validSize, - validSize, 1, KLEIDICV_BORDER_TYPE_REPLICATE, context)); + validSize, 1, 15, 15, 0.0, 0.0, KLEIDICV_BORDER_TYPE_REPLICATE, + context)); EXPECT_EQ(KLEIDICV_ERROR_ALIGNMENT, - gaussian_blur_15x15()( + gaussian_blur()( src, sizeof(TypeParam), dst, sizeof(TypeParam) + 1, validSize, - validSize, 1, KLEIDICV_BORDER_TYPE_REPLICATE, context)); - EXPECT_EQ(KLEIDICV_OK, kleidicv_filter_release(context)); + validSize, 1, 15, 15, 0.0, 0.0, KLEIDICV_BORDER_TYPE_REPLICATE, + context)); + + EXPECT_EQ(KLEIDICV_OK, kleidicv_filter_context_release(context)); } TYPED_TEST(GaussianBlur, ZeroImageSize3x3) { TypeParam src[1] = {}, dst[1]; kleidicv_filter_context_t *context = nullptr; ASSERT_EQ(KLEIDICV_OK, - kleidicv_filter_create(&context, 1, 2 * sizeof(TypeParam), - kleidicv_rectangle_t{0, 1})); + kleidicv_filter_context_create(&context, 1, 3, 3, 1, 1)); EXPECT_EQ(KLEIDICV_ERROR_NOT_IMPLEMENTED, - gaussian_blur_3x3()( - src, sizeof(TypeParam), dst, sizeof(TypeParam), 0, 1, 1, - KLEIDICV_BORDER_TYPE_REFLECT, context)); - EXPECT_EQ(KLEIDICV_OK, kleidicv_filter_release(context)); - - ASSERT_EQ(KLEIDICV_OK, - kleidicv_filter_create(&context, 1, 2 * sizeof(TypeParam), - kleidicv_rectangle_t{1, 0})); + gaussian_blur()( + src, sizeof(TypeParam), dst, sizeof(TypeParam), 0, 1, 1, 3, 3, + 0.0, 0.0, KLEIDICV_BORDER_TYPE_REFLECT, context)); EXPECT_EQ(KLEIDICV_ERROR_NOT_IMPLEMENTED, - gaussian_blur_3x3()( - src, sizeof(TypeParam), dst, sizeof(TypeParam), 1, 0, 1, - KLEIDICV_BORDER_TYPE_REFLECT, context)); - EXPECT_EQ(KLEIDICV_OK, kleidicv_filter_release(context)); + gaussian_blur()( + src, sizeof(TypeParam), dst, sizeof(TypeParam), 1, 0, 1, 3, 3, + 0.0, 0.0, KLEIDICV_BORDER_TYPE_REFLECT, context)); + EXPECT_EQ(KLEIDICV_OK, kleidicv_filter_context_release(context)); } TYPED_TEST(GaussianBlur, ZeroImageSize5x5) { TypeParam src[1] = {}, dst[1]; kleidicv_filter_context_t *context = nullptr; ASSERT_EQ(KLEIDICV_OK, - kleidicv_filter_create(&context, 1, 2 * sizeof(TypeParam), - kleidicv_rectangle_t{0, 1})); + kleidicv_filter_context_create(&context, 1, 5, 5, 1, 1)); EXPECT_EQ(KLEIDICV_ERROR_NOT_IMPLEMENTED, - gaussian_blur_5x5()( - src, sizeof(TypeParam), dst, sizeof(TypeParam), 0, 1, 1, - KLEIDICV_BORDER_TYPE_REFLECT, context)); - EXPECT_EQ(KLEIDICV_OK, kleidicv_filter_release(context)); - - ASSERT_EQ(KLEIDICV_OK, - kleidicv_filter_create(&context, 1, 2 * sizeof(TypeParam), - kleidicv_rectangle_t{1, 0})); + gaussian_blur()( + src, sizeof(TypeParam), dst, sizeof(TypeParam), 0, 1, 1, 5, 5, + 0.0, 0.0, KLEIDICV_BORDER_TYPE_REFLECT, context)); EXPECT_EQ(KLEIDICV_ERROR_NOT_IMPLEMENTED, - gaussian_blur_5x5()( - src, sizeof(TypeParam), dst, sizeof(TypeParam), 1, 0, 1, - KLEIDICV_BORDER_TYPE_REFLECT, context)); - EXPECT_EQ(KLEIDICV_OK, kleidicv_filter_release(context)); + gaussian_blur()( + src, sizeof(TypeParam), dst, sizeof(TypeParam), 1, 0, 1, 5, 5, + 0.0, 0.0, KLEIDICV_BORDER_TYPE_REFLECT, context)); + EXPECT_EQ(KLEIDICV_OK, kleidicv_filter_context_release(context)); } TYPED_TEST(GaussianBlur, ZeroImageSize7x7) { TypeParam src[1] = {}, dst[1]; kleidicv_filter_context_t *context = nullptr; ASSERT_EQ(KLEIDICV_OK, - kleidicv_filter_create(&context, 1, 2 * sizeof(TypeParam), - kleidicv_rectangle_t{0, 1})); + kleidicv_filter_context_create(&context, 1, 7, 7, 1, 1)); EXPECT_EQ(KLEIDICV_ERROR_NOT_IMPLEMENTED, - gaussian_blur_7x7()( - src, sizeof(TypeParam), dst, sizeof(TypeParam), 0, 1, 1, - KLEIDICV_BORDER_TYPE_REFLECT, context)); - EXPECT_EQ(KLEIDICV_OK, kleidicv_filter_release(context)); - - ASSERT_EQ(KLEIDICV_OK, - kleidicv_filter_create(&context, 1, 2 * sizeof(TypeParam), - kleidicv_rectangle_t{1, 0})); + gaussian_blur()( + src, sizeof(TypeParam), dst, sizeof(TypeParam), 0, 1, 1, 7, 7, + 0.0, 0.0, KLEIDICV_BORDER_TYPE_REFLECT, context)); EXPECT_EQ(KLEIDICV_ERROR_NOT_IMPLEMENTED, - gaussian_blur_7x7()( - src, sizeof(TypeParam), dst, sizeof(TypeParam), 1, 0, 1, - KLEIDICV_BORDER_TYPE_REFLECT, context)); - EXPECT_EQ(KLEIDICV_OK, kleidicv_filter_release(context)); + gaussian_blur()( + src, sizeof(TypeParam), dst, sizeof(TypeParam), 1, 0, 1, 7, 7, + 0.0, 0.0, KLEIDICV_BORDER_TYPE_REFLECT, context)); + EXPECT_EQ(KLEIDICV_OK, kleidicv_filter_context_release(context)); } TYPED_TEST(GaussianBlur, ZeroImageSize15x15) { TypeParam src[1] = {}, dst[1]; kleidicv_filter_context_t *context = nullptr; ASSERT_EQ(KLEIDICV_OK, - kleidicv_filter_create(&context, 1, 4 * sizeof(TypeParam), - kleidicv_rectangle_t{0, 1})); + kleidicv_filter_context_create(&context, 1, 15, 15, 1, 1)); EXPECT_EQ(KLEIDICV_ERROR_NOT_IMPLEMENTED, - gaussian_blur_15x15()( - src, sizeof(TypeParam), dst, sizeof(TypeParam), 0, 1, 1, - KLEIDICV_BORDER_TYPE_REFLECT, context)); - EXPECT_EQ(KLEIDICV_OK, kleidicv_filter_release(context)); - - ASSERT_EQ(KLEIDICV_OK, - kleidicv_filter_create(&context, 1, 4 * sizeof(TypeParam), - kleidicv_rectangle_t{1, 0})); + gaussian_blur()( + src, sizeof(TypeParam), dst, sizeof(TypeParam), 0, 1, 1, 15, 15, + 0.0, 0.0, KLEIDICV_BORDER_TYPE_REFLECT, context)); EXPECT_EQ(KLEIDICV_ERROR_NOT_IMPLEMENTED, - gaussian_blur_15x15()( - src, sizeof(TypeParam), dst, sizeof(TypeParam), 1, 0, 1, - KLEIDICV_BORDER_TYPE_REFLECT, context)); - EXPECT_EQ(KLEIDICV_OK, kleidicv_filter_release(context)); + gaussian_blur()( + src, sizeof(TypeParam), dst, sizeof(TypeParam), 1, 0, 1, 15, 15, + 0.0, 0.0, KLEIDICV_BORDER_TYPE_REFLECT, context)); + EXPECT_EQ(KLEIDICV_OK, kleidicv_filter_context_release(context)); } TYPED_TEST(GaussianBlur, ValidImageSize3x3) { using KernelTestParams = GaussianBlurKernelTestParams; kleidicv_filter_context_t *context = nullptr; size_t validSize = KernelTestParams::kKernelSize - 1; - ASSERT_EQ(KLEIDICV_OK, - kleidicv_filter_create(&context, 1, 2 * sizeof(TypeParam), - kleidicv_rectangle_t{validSize, validSize})); + ASSERT_EQ(KLEIDICV_OK, kleidicv_filter_context_create(&context, 1, 3, 3, + validSize, validSize)); test::Array2D src{validSize, validSize, test::Options::vector_length()}; src.set(0, 0, {1, 2}); @@ -520,20 +538,19 @@ TYPED_TEST(GaussianBlur, ValidImageSize3x3) { test::Array2D dst{validSize, validSize, test::Options::vector_length()}; - EXPECT_EQ(KLEIDICV_OK, - gaussian_blur_3x3()( - src.data(), src.stride(), dst.data(), dst.stride(), validSize, - validSize, 1, KLEIDICV_BORDER_TYPE_REVERSE, context)); - EXPECT_EQ(KLEIDICV_OK, kleidicv_filter_release(context)); + EXPECT_EQ(KLEIDICV_OK, gaussian_blur()( + src.data(), src.stride(), dst.data(), dst.stride(), + validSize, validSize, 1, 3, 3, 0.0, 0.0, + KLEIDICV_BORDER_TYPE_REVERSE, context)); + EXPECT_EQ(KLEIDICV_OK, kleidicv_filter_context_release(context)); } TYPED_TEST(GaussianBlur, ValidImageSize5x5) { using KernelTestParams = GaussianBlurKernelTestParams; kleidicv_filter_context_t *context = nullptr; size_t validSize = KernelTestParams::kKernelSize - 1; - ASSERT_EQ(KLEIDICV_OK, - kleidicv_filter_create(&context, 1, 2 * sizeof(TypeParam), - kleidicv_rectangle_t{validSize, validSize})); + ASSERT_EQ(KLEIDICV_OK, kleidicv_filter_context_create(&context, 1, 5, 5, + validSize, validSize)); test::Array2D src{validSize, validSize, test::Options::vector_length()}; src.set(0, 0, {1, 2, 3, 4}); @@ -543,20 +560,19 @@ TYPED_TEST(GaussianBlur, ValidImageSize5x5) { test::Array2D dst{validSize, validSize, test::Options::vector_length()}; - EXPECT_EQ(KLEIDICV_OK, - gaussian_blur_5x5()( - src.data(), src.stride(), dst.data(), dst.stride(), validSize, - validSize, 1, KLEIDICV_BORDER_TYPE_REVERSE, context)); - EXPECT_EQ(KLEIDICV_OK, kleidicv_filter_release(context)); + EXPECT_EQ(KLEIDICV_OK, gaussian_blur()( + src.data(), src.stride(), dst.data(), dst.stride(), + validSize, validSize, 1, 5, 5, 0.0, 0.0, + KLEIDICV_BORDER_TYPE_REVERSE, context)); + EXPECT_EQ(KLEIDICV_OK, kleidicv_filter_context_release(context)); } TYPED_TEST(GaussianBlur, ValidImageSize7x7) { using KernelTestParams = GaussianBlurKernelTestParams; kleidicv_filter_context_t *context = nullptr; size_t validSize = KernelTestParams::kKernelSize - 1; - ASSERT_EQ(KLEIDICV_OK, - kleidicv_filter_create(&context, 1, 2 * sizeof(TypeParam), - kleidicv_rectangle_t{validSize, validSize})); + ASSERT_EQ(KLEIDICV_OK, kleidicv_filter_context_create(&context, 1, 7, 7, + validSize, validSize)); test::Array2D src{validSize, validSize, test::Options::vector_length()}; src.set(0, 0, {1, 2, 3, 4, 5, 6}); @@ -568,20 +584,19 @@ TYPED_TEST(GaussianBlur, ValidImageSize7x7) { test::Array2D dst{validSize, validSize, test::Options::vector_length()}; - EXPECT_EQ(KLEIDICV_OK, - gaussian_blur_7x7()( - src.data(), src.stride(), dst.data(), dst.stride(), validSize, - validSize, 1, KLEIDICV_BORDER_TYPE_REVERSE, context)); - EXPECT_EQ(KLEIDICV_OK, kleidicv_filter_release(context)); + EXPECT_EQ(KLEIDICV_OK, gaussian_blur()( + src.data(), src.stride(), dst.data(), dst.stride(), + validSize, validSize, 1, 7, 7, 0.0, 0.0, + KLEIDICV_BORDER_TYPE_REVERSE, context)); + EXPECT_EQ(KLEIDICV_OK, kleidicv_filter_context_release(context)); } TYPED_TEST(GaussianBlur, ValidImageSize15x15) { using KernelTestParams = GaussianBlurKernelTestParams; kleidicv_filter_context_t *context = nullptr; size_t validSize = KernelTestParams::kKernelSize - 1; - ASSERT_EQ(KLEIDICV_OK, - kleidicv_filter_create(&context, 1, 4 * sizeof(TypeParam), - kleidicv_rectangle_t{validSize, validSize})); + ASSERT_EQ(KLEIDICV_OK, kleidicv_filter_context_create(&context, 1, 15, 15, + validSize, validSize)); test::Array2D src{validSize, validSize, test::Options::vector_length()}; src.set(0, 0, {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14}); @@ -601,366 +616,356 @@ TYPED_TEST(GaussianBlur, ValidImageSize15x15) { test::Array2D dst{validSize, validSize, test::Options::vector_length()}; - EXPECT_EQ(KLEIDICV_OK, - gaussian_blur_15x15()( - src.data(), src.stride(), dst.data(), dst.stride(), validSize, - validSize, 1, KLEIDICV_BORDER_TYPE_REVERSE, context)); - EXPECT_EQ(KLEIDICV_OK, kleidicv_filter_release(context)); + EXPECT_EQ(KLEIDICV_OK, gaussian_blur()( + src.data(), src.stride(), dst.data(), dst.stride(), + validSize, validSize, 1, 15, 15, 0.0, 0.0, + KLEIDICV_BORDER_TYPE_REVERSE, context)); + EXPECT_EQ(KLEIDICV_OK, kleidicv_filter_context_release(context)); } TYPED_TEST(GaussianBlur, UndersizeImage3x3) { using KernelTestParams = GaussianBlurKernelTestParams; kleidicv_filter_context_t *context = nullptr; size_t underSize = KernelTestParams::kKernelSize - 2; - size_t validWidth = KernelTestParams::kKernelSize + 10; - size_t validHeight = KernelTestParams::kKernelSize + 5; - ASSERT_EQ(KLEIDICV_OK, - kleidicv_filter_create(&context, 1, 2 * sizeof(TypeParam), - kleidicv_rectangle_t{underSize, underSize})); + size_t validSize = KernelTestParams::kKernelSize - 1; + ASSERT_EQ(KLEIDICV_OK, kleidicv_filter_context_create(&context, 1, 3, 3, + validSize, validSize)); TypeParam src[1] = {}, dst[1]; - EXPECT_EQ(KLEIDICV_ERROR_NOT_IMPLEMENTED, - gaussian_blur_3x3()( - src, sizeof(TypeParam), dst, sizeof(TypeParam), underSize, - underSize, 1, KLEIDICV_BORDER_TYPE_REPLICATE, context)); - EXPECT_EQ(KLEIDICV_OK, kleidicv_filter_release(context)); - ASSERT_EQ(KLEIDICV_OK, kleidicv_filter_create( - &context, 1, 2 * sizeof(TypeParam), - kleidicv_rectangle_t{underSize, validHeight})); - EXPECT_EQ(KLEIDICV_ERROR_NOT_IMPLEMENTED, - gaussian_blur_3x3()( - src, sizeof(TypeParam), dst, sizeof(TypeParam), underSize, - validHeight, 1, KLEIDICV_BORDER_TYPE_REPLICATE, context)); - EXPECT_EQ(KLEIDICV_OK, kleidicv_filter_release(context)); - ASSERT_EQ(KLEIDICV_OK, kleidicv_filter_create( - &context, 1, 2 * sizeof(TypeParam), - kleidicv_rectangle_t{validWidth, underSize})); - EXPECT_EQ(KLEIDICV_ERROR_NOT_IMPLEMENTED, - gaussian_blur_3x3()( - src, sizeof(TypeParam), dst, sizeof(TypeParam), validWidth, - underSize, 1, KLEIDICV_BORDER_TYPE_REPLICATE, context)); - EXPECT_EQ(KLEIDICV_OK, kleidicv_filter_release(context)); + EXPECT_EQ( + KLEIDICV_ERROR_NOT_IMPLEMENTED, + gaussian_blur()(src, sizeof(TypeParam), dst, sizeof(TypeParam), + underSize, underSize, 1, 3, 3, 0.0, 0.0, + KLEIDICV_BORDER_TYPE_REPLICATE, context)); + EXPECT_EQ( + KLEIDICV_ERROR_NOT_IMPLEMENTED, + gaussian_blur()(src, sizeof(TypeParam), dst, sizeof(TypeParam), + underSize, validSize, 1, 3, 3, 0.0, 0.0, + KLEIDICV_BORDER_TYPE_REPLICATE, context)); + EXPECT_EQ( + KLEIDICV_ERROR_NOT_IMPLEMENTED, + gaussian_blur()(src, sizeof(TypeParam), dst, sizeof(TypeParam), + validSize, underSize, 1, 3, 3, 0.0, 0.0, + KLEIDICV_BORDER_TYPE_REPLICATE, context)); + EXPECT_EQ(KLEIDICV_OK, kleidicv_filter_context_release(context)); } TYPED_TEST(GaussianBlur, UndersizeImage5x5) { using KernelTestParams = GaussianBlurKernelTestParams; kleidicv_filter_context_t *context = nullptr; size_t underSize = KernelTestParams::kKernelSize - 2; - size_t validWidth = KernelTestParams::kKernelSize + 8; - size_t validHeight = KernelTestParams::kKernelSize + 3; - ASSERT_EQ(KLEIDICV_OK, - kleidicv_filter_create(&context, 1, 2 * sizeof(TypeParam), - kleidicv_rectangle_t{underSize, underSize})); + size_t validSize = KernelTestParams::kKernelSize - 1; + ASSERT_EQ(KLEIDICV_OK, kleidicv_filter_context_create(&context, 1, 5, 5, + validSize, validSize)); TypeParam src[1] = {}, dst[1]; - EXPECT_EQ(KLEIDICV_ERROR_NOT_IMPLEMENTED, - gaussian_blur_5x5()( - src, sizeof(TypeParam), dst, sizeof(TypeParam), underSize, - underSize, 1, KLEIDICV_BORDER_TYPE_REPLICATE, context)); - EXPECT_EQ(KLEIDICV_OK, kleidicv_filter_release(context)); - ASSERT_EQ(KLEIDICV_OK, kleidicv_filter_create( - &context, 1, 2 * sizeof(TypeParam), - kleidicv_rectangle_t{underSize, validHeight})); - EXPECT_EQ(KLEIDICV_ERROR_NOT_IMPLEMENTED, - gaussian_blur_5x5()( - src, sizeof(TypeParam), dst, sizeof(TypeParam), underSize, - validHeight, 1, KLEIDICV_BORDER_TYPE_REPLICATE, context)); - EXPECT_EQ(KLEIDICV_OK, kleidicv_filter_release(context)); - ASSERT_EQ(KLEIDICV_OK, kleidicv_filter_create( - &context, 1, 2 * sizeof(TypeParam), - kleidicv_rectangle_t{validWidth, underSize})); - EXPECT_EQ(KLEIDICV_ERROR_NOT_IMPLEMENTED, - gaussian_blur_5x5()( - src, sizeof(TypeParam), dst, sizeof(TypeParam), validWidth, - underSize, 1, KLEIDICV_BORDER_TYPE_REPLICATE, context)); - EXPECT_EQ(KLEIDICV_OK, kleidicv_filter_release(context)); + EXPECT_EQ( + KLEIDICV_ERROR_NOT_IMPLEMENTED, + gaussian_blur()(src, sizeof(TypeParam), dst, sizeof(TypeParam), + underSize, underSize, 1, 5, 5, 0.0, 0.0, + KLEIDICV_BORDER_TYPE_REPLICATE, context)); + EXPECT_EQ( + KLEIDICV_ERROR_NOT_IMPLEMENTED, + gaussian_blur()(src, sizeof(TypeParam), dst, sizeof(TypeParam), + underSize, validSize, 1, 5, 5, 0.0, 0.0, + KLEIDICV_BORDER_TYPE_REPLICATE, context)); + EXPECT_EQ( + KLEIDICV_ERROR_NOT_IMPLEMENTED, + gaussian_blur()(src, sizeof(TypeParam), dst, sizeof(TypeParam), + validSize, underSize, 1, 5, 5, 0.0, 0.0, + KLEIDICV_BORDER_TYPE_REPLICATE, context)); + EXPECT_EQ(KLEIDICV_OK, kleidicv_filter_context_release(context)); } TYPED_TEST(GaussianBlur, UndersizeImage7x7) { using KernelTestParams = GaussianBlurKernelTestParams; kleidicv_filter_context_t *context = nullptr; size_t underSize = KernelTestParams::kKernelSize - 2; - size_t validWidth = KernelTestParams::kKernelSize + 6; - size_t validHeight = KernelTestParams::kKernelSize + 1; - ASSERT_EQ(KLEIDICV_OK, - kleidicv_filter_create(&context, 1, 2 * sizeof(TypeParam), - kleidicv_rectangle_t{underSize, underSize})); + size_t validSize = KernelTestParams::kKernelSize - 1; + ASSERT_EQ(KLEIDICV_OK, kleidicv_filter_context_create(&context, 1, 7, 7, + validSize, validSize)); TypeParam src[1] = {}, dst[1]; - EXPECT_EQ(KLEIDICV_ERROR_NOT_IMPLEMENTED, - gaussian_blur_7x7()( - src, sizeof(TypeParam), dst, sizeof(TypeParam), underSize, - underSize, 1, KLEIDICV_BORDER_TYPE_REPLICATE, context)); - EXPECT_EQ(KLEIDICV_OK, kleidicv_filter_release(context)); - ASSERT_EQ(KLEIDICV_OK, kleidicv_filter_create( - &context, 1, 2 * sizeof(TypeParam), - kleidicv_rectangle_t{underSize, validHeight})); - EXPECT_EQ(KLEIDICV_ERROR_NOT_IMPLEMENTED, - gaussian_blur_7x7()( - src, sizeof(TypeParam), dst, sizeof(TypeParam), underSize, - validHeight, 1, KLEIDICV_BORDER_TYPE_REPLICATE, context)); - EXPECT_EQ(KLEIDICV_OK, kleidicv_filter_release(context)); - ASSERT_EQ(KLEIDICV_OK, kleidicv_filter_create( - &context, 1, 2 * sizeof(TypeParam), - kleidicv_rectangle_t{validWidth, underSize})); - EXPECT_EQ(KLEIDICV_ERROR_NOT_IMPLEMENTED, - gaussian_blur_7x7()( - src, sizeof(TypeParam), dst, sizeof(TypeParam), validWidth, - underSize, 1, KLEIDICV_BORDER_TYPE_REPLICATE, context)); - EXPECT_EQ(KLEIDICV_OK, kleidicv_filter_release(context)); + EXPECT_EQ( + KLEIDICV_ERROR_NOT_IMPLEMENTED, + gaussian_blur()(src, sizeof(TypeParam), dst, sizeof(TypeParam), + underSize, underSize, 1, 7, 7, 0.0, 0.0, + KLEIDICV_BORDER_TYPE_REPLICATE, context)); + EXPECT_EQ( + KLEIDICV_ERROR_NOT_IMPLEMENTED, + gaussian_blur()(src, sizeof(TypeParam), dst, sizeof(TypeParam), + underSize, validSize, 1, 7, 7, 0.0, 0.0, + KLEIDICV_BORDER_TYPE_REPLICATE, context)); + EXPECT_EQ( + KLEIDICV_ERROR_NOT_IMPLEMENTED, + gaussian_blur()(src, sizeof(TypeParam), dst, sizeof(TypeParam), + validSize, underSize, 1, 7, 7, 0.0, 0.0, + KLEIDICV_BORDER_TYPE_REPLICATE, context)); + EXPECT_EQ(KLEIDICV_OK, kleidicv_filter_context_release(context)); } TYPED_TEST(GaussianBlur, UndersizeImage15x15) { using KernelTestParams = GaussianBlurKernelTestParams; kleidicv_filter_context_t *context = nullptr; size_t underSize = KernelTestParams::kKernelSize - 2; - size_t validWidth = KernelTestParams::kKernelSize + 10; - size_t validHeight = KernelTestParams::kKernelSize + 5; - ASSERT_EQ(KLEIDICV_OK, - kleidicv_filter_create(&context, 1, 4 * sizeof(TypeParam), - kleidicv_rectangle_t{underSize, underSize})); + size_t validSize = KernelTestParams::kKernelSize - 1; + ASSERT_EQ(KLEIDICV_OK, kleidicv_filter_context_create(&context, 1, 15, 15, + validSize, validSize)); TypeParam src[1] = {}, dst[1]; - EXPECT_EQ(KLEIDICV_ERROR_NOT_IMPLEMENTED, - gaussian_blur_15x15()( - src, sizeof(TypeParam), dst, sizeof(TypeParam), underSize, - underSize, 1, KLEIDICV_BORDER_TYPE_REPLICATE, context)); - EXPECT_EQ(KLEIDICV_OK, kleidicv_filter_release(context)); - ASSERT_EQ(KLEIDICV_OK, kleidicv_filter_create( - &context, 1, 4 * sizeof(TypeParam), - kleidicv_rectangle_t{underSize, validHeight})); - EXPECT_EQ(KLEIDICV_ERROR_NOT_IMPLEMENTED, - gaussian_blur_15x15()( - src, sizeof(TypeParam), dst, sizeof(TypeParam), underSize, - validHeight, 1, KLEIDICV_BORDER_TYPE_REPLICATE, context)); - EXPECT_EQ(KLEIDICV_OK, kleidicv_filter_release(context)); - ASSERT_EQ(KLEIDICV_OK, kleidicv_filter_create( - &context, 1, 4 * sizeof(TypeParam), - kleidicv_rectangle_t{validWidth, underSize})); - EXPECT_EQ(KLEIDICV_ERROR_NOT_IMPLEMENTED, - gaussian_blur_15x15()( - src, sizeof(TypeParam), dst, sizeof(TypeParam), validWidth, - underSize, 1, KLEIDICV_BORDER_TYPE_REPLICATE, context)); - EXPECT_EQ(KLEIDICV_OK, kleidicv_filter_release(context)); + EXPECT_EQ( + KLEIDICV_ERROR_NOT_IMPLEMENTED, + gaussian_blur()(src, sizeof(TypeParam), dst, sizeof(TypeParam), + underSize, underSize, 1, 15, 15, 0.0, 0.0, + KLEIDICV_BORDER_TYPE_REPLICATE, context)); + EXPECT_EQ( + KLEIDICV_ERROR_NOT_IMPLEMENTED, + gaussian_blur()(src, sizeof(TypeParam), dst, sizeof(TypeParam), + underSize, validSize, 1, 15, 15, 0.0, 0.0, + KLEIDICV_BORDER_TYPE_REPLICATE, context)); + EXPECT_EQ( + KLEIDICV_ERROR_NOT_IMPLEMENTED, + gaussian_blur()(src, sizeof(TypeParam), dst, sizeof(TypeParam), + validSize, underSize, 1, 15, 15, 0.0, 0.0, + KLEIDICV_BORDER_TYPE_REPLICATE, context)); + EXPECT_EQ(KLEIDICV_OK, kleidicv_filter_context_release(context)); } TYPED_TEST(GaussianBlur, OversizeImage) { kleidicv_filter_context_t *context = nullptr; ASSERT_EQ(KLEIDICV_OK, - kleidicv_filter_create(&context, 1, 2 * sizeof(TypeParam), - kleidicv_rectangle_t{1, 1})); + kleidicv_filter_context_create(&context, 1, 15, 15, 1, 1)); TypeParam src[1], dst[1]; + EXPECT_EQ( + KLEIDICV_ERROR_RANGE, + gaussian_blur()(src, sizeof(TypeParam), dst, sizeof(TypeParam), + KLEIDICV_MAX_IMAGE_PIXELS + 1, 1, 1, 3, 3, 0.0, + 0.0, KLEIDICV_BORDER_TYPE_REFLECT, context)); EXPECT_EQ(KLEIDICV_ERROR_RANGE, - gaussian_blur_3x3()( - src, sizeof(TypeParam), dst, sizeof(TypeParam), - KLEIDICV_MAX_IMAGE_PIXELS + 1, 1, 1, - KLEIDICV_BORDER_TYPE_REFLECT, context)); - EXPECT_EQ(KLEIDICV_ERROR_RANGE, - gaussian_blur_3x3()( + gaussian_blur()( src, sizeof(TypeParam), dst, sizeof(TypeParam), - KLEIDICV_MAX_IMAGE_PIXELS, KLEIDICV_MAX_IMAGE_PIXELS, 1, - KLEIDICV_BORDER_TYPE_REFLECT, context)); + KLEIDICV_MAX_IMAGE_PIXELS, KLEIDICV_MAX_IMAGE_PIXELS, 1, 3, 3, + 0.0, 0.0, KLEIDICV_BORDER_TYPE_REFLECT, context)); + EXPECT_EQ( + KLEIDICV_ERROR_RANGE, + gaussian_blur()(src, sizeof(TypeParam), dst, sizeof(TypeParam), + KLEIDICV_MAX_IMAGE_PIXELS + 1, 1, 1, 5, 5, 0.0, + 0.0, KLEIDICV_BORDER_TYPE_REFLECT, context)); EXPECT_EQ(KLEIDICV_ERROR_RANGE, - gaussian_blur_5x5()( + gaussian_blur()( src, sizeof(TypeParam), dst, sizeof(TypeParam), - KLEIDICV_MAX_IMAGE_PIXELS + 1, 1, 1, - KLEIDICV_BORDER_TYPE_REFLECT, context)); + KLEIDICV_MAX_IMAGE_PIXELS, KLEIDICV_MAX_IMAGE_PIXELS, 1, 5, 5, + 0.0, 0.0, KLEIDICV_BORDER_TYPE_REFLECT, context)); + EXPECT_EQ( + KLEIDICV_ERROR_RANGE, + gaussian_blur()(src, sizeof(TypeParam), dst, sizeof(TypeParam), + KLEIDICV_MAX_IMAGE_PIXELS + 1, 1, 1, 7, 7, 0.0, + 0.0, KLEIDICV_BORDER_TYPE_REFLECT, context)); EXPECT_EQ(KLEIDICV_ERROR_RANGE, - gaussian_blur_5x5()( + gaussian_blur()( src, sizeof(TypeParam), dst, sizeof(TypeParam), - KLEIDICV_MAX_IMAGE_PIXELS, KLEIDICV_MAX_IMAGE_PIXELS, 1, - KLEIDICV_BORDER_TYPE_REFLECT, context)); + KLEIDICV_MAX_IMAGE_PIXELS, KLEIDICV_MAX_IMAGE_PIXELS, 1, 7, 7, + 0.0, 0.0, KLEIDICV_BORDER_TYPE_REFLECT, context)); EXPECT_EQ(KLEIDICV_ERROR_RANGE, - gaussian_blur_7x7()( + gaussian_blur()( src, sizeof(TypeParam), dst, sizeof(TypeParam), - KLEIDICV_MAX_IMAGE_PIXELS + 1, 1, 1, + KLEIDICV_MAX_IMAGE_PIXELS + 1, 1, 1, 15, 15, 0.0, 0.0, KLEIDICV_BORDER_TYPE_REFLECT, context)); EXPECT_EQ(KLEIDICV_ERROR_RANGE, - gaussian_blur_7x7()( + gaussian_blur()( src, sizeof(TypeParam), dst, sizeof(TypeParam), - KLEIDICV_MAX_IMAGE_PIXELS, KLEIDICV_MAX_IMAGE_PIXELS, 1, - KLEIDICV_BORDER_TYPE_REFLECT, context)); - EXPECT_EQ(KLEIDICV_ERROR_RANGE, - gaussian_blur_15x15()( - src, sizeof(TypeParam), dst, sizeof(TypeParam), - KLEIDICV_MAX_IMAGE_PIXELS + 1, 1, 1, - KLEIDICV_BORDER_TYPE_REFLECT, context)); - EXPECT_EQ(KLEIDICV_ERROR_RANGE, - gaussian_blur_15x15()( - src, sizeof(TypeParam), dst, sizeof(TypeParam), - KLEIDICV_MAX_IMAGE_PIXELS, KLEIDICV_MAX_IMAGE_PIXELS, 1, - KLEIDICV_BORDER_TYPE_REFLECT, context)); - EXPECT_EQ(KLEIDICV_OK, kleidicv_filter_release(context)); + KLEIDICV_MAX_IMAGE_PIXELS, KLEIDICV_MAX_IMAGE_PIXELS, 1, 15, 15, + 0.0, 0.0, KLEIDICV_BORDER_TYPE_REFLECT, context)); + EXPECT_EQ(KLEIDICV_OK, kleidicv_filter_context_release(context)); } TYPED_TEST(GaussianBlur, ChannelNumber) { - using KernelTestParams3x3 = GaussianBlurKernelTestParams; - using KernelTestParams5x5 = GaussianBlurKernelTestParams; - using KernelTestParams7x7 = GaussianBlurKernelTestParams; using KernelTestParams15x15 = GaussianBlurKernelTestParams; kleidicv_filter_context_t *context = nullptr; - size_t validSize = KernelTestParams3x3::kKernelSize - 1; + size_t validSize = KernelTestParams15x15::kKernelSize - 1; - ASSERT_EQ(KLEIDICV_OK, - kleidicv_filter_create(&context, 1, 2 * sizeof(TypeParam), - kleidicv_rectangle_t{validSize, validSize})); + ASSERT_EQ(KLEIDICV_OK, kleidicv_filter_context_create(&context, 1, 15, 15, + validSize, validSize)); TypeParam src[1], dst[1]; EXPECT_EQ(KLEIDICV_ERROR_RANGE, - gaussian_blur_3x3()( + gaussian_blur()( src, sizeof(TypeParam), dst, sizeof(TypeParam), validSize, - validSize, KLEIDICV_MAXIMUM_CHANNEL_COUNT + 1, + validSize, KLEIDICV_MAXIMUM_CHANNEL_COUNT + 1, 3, 3, 0.0, 0.0, KLEIDICV_BORDER_TYPE_REFLECT, context)); - validSize = KernelTestParams5x5::kKernelSize - 1; EXPECT_EQ(KLEIDICV_ERROR_RANGE, - gaussian_blur_5x5()( + gaussian_blur()( src, sizeof(TypeParam), dst, sizeof(TypeParam), validSize, - validSize, KLEIDICV_MAXIMUM_CHANNEL_COUNT + 1, + validSize, KLEIDICV_MAXIMUM_CHANNEL_COUNT + 1, 5, 5, 0.0, 0.0, KLEIDICV_BORDER_TYPE_REFLECT, context)); - validSize = KernelTestParams7x7::kKernelSize - 1; EXPECT_EQ(KLEIDICV_ERROR_RANGE, - gaussian_blur_7x7()( + gaussian_blur()( src, sizeof(TypeParam), dst, sizeof(TypeParam), validSize, - validSize, KLEIDICV_MAXIMUM_CHANNEL_COUNT + 1, + validSize, KLEIDICV_MAXIMUM_CHANNEL_COUNT + 1, 7, 7, 0.0, 0.0, KLEIDICV_BORDER_TYPE_REFLECT, context)); - validSize = KernelTestParams15x15::kKernelSize - 1; EXPECT_EQ(KLEIDICV_ERROR_RANGE, - gaussian_blur_15x15()( + gaussian_blur()( src, sizeof(TypeParam), dst, sizeof(TypeParam), validSize, - validSize, KLEIDICV_MAXIMUM_CHANNEL_COUNT + 1, + validSize, KLEIDICV_MAXIMUM_CHANNEL_COUNT + 1, 15, 15, 0.0, 0.0, KLEIDICV_BORDER_TYPE_REFLECT, context)); - EXPECT_EQ(KLEIDICV_OK, kleidicv_filter_release(context)); + EXPECT_EQ(KLEIDICV_OK, kleidicv_filter_context_release(context)); } -TYPED_TEST(GaussianBlur, InvalidContextSizeType) { - using KernelTestParams3x3 = GaussianBlurKernelTestParams; - using KernelTestParams5x5 = GaussianBlurKernelTestParams; - using KernelTestParams7x7 = GaussianBlurKernelTestParams; +TYPED_TEST(GaussianBlur, InvalidContextKernelSize) { using KernelTestParams15x15 = GaussianBlurKernelTestParams; kleidicv_filter_context_t *context = nullptr; - size_t validSize = KernelTestParams3x3::kKernelSize - 1; - - ASSERT_EQ(KLEIDICV_OK, - kleidicv_filter_create(&context, 1, 2 * sizeof(TypeParam) + 1, - kleidicv_rectangle_t{validSize, validSize})); - TypeParam src[1], dst[1]; - EXPECT_EQ(KLEIDICV_ERROR_CONTEXT_MISMATCH, - gaussian_blur_3x3()( - src, sizeof(TypeParam), dst, sizeof(TypeParam), validSize, - validSize, 1, KLEIDICV_BORDER_TYPE_REFLECT, context)); - validSize = KernelTestParams5x5::kKernelSize - 1; - EXPECT_EQ(KLEIDICV_ERROR_CONTEXT_MISMATCH, - gaussian_blur_5x5()( - src, sizeof(TypeParam), dst, sizeof(TypeParam), validSize, - validSize, 1, KLEIDICV_BORDER_TYPE_REFLECT, context)); - validSize = KernelTestParams7x7::kKernelSize - 1; - EXPECT_EQ(KLEIDICV_ERROR_CONTEXT_MISMATCH, - gaussian_blur_7x7()( - src, sizeof(TypeParam), dst, sizeof(TypeParam), validSize, - validSize, 1, KLEIDICV_BORDER_TYPE_REFLECT, context)); - - EXPECT_EQ(KLEIDICV_OK, kleidicv_filter_release(context)); - ASSERT_EQ(KLEIDICV_OK, - kleidicv_filter_create(&context, 1, 4 * sizeof(TypeParam) + 1, - kleidicv_rectangle_t{validSize, validSize})); - - validSize = KernelTestParams15x15::kKernelSize - 1; - EXPECT_EQ(KLEIDICV_ERROR_CONTEXT_MISMATCH, - gaussian_blur_15x15()( - src, sizeof(TypeParam), dst, sizeof(TypeParam), validSize, - validSize, 1, KLEIDICV_BORDER_TYPE_REFLECT, context)); - EXPECT_EQ(KLEIDICV_OK, kleidicv_filter_release(context)); -} - -TYPED_TEST(GaussianBlur, InvalidContextChannelNumber) { - using KernelTestParams3x3 = GaussianBlurKernelTestParams; - using KernelTestParams5x5 = GaussianBlurKernelTestParams; - using KernelTestParams7x7 = GaussianBlurKernelTestParams; + size_t validSize = KernelTestParams15x15::kKernelSize - 1; + + ASSERT_EQ(KLEIDICV_OK, kleidicv_filter_context_create(&context, 1, 5, 5, + validSize, validSize)); + TypeParam src[256], dst[256]; + EXPECT_EQ(KLEIDICV_OK, gaussian_blur()( + src, sizeof(TypeParam), dst, sizeof(TypeParam), + validSize, validSize, 1, 3, 3, 0.0, 0.0, + KLEIDICV_BORDER_TYPE_REFLECT, context)); + EXPECT_EQ(KLEIDICV_OK, gaussian_blur()( + src, sizeof(TypeParam), dst, sizeof(TypeParam), + validSize, validSize, 1, 5, 5, 0.0, 0.0, + KLEIDICV_BORDER_TYPE_REFLECT, context)); + EXPECT_EQ(KLEIDICV_OK, gaussian_blur()( + src, sizeof(TypeParam), dst, sizeof(TypeParam), + validSize, validSize, 1, 7, 7, 0.0, 0.0, + KLEIDICV_BORDER_TYPE_REFLECT, context)); + EXPECT_EQ( + KLEIDICV_ERROR_CONTEXT_MISMATCH, + gaussian_blur()(src, sizeof(TypeParam), dst, sizeof(TypeParam), + validSize, validSize, 1, 15, 15, 0.0, 0.0, + KLEIDICV_BORDER_TYPE_REFLECT, context)); + + EXPECT_EQ(KLEIDICV_OK, kleidicv_filter_context_release(context)); + ASSERT_EQ(KLEIDICV_OK, kleidicv_filter_context_create(&context, 1, 15, 15, + validSize, validSize)); + + EXPECT_EQ(KLEIDICV_OK, gaussian_blur()( + src, sizeof(TypeParam), dst, sizeof(TypeParam), + validSize, validSize, 1, 3, 3, 0.0, 0.0, + KLEIDICV_BORDER_TYPE_REFLECT, context)); + EXPECT_EQ(KLEIDICV_OK, gaussian_blur()( + src, sizeof(TypeParam), dst, sizeof(TypeParam), + validSize, validSize, 1, 15, 15, 0.0, 0.0, + KLEIDICV_BORDER_TYPE_REFLECT, context)); + EXPECT_EQ(KLEIDICV_OK, kleidicv_filter_context_release(context)); +} + +TYPED_TEST(GaussianBlur, InvalidContextMaxChannels) { using KernelTestParams15x15 = GaussianBlurKernelTestParams; kleidicv_filter_context_t *context = nullptr; - size_t validSize = KernelTestParams3x3::kKernelSize - 1; + size_t validSize = KernelTestParams15x15::kKernelSize - 1; - ASSERT_EQ(KLEIDICV_OK, - kleidicv_filter_create(&context, 2, 2 * sizeof(TypeParam), - kleidicv_rectangle_t{validSize, validSize})); + ASSERT_EQ(KLEIDICV_OK, kleidicv_filter_context_create(&context, 1, 15, 15, + validSize, validSize)); TypeParam src[1], dst[1]; - EXPECT_EQ(KLEIDICV_ERROR_CONTEXT_MISMATCH, - gaussian_blur_3x3()( - src, sizeof(TypeParam), dst, sizeof(TypeParam), validSize, - validSize, 1, KLEIDICV_BORDER_TYPE_REFLECT, context)); - - validSize = KernelTestParams5x5::kKernelSize - 1; - EXPECT_EQ(KLEIDICV_ERROR_CONTEXT_MISMATCH, - gaussian_blur_5x5()( - src, sizeof(TypeParam), dst, sizeof(TypeParam), validSize, - validSize, 1, KLEIDICV_BORDER_TYPE_REFLECT, context)); - - validSize = KernelTestParams7x7::kKernelSize - 1; - EXPECT_EQ(KLEIDICV_ERROR_CONTEXT_MISMATCH, - gaussian_blur_7x7()( - src, sizeof(TypeParam), dst, sizeof(TypeParam), validSize, - validSize, 1, KLEIDICV_BORDER_TYPE_REFLECT, context)); - - EXPECT_EQ(KLEIDICV_OK, kleidicv_filter_release(context)); - ASSERT_EQ(KLEIDICV_OK, - kleidicv_filter_create(&context, 2, 4 * sizeof(TypeParam), - kleidicv_rectangle_t{validSize, validSize})); - - validSize = KernelTestParams15x15::kKernelSize - 1; - EXPECT_EQ(KLEIDICV_ERROR_CONTEXT_MISMATCH, - gaussian_blur_15x15()( - src, sizeof(TypeParam), dst, sizeof(TypeParam), validSize, - validSize, 1, KLEIDICV_BORDER_TYPE_REFLECT, context)); - EXPECT_EQ(KLEIDICV_OK, kleidicv_filter_release(context)); + EXPECT_EQ( + KLEIDICV_ERROR_CONTEXT_MISMATCH, + gaussian_blur()(src, sizeof(TypeParam), dst, sizeof(TypeParam), + validSize, validSize, 2, 3, 3, 0.0, 0.0, + KLEIDICV_BORDER_TYPE_REFLECT, context)); + + EXPECT_EQ( + KLEIDICV_ERROR_CONTEXT_MISMATCH, + gaussian_blur()(src, sizeof(TypeParam), dst, sizeof(TypeParam), + validSize, validSize, 2, 5, 5, 0.0, 0.0, + KLEIDICV_BORDER_TYPE_REFLECT, context)); + + EXPECT_EQ( + KLEIDICV_ERROR_CONTEXT_MISMATCH, + gaussian_blur()(src, sizeof(TypeParam), dst, sizeof(TypeParam), + validSize, validSize, 2, 7, 7, 0.0, 0.0, + KLEIDICV_BORDER_TYPE_REFLECT, context)); + + EXPECT_EQ( + KLEIDICV_ERROR_CONTEXT_MISMATCH, + gaussian_blur()(src, sizeof(TypeParam), dst, sizeof(TypeParam), + validSize, validSize, 2, 15, 15, 0.0, 0.0, + KLEIDICV_BORDER_TYPE_REFLECT, context)); + EXPECT_EQ(KLEIDICV_OK, kleidicv_filter_context_release(context)); } TYPED_TEST(GaussianBlur, InvalidContextImageSize) { - using KernelTestParams3x3 = GaussianBlurKernelTestParams; - using KernelTestParams5x5 = GaussianBlurKernelTestParams; - using KernelTestParams7x7 = GaussianBlurKernelTestParams; using KernelTestParams15x15 = GaussianBlurKernelTestParams; kleidicv_filter_context_t *context = nullptr; - size_t validSize = KernelTestParams3x3::kKernelSize - 1; + size_t validSize = KernelTestParams15x15::kKernelSize - 1; - ASSERT_EQ(KLEIDICV_OK, - kleidicv_filter_create(&context, 1, 2 * sizeof(TypeParam), - kleidicv_rectangle_t{validSize, validSize})); + ASSERT_EQ(KLEIDICV_OK, kleidicv_filter_context_create(&context, 1, 15, 15, + validSize, validSize)); TypeParam src[1], dst[1]; - EXPECT_EQ(KLEIDICV_ERROR_CONTEXT_MISMATCH, - gaussian_blur_3x3()( - src, sizeof(TypeParam), dst, sizeof(TypeParam), validSize + 1, - validSize + 1, 1, KLEIDICV_BORDER_TYPE_REFLECT, context)); - - validSize = KernelTestParams5x5::kKernelSize - 1; - EXPECT_EQ(KLEIDICV_ERROR_CONTEXT_MISMATCH, - gaussian_blur_5x5()( - src, sizeof(TypeParam), dst, sizeof(TypeParam), validSize + 1, - validSize + 1, 1, KLEIDICV_BORDER_TYPE_REFLECT, context)); - - validSize = KernelTestParams7x7::kKernelSize - 1; - EXPECT_EQ(KLEIDICV_ERROR_CONTEXT_MISMATCH, - gaussian_blur_7x7()( - src, sizeof(TypeParam), dst, sizeof(TypeParam), validSize + 1, - validSize + 1, 1, KLEIDICV_BORDER_TYPE_REFLECT, context)); - - EXPECT_EQ(KLEIDICV_OK, kleidicv_filter_release(context)); - ASSERT_EQ(KLEIDICV_OK, - kleidicv_filter_create(&context, 1, 4 * sizeof(TypeParam), - kleidicv_rectangle_t{validSize, validSize})); - - validSize = KernelTestParams15x15::kKernelSize - 1; - EXPECT_EQ(KLEIDICV_ERROR_CONTEXT_MISMATCH, - gaussian_blur_15x15()( - src, sizeof(TypeParam), dst, sizeof(TypeParam), validSize + 1, - validSize + 1, 1, KLEIDICV_BORDER_TYPE_REFLECT, context)); - EXPECT_EQ(KLEIDICV_OK, kleidicv_filter_release(context)); + EXPECT_EQ( + KLEIDICV_ERROR_CONTEXT_MISMATCH, + gaussian_blur()(src, sizeof(TypeParam), dst, sizeof(TypeParam), + validSize + 1, validSize, 1, 3, 3, 0.0, 0.0, + KLEIDICV_BORDER_TYPE_REFLECT, context)); + EXPECT_EQ( + KLEIDICV_ERROR_CONTEXT_MISMATCH, + gaussian_blur()(src, sizeof(TypeParam), dst, sizeof(TypeParam), + validSize, validSize + 1, 1, 3, 3, 0.0, 0.0, + KLEIDICV_BORDER_TYPE_REFLECT, context)); + EXPECT_EQ( + KLEIDICV_ERROR_CONTEXT_MISMATCH, + gaussian_blur()(src, sizeof(TypeParam), dst, sizeof(TypeParam), + validSize + 1, validSize + 1, 1, 3, 3, 0.0, + 0.0, KLEIDICV_BORDER_TYPE_REFLECT, context)); + + EXPECT_EQ( + KLEIDICV_ERROR_CONTEXT_MISMATCH, + gaussian_blur()(src, sizeof(TypeParam), dst, sizeof(TypeParam), + validSize + 1, validSize, 1, 5, 5, 0.0, 0.0, + KLEIDICV_BORDER_TYPE_REFLECT, context)); + EXPECT_EQ( + KLEIDICV_ERROR_CONTEXT_MISMATCH, + gaussian_blur()(src, sizeof(TypeParam), dst, sizeof(TypeParam), + validSize, validSize + 1, 1, 5, 5, 0.0, 0.0, + KLEIDICV_BORDER_TYPE_REFLECT, context)); + EXPECT_EQ( + KLEIDICV_ERROR_CONTEXT_MISMATCH, + gaussian_blur()(src, sizeof(TypeParam), dst, sizeof(TypeParam), + validSize + 1, validSize + 1, 1, 5, 5, 0.0, + 0.0, KLEIDICV_BORDER_TYPE_REFLECT, context)); + + EXPECT_EQ( + KLEIDICV_ERROR_CONTEXT_MISMATCH, + gaussian_blur()(src, sizeof(TypeParam), dst, sizeof(TypeParam), + validSize + 1, validSize, 1, 7, 7, 0.0, 0.0, + KLEIDICV_BORDER_TYPE_REFLECT, context)); + EXPECT_EQ( + KLEIDICV_ERROR_CONTEXT_MISMATCH, + gaussian_blur()(src, sizeof(TypeParam), dst, sizeof(TypeParam), + validSize, validSize + 1, 1, 7, 7, 0.0, 0.0, + KLEIDICV_BORDER_TYPE_REFLECT, context)); + EXPECT_EQ( + KLEIDICV_ERROR_CONTEXT_MISMATCH, + gaussian_blur()(src, sizeof(TypeParam), dst, sizeof(TypeParam), + validSize + 1, validSize + 1, 1, 7, 7, 0.0, + 0.0, KLEIDICV_BORDER_TYPE_REFLECT, context)); + + EXPECT_EQ( + KLEIDICV_ERROR_CONTEXT_MISMATCH, + gaussian_blur()(src, sizeof(TypeParam), dst, sizeof(TypeParam), + validSize + 1, validSize, 1, 15, 15, 0.0, 0.0, + KLEIDICV_BORDER_TYPE_REFLECT, context)); + EXPECT_EQ( + KLEIDICV_ERROR_CONTEXT_MISMATCH, + gaussian_blur()(src, sizeof(TypeParam), dst, sizeof(TypeParam), + validSize, validSize + 1, 1, 15, 15, 0.0, 0.0, + KLEIDICV_BORDER_TYPE_REFLECT, context)); + EXPECT_EQ( + KLEIDICV_ERROR_CONTEXT_MISMATCH, + gaussian_blur()(src, sizeof(TypeParam), dst, sizeof(TypeParam), + validSize + 1, validSize + 1, 1, 15, 15, 0.0, + 0.0, KLEIDICV_BORDER_TYPE_REFLECT, context)); + + EXPECT_EQ(KLEIDICV_OK, kleidicv_filter_context_release(context)); } #ifdef KLEIDICV_ALLOCATION_TESTS TEST(FilterCreate, CannotAllocateFilter) { MockMallocToFail::enable(); kleidicv_filter_context_t *context = nullptr; - kleidicv_rectangle_t rect{KLEIDICV_MAX_IMAGE_PIXELS, 1}; EXPECT_EQ(KLEIDICV_ERROR_ALLOCATION, - kleidicv_filter_create(&context, 1, 1, rect)); + kleidicv_filter_context_create(&context, 1, 1, 1, + KLEIDICV_MAX_IMAGE_PIXELS, 1)); MockMallocToFail::disable(); } #endif @@ -974,17 +979,17 @@ TEST(FilterCreate, OversizeImage) { KLEIDICV_MAX_IMAGE_PIXELS}, }) { EXPECT_EQ(KLEIDICV_ERROR_RANGE, - kleidicv_filter_create(&context, 1, 1, rect)); + kleidicv_filter_context_create(&context, 1, 1, 1, rect.width, + rect.height)); ASSERT_EQ(nullptr, context); } } -TEST(FilterCreate, TypeSize) { +TEST(FilterCreate, DifferentKernelSize) { kleidicv_filter_context_t *context = nullptr; - EXPECT_EQ(KLEIDICV_ERROR_RANGE, - kleidicv_filter_create(&context, 1, KLEIDICV_MAXIMUM_TYPE_SIZE + 1, - kleidicv_rectangle_t{1, 1})); + EXPECT_EQ(KLEIDICV_ERROR_NOT_IMPLEMENTED, + kleidicv_filter_context_create(&context, 1, 7, 15, 1, 1)); ASSERT_EQ(nullptr, context); } @@ -992,15 +997,17 @@ TEST(FilterCreate, ChannelNumber) { kleidicv_filter_context_t *context = nullptr; EXPECT_EQ(KLEIDICV_ERROR_RANGE, - kleidicv_filter_create(&context, KLEIDICV_MAXIMUM_CHANNEL_COUNT + 1, - 1, kleidicv_rectangle_t{1, 1})); + kleidicv_filter_context_create( + &context, KLEIDICV_MAXIMUM_CHANNEL_COUNT + 1, 1, 1, 1, 1)); ASSERT_EQ(nullptr, context); } TEST(FilterCreate, NullPointer) { EXPECT_EQ(KLEIDICV_ERROR_NULL_POINTER, - kleidicv_filter_create(nullptr, 1, 1, kleidicv_rectangle_t{1, 1})); + kleidicv_filter_context_create(nullptr, 1, 1, 1, 1, 1)); } + TEST(FilterRelease, NullPointer) { - EXPECT_EQ(KLEIDICV_ERROR_NULL_POINTER, kleidicv_filter_release(nullptr)); + EXPECT_EQ(KLEIDICV_ERROR_NULL_POINTER, + kleidicv_filter_context_release(nullptr)); } -- GitLab From bbe785d4da13269a943c1a7a681973bf1bca2746 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Igor=20Podgain=C3=B5i?= Date: Tue, 25 Jun 2024 13:44:16 +0200 Subject: [PATCH 2/2] Update CHANGELOG.md and doc/opencv.md Add a new entry to the changelog and fix excessive spacing in the doc/opencv.md file. --- CHANGELOG.md | 2 ++ doc/opencv.md | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index d8572f877..5690737b3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -31,6 +31,8 @@ This changelog aims to follow the guiding principles of ### Fixed ### Changed +- Filter context creation API specification. +- Gaussian Blur API specification. ### Removed diff --git a/doc/opencv.md b/doc/opencv.md index a11101986..d9219c172 100644 --- a/doc/opencv.md +++ b/doc/opencv.md @@ -104,7 +104,7 @@ Notes on parameters: ### `gaussian_blur` Blurs an image using a Gaussian filter.\ -Currently does not support non-zero margins. Kernel shape is restricted to square (`kernel width == kernel height`). Kernel standard deviation cannot be customized via `sigmaX` and `sigmaY` and is calculated based on kernel size. +Currently does not support non-zero margins. Kernel shape is restricted to square (`kernelWidth == kernelHeight`). Kernel standard deviation cannot be customized via `sigmaX` and `sigmaY` and is calculated based on kernel size. Notes on parameters: * `depth` - only supports `CV_8U` depth. -- GitLab