From 2ffdc3e62090b6251ca7329c440d73bd47c3d2a1 Mon Sep 17 00:00:00 2001 From: Michael Platings Date: Mon, 5 Feb 2024 16:14:50 +0000 Subject: [PATCH] Remove parameters structs from API Having a mixture of input and output variables across both function arguments and struct members was inconsistent. "params" has been replaced with an opaque "context" pointer. --- adapters/opencv/intrinsiccv_hal.cpp | 122 +++++++++--------- intrinsiccv/include/ctypes.h | 19 +-- intrinsiccv/include/filters/gaussian_blur.h | 46 ++++--- intrinsiccv/include/intrinsiccv.h | 20 +-- intrinsiccv/include/morphology/workspace.h | 39 +++++- intrinsiccv/src/filters/gaussian_blur_api.cpp | 25 ++-- .../src/filters/gaussian_blur_neon.cpp | 16 +-- intrinsiccv/src/filters/gaussian_blur_sc.h | 9 +- .../src/filters/gaussian_blur_sme2.cpp | 4 +- .../src/filters/gaussian_blur_sve2.cpp | 4 +- intrinsiccv/src/morphology/morphology_api.cpp | 38 +++--- .../src/morphology/morphology_neon.cpp | 49 ++++--- intrinsiccv/src/morphology/morphology_sc.h | 56 ++++---- .../src/morphology/morphology_sme2.cpp | 11 +- .../src/morphology/morphology_sve2.cpp | 11 +- test/api/test_gaussian_blur.cpp | 24 +--- test/api/test_morphology.cpp | 73 +++-------- 17 files changed, 265 insertions(+), 301 deletions(-) diff --git a/adapters/opencv/intrinsiccv_hal.cpp b/adapters/opencv/intrinsiccv_hal.cpp index 8918201d9..df01e32ce 100644 --- a/adapters/opencv/intrinsiccv_hal.cpp +++ b/adapters/opencv/intrinsiccv_hal.cpp @@ -292,38 +292,42 @@ int gaussian_blur(const uchar *src_data, size_t src_step, uchar *dst_data, return CV_HAL_ERROR_NOT_IMPLEMENTED; } - intrinsiccv_filter_params_t params; - params.channels = cn; - params.type_size = get_type_size(depth); - if (params.type_size == SIZE_MAX) { + intrinsiccv_filter_context_t *context; + size_t type_size = get_type_size(depth); + if (type_size == SIZE_MAX) { return CV_HAL_ERROR_NOT_IMPLEMENTED; } - params.type_size *= 2; /* widening */ + type_size *= 2; /* widening */ intrinsiccv_rectangle_t image = { .width = static_cast(width), .height = static_cast(height)}; if (intrinsiccv_error_t create_err = - intrinsiccv_filter_create(¶ms, image)) { + intrinsiccv_filter_create(&context, cn, type_size, image)) { return convert_error(create_err); } intrinsiccv_error_t blur_err = impl(reinterpret_cast(src_data), src_step, reinterpret_cast(dst_data), dst_step, width, height, cn, - intrinsiccv_border_type, ¶ms); + intrinsiccv_border_type, context); - intrinsiccv_error_t release_err = intrinsiccv_filter_release(¶ms); + intrinsiccv_error_t release_err = intrinsiccv_filter_release(context); return convert_error(blur_err ? blur_err : release_err); } -int morphology_init(cvhalFilter2D **context, int operation, int src_type, +struct MorphologyParams { + intrinsiccv_morphology_context_t *context; + decltype(intrinsiccv_dilate_u8) *impl; +}; + +int morphology_init(cvhalFilter2D **cvcontext, int operation, int src_type, int dst_type, int max_width, int max_height, int kernel_type, uchar *kernel_data, size_t kernel_step, int kernel_width, int kernel_height, int anchor_x, - int anchor_y, int border_type, - const double border_values[4], int iterations, + int anchor_y, int cvborder_type, + const double cvborder_values[4], int iterations, bool allow_submatrix, bool allow_in_place) { INTRINSICCV_EXIT_WITH_NOT_IMPLEMENTED_IF_NEEDED(); @@ -342,6 +346,11 @@ int morphology_init(cvhalFilter2D **context, int operation, int src_type, return CV_HAL_ERROR_NOT_IMPLEMENTED; } + intrinsiccv_border_type_t border_type; + if (from_opencv(cvborder_type, border_type)) { + return CV_HAL_ERROR_NOT_IMPLEMENTED; + } + if (border_type != intrinsiccv_border_type_t::INTRINSICCV_BORDER_TYPE_CONSTANT) { return CV_HAL_ERROR_NOT_IMPLEMENTED; @@ -369,75 +378,68 @@ int morphology_init(cvhalFilter2D **context, int operation, int src_type, } // Use std::unique_ptr to make error returns safer. - auto params = std::make_unique(); + auto params = std::make_unique(); if (!params) { return CV_HAL_ERROR_UNKNOWN; } - params->kernel.width = - static_castkernel.width)>(kernel_width); - params->kernel.height = - static_castkernel.height)>(kernel_height); - params->anchor.x = static_castanchor.x)>(anchor_x); - params->anchor.y = static_castanchor.y)>(anchor_y); - params->channels = (src_type >> CV_CN_SHIFT) + 1; - params->iterations = static_castiterations)>(iterations); - params->type_size = get_type_size(CV_MAT_DEPTH(src_type)); - if (SIZE_MAX == params->type_size) { + size_t channels = (src_type >> CV_CN_SHIFT) + 1; + size_t type_size = get_type_size(CV_MAT_DEPTH(src_type)); + if (SIZE_MAX == type_size) { return CV_HAL_ERROR_NOT_IMPLEMENTED; } - if (from_opencv(border_type, params->border_type)) { - return CV_HAL_ERROR_NOT_IMPLEMENTED; - } - - if (params->border_type == + intrinsiccv_border_values_t border_values = {}; + if (border_type == intrinsiccv_border_type_t::INTRINSICCV_BORDER_TYPE_CONSTANT) { - params->border_values.top = border_values[0]; - params->border_values.left = border_values[1]; - params->border_values.bottom = border_values[2]; - params->border_values.right = border_values[3]; + border_values.top = cvborder_values[0]; + border_values.left = cvborder_values[1]; + border_values.bottom = cvborder_values[2]; + border_values.right = cvborder_values[3]; // In case of default border values for dilate() '0' should be used. auto border_max_value = - std::numeric_limitsborder_values.top)>::max(); + std::numeric_limits::max(); if ((operation == CV_HAL_MORPH_DILATE) && - (params->border_values.top == border_max_value) && - (params->border_values.left == border_max_value) && - (params->border_values.bottom == border_max_value) && - (params->border_values.right == border_max_value)) { - params->border_values.top = 0; - params->border_values.left = 0; - params->border_values.bottom = 0; - params->border_values.right = 0; + (border_values.top == border_max_value) && + (border_values.left == border_max_value) && + (border_values.bottom == border_max_value) && + (border_values.right == border_max_value)) { + border_values.top = 0; + border_values.left = 0; + border_values.bottom = 0; + border_values.right = 0; } } switch (operation) { case CV_HAL_MORPH_DILATE: - params->impl = reinterpret_cast(intrinsiccv_dilate_u8); + params->impl = intrinsiccv_dilate_u8; break; case CV_HAL_MORPH_ERODE: - params->impl = reinterpret_cast(intrinsiccv_erode_u8); + params->impl = intrinsiccv_erode_u8; break; default: return CV_HAL_ERROR_NOT_IMPLEMENTED; } - intrinsiccv_rectangle_t image = { - .width = static_cast(max_width), - .height = - static_cast(max_height)}; - if (intrinsiccv_error_t err = - intrinsiccv_morphology_create(params.get(), image)) { + if (intrinsiccv_error_t err = intrinsiccv_morphology_create( + ¶ms->context, + intrinsiccv_rectangle_t{static_cast(kernel_width), + static_cast(kernel_height)}, + intrinsiccv_point_t{static_cast(anchor_x), + static_cast(anchor_y)}, + border_type, border_values, channels, iterations, type_size, + intrinsiccv_rectangle_t{static_cast(max_width), + static_cast(max_height)})) { return convert_error(err); } - *context = reinterpret_cast(params.release()); + *cvcontext = reinterpret_cast(params.release()); return CV_HAL_ERROR_OK; } -int morphology_operation(cvhalFilter2D *context, uchar *src_data, +int morphology_operation(cvhalFilter2D *cvcontext, uchar *src_data, size_t src_step, uchar *dst_data, size_t dst_step, int width, int height, int src_full_width, int src_full_height, int src_roi_x, int src_roi_y, @@ -455,20 +457,20 @@ int morphology_operation(cvhalFilter2D *context, uchar *src_data, (void)dst_roi_x; (void)dst_roi_y; - auto params = reinterpret_cast(context); - auto impl = reinterpret_cast(params->impl); - return convert_error(impl(reinterpret_cast(src_data), - src_step, reinterpret_cast(dst_data), - dst_step, static_cast(width), - static_cast(height), params)); + auto params = reinterpret_cast(cvcontext); + return convert_error( + params->impl(reinterpret_cast(src_data), src_step, + reinterpret_cast(dst_data), dst_step, + static_cast(width), static_cast(height), + params->context)); } -int morphology_free(cvhalFilter2D *context) { +int morphology_free(cvhalFilter2D *cvcontext) { INTRINSICCV_EXIT_WITH_NOT_IMPLEMENTED_IF_NEEDED(); - auto params = std::unique_ptr( - reinterpret_cast(context)); - return convert_error(intrinsiccv_morphology_release(params.get())); + std::unique_ptr params( + reinterpret_cast(cvcontext)); + return convert_error(intrinsiccv_morphology_release(params->context)); } int sobel(const uchar *src_data, size_t src_step, uchar *dst_data, diff --git a/intrinsiccv/include/ctypes.h b/intrinsiccv/include/ctypes.h index 46caa0fa4..41494c38f 100644 --- a/intrinsiccv/include/ctypes.h +++ b/intrinsiccv/include/ctypes.h @@ -72,22 +72,9 @@ typedef enum { INTRINSICCV_BORDER_TYPE_NONE, } intrinsiccv_border_type_t; -typedef struct { - intrinsiccv_rectangle_t kernel; - intrinsiccv_point_t anchor; - intrinsiccv_border_type_t border_type; - intrinsiccv_border_values_t border_values; - size_t channels; - size_t iterations; - size_t type_size; - void *impl; - void *data; -} intrinsiccv_morphology_params_t; +typedef struct intrinsiccv_morphology_context_t_ + intrinsiccv_morphology_context_t; -typedef struct { - size_t channels; - size_t type_size; - void *workspace; -} intrinsiccv_filter_params_t; +typedef struct intrinsiccv_filter_context_t_ intrinsiccv_filter_context_t; #endif // INTRINSICCV_CTYPES_H diff --git a/intrinsiccv/include/filters/gaussian_blur.h b/intrinsiccv/include/filters/gaussian_blur.h index 10eb43beb..301c6e7eb 100644 --- a/intrinsiccv/include/filters/gaussian_blur.h +++ b/intrinsiccv/include/filters/gaussian_blur.h @@ -12,37 +12,41 @@ namespace intrinsiccv { namespace neon { -intrinsiccv_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, - intrinsiccv_border_type_t border_type, - const intrinsiccv_filter_params_t *params); - -intrinsiccv_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, - intrinsiccv_border_type_t border_type, - const intrinsiccv_filter_params_t *params); +intrinsiccv_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, + intrinsiccv_border_type_t border_type, + intrinsiccv_filter_context_t *context); + +intrinsiccv_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, + intrinsiccv_border_type_t border_type, + intrinsiccv_filter_context_t *context); } // namespace neon namespace sve2 { -intrinsiccv_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, - intrinsiccv_border_type_t border_type, - const intrinsiccv_filter_params_t *params); +intrinsiccv_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, + intrinsiccv_border_type_t border_type, + intrinsiccv_filter_context_t *context); } // namespace sve2 namespace sme2 { -intrinsiccv_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, - intrinsiccv_border_type_t border_type, - const intrinsiccv_filter_params_t *params); +intrinsiccv_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, + intrinsiccv_border_type_t border_type, + intrinsiccv_filter_context_t *context); } // namespace sme2 diff --git a/intrinsiccv/include/intrinsiccv.h b/intrinsiccv/include/intrinsiccv.h index 4ce617922..91471de6d 100644 --- a/intrinsiccv/include/intrinsiccv.h +++ b/intrinsiccv/include/intrinsiccv.h @@ -570,18 +570,21 @@ intrinsiccv_error_t intrinsiccv_threshold_binary_u8( size_t width, size_t height, uint8_t threshold, uint8_t value); intrinsiccv_error_t intrinsiccv_morphology_create( - intrinsiccv_morphology_params_t *params, intrinsiccv_rectangle_t image); + intrinsiccv_morphology_context_t **context, intrinsiccv_rectangle_t kernel, + intrinsiccv_point_t anchor, intrinsiccv_border_type_t border_type, + intrinsiccv_border_values_t border_values, size_t channels, + size_t iterations, size_t type_size, intrinsiccv_rectangle_t image); intrinsiccv_error_t intrinsiccv_morphology_release( - intrinsiccv_morphology_params_t *params); + intrinsiccv_morphology_context_t *context); intrinsiccv_error_t intrinsiccv_dilate_u8( const uint8_t *src, size_t src_stride, uint8_t *dst, size_t dst_stride, - size_t width, size_t height, const intrinsiccv_morphology_params_t *params); + size_t width, size_t height, intrinsiccv_morphology_context_t *context); intrinsiccv_error_t intrinsiccv_erode_u8( const uint8_t *src, size_t src_stride, uint8_t *dst, size_t dst_stride, - size_t width, size_t height, const intrinsiccv_morphology_params_t *params); + size_t width, size_t height, intrinsiccv_morphology_context_t *context); /// Counts how many nonzero elements are in the source data. /// @@ -709,22 +712,23 @@ intrinsiccv_error_t intrinsiccv_canny_u8(const uint8_t *src, size_t src_stride, double high_threshold); intrinsiccv_error_t intrinsiccv_filter_create( - intrinsiccv_filter_params_t *params, intrinsiccv_rectangle_t image); + intrinsiccv_filter_context_t **context, size_t channels, size_t type_size, + intrinsiccv_rectangle_t image); intrinsiccv_error_t intrinsiccv_filter_release( - intrinsiccv_filter_params_t *params); + intrinsiccv_filter_context_t *context); intrinsiccv_error_t intrinsiccv_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, intrinsiccv_border_type_t border_type, - const intrinsiccv_filter_params_t *params); + intrinsiccv_filter_context_t *context); intrinsiccv_error_t intrinsiccv_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, intrinsiccv_border_type_t border_type, - const intrinsiccv_filter_params_t *params); + intrinsiccv_filter_context_t *context); /// Splits a multi channel source stream into separate 1-channel streams. /// diff --git a/intrinsiccv/include/morphology/workspace.h b/intrinsiccv/include/morphology/workspace.h index b932fec9b..00335c383 100644 --- a/intrinsiccv/include/morphology/workspace.h +++ b/intrinsiccv/include/morphology/workspace.h @@ -41,14 +41,20 @@ class MorphologyWorkspace final { MorphologyWorkspace() = delete; // Creates a workspace on the heap. - static Pointer create(Rectangle rect, Rectangle kernel, Margin margin, - size_t channels, size_t buffer_type_size) - INTRINSICCV_STREAMING_COMPATIBLE { + static Pointer create( + intrinsiccv_rectangle_t kernel, intrinsiccv_point_t anchor, + intrinsiccv_border_type_t border_type, + intrinsiccv_border_values_t border_values, size_t channels, + size_t iterations, size_t type_size, + intrinsiccv_rectangle_t image) INTRINSICCV_STREAMING_COMPATIBLE { // These values are arbitrarily choosen. - const size_t rows_per_iteration = std::max(2 * kernel.height(), 32UL); + const size_t rows_per_iteration = std::max(2 * kernel.height, 32UL); // To avoid load/store penalties. const size_t kAlignment = 16; + Rectangle rect{image}; + Margin margin{kernel, anchor}; + // A single wide row which can hold one row worth of data in addition // to left and right margins. size_t wide_rows_width = margin.left() + rect.width() + margin.right(); @@ -59,7 +65,7 @@ class MorphologyWorkspace final { wide_rows_size += kAlignment - 1; // Multiple buffer rows to hold rows without any borders. - size_t buffer_rows_width = buffer_type_size * rect.width(); + size_t buffer_rows_width = type_size * rect.width(); size_t buffer_rows_stride = buffer_rows_width * channels; buffer_rows_stride = __builtin_align_up(buffer_rows_stride, kAlignment); size_t buffer_rows_height = 2 * rows_per_iteration; @@ -97,9 +103,25 @@ class MorphologyWorkspace final { workspace->wide_rows_offset_ = wide_rows_address - &workspace->data_[0]; workspace->wide_rows_stride_ = wide_rows_stride; + workspace->kernel_ = kernel; + workspace->anchor_ = anchor; + workspace->border_type_ = border_type; + workspace->border_values_ = border_values; + workspace->channels_ = channels; + workspace->iterations_ = iterations; + workspace->type_size_ = type_size; + return workspace; } + intrinsiccv_rectangle_t kernel() const { return kernel_; } + intrinsiccv_point_t anchor() const { return anchor_; } + intrinsiccv_border_type_t border_type() const { return border_type_; } + intrinsiccv_border_values_t border_values() const { return border_values_; } + size_t channels() const { return channels_; } + size_t iterations() const { return iterations_; } + size_t type_size() const { return type_size_; } + // This function is too complex, but disable the warning for now. // NOLINTBEGIN(readability-function-cognitive-complexity) template @@ -343,6 +365,13 @@ class MorphologyWorkspace final { static_assert(sizeof(Pointer) == sizeof(void *), "Unexpected type size"); + intrinsiccv_rectangle_t kernel_; + intrinsiccv_point_t anchor_; + intrinsiccv_border_type_t border_type_; + intrinsiccv_border_values_t border_values_; + size_t iterations_; + size_t type_size_; + // Number of wide rows in this workspace. size_t rows_per_iteration_; // Size of the data in bytes within a row. diff --git a/intrinsiccv/src/filters/gaussian_blur_api.cpp b/intrinsiccv/src/filters/gaussian_blur_api.cpp index ee9f96eba..55fe9879b 100644 --- a/intrinsiccv/src/filters/gaussian_blur_api.cpp +++ b/intrinsiccv/src/filters/gaussian_blur_api.cpp @@ -12,30 +12,31 @@ namespace intrinsiccv { extern "C" { intrinsiccv_error_t intrinsiccv_filter_create( - intrinsiccv_filter_params_t *params, intrinsiccv_rectangle_t image) { - CHECK_POINTERS(params); - auto workspace = SeparableFilterWorkspace::create( - Rectangle{image}, params->channels, params->type_size); + intrinsiccv_filter_context_t **context, size_t channels, size_t type_size, + intrinsiccv_rectangle_t image) { + CHECK_POINTERS(context); + auto workspace = + SeparableFilterWorkspace::create(Rectangle{image}, channels, type_size); if (!workspace) { + *context = nullptr; return INTRINSICCV_ERROR_ALLOCATION; } - params->workspace = reinterpret_cast(workspace.release()); + *context = + reinterpret_cast(workspace.release()); return INTRINSICCV_OK; } intrinsiccv_error_t intrinsiccv_filter_release( - intrinsiccv_filter_params_t *params) { - CHECK_POINTERS(params); - CHECK_POINTERS(params->workspace); + intrinsiccv_filter_context_t *context) { + CHECK_POINTERS(context); // Deliberately create and immediately destroy a unique_ptr to delete the // workspace. // NOLINTBEGIN(bugprone-unused-raii) SeparableFilterWorkspace::Pointer{ - reinterpret_cast(params->workspace)}; + reinterpret_cast(context)}; // NOLINTEND(bugprone-unused-raii) - params->workspace = nullptr; return INTRINSICCV_OK; } @@ -47,7 +48,7 @@ INTRINSICCV_MULTIVERSION_C_API(intrinsiccv_gaussian_blur_3x3_u8, uint8_t *dst, size_t dst_stride, size_t width, size_t height, size_t channels, intrinsiccv_border_type_t border_type, - const intrinsiccv_filter_params_t *params); + intrinsiccv_filter_context_t *context); INTRINSICCV_MULTIVERSION_C_API( intrinsiccv_gaussian_blur_5x5_u8, intrinsiccv::neon::gaussian_blur_5x5_u8, @@ -55,6 +56,6 @@ INTRINSICCV_MULTIVERSION_C_API( intrinsiccv::sme2::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, intrinsiccv_border_type_t border_type, - const intrinsiccv_filter_params_t *params); + intrinsiccv_filter_context_t *context); } // namespace intrinsiccv diff --git a/intrinsiccv/src/filters/gaussian_blur_neon.cpp b/intrinsiccv/src/filters/gaussian_blur_neon.cpp index 59f947eae..d858478da 100644 --- a/intrinsiccv/src/filters/gaussian_blur_neon.cpp +++ b/intrinsiccv/src/filters/gaussian_blur_neon.cpp @@ -147,18 +147,16 @@ intrinsiccv_error_t discrete_gaussian_blur( const ScalarType *src, size_t src_stride, ScalarType *dst, size_t dst_stride, size_t width, size_t height, size_t channels, intrinsiccv_border_type_t border_type, - const intrinsiccv_filter_params_t *params) { + intrinsiccv_filter_context_t *context) { using GaussianBlurFilterType = DiscreteGaussianBlur; - CHECK_POINTERS(src, dst, params); - CHECK_POINTERS(params->workspace); + CHECK_POINTERS(src, dst, context); Rectangle rect{width, height}; Rows src_rows{src, src_stride, channels}; Rows dst_rows{dst, dst_stride, channels}; - auto *workspace = - reinterpret_cast(params->workspace); + auto *workspace = reinterpret_cast(context); GaussianBlurFilterType blur; SeparableFilter filter{blur}; @@ -171,10 +169,10 @@ intrinsiccv_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, intrinsiccv_border_type_t border_type, - const intrinsiccv_filter_params_t *params) { + intrinsiccv_filter_context_t *context) { return discrete_gaussian_blur(src, src_stride, dst, dst_stride, width, height, channels, - border_type, params); + border_type, context); } INTRINSICCV_TARGET_FN_ATTRS @@ -182,10 +180,10 @@ intrinsiccv_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, intrinsiccv_border_type_t border_type, - const intrinsiccv_filter_params_t *params) { + intrinsiccv_filter_context_t *context) { return discrete_gaussian_blur(src, src_stride, dst, dst_stride, width, height, channels, - border_type, params); + border_type, context); } } // namespace intrinsiccv::neon diff --git a/intrinsiccv/src/filters/gaussian_blur_sc.h b/intrinsiccv/src/filters/gaussian_blur_sc.h index 7ef65334e..4adb4677d 100644 --- a/intrinsiccv/src/filters/gaussian_blur_sc.h +++ b/intrinsiccv/src/filters/gaussian_blur_sc.h @@ -87,19 +87,16 @@ intrinsiccv_error_t discrete_gaussian_blur( const ScalarType *src, size_t src_stride, ScalarType *dst, size_t dst_stride, size_t width, size_t height, size_t channels, intrinsiccv_border_type_t border_type, - const intrinsiccv_filter_params_t *params) - INTRINSICCV_STREAMING_COMPATIBLE { + intrinsiccv_filter_context_t *context) INTRINSICCV_STREAMING_COMPATIBLE { using GaussianBlurFilterType = DiscreteGaussianBlur; - CHECK_POINTERS(src, dst, params); - CHECK_POINTERS(params->workspace); + CHECK_POINTERS(src, dst, context); Rectangle rect{width, height}; Rows src_rows{src, src_stride, channels}; Rows dst_rows{dst, dst_stride, channels}; - auto *workspace = - reinterpret_cast(params->workspace); + auto *workspace = reinterpret_cast(context); GaussianBlurFilterType blur; SeparableFilter filter{blur}; diff --git a/intrinsiccv/src/filters/gaussian_blur_sme2.cpp b/intrinsiccv/src/filters/gaussian_blur_sme2.cpp index e68052bf2..ea6ec7e1d 100644 --- a/intrinsiccv/src/filters/gaussian_blur_sme2.cpp +++ b/intrinsiccv/src/filters/gaussian_blur_sme2.cpp @@ -11,10 +11,10 @@ INTRINSICCV_LOCALLY_STREAMING INTRINSICCV_TARGET_FN_ATTRS intrinsiccv_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, intrinsiccv_border_type_t border_type, - const intrinsiccv_filter_params_t *params) { + intrinsiccv_filter_context_t *context) { return sve2::discrete_gaussian_blur( src, src_stride, dst, dst_stride, width, height, channels, border_type, - params); + context); } } // namespace intrinsiccv::sme2 diff --git a/intrinsiccv/src/filters/gaussian_blur_sve2.cpp b/intrinsiccv/src/filters/gaussian_blur_sve2.cpp index 4106f5b7d..45cae08dd 100644 --- a/intrinsiccv/src/filters/gaussian_blur_sve2.cpp +++ b/intrinsiccv/src/filters/gaussian_blur_sve2.cpp @@ -12,10 +12,10 @@ intrinsiccv_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, intrinsiccv_border_type_t border_type, - const intrinsiccv_filter_params_t *params) { + intrinsiccv_filter_context_t *context) { return discrete_gaussian_blur(src, src_stride, dst, dst_stride, width, height, channels, - border_type, params); + border_type, context); } } // namespace intrinsiccv::sve2 diff --git a/intrinsiccv/src/morphology/morphology_api.cpp b/intrinsiccv/src/morphology/morphology_api.cpp index f715bb702..93c25cb2d 100644 --- a/intrinsiccv/src/morphology/morphology_api.cpp +++ b/intrinsiccv/src/morphology/morphology_api.cpp @@ -13,12 +13,12 @@ namespace neon { template intrinsiccv_error_t dilate(const T *src, size_t src_stride, T *dst, size_t dst_stride, size_t width, size_t height, - const intrinsiccv_morphology_params_t *params); + intrinsiccv_morphology_context_t *context); template intrinsiccv_error_t erode(const T *src, size_t src_stride, T *dst, size_t dst_stride, size_t width, size_t height, - const intrinsiccv_morphology_params_t *params); + intrinsiccv_morphology_context_t *context); } // namespace neon @@ -27,12 +27,12 @@ namespace sve2 { template intrinsiccv_error_t dilate(const T *src, size_t src_stride, T *dst, size_t dst_stride, size_t width, size_t height, - const intrinsiccv_morphology_params_t *params); + intrinsiccv_morphology_context_t *context); template intrinsiccv_error_t erode(const T *src, size_t src_stride, T *dst, size_t dst_stride, size_t width, size_t height, - const intrinsiccv_morphology_params_t *params); + intrinsiccv_morphology_context_t *context); } // namespace sve2 @@ -41,45 +41,47 @@ namespace sme2 { template intrinsiccv_error_t dilate(const T *src, size_t src_stride, T *dst, size_t dst_stride, size_t width, size_t height, - const intrinsiccv_morphology_params_t *params); + intrinsiccv_morphology_context_t *context); template intrinsiccv_error_t erode(const T *src, size_t src_stride, T *dst, size_t dst_stride, size_t width, size_t height, - const intrinsiccv_morphology_params_t *params); + intrinsiccv_morphology_context_t *context); } // namespace sme2 extern "C" { intrinsiccv_error_t intrinsiccv_morphology_create( - intrinsiccv_morphology_params_t *params, intrinsiccv_rectangle_t image) { - CHECK_POINTERS(params); + intrinsiccv_morphology_context_t **context, intrinsiccv_rectangle_t kernel, + intrinsiccv_point_t anchor, intrinsiccv_border_type_t border_type, + intrinsiccv_border_values_t border_values, size_t channels, + size_t iterations, size_t type_size, intrinsiccv_rectangle_t image) { + CHECK_POINTERS(context); auto workspace = - MorphologyWorkspace::create(Rectangle{image}, Rectangle{params->kernel}, - Margin{params->kernel, params->anchor}, - params->channels, params->type_size); + MorphologyWorkspace::create(kernel, anchor, border_type, border_values, + channels, iterations, type_size, image); if (!workspace) { + *context = nullptr; return INTRINSICCV_ERROR_ALLOCATION; } - params->data = reinterpret_cast(workspace.release()); + *context = + reinterpret_cast(workspace.release()); return INTRINSICCV_OK; } intrinsiccv_error_t intrinsiccv_morphology_release( - intrinsiccv_morphology_params_t *params) { - CHECK_POINTERS(params); - CHECK_POINTERS(params->data); + intrinsiccv_morphology_context_t *context) { + CHECK_POINTERS(context); // Deliberately create and immediately destroy a unique_ptr to delete the // workspace. // NOLINTBEGIN(bugprone-unused-raii) MorphologyWorkspace::Pointer{ - reinterpret_cast(params->data)}; + reinterpret_cast(context)}; // NOLINTEND(bugprone-unused-raii) - params->data = nullptr; return INTRINSICCV_OK; } @@ -91,7 +93,7 @@ intrinsiccv_error_t intrinsiccv_morphology_release( INTRINSICCV_SVE2_IMPL_IF(intrinsiccv::sve2::tname), \ intrinsiccv::sme2::tname, const type *src, size_t src_stride, \ type *dst, size_t dst_stride, size_t width, size_t height, \ - const intrinsiccv_morphology_params_t *) + intrinsiccv_morphology_context_t *) INTRINSICCV_DEFINE_C_API(intrinsiccv_dilate_u8, dilate, uint8_t); INTRINSICCV_DEFINE_C_API(intrinsiccv_erode_u8, erode, uint8_t); diff --git a/intrinsiccv/src/morphology/morphology_neon.cpp b/intrinsiccv/src/morphology/morphology_neon.cpp index d7886c2c9..f88eb791a 100644 --- a/intrinsiccv/src/morphology/morphology_neon.cpp +++ b/intrinsiccv/src/morphology/morphology_neon.cpp @@ -489,25 +489,24 @@ class DilateOperation final { template intrinsiccv_error_t dilate(const T *src, size_t src_stride, T *dst, size_t dst_stride, size_t width, size_t height, - const intrinsiccv_morphology_params_t *params) { - CHECK_POINTERS(src, dst, params); - CHECK_POINTERS(params->impl, params->data); + intrinsiccv_morphology_context_t *context) { + CHECK_POINTERS(src, dst, context); - Rectangle rect{width, height}; - Rectangle kernel{params->kernel}; - Rows src_rows{src, src_stride, params->channels}; - Rows dst_rows{dst, dst_stride, params->channels}; - Margin margin{params->kernel, params->anchor}; - Border border{params->border_values}; + auto *workspace = reinterpret_cast(context); - auto *workspace = reinterpret_cast(params->data); + Rectangle rect{width, height}; + Rectangle kernel{workspace->kernel()}; + Rows src_rows{src, src_stride, workspace->channels()}; + Rows dst_rows{dst, dst_stride, workspace->channels()}; + Margin margin{workspace->kernel(), workspace->anchor()}; + Border border{workspace->border_values()}; Rows current_src_rows = src_rows; Rows current_dst_rows = dst_rows; - for (size_t iteration = 0; iteration < params->iterations; ++iteration) { + for (size_t iteration = 0; iteration < workspace->iterations(); ++iteration) { DilateOperation operation{kernel}; workspace->process(rect, current_src_rows, current_dst_rows, margin, border, - params->border_type, operation); + workspace->border_type(), operation); // Update source for the next iteration. current_src_rows = dst_rows; } @@ -543,25 +542,24 @@ class ErodeOperation final { template intrinsiccv_error_t erode(const T *src, size_t src_stride, T *dst, size_t dst_stride, size_t width, size_t height, - const intrinsiccv_morphology_params_t *params) { - CHECK_POINTERS(src, dst, params); - CHECK_POINTERS(params->impl, params->data); + intrinsiccv_morphology_context_t *context) { + CHECK_POINTERS(src, dst, context); - Rectangle rect{width, height}; - Rectangle kernel{params->kernel}; - Rows src_rows{src, src_stride, params->channels}; - Rows dst_rows{dst, dst_stride, params->channels}; - Margin margin{params->kernel, params->anchor}; - Border border{params->border_values}; + auto *workspace = reinterpret_cast(context); - auto *workspace = reinterpret_cast(params->data); + Rectangle rect{width, height}; + Rectangle kernel{workspace->kernel()}; + Rows src_rows{src, src_stride, workspace->channels()}; + Rows dst_rows{dst, dst_stride, workspace->channels()}; + Margin margin{workspace->kernel(), workspace->anchor()}; + Border border{workspace->border_values()}; Rows current_src_rows = src_rows; Rows current_dst_rows = dst_rows; - for (size_t iteration = 0; iteration < params->iterations; ++iteration) { + for (size_t iteration = 0; iteration < workspace->iterations(); ++iteration) { ErodeOperation operation{kernel}; workspace->process(rect, current_src_rows, current_dst_rows, margin, border, - params->border_type, operation); + workspace->border_type(), operation); // Update source for the next iteration. current_src_rows = dst_rows; } @@ -571,8 +569,7 @@ intrinsiccv_error_t erode(const T *src, size_t src_stride, T *dst, #define INTRINSICCV_INSTANTIATE_TEMPLATE(name, type) \ template INTRINSICCV_TARGET_FN_ATTRS intrinsiccv_error_t name( \ const type *src, size_t src_stride, type *dst, size_t dst_stride, \ - size_t width, size_t height, \ - const intrinsiccv_morphology_params_t *params) + size_t width, size_t height, intrinsiccv_morphology_context_t *context) INTRINSICCV_INSTANTIATE_TEMPLATE(dilate, uint8_t); INTRINSICCV_INSTANTIATE_TEMPLATE(erode, uint8_t); diff --git a/intrinsiccv/src/morphology/morphology_sc.h b/intrinsiccv/src/morphology/morphology_sc.h index fdcadbfd9..bdbc6154a 100644 --- a/intrinsiccv/src/morphology/morphology_sc.h +++ b/intrinsiccv/src/morphology/morphology_sc.h @@ -448,28 +448,28 @@ class DilateOperation final { }; // end of class DilateOperation template -static intrinsiccv_error_t dilate_sc( - const T *src, size_t src_stride, T *dst, size_t dst_stride, size_t width, - size_t height, const intrinsiccv_morphology_params_t *params) +static intrinsiccv_error_t dilate_sc(const T *src, size_t src_stride, T *dst, + size_t dst_stride, size_t width, + size_t height, + intrinsiccv_morphology_context_t *context) INTRINSICCV_STREAMING_COMPATIBLE { - CHECK_POINTERS(src, dst, params); - CHECK_POINTERS(params->impl, params->data); + CHECK_POINTERS(src, dst, context); - Rectangle rect{width, height}; - Rectangle kernel{params->kernel}; - Rows src_rows{src, src_stride, params->channels}; - Rows dst_rows{dst, dst_stride, params->channels}; - Margin margin{params->kernel, params->anchor}; - Border border{params->border_values}; + auto *workspace = reinterpret_cast(context); - auto *workspace = reinterpret_cast(params->data); + Rectangle rect{width, height}; + Rectangle kernel{workspace->kernel()}; + Rows src_rows{src, src_stride, workspace->channels()}; + Rows dst_rows{dst, dst_stride, workspace->channels()}; + Margin margin{workspace->kernel(), workspace->anchor()}; + Border border{workspace->border_values()}; Rows current_src_rows = src_rows; Rows current_dst_rows = dst_rows; - for (size_t iteration = 0; iteration < params->iterations; ++iteration) { + for (size_t iteration = 0; iteration < workspace->iterations(); ++iteration) { DilateOperation operation{kernel}; workspace->process(rect, current_src_rows, current_dst_rows, margin, border, - params->border_type, operation); + workspace->border_type(), operation); // Update source for the next iteration. current_src_rows = dst_rows; } @@ -506,28 +506,28 @@ class ErodeOperation final { }; // end of class ErodeOperation template -static intrinsiccv_error_t erode_sc( - const T *src, size_t src_stride, T *dst, size_t dst_stride, size_t width, - size_t height, const intrinsiccv_morphology_params_t *params) +static intrinsiccv_error_t erode_sc(const T *src, size_t src_stride, T *dst, + size_t dst_stride, size_t width, + size_t height, + intrinsiccv_morphology_context_t *context) INTRINSICCV_STREAMING_COMPATIBLE { - CHECK_POINTERS(src, dst, params); - CHECK_POINTERS(params->impl, params->data); + CHECK_POINTERS(src, dst, context); - Rectangle rect{width, height}; - Rectangle kernel{params->kernel}; - Rows src_rows{src, src_stride, params->channels}; - Rows dst_rows{dst, dst_stride, params->channels}; - Margin margin{params->kernel, params->anchor}; - Border border{params->border_values}; + auto *workspace = reinterpret_cast(context); - auto *workspace = reinterpret_cast(params->data); + Rectangle rect{width, height}; + Rectangle kernel{workspace->kernel()}; + Rows src_rows{src, src_stride, workspace->channels()}; + Rows dst_rows{dst, dst_stride, workspace->channels()}; + Margin margin{workspace->kernel(), workspace->anchor()}; + Border border{workspace->border_values()}; Rows current_src_rows = src_rows; Rows current_dst_rows = dst_rows; - for (size_t iteration = 0; iteration < params->iterations; ++iteration) { + for (size_t iteration = 0; iteration < workspace->iterations(); ++iteration) { ErodeOperation operation{kernel}; workspace->process(rect, current_src_rows, current_dst_rows, margin, border, - params->border_type, operation); + workspace->border_type(), operation); // Update source for the next iteration. current_src_rows = dst_rows; } diff --git a/intrinsiccv/src/morphology/morphology_sme2.cpp b/intrinsiccv/src/morphology/morphology_sme2.cpp index c7e003a9f..32f9e2d7f 100644 --- a/intrinsiccv/src/morphology/morphology_sme2.cpp +++ b/intrinsiccv/src/morphology/morphology_sme2.cpp @@ -9,24 +9,23 @@ namespace intrinsiccv::sme2 { template INTRINSICCV_LOCALLY_STREAMING INTRINSICCV_TARGET_FN_ATTRS intrinsiccv_error_t dilate(const T *src, size_t src_stride, T *dst, size_t dst_stride, size_t width, - size_t height, const intrinsiccv_morphology_params_t *params) { + size_t height, intrinsiccv_morphology_context_t *context) { return intrinsiccv::sve2::dilate_sc(src, src_stride, dst, dst_stride, - width, height, params); + width, height, context); } template INTRINSICCV_LOCALLY_STREAMING INTRINSICCV_TARGET_FN_ATTRS intrinsiccv_error_t erode(const T *src, size_t src_stride, T *dst, size_t dst_stride, size_t width, - size_t height, const intrinsiccv_morphology_params_t *params) { + size_t height, intrinsiccv_morphology_context_t *context) { return intrinsiccv::sve2::erode_sc(src, src_stride, dst, dst_stride, width, - height, params); + height, context); } #define INTRINSICCV_INSTANTIATE_TEMPLATE(name, type) \ template INTRINSICCV_TARGET_FN_ATTRS intrinsiccv_error_t name( \ const type *src, size_t src_stride, type *dst, size_t dst_stride, \ - size_t width, size_t height, \ - const intrinsiccv_morphology_params_t *params) + size_t width, size_t height, intrinsiccv_morphology_context_t *context) INTRINSICCV_INSTANTIATE_TEMPLATE(dilate, uint8_t); INTRINSICCV_INSTANTIATE_TEMPLATE(erode, uint8_t); diff --git a/intrinsiccv/src/morphology/morphology_sve2.cpp b/intrinsiccv/src/morphology/morphology_sve2.cpp index 9ee454f59..b66abd956 100644 --- a/intrinsiccv/src/morphology/morphology_sve2.cpp +++ b/intrinsiccv/src/morphology/morphology_sve2.cpp @@ -9,22 +9,21 @@ namespace intrinsiccv::sve2 { template INTRINSICCV_TARGET_FN_ATTRS intrinsiccv_error_t dilate(const T *src, size_t src_stride, T *dst, size_t dst_stride, size_t width, - size_t height, const intrinsiccv_morphology_params_t *params) { - return dilate_sc(src, src_stride, dst, dst_stride, width, height, params); + size_t height, intrinsiccv_morphology_context_t *context) { + return dilate_sc(src, src_stride, dst, dst_stride, width, height, context); } template INTRINSICCV_TARGET_FN_ATTRS intrinsiccv_error_t erode(const T *src, size_t src_stride, T *dst, size_t dst_stride, size_t width, - size_t height, const intrinsiccv_morphology_params_t *params) { - return erode_sc(src, src_stride, dst, dst_stride, width, height, params); + size_t height, intrinsiccv_morphology_context_t *context) { + return erode_sc(src, src_stride, dst, dst_stride, width, height, context); } #define INTRINSICCV_INSTANTIATE_TEMPLATE(name, type) \ template INTRINSICCV_TARGET_FN_ATTRS intrinsiccv_error_t name( \ const type *src, size_t src_stride, type *dst, size_t dst_stride, \ - size_t width, size_t height, \ - const intrinsiccv_morphology_params_t *params) + size_t width, size_t height, intrinsiccv_morphology_context_t *context) INTRINSICCV_INSTANTIATE_TEMPLATE(dilate, uint8_t); INTRINSICCV_INSTANTIATE_TEMPLATE(erode, uint8_t); diff --git a/test/api/test_gaussian_blur.cpp b/test/api/test_gaussian_blur.cpp index b880a112e..e0c5f3f61 100644 --- a/test/api/test_gaussian_blur.cpp +++ b/test/api/test_gaussian_blur.cpp @@ -23,28 +23,16 @@ class GaussianBlurTest : public testing::Test {}; TYPED_TEST_SUITE(GaussianBlurTest, ElementTypes); TYPED_TEST(GaussianBlurTest, NullPointer) { - intrinsiccv_filter_params_t params = { - .channels = 1, - .type_size = sizeof(TypeParam), - .workspace = nullptr, - }; + intrinsiccv_filter_context_t *context = nullptr; ASSERT_EQ(INTRINSICCV_OK, - intrinsiccv_filter_create(¶ms, intrinsiccv_rectangle_t{1, 1})); + intrinsiccv_filter_create(&context, 1, sizeof(TypeParam), + intrinsiccv_rectangle_t{1, 1})); TypeParam src[1] = {}, dst[1]; test::test_null_args(gaussian_blur_3x3(), src, sizeof(TypeParam), dst, sizeof(TypeParam), 1, 1, 1, - INTRINSICCV_BORDER_TYPE_REFLECT, ¶ms); + INTRINSICCV_BORDER_TYPE_REFLECT, context); test::test_null_args(gaussian_blur_5x5(), src, sizeof(TypeParam), dst, sizeof(TypeParam), 1, 1, 1, - INTRINSICCV_BORDER_TYPE_REFLECT, ¶ms); - EXPECT_EQ(INTRINSICCV_OK, intrinsiccv_filter_release(¶ms)); - EXPECT_EQ(nullptr, params.workspace); - EXPECT_EQ(INTRINSICCV_ERROR_NULL_POINTER, - gaussian_blur_3x3()( - src, sizeof(TypeParam), dst, sizeof(TypeParam), 1, 1, 1, - INTRINSICCV_BORDER_TYPE_REFLECT, ¶ms)); - EXPECT_EQ(INTRINSICCV_ERROR_NULL_POINTER, - gaussian_blur_5x5()( - src, sizeof(TypeParam), dst, sizeof(TypeParam), 1, 1, 1, - INTRINSICCV_BORDER_TYPE_REFLECT, ¶ms)); + INTRINSICCV_BORDER_TYPE_REFLECT, context); + EXPECT_EQ(INTRINSICCV_OK, intrinsiccv_filter_release(context)); } diff --git a/test/api/test_morphology.cpp b/test/api/test_morphology.cpp index 957df297b..76826c745 100644 --- a/test/api/test_morphology.cpp +++ b/test/api/test_morphology.cpp @@ -26,74 +26,31 @@ using ElementTypes = ::testing::Types; TYPED_TEST_SUITE(DilateTest, ElementTypes); TYPED_TEST_SUITE(ErodeTest, ElementTypes); -static intrinsiccv_morphology_params_t make_minimal_params(size_t type_size) { - intrinsiccv_morphology_params_t params = { - .kernel = {1, 1}, - .anchor = {0, 0}, - .border_type = INTRINSICCV_BORDER_TYPE_REPLICATE, - .border_values = {0, 0, 1, 1}, - .channels = 1, - .iterations = 1, - .type_size = type_size, - .impl = nullptr, - .data = nullptr, - }; - return params; +static intrinsiccv_error_t make_minimal_context( + intrinsiccv_morphology_context_t **context, size_t type_size) { + return intrinsiccv_morphology_create( + context, intrinsiccv_rectangle_t{1, 1}, intrinsiccv_point_t{0, 0}, + INTRINSICCV_BORDER_TYPE_REPLICATE, + intrinsiccv_border_values_t{0, 0, 1, 1}, 1, 1, type_size, + intrinsiccv_rectangle_t{1, 1}); } TYPED_TEST(DilateTest, NullPointer) { - intrinsiccv_morphology_params_t params = - make_minimal_params(sizeof(TypeParam)); - ASSERT_EQ(INTRINSICCV_OK, intrinsiccv_morphology_create( - ¶ms, intrinsiccv_rectangle_t{1, 1})); + intrinsiccv_morphology_context_t *context = nullptr; + ASSERT_EQ(INTRINSICCV_OK, make_minimal_context(&context, sizeof(TypeParam))); TypeParam src[1] = {}, dst[1]; test::test_null_args(dilate(), src, sizeof(TypeParam), dst, - sizeof(TypeParam), 1, 1, ¶ms); - - { - intrinsiccv_morphology_params_t invalid_params = params; - invalid_params.impl = nullptr; - EXPECT_EQ(INTRINSICCV_ERROR_NULL_POINTER, - dilate()(src, sizeof(TypeParam), dst, - sizeof(TypeParam), 1, 1, &invalid_params)); - } - - { - intrinsiccv_morphology_params_t invalid_params = params; - invalid_params.data = nullptr; - EXPECT_EQ(INTRINSICCV_ERROR_NULL_POINTER, - dilate()(src, sizeof(TypeParam), dst, - sizeof(TypeParam), 1, 1, &invalid_params)); - } - - EXPECT_EQ(INTRINSICCV_OK, intrinsiccv_morphology_release(¶ms)); + sizeof(TypeParam), 1, 1, context); + EXPECT_EQ(INTRINSICCV_OK, intrinsiccv_morphology_release(context)); } TYPED_TEST(ErodeTest, NullPointer) { - intrinsiccv_morphology_params_t params = - make_minimal_params(sizeof(TypeParam)); - ASSERT_EQ(INTRINSICCV_OK, intrinsiccv_morphology_create( - ¶ms, intrinsiccv_rectangle_t{1, 1})); + intrinsiccv_morphology_context_t *context = nullptr; + ASSERT_EQ(INTRINSICCV_OK, make_minimal_context(&context, sizeof(TypeParam))); TypeParam src[1] = {}, dst[1]; test::test_null_args(erode(), src, sizeof(TypeParam), dst, - sizeof(TypeParam), 1, 1, ¶ms); - - { - intrinsiccv_morphology_params_t invalid_params = params; - invalid_params.impl = nullptr; - EXPECT_EQ(INTRINSICCV_ERROR_NULL_POINTER, - erode()(src, sizeof(TypeParam), dst, sizeof(TypeParam), - 1, 1, &invalid_params)); - } - - { - intrinsiccv_morphology_params_t invalid_params = params; - invalid_params.data = nullptr; - EXPECT_EQ(INTRINSICCV_ERROR_NULL_POINTER, - erode()(src, sizeof(TypeParam), dst, sizeof(TypeParam), - 1, 1, &invalid_params)); - } + sizeof(TypeParam), 1, 1, context); - EXPECT_EQ(INTRINSICCV_OK, intrinsiccv_morphology_release(¶ms)); + EXPECT_EQ(INTRINSICCV_OK, intrinsiccv_morphology_release(context)); } -- GitLab