diff --git a/adapters/opencv/intrinsiccv_hal.cpp b/adapters/opencv/intrinsiccv_hal.cpp index 12936a35d63474e47302a1331bc95b44e273d202..ec4697269afb38f2d10203fddcacdb66f1cd0735 100644 --- a/adapters/opencv/intrinsiccv_hal.cpp +++ b/adapters/opencv/intrinsiccv_hal.cpp @@ -274,17 +274,6 @@ int gaussian_blur(const uchar *src_data, size_t src_step, uchar *dst_data, return CV_HAL_ERROR_NOT_IMPLEMENTED; } - switch (intrinsiccv_border_type) { - case INTRINSICCV_BORDER_TYPE_REPLICATE: - case INTRINSICCV_BORDER_TYPE_REFLECT: - case INTRINSICCV_BORDER_TYPE_WRAP: - case INTRINSICCV_BORDER_TYPE_REVERSE: - break; - - default: - return CV_HAL_ERROR_NOT_IMPLEMENTED; - } - decltype(intrinsiccv_gaussian_blur_3x3_u8) *impl{nullptr}; if ((ksize_width == 3) && (ksize_height == 3) && (width >= 3) && (height >= 3)) { diff --git a/intrinsiccv/include/intrinsiccv/morphology/workspace.h b/intrinsiccv/include/intrinsiccv/morphology/workspace.h index 0c5d7f3e4377a44fee26dfa3de8f2cbbbfa1a5fe..dba777b623d3e1efa9998c8ba45771b4094f24dd 100644 --- a/intrinsiccv/include/intrinsiccv/morphology/workspace.h +++ b/intrinsiccv/include/intrinsiccv/morphology/workspace.h @@ -8,6 +8,7 @@ #include #include #include +#include #include "intrinsiccv/intrinsiccv.h" #include "intrinsiccv/types.h" @@ -37,15 +38,31 @@ class MorphologyWorkspace final { using Pointer = std::unique_ptr; + enum class BorderType { + CONSTANT, + REPLICATE, + }; + + static std::optional get_border_type( + intrinsiccv_border_type_t border_type) INTRINSICCV_STREAMING_COMPATIBLE { + switch (border_type) { + case INTRINSICCV_BORDER_TYPE_REPLICATE: + return BorderType::REPLICATE; + case INTRINSICCV_BORDER_TYPE_CONSTANT: + return BorderType::CONSTANT; + default: + return std::optional(); + } + } + // MorphologyWorkspace is only constructible with create(). MorphologyWorkspace() = delete; // Creates a workspace on the heap. 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, + BorderType 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); @@ -116,7 +133,7 @@ class MorphologyWorkspace final { intrinsiccv_rectangle_t kernel() const { return kernel_; } intrinsiccv_point_t anchor() const { return anchor_; } - intrinsiccv_border_type_t border_type() const { return border_type_; } + BorderType 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_; } @@ -127,8 +144,7 @@ class MorphologyWorkspace final { template void process(Rectangle rect, Rows src_rows, Rows dst_rows, Margin margin, - Border border, - intrinsiccv_border_type_t border_type, + Border border, BorderType border_type, O operation) INTRINSICCV_STREAMING_COMPATIBLE { using S = typename O::SourceType; using B = typename O::BufferType; @@ -161,7 +177,7 @@ class MorphologyWorkspace final { if (size_t horizontal_height = get_next_horizontal_height()) { for (size_t index = 0; index < horizontal_height; ++index) { switch (border_type) { - case intrinsiccv_border_type_t::INTRINSICCV_BORDER_TYPE_CONSTANT: { + case BorderType::CONSTANT: { make_constant_border(wide_rows, 0, margin.left(), left_border_value); @@ -186,7 +202,7 @@ class MorphologyWorkspace final { ++row_index_; } break; - case intrinsiccv_border_type_t::INTRINSICCV_BORDER_TYPE_REPLICATE: { + case BorderType::REPLICATE: { Rows current_src_row; if (row_index_ < margin.top()) { @@ -209,14 +225,6 @@ class MorphologyWorkspace final { // Advance counters. ++row_index_; } break; - - case intrinsiccv_border_type_t::INTRINSICCV_BORDER_TYPE_REFLECT: - case intrinsiccv_border_type_t::INTRINSICCV_BORDER_TYPE_REVERSE: - case intrinsiccv_border_type_t::INTRINSICCV_BORDER_TYPE_WRAP: - case intrinsiccv_border_type_t::INTRINSICCV_BORDER_TYPE_TRANSPARENT: - case intrinsiccv_border_type_t::INTRINSICCV_BORDER_TYPE_NONE: - default: - break; } // switch (border_type) // [Step 2] Process the preloaded data. @@ -232,7 +240,7 @@ class MorphologyWorkspace final { size_t horizontal_height = get_next_horizontal_height(); for (size_t index = 0; index < horizontal_height; ++index) { switch (border_type) { - case intrinsiccv_border_type_t::INTRINSICCV_BORDER_TYPE_CONSTANT: { + case BorderType::CONSTANT: { if (row_index_ < (margin.top() + rect.height())) { // Constant left and right borders with source data. copy_data(src_rows, wide_rows.at(0, margin.left()), @@ -248,7 +256,7 @@ class MorphologyWorkspace final { ++row_index_; } break; - case intrinsiccv_border_type_t::INTRINSICCV_BORDER_TYPE_REPLICATE: { + case BorderType::REPLICATE: { Rows current_src_row; if (row_index_ < (margin.top() + rect.height())) { @@ -269,14 +277,6 @@ class MorphologyWorkspace final { // Advance counters. ++row_index_; } break; - - case intrinsiccv_border_type_t::INTRINSICCV_BORDER_TYPE_REFLECT: - case intrinsiccv_border_type_t::INTRINSICCV_BORDER_TYPE_REVERSE: - case intrinsiccv_border_type_t::INTRINSICCV_BORDER_TYPE_WRAP: - case intrinsiccv_border_type_t::INTRINSICCV_BORDER_TYPE_TRANSPARENT: - case intrinsiccv_border_type_t::INTRINSICCV_BORDER_TYPE_NONE: - default: - break; } // switch (border_type) operation.process_horizontal(Rectangle{rect.width(), 1UL}, wide_rows, @@ -367,7 +367,7 @@ class MorphologyWorkspace final { intrinsiccv_rectangle_t kernel_; intrinsiccv_point_t anchor_; - intrinsiccv_border_type_t border_type_; + BorderType border_type_; intrinsiccv_border_values_t border_values_; size_t iterations_; size_t type_size_; diff --git a/intrinsiccv/include/intrinsiccv/neon.h b/intrinsiccv/include/intrinsiccv/neon.h index 9030483a7f37c9a833583af76f48e2e436eb9d6b..d4c80d95c65511d21e0b29d7e4a1ca282759e4b3 100644 --- a/intrinsiccv/include/intrinsiccv/neon.h +++ b/intrinsiccv/include/intrinsiccv/neon.h @@ -333,6 +333,7 @@ class SeparableFilter { using BufferVecTraits = typename neon::VecTraits; using BufferVectorType = typename BufferVecTraits::VectorType; using BorderInfoType = typename intrinsiccv::FixedBorderInfo3x3; + using BorderType = FixedBorderType; using BorderOffsets = typename BorderInfoType::Offsets; explicit SeparableFilter(FilterType filter) : filter_{filter} {} @@ -463,6 +464,7 @@ class SeparableFilter { using BufferVecTraits = typename neon::VecTraits; using BufferVectorType = typename BufferVecTraits::VectorType; using BorderInfoType = typename intrinsiccv::FixedBorderInfo5x5; + using BorderType = FixedBorderType; using BorderOffsets = typename BorderInfoType::Offsets; explicit SeparableFilter(FilterType filter) : filter_{filter} {} diff --git a/intrinsiccv/include/intrinsiccv/sve2.h b/intrinsiccv/include/intrinsiccv/sve2.h index dd21a4e7ad7302fe658da6c5ab86ea3dc8fdbaf4..3bfae8108a13a372f4fc109839d6120b3caf8d06 100644 --- a/intrinsiccv/include/intrinsiccv/sve2.h +++ b/intrinsiccv/include/intrinsiccv/sve2.h @@ -482,6 +482,7 @@ class SeparableFilter { using BufferVecTraits = typename sve2::VecTraits; using BufferVectorType = typename BufferVecTraits::VectorType; using BorderInfoType = typename intrinsiccv::FixedBorderInfo3x3; + using BorderType = FixedBorderType; using BorderOffsets = typename BorderInfoType::Offsets; explicit SeparableFilter(FilterType filter) INTRINSICCV_STREAMING_COMPATIBLE @@ -617,6 +618,7 @@ class SeparableFilter { using BufferVecTraits = typename sve2::VecTraits; using BufferVectorType = typename BufferVecTraits::VectorType; using BorderInfoType = typename intrinsiccv::FixedBorderInfo5x5; + using BorderType = FixedBorderType; using BorderOffsets = typename BorderInfoType::Offsets; explicit SeparableFilter(FilterType filter) INTRINSICCV_STREAMING_COMPATIBLE diff --git a/intrinsiccv/include/intrinsiccv/workspace/borders.h b/intrinsiccv/include/intrinsiccv/workspace/borders.h index f849f6f35fac065317113bed04c0a21ef1d927b6..7562af193a0061bfa5610affa57d51025a75f7c4 100644 --- a/intrinsiccv/include/intrinsiccv/workspace/borders.h +++ b/intrinsiccv/include/intrinsiccv/workspace/borders.h @@ -5,10 +5,35 @@ #ifndef INTRINSICCV_WORKSPACE_BORDERS_H #define INTRINSICCV_WORKSPACE_BORDERS_H +#include + #include "intrinsiccv/intrinsiccv.h" namespace intrinsiccv { +enum class FixedBorderType { + REPLICATE, + REFLECT, + WRAP, + REVERSE, +}; + +inline std::optional get_fixed_border_type( + intrinsiccv_border_type_t border_type) INTRINSICCV_STREAMING_COMPATIBLE { + switch (border_type) { + case INTRINSICCV_BORDER_TYPE_REPLICATE: + return FixedBorderType::REPLICATE; + case INTRINSICCV_BORDER_TYPE_REFLECT: + return FixedBorderType::REFLECT; + case INTRINSICCV_BORDER_TYPE_WRAP: + return FixedBorderType::WRAP; + case INTRINSICCV_BORDER_TYPE_REVERSE: + return FixedBorderType::REVERSE; + default: + return std::optional(); + } +} + // Border offsets for fixed-size filters. template class FixedBorderInfo; @@ -32,7 +57,7 @@ class FixedBorderInfo final { size_t offsets_[3]; }; - FixedBorderInfo(size_t height, intrinsiccv_border_type_t border_type) + FixedBorderInfo(size_t height, FixedBorderType border_type) : height_(height), border_type_(border_type) {} // Retuns offsets without the influence of any border. @@ -42,22 +67,18 @@ class FixedBorderInfo final { Offsets offsets_with_left_border(size_t /* column_index */) const INTRINSICCV_STREAMING_COMPATIBLE { switch (border_type_) { - case INTRINSICCV_BORDER_TYPE_REPLICATE: - case INTRINSICCV_BORDER_TYPE_REFLECT: + case FixedBorderType::REPLICATE: + case FixedBorderType::REFLECT: return get(0, 0, 1); break; - case INTRINSICCV_BORDER_TYPE_WRAP: + case FixedBorderType::WRAP: return get(height_ - 1, 0, 1); break; - case INTRINSICCV_BORDER_TYPE_REVERSE: + case FixedBorderType::REVERSE: return get(1, 0, 1); break; - - default: - // There is no good value to return here. - return Offsets{}; } } @@ -65,16 +86,16 @@ class FixedBorderInfo final { Offsets offsets_with_right_border(size_t /* column_index */) const INTRINSICCV_STREAMING_COMPATIBLE { switch (border_type_) { - case INTRINSICCV_BORDER_TYPE_REPLICATE: - case INTRINSICCV_BORDER_TYPE_REFLECT: + case FixedBorderType::REPLICATE: + case FixedBorderType::REFLECT: return get(-1, 0, 0); break; - case INTRINSICCV_BORDER_TYPE_WRAP: + case FixedBorderType::WRAP: return get(-1, 0, 1 - height_); break; - case INTRINSICCV_BORDER_TYPE_REVERSE: + case FixedBorderType::REVERSE: return get(-1, 0, -1); break; @@ -105,7 +126,7 @@ class FixedBorderInfo final { } size_t height_; - intrinsiccv_border_type_t border_type_; + FixedBorderType border_type_; }; // end of class FixedBorderInfo // Border offsets for 5x5 filters. @@ -132,7 +153,7 @@ class FixedBorderInfo final { size_t offsets_[5]; }; - FixedBorderInfo(size_t height, intrinsiccv_border_type_t border_type) + FixedBorderInfo(size_t height, FixedBorderType border_type) : height_(height), border_type_(border_type) {} // Retuns offsets without the influence of any border. @@ -144,7 +165,7 @@ class FixedBorderInfo final { Offsets offsets_with_left_border(size_t column_index) const INTRINSICCV_STREAMING_COMPATIBLE { switch (border_type_) { - case INTRINSICCV_BORDER_TYPE_REPLICATE: + case FixedBorderType::REPLICATE: if (column_index == 0) { return get(0, 0, 0, 1, 2); } else { @@ -152,7 +173,7 @@ class FixedBorderInfo final { } break; - case INTRINSICCV_BORDER_TYPE_REFLECT: + case FixedBorderType::REFLECT: if (column_index == 0) { return get(1, 0, 0, 1, 2); } else { @@ -160,7 +181,7 @@ class FixedBorderInfo final { } break; - case INTRINSICCV_BORDER_TYPE_WRAP: + case FixedBorderType::WRAP: if (column_index == 0) { return get(height_ - 2, height_ - 1, 0, 1, 2); } else { @@ -168,7 +189,7 @@ class FixedBorderInfo final { } break; - case INTRINSICCV_BORDER_TYPE_REVERSE: + case FixedBorderType::REVERSE: if (column_index == 0) { return get(2, 1, 0, 1, 2); } else { @@ -186,7 +207,7 @@ class FixedBorderInfo final { Offsets offsets_with_right_border(size_t column_index) const INTRINSICCV_STREAMING_COMPATIBLE { switch (border_type_) { - case INTRINSICCV_BORDER_TYPE_REPLICATE: + case FixedBorderType::REPLICATE: if (column_index == (height_ - 2)) { return get(-2, -1, 0, 1, 1); } else { @@ -194,7 +215,7 @@ class FixedBorderInfo final { } break; - case INTRINSICCV_BORDER_TYPE_REFLECT: + case FixedBorderType::REFLECT: if (column_index == (height_ - 2)) { return get(-2, -1, 0, 1, 1); } else { @@ -202,7 +223,7 @@ class FixedBorderInfo final { } break; - case INTRINSICCV_BORDER_TYPE_WRAP: + case FixedBorderType::WRAP: if (column_index == (height_ - 2)) { return get(-2, -1, 0, 1, 2 - height_); } else { @@ -210,7 +231,7 @@ class FixedBorderInfo final { } break; - case INTRINSICCV_BORDER_TYPE_REVERSE: + case FixedBorderType::REVERSE: if (column_index == (height_ - 2)) { return get(-2, -1, 0, 1, 0); } else { @@ -246,7 +267,7 @@ class FixedBorderInfo final { } size_t height_; - intrinsiccv_border_type_t border_type_; + FixedBorderType border_type_; }; // end of class FixedBorderInfo // Shorthand for 3x3 filter border type. diff --git a/intrinsiccv/include/intrinsiccv/workspace/separable.h b/intrinsiccv/include/intrinsiccv/workspace/separable.h index c0351368cbdfe32038936ee139fbb92f7949fa36..1d456838f4f0de13b4aba4e0b504b9345befd1a3 100644 --- a/intrinsiccv/include/intrinsiccv/workspace/separable.h +++ b/intrinsiccv/include/intrinsiccv/workspace/separable.h @@ -118,7 +118,7 @@ class SeparableFilterWorkspace final { void process(Rectangle rect, Rows src_rows, Rows dst_rows, - size_t channels, intrinsiccv_border_type_t border_type, + size_t channels, typename FilterType::BorderType border_type, FilterType filter) INTRINSICCV_STREAMING_COMPATIBLE { // Border helper which calculates border offsets. typename FilterType::BorderInfoType vertical_border{rect.height(), diff --git a/intrinsiccv/src/filters/gaussian_blur_neon.cpp b/intrinsiccv/src/filters/gaussian_blur_neon.cpp index 41183f1a4345c591a9576ce13a3dd471ebe3f5f0..7659cabcabb48e51e1076d47079e544207b3d28f 100644 --- a/intrinsiccv/src/filters/gaussian_blur_neon.cpp +++ b/intrinsiccv/src/filters/gaussian_blur_neon.cpp @@ -160,9 +160,16 @@ intrinsiccv_error_t discrete_gaussian_blur( auto *workspace = reinterpret_cast(context); + auto fixed_border_type = get_fixed_border_type(border_type); + + if (!fixed_border_type) { + return INTRINSICCV_ERROR_NOT_IMPLEMENTED; + } + GaussianBlurFilterType blur; SeparableFilter filter{blur}; - workspace->process(rect, src_rows, dst_rows, channels, border_type, filter); + workspace->process(rect, src_rows, dst_rows, channels, *fixed_border_type, + filter); return INTRINSICCV_OK; } diff --git a/intrinsiccv/src/filters/gaussian_blur_sc.h b/intrinsiccv/src/filters/gaussian_blur_sc.h index 1c07636c18a8c6fe55e72a4753b0162e6c293c15..be87e4671ebb5f117c50ef36b0ca4e09a2f2c5fc 100644 --- a/intrinsiccv/src/filters/gaussian_blur_sc.h +++ b/intrinsiccv/src/filters/gaussian_blur_sc.h @@ -102,7 +102,15 @@ intrinsiccv_error_t discrete_gaussian_blur( GaussianBlurFilterType blur; SeparableFilter filter{blur}; - workspace->process(rect, src_rows, dst_rows, channels, border_type, filter); + + auto fixed_border_type = get_fixed_border_type(border_type); + + if (!fixed_border_type) { + return INTRINSICCV_ERROR_NOT_IMPLEMENTED; + } + + workspace->process(rect, src_rows, dst_rows, channels, *fixed_border_type, + filter); return INTRINSICCV_OK; } diff --git a/intrinsiccv/src/filters/sobel_neon.cpp b/intrinsiccv/src/filters/sobel_neon.cpp index 3426f75705a5d469403bfe724e50be8740ca9df6..4ceb9def89a0e434c880ff8e5b5bff4a6bc030f8 100644 --- a/intrinsiccv/src/filters/sobel_neon.cpp +++ b/intrinsiccv/src/filters/sobel_neon.cpp @@ -148,7 +148,7 @@ intrinsiccv_error_t sobel_3x3_horizontal_s16_u8(const uint8_t *src, HorizontalSobel3x3 horizontal_sobel; SeparableFilter3x3> filter{horizontal_sobel}; workspace->process(rect, src_rows, dst_rows, channels, - INTRINSICCV_BORDER_TYPE_REPLICATE, filter); + FixedBorderType::REPLICATE, filter); return INTRINSICCV_OK; } @@ -173,7 +173,7 @@ intrinsiccv_error_t sobel_3x3_vertical_s16_u8(const uint8_t *src, VerticalSobel3x3 vertical_sobel; SeparableFilter3x3> filter{vertical_sobel}; workspace->process(rect, src_rows, dst_rows, channels, - INTRINSICCV_BORDER_TYPE_REPLICATE, filter); + FixedBorderType::REPLICATE, filter); return INTRINSICCV_OK; } diff --git a/intrinsiccv/src/filters/sobel_sc.h b/intrinsiccv/src/filters/sobel_sc.h index 6fad83d5ef8b778b63b9c52eb921b77f28afe94f..493c3816339bd9b3be780ae389a1af879d59a579 100644 --- a/intrinsiccv/src/filters/sobel_sc.h +++ b/intrinsiccv/src/filters/sobel_sc.h @@ -139,7 +139,7 @@ static intrinsiccv_error_t sobel_3x3_horizontal_s16_u8_sc( sve2::SeparableFilter3x3> filter{ horizontal_sobel}; workspace->process(rect, src_rows, dst_rows, channels, - INTRINSICCV_BORDER_TYPE_REPLICATE, filter); + FixedBorderType::REPLICATE, filter); return INTRINSICCV_OK; } @@ -164,7 +164,7 @@ static intrinsiccv_error_t sobel_3x3_vertical_s16_u8_sc( VerticalSobel3x3 vertical_sobel; sve2::SeparableFilter3x3> filter{vertical_sobel}; workspace->process(rect, src_rows, dst_rows, channels, - INTRINSICCV_BORDER_TYPE_REPLICATE, filter); + FixedBorderType::REPLICATE, filter); return INTRINSICCV_OK; } diff --git a/intrinsiccv/src/morphology/morphology_api.cpp b/intrinsiccv/src/morphology/morphology_api.cpp index fd2084c149f0aa67e264568687047afa942eee0c..05bd288d77db76b28728f7bddd3567ffc28ee27f 100644 --- a/intrinsiccv/src/morphology/morphology_api.cpp +++ b/intrinsiccv/src/morphology/morphology_api.cpp @@ -59,9 +59,16 @@ intrinsiccv_error_t intrinsiccv_morphology_create( size_t iterations, size_t type_size, intrinsiccv_rectangle_t image) { CHECK_POINTERS(context); - auto workspace = - MorphologyWorkspace::create(kernel, anchor, border_type, border_values, - channels, iterations, type_size, image); + auto morphology_border_type = + MorphologyWorkspace::get_border_type(border_type); + + if (!morphology_border_type) { + return INTRINSICCV_ERROR_NOT_IMPLEMENTED; + } + + auto workspace = MorphologyWorkspace::create( + kernel, anchor, *morphology_border_type, border_values, channels, + iterations, type_size, image); if (!workspace) { *context = nullptr; return INTRINSICCV_ERROR_ALLOCATION; diff --git a/test/api/test_gaussian_blur.cpp b/test/api/test_gaussian_blur.cpp index 591bae4ac942abd28fe5d1bf56752c281d1758ce..8988ffbeca0d0f3c694359b3e024f1c3829f35c8 100644 --- a/test/api/test_gaussian_blur.cpp +++ b/test/api/test_gaussian_blur.cpp @@ -22,6 +22,29 @@ class GaussianBlurTest : public testing::Test {}; TYPED_TEST_SUITE(GaussianBlurTest, ElementTypes); +TYPED_TEST(GaussianBlurTest, UnsupportedBorderType) { + intrinsiccv_filter_context_t *context = nullptr; + ASSERT_EQ(INTRINSICCV_OK, + intrinsiccv_filter_create(&context, 1, sizeof(TypeParam), + intrinsiccv_rectangle_t{1, 1})); + TypeParam src[1] = {}, dst[1]; + for (intrinsiccv_border_type_t border : { + INTRINSICCV_BORDER_TYPE_CONSTANT, + INTRINSICCV_BORDER_TYPE_TRANSPARENT, + INTRINSICCV_BORDER_TYPE_NONE, + }) { + EXPECT_EQ(INTRINSICCV_ERROR_NOT_IMPLEMENTED, + gaussian_blur_3x3()(src, sizeof(TypeParam), dst, + sizeof(TypeParam), 1, 1, 1, border, + context)); + EXPECT_EQ(INTRINSICCV_ERROR_NOT_IMPLEMENTED, + gaussian_blur_5x5()(src, sizeof(TypeParam), dst, + sizeof(TypeParam), 1, 1, 1, border, + context)); + } + EXPECT_EQ(INTRINSICCV_OK, intrinsiccv_filter_release(context)); +} + TYPED_TEST(GaussianBlurTest, NullPointer) { intrinsiccv_filter_context_t *context = nullptr; ASSERT_EQ(INTRINSICCV_OK, diff --git a/test/api/test_morphology.cpp b/test/api/test_morphology.cpp index b8ff5116e4ef3d81937de36b794347db2a6a3d6f..72a06cade899cd98841e2da15a0481d29aba274e 100644 --- a/test/api/test_morphology.cpp +++ b/test/api/test_morphology.cpp @@ -16,6 +16,9 @@ INTRINSICCV_DILATE(uint8_t, u8); INTRINSICCV_ERODE(uint8_t, u8); +template +class MorphologyTest : public testing::Test {}; + template class DilateTest : public testing::Test {}; @@ -23,9 +26,29 @@ template class ErodeTest : public testing::Test {}; using ElementTypes = ::testing::Types; +TYPED_TEST_SUITE(MorphologyTest, ElementTypes); TYPED_TEST_SUITE(DilateTest, ElementTypes); TYPED_TEST_SUITE(ErodeTest, ElementTypes); +TYPED_TEST(MorphologyTest, UnsupportedBorderType) { + for (intrinsiccv_border_type_t border : { + INTRINSICCV_BORDER_TYPE_REFLECT, + INTRINSICCV_BORDER_TYPE_WRAP, + INTRINSICCV_BORDER_TYPE_REVERSE, + INTRINSICCV_BORDER_TYPE_TRANSPARENT, + INTRINSICCV_BORDER_TYPE_NONE, + }) { + intrinsiccv_morphology_context_t *context = nullptr; + EXPECT_EQ( + INTRINSICCV_ERROR_NOT_IMPLEMENTED, + intrinsiccv_morphology_create( + &context, intrinsiccv_rectangle_t{1, 1}, intrinsiccv_point_t{0, 0}, + border, intrinsiccv_border_values_t{0, 0, 1, 1}, 1, 1, + sizeof(TypeParam), intrinsiccv_rectangle_t{1, 1})); + ASSERT_EQ(nullptr, context); + } +} + static intrinsiccv_error_t make_minimal_context( intrinsiccv_morphology_context_t **context, size_t type_size) { return intrinsiccv_morphology_create(