From e3b76df18ab4bbef31698b8c96d38760bf2aaac4 Mon Sep 17 00:00:00 2001 From: Michael Platings Date: Wed, 6 Mar 2024 10:57:56 +0000 Subject: [PATCH] Handle zero sized images Where it is possible to handle zero sized images in a valid way (e.g. mapping from one zero sized image to another) then permit such inputs. For functions that must return some property of the image that will be undefined if it has no size, require that the image size must be greater than 1. --- intrinsiccv/include/intrinsiccv/intrinsiccv.h | 8 +-- .../intrinsiccv/morphology/workspace.h | 4 ++ .../include/intrinsiccv/workspace/separable.h | 4 ++ intrinsiccv/src/analysis/min_max_loc_neon.cpp | 4 ++ intrinsiccv/src/analysis/min_max_neon.cpp | 4 ++ test/api/test_add_abs_with_threshold.cpp | 12 +++- test/api/test_canny.cpp | 12 +++- test/api/test_count_nonzeros.cpp | 12 +++- test/api/test_gaussian_blur.cpp | 28 +++++++++- test/api/test_merge.cpp | 17 +++++- test/api/test_min_max.cpp | 26 ++++++++- test/api/test_morphology.cpp | 56 ++++++++++++++++++- test/api/test_resize_to_quarter.cpp | 12 +++- test/api/test_rgb_and_gray.cpp | 5 ++ test/api/test_saturating_absdiff.cpp | 12 +++- test/api/test_saturating_add.cpp | 12 +++- test/api/test_saturating_multiply.cpp | 12 +++- test/api/test_saturating_sub.cpp | 12 +++- test/api/test_scale.cpp | 10 +++- test/api/test_sobel.cpp | 26 ++++++++- test/api/test_split.cpp | 17 +++++- test/api/test_threshold_binary.cpp | 12 +++- test/api/test_transpose.cpp | 12 +++- test/api/test_yuv_to_rgb.cpp | 9 +++ 24 files changed, 312 insertions(+), 26 deletions(-) diff --git a/intrinsiccv/include/intrinsiccv/intrinsiccv.h b/intrinsiccv/include/intrinsiccv/intrinsiccv.h index 320d2f765..c691afc7c 100644 --- a/intrinsiccv/include/intrinsiccv/intrinsiccv.h +++ b/intrinsiccv/include/intrinsiccv/intrinsiccv.h @@ -1153,8 +1153,8 @@ intrinsiccv_error_t intrinsiccv_merge(const void **srcs, /// start of the next row in the source data. Must not be /// less than width * sizeof(type). /// Must be a multiple of sizeof(type). -/// @param width Number of elements in a row. -/// @param height Number of rows in the data. +/// @param width Number of elements in a row. Must be greater than 0. +/// @param height Number of rows in the data. Must be greater than 0. /// @param min_value Pointer to save result minimum value to, or nullptr if /// minimum is not to be calculated. /// @param max_value Pointer to save result maximum value to, or nullptr if @@ -1195,8 +1195,8 @@ intrinsiccv_error_t intrinsiccv_min_max_s32(const int32_t *src, /// start of the next row in the source data. Must not be /// less than width * sizeof(type). /// Must be a multiple of sizeof(type). -/// @param width Number of elements in a row. -/// @param height Number of rows in the data. +/// @param width Number of elements in a row. Must be greater than 0. +/// @param height Number of rows in the data. Must be greater than 0. /// @param min_offset Pointer to save result offset of minimum value to, or /// nullptr if minimum is not to be calculated. /// @param max_offset Pointer to save result offset of maximum value to, or diff --git a/intrinsiccv/include/intrinsiccv/morphology/workspace.h b/intrinsiccv/include/intrinsiccv/morphology/workspace.h index 0668ce8c7..022e1ab72 100644 --- a/intrinsiccv/include/intrinsiccv/morphology/workspace.h +++ b/intrinsiccv/include/intrinsiccv/morphology/workspace.h @@ -161,6 +161,10 @@ class MorphologyWorkspace final { using S = typename O::SourceType; using B = typename O::BufferType; + if (INTRINSICCV_UNLIKELY(rect.width() == 0 || rect.height() == 0)) { + return; + } + // Wide rows which can hold data with left and right margins. auto wide_rows = Rows{reinterpret_cast(&data_[wide_rows_offset_]), wide_rows_stride_, channels_}; diff --git a/intrinsiccv/include/intrinsiccv/workspace/separable.h b/intrinsiccv/include/intrinsiccv/workspace/separable.h index c26d082aa..599e1186b 100644 --- a/intrinsiccv/include/intrinsiccv/workspace/separable.h +++ b/intrinsiccv/include/intrinsiccv/workspace/separable.h @@ -127,6 +127,10 @@ class SeparableFilterWorkspace final { Rows dst_rows, size_t channels, typename FilterType::BorderType border_type, FilterType filter) INTRINSICCV_STREAMING_COMPATIBLE { + if (INTRINSICCV_UNLIKELY(rect.width() == 0 || rect.height() == 0)) { + return; + } + // Border helper which calculates border offsets. typename FilterType::BorderInfoType vertical_border{rect.height(), border_type}; diff --git a/intrinsiccv/src/analysis/min_max_loc_neon.cpp b/intrinsiccv/src/analysis/min_max_loc_neon.cpp index 99b355836..ef88a219a 100644 --- a/intrinsiccv/src/analysis/min_max_loc_neon.cpp +++ b/intrinsiccv/src/analysis/min_max_loc_neon.cpp @@ -313,6 +313,10 @@ intrinsiccv_error_t min_max_loc(const ScalarType *src, size_t src_stride, CHECK_POINTER_AND_STRIDE(src, src_stride); CHECK_IMAGE_SIZE(width, height); + if (INTRINSICCV_UNLIKELY(width == 0 || height == 0)) { + return INTRINSICCV_ERROR_RANGE; + } + Rectangle rect{width, height}; Rows src_rows{src, src_stride}; MinMaxLoc operation; diff --git a/intrinsiccv/src/analysis/min_max_neon.cpp b/intrinsiccv/src/analysis/min_max_neon.cpp index 8d9b45834..82af0e523 100644 --- a/intrinsiccv/src/analysis/min_max_neon.cpp +++ b/intrinsiccv/src/analysis/min_max_neon.cpp @@ -51,6 +51,10 @@ intrinsiccv_error_t min_max(const ScalarType *src, size_t src_stride, CHECK_POINTER_AND_STRIDE(src, src_stride); CHECK_IMAGE_SIZE(width, height); + if (INTRINSICCV_UNLIKELY(width == 0 || height == 0)) { + return INTRINSICCV_ERROR_RANGE; + } + Rectangle rect{width, height}; Rows src_rows{src, src_stride}; MinMax operation; diff --git a/test/api/test_add_abs_with_threshold.cpp b/test/api/test_add_abs_with_threshold.cpp index 1246d6948..d7d1ea890 100644 --- a/test/api/test_add_abs_with_threshold.cpp +++ b/test/api/test_add_abs_with_threshold.cpp @@ -182,7 +182,17 @@ TYPED_TEST(SaturatingAddAbsWithThresholdTest, Misalignment) { sizeof(TypeParam) + 1, 1, 1, 1)); } -TYPED_TEST(SaturatingAddAbsWithThresholdTest, ImageSize) { +TYPED_TEST(SaturatingAddAbsWithThresholdTest, ZeroImageSize) { + TypeParam src[1] = {}, dst[1]; + EXPECT_EQ(INTRINSICCV_OK, intrinsiccv_saturating_add_abs_with_threshold_s16( + src, sizeof(TypeParam), src, sizeof(TypeParam), + dst, sizeof(TypeParam), 0, 1, 1)); + EXPECT_EQ(INTRINSICCV_OK, intrinsiccv_saturating_add_abs_with_threshold_s16( + src, sizeof(TypeParam), src, sizeof(TypeParam), + dst, sizeof(TypeParam), 1, 0, 1)); +} + +TYPED_TEST(SaturatingAddAbsWithThresholdTest, OversizeImage) { TypeParam src[1] = {}, dst[1]; EXPECT_EQ(INTRINSICCV_ERROR_RANGE, intrinsiccv_saturating_add_abs_with_threshold_s16( diff --git a/test/api/test_canny.cpp b/test/api/test_canny.cpp index 36f45577e..4be2534d6 100644 --- a/test/api/test_canny.cpp +++ b/test/api/test_canny.cpp @@ -41,7 +41,17 @@ TYPED_TEST(CannyTest, Misalignment) { sizeof(TypeParam) + 1, 1, 1, 0.0, 1.0)); } -TYPED_TEST(CannyTest, ImageSize) { +TYPED_TEST(CannyTest, ZeroImageSize) { + TypeParam src[1] = {}, dst[1]; + EXPECT_EQ(INTRINSICCV_OK, + canny()(src, sizeof(TypeParam), dst, sizeof(TypeParam), + 0, 1, 0.0, 1.0)); + EXPECT_EQ(INTRINSICCV_OK, + canny()(src, sizeof(TypeParam), dst, sizeof(TypeParam), + 1, 0, 0.0, 1.0)); +} + +TYPED_TEST(CannyTest, OversizeImage) { TypeParam src[1], dst[1]; EXPECT_EQ(INTRINSICCV_ERROR_RANGE, canny()(src, sizeof(TypeParam), dst, sizeof(TypeParam), diff --git a/test/api/test_count_nonzeros.cpp b/test/api/test_count_nonzeros.cpp index f8063cc9f..80abe474a 100644 --- a/test/api/test_count_nonzeros.cpp +++ b/test/api/test_count_nonzeros.cpp @@ -131,7 +131,17 @@ TYPED_TEST(CountNonZeros, Misalignment) { count_nonzeros()(src, sizeof(TypeParam) + 1, 1, 1, &count)); } -TYPED_TEST(CountNonZeros, ImageSize) { +TYPED_TEST(CountNonZeros, ZeroImageSize) { + TypeParam src[1] = {}; + size_t count = 123; + EXPECT_EQ(INTRINSICCV_OK, + count_nonzeros()(src, sizeof(TypeParam), 0, 1, &count)); + EXPECT_EQ(INTRINSICCV_OK, + count_nonzeros()(src, sizeof(TypeParam), 1, 0, &count)); + EXPECT_EQ(0, count); +} + +TYPED_TEST(CountNonZeros, OversizeImage) { TypeParam src[1] = {}; size_t count = 0; EXPECT_EQ( diff --git a/test/api/test_gaussian_blur.cpp b/test/api/test_gaussian_blur.cpp index 51f29b428..f0ed05f3b 100644 --- a/test/api/test_gaussian_blur.cpp +++ b/test/api/test_gaussian_blur.cpp @@ -257,7 +257,29 @@ TYPED_TEST(GaussianBlur, Misalignment) { EXPECT_EQ(INTRINSICCV_OK, intrinsiccv_filter_release(context)); } -TYPED_TEST(GaussianBlur, ImageSize) { +TYPED_TEST(GaussianBlur, ZeroImageSize) { + TypeParam src[1] = {}, dst[1]; + intrinsiccv_filter_context_t *context = nullptr; + ASSERT_EQ(INTRINSICCV_OK, + intrinsiccv_filter_create(&context, 1, 2 * sizeof(TypeParam), + intrinsiccv_rectangle_t{0, 1})); + EXPECT_EQ(INTRINSICCV_OK, + gaussian_blur_3x3()( + src, sizeof(TypeParam), dst, sizeof(TypeParam), 0, 1, 1, + INTRINSICCV_BORDER_TYPE_REFLECT, context)); + EXPECT_EQ(INTRINSICCV_OK, intrinsiccv_filter_release(context)); + + ASSERT_EQ(INTRINSICCV_OK, + intrinsiccv_filter_create(&context, 1, 2 * sizeof(TypeParam), + intrinsiccv_rectangle_t{1, 0})); + EXPECT_EQ(INTRINSICCV_OK, + gaussian_blur_3x3()( + src, sizeof(TypeParam), dst, sizeof(TypeParam), 1, 0, 1, + INTRINSICCV_BORDER_TYPE_REFLECT, context)); + EXPECT_EQ(INTRINSICCV_OK, intrinsiccv_filter_release(context)); +} + +TYPED_TEST(GaussianBlur, OversizeImage) { intrinsiccv_filter_context_t *context = nullptr; ASSERT_EQ(INTRINSICCV_OK, intrinsiccv_filter_create(&context, 1, 2 * sizeof(TypeParam), @@ -356,7 +378,7 @@ TYPED_TEST(GaussianBlur, InvalidContextImageSize) { EXPECT_EQ(INTRINSICCV_OK, intrinsiccv_filter_release(context)); } -TEST(FilterCreate, TooBigImage) { +TEST(FilterCreate, CannotAllocateFilter) { MockMallocToFail::enable(); intrinsiccv_filter_context_t *context = nullptr; intrinsiccv_rectangle_t rect{INTRINSICCV_MAX_IMAGE_PIXELS, 1}; @@ -365,7 +387,7 @@ TEST(FilterCreate, TooBigImage) { MockMallocToFail::disable(); } -TEST(FilterCreate, ImageSize) { +TEST(FilterCreate, OversizeImage) { intrinsiccv_filter_context_t *context = nullptr; for (intrinsiccv_rectangle_t rect : { diff --git a/test/api/test_merge.cpp b/test/api/test_merge.cpp index 61d8be67d..6259929e5 100644 --- a/test/api/test_merge.cpp +++ b/test/api/test_merge.cpp @@ -224,7 +224,22 @@ TYPED_TEST(Merge, Misalignment) { } } -TYPED_TEST(Merge, ImageSize) { +TYPED_TEST(Merge, ZeroImageSize) { + const size_t kChannels = 2; + TypeParam src1[1] = {}, src2[1] = {}, dst[1]; + const void* srcs[kChannels] = {src1, src2}; + size_t src_strides[kChannels] = {sizeof(TypeParam), sizeof(TypeParam)}; + const size_t dst_stride = kChannels * sizeof(TypeParam); + + EXPECT_EQ(INTRINSICCV_OK, + intrinsiccv_merge(srcs, src_strides, dst, dst_stride, 0, 1, + kChannels, sizeof(TypeParam))); + EXPECT_EQ(INTRINSICCV_OK, + intrinsiccv_merge(srcs, src_strides, dst, dst_stride, 1, 0, + kChannels, sizeof(TypeParam))); +} + +TYPED_TEST(Merge, OversizeImage) { const size_t kChannels = 2; TypeParam src1[1], src2[1], dst[1]; const void* srcs[kChannels] = {src1, src2}; diff --git a/test/api/test_min_max.cpp b/test/api/test_min_max.cpp index 91a7542d0..999c448c6 100644 --- a/test/api/test_min_max.cpp +++ b/test/api/test_min_max.cpp @@ -311,7 +311,17 @@ TYPED_TEST(MinMax, Misalignment) { &max_value)); } -TYPED_TEST(MinMax, ImageSize) { +TYPED_TEST(MinMax, ZeroImageSize) { + TypeParam src[1] = {}, min_value, max_value; + EXPECT_EQ(INTRINSICCV_ERROR_RANGE, + min_max()(src, sizeof(TypeParam), 0, 1, &min_value, + &max_value)); + EXPECT_EQ(INTRINSICCV_ERROR_RANGE, + min_max()(src, sizeof(TypeParam), 1, 0, &min_value, + &max_value)); +} + +TYPED_TEST(MinMax, OversizeImage) { TypeParam src[1] = {}, min_value, max_value; EXPECT_EQ(INTRINSICCV_ERROR_RANGE, min_max()(src, sizeof(TypeParam), @@ -334,7 +344,19 @@ TYPED_TEST(MinMaxLoc, API) { MinMaxLocTest{}.test(); } -TYPED_TEST(MinMaxLoc, ImageSize) { +TYPED_TEST(MinMaxLoc, ZeroImageSize) { + TypeParam src[1] = {}; + size_t min_offset = 0, max_offset = 0; + + EXPECT_EQ(INTRINSICCV_ERROR_RANGE, + min_max_loc()(src, sizeof(TypeParam), 0, 1, &min_offset, + &max_offset)); + EXPECT_EQ(INTRINSICCV_ERROR_RANGE, + min_max_loc()(src, sizeof(TypeParam), 1, 0, &min_offset, + &max_offset)); +} + +TYPED_TEST(MinMaxLoc, OversizeImage) { TypeParam src[1] = {}; size_t min_offset = 0, max_offset = 8; diff --git a/test/api/test_morphology.cpp b/test/api/test_morphology.cpp index 0d189337d..ee49801e1 100644 --- a/test/api/test_morphology.cpp +++ b/test/api/test_morphology.cpp @@ -507,7 +507,33 @@ TYPED_TEST(Morphology, ErodeMisalignment) { EXPECT_EQ(INTRINSICCV_OK, intrinsiccv_morphology_release(context)); } -TYPED_TEST(Morphology, DilateImageSize) { +TYPED_TEST(Morphology, DilateZeroImageSize) { + intrinsiccv_morphology_context_t *context = nullptr; + TypeParam src[1], dst[1]; + ASSERT_EQ(INTRINSICCV_OK, + 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, + sizeof(TypeParam), intrinsiccv_rectangle_t{0, 1})); + EXPECT_EQ(INTRINSICCV_OK, + DilateParams::api()(src, sizeof(TypeParam), dst, + sizeof(TypeParam), 0, 1, context)); + EXPECT_EQ(INTRINSICCV_OK, intrinsiccv_morphology_release(context)); + + ASSERT_EQ(INTRINSICCV_OK, + 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, + sizeof(TypeParam), intrinsiccv_rectangle_t{1, 0})); + EXPECT_EQ(INTRINSICCV_OK, + DilateParams::api()(src, sizeof(TypeParam), dst, + sizeof(TypeParam), 1, 0, context)); + EXPECT_EQ(INTRINSICCV_OK, intrinsiccv_morphology_release(context)); +} + +TYPED_TEST(Morphology, DilateOversizeImage) { intrinsiccv_morphology_context_t *context = nullptr; ASSERT_EQ(INTRINSICCV_OK, make_minimal_context(&context, sizeof(TypeParam))); TypeParam src[1], dst[1]; @@ -523,7 +549,33 @@ TYPED_TEST(Morphology, DilateImageSize) { EXPECT_EQ(INTRINSICCV_OK, intrinsiccv_morphology_release(context)); } -TYPED_TEST(Morphology, ErodeImageSize) { +TYPED_TEST(Morphology, ErodeZeroImageSize) { + intrinsiccv_morphology_context_t *context = nullptr; + TypeParam src[1], dst[1]; + ASSERT_EQ(INTRINSICCV_OK, + 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, + sizeof(TypeParam), intrinsiccv_rectangle_t{0, 1})); + EXPECT_EQ(INTRINSICCV_OK, + ErodeParams::api()(src, sizeof(TypeParam), dst, + sizeof(TypeParam), 0, 1, context)); + EXPECT_EQ(INTRINSICCV_OK, intrinsiccv_morphology_release(context)); + + ASSERT_EQ(INTRINSICCV_OK, + 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, + sizeof(TypeParam), intrinsiccv_rectangle_t{1, 0})); + EXPECT_EQ(INTRINSICCV_OK, + ErodeParams::api()(src, sizeof(TypeParam), dst, + sizeof(TypeParam), 1, 0, context)); + EXPECT_EQ(INTRINSICCV_OK, intrinsiccv_morphology_release(context)); +} + +TYPED_TEST(Morphology, ErodeOversizeImage) { intrinsiccv_morphology_context_t *context = nullptr; ASSERT_EQ(INTRINSICCV_OK, make_minimal_context(&context, sizeof(TypeParam))); TypeParam src[1], dst[1]; diff --git a/test/api/test_resize_to_quarter.cpp b/test/api/test_resize_to_quarter.cpp index a9e703048..7df0e8e88 100644 --- a/test/api/test_resize_to_quarter.cpp +++ b/test/api/test_resize_to_quarter.cpp @@ -219,7 +219,17 @@ TEST(ResizeToQuarter, NullPointer) { 1, 1); } -TEST(ResizeToQuarter, ImageSize) { +TEST(ResizeToQuarter, ZeroImageSize) { + const uint8_t src[1] = {}; + uint8_t dst[1]; + + EXPECT_EQ(INTRINSICCV_OK, + intrinsiccv_resize_to_quarter_u8(src, 1, 0, 1, dst, 1, 0, 1)); + EXPECT_EQ(INTRINSICCV_OK, + intrinsiccv_resize_to_quarter_u8(src, 1, 1, 0, dst, 1, 1, 0)); +} + +TEST(ResizeToQuarter, InvalidImageSize) { const uint8_t src[1] = {}; uint8_t dst[1]; diff --git a/test/api/test_rgb_and_gray.cpp b/test/api/test_rgb_and_gray.cpp index 24ee251f9..5528589c7 100644 --- a/test/api/test_rgb_and_gray.cpp +++ b/test/api/test_rgb_and_gray.cpp @@ -100,6 +100,11 @@ class ColourTest final { test::test_null_args(impl, source.data(), source.stride(), actual.data(), actual.stride(), logical_width, actual.height()); + EXPECT_EQ(INTRINSICCV_OK, impl(source.data(), source.stride(), + actual.data(), actual.stride(), 0, 1)); + EXPECT_EQ(INTRINSICCV_OK, impl(source.data(), source.stride(), + actual.data(), actual.stride(), 1, 0)); + EXPECT_EQ(INTRINSICCV_ERROR_RANGE, impl(source.data(), source.stride(), actual.data(), actual.stride(), INTRINSICCV_MAX_IMAGE_PIXELS + 1, 1)); diff --git a/test/api/test_saturating_absdiff.cpp b/test/api/test_saturating_absdiff.cpp index fa27a7670..0fe9daad4 100644 --- a/test/api/test_saturating_absdiff.cpp +++ b/test/api/test_saturating_absdiff.cpp @@ -123,7 +123,17 @@ TYPED_TEST(SaturatingAbsDiff, Misalignment) { sizeof(TypeParam) + 1, 1, 1)); } -TYPED_TEST(SaturatingAbsDiff, ImageSize) { +TYPED_TEST(SaturatingAbsDiff, ZeroImageSize) { + TypeParam src[1] = {}, dst[1]; + EXPECT_EQ(INTRINSICCV_OK, saturating_absdiff()( + src, sizeof(TypeParam), src, sizeof(TypeParam), + dst, sizeof(TypeParam), 0, 1)); + EXPECT_EQ(INTRINSICCV_OK, saturating_absdiff()( + src, sizeof(TypeParam), src, sizeof(TypeParam), + dst, sizeof(TypeParam), 1, 0)); +} + +TYPED_TEST(SaturatingAbsDiff, OversizeImage) { TypeParam src[1] = {}, dst[1]; EXPECT_EQ(INTRINSICCV_ERROR_RANGE, saturating_absdiff()( diff --git a/test/api/test_saturating_add.cpp b/test/api/test_saturating_add.cpp index 2964f7d10..224d56c51 100644 --- a/test/api/test_saturating_add.cpp +++ b/test/api/test_saturating_add.cpp @@ -115,7 +115,17 @@ TYPED_TEST(SaturatingAdd, Misalignment) { sizeof(TypeParam) + 1, 1, 1)); } -TYPED_TEST(SaturatingAdd, ImageSize) { +TYPED_TEST(SaturatingAdd, ZeroImageSize) { + TypeParam src[1] = {}, dst[1]; + EXPECT_EQ(INTRINSICCV_OK, saturating_add()( + src, sizeof(TypeParam), src, sizeof(TypeParam), + dst, sizeof(TypeParam), 0, 1)); + EXPECT_EQ(INTRINSICCV_OK, saturating_add()( + src, sizeof(TypeParam), src, sizeof(TypeParam), + dst, sizeof(TypeParam), 1, 0)); +} + +TYPED_TEST(SaturatingAdd, OversizeImage) { TypeParam src[1] = {}, dst[1]; EXPECT_EQ(INTRINSICCV_ERROR_RANGE, saturating_add()( diff --git a/test/api/test_saturating_multiply.cpp b/test/api/test_saturating_multiply.cpp index 8112f373b..321dcc1ed 100644 --- a/test/api/test_saturating_multiply.cpp +++ b/test/api/test_saturating_multiply.cpp @@ -123,7 +123,17 @@ TYPED_TEST(SaturatingMultiply, Misalignment) { sizeof(TypeParam) + 1, 1, 1, 1)); } -TYPED_TEST(SaturatingMultiply, ImageSize) { +TYPED_TEST(SaturatingMultiply, ZeroImageSize) { + TypeParam src[1] = {}, dst[1]; + EXPECT_EQ(INTRINSICCV_OK, saturating_multiply()( + src, sizeof(TypeParam), src, sizeof(TypeParam), + dst, sizeof(TypeParam), 0, 1, 1)); + EXPECT_EQ(INTRINSICCV_OK, saturating_multiply()( + src, sizeof(TypeParam), src, sizeof(TypeParam), + dst, sizeof(TypeParam), 1, 0, 1)); +} + +TYPED_TEST(SaturatingMultiply, OversizeImage) { TypeParam src[1] = {}, dst[1]; EXPECT_EQ(INTRINSICCV_ERROR_RANGE, saturating_multiply()( diff --git a/test/api/test_saturating_sub.cpp b/test/api/test_saturating_sub.cpp index 71737b99d..0c1fb80a6 100644 --- a/test/api/test_saturating_sub.cpp +++ b/test/api/test_saturating_sub.cpp @@ -117,7 +117,17 @@ TYPED_TEST(SaturatingSub, Misalignment) { sizeof(TypeParam) + 1, 1, 1)); } -TYPED_TEST(SaturatingSub, ImageSize) { +TYPED_TEST(SaturatingSub, ZeroImageSize) { + TypeParam src[1] = {}, dst[1]; + EXPECT_EQ(INTRINSICCV_OK, saturating_sub()( + src, sizeof(TypeParam), src, sizeof(TypeParam), + dst, sizeof(TypeParam), 0, 1)); + EXPECT_EQ(INTRINSICCV_OK, saturating_sub()( + src, sizeof(TypeParam), src, sizeof(TypeParam), + dst, sizeof(TypeParam), 1, 0)); +} + +TYPED_TEST(SaturatingSub, OversizeImage) { TypeParam src[1] = {}, dst[1]; EXPECT_EQ(INTRINSICCV_ERROR_RANGE, saturating_sub()( diff --git a/test/api/test_scale.cpp b/test/api/test_scale.cpp index b1c0bef68..df177a1fa 100644 --- a/test/api/test_scale.cpp +++ b/test/api/test_scale.cpp @@ -412,7 +412,15 @@ TYPED_TEST(ScaleTest, Misalignment) { sizeof(TypeParam) + 1, 1, 1, 2, 0)); } -TYPED_TEST(ScaleTest, ImageSize) { +TYPED_TEST(ScaleTest, ZeroImageSize) { + TypeParam src[1] = {}, dst[1]; + EXPECT_EQ(INTRINSICCV_OK, scale()(src, sizeof(TypeParam), dst, + sizeof(TypeParam), 0, 1, 2, 0)); + EXPECT_EQ(INTRINSICCV_OK, scale()(src, sizeof(TypeParam), dst, + sizeof(TypeParam), 1, 0, 2, 0)); +} + +TYPED_TEST(ScaleTest, OversizeImage) { TypeParam src[1] = {}, dst[1]; EXPECT_EQ(INTRINSICCV_ERROR_RANGE, scale()(src, sizeof(TypeParam), dst, sizeof(TypeParam), diff --git a/test/api/test_sobel.cpp b/test/api/test_sobel.cpp index 7c1829435..1d45d5835 100644 --- a/test/api/test_sobel.cpp +++ b/test/api/test_sobel.cpp @@ -150,7 +150,18 @@ TYPED_TEST(Sobel, MisalignmentVertical) { } } -TYPED_TEST(Sobel, ImageSizeHorizontal) { +TYPED_TEST(Sobel, ZeroImageSizeHorizontal) { + using KernelTestParams = SobelKernelTestParams; + typename KernelTestParams::InputType src[1] = {}; + typename KernelTestParams::OutputType dst[1]; + + EXPECT_EQ(INTRINSICCV_OK, sobel_3x3_horizontal()( + src, sizeof(src), dst, sizeof(dst), 0, 1, 1)); + EXPECT_EQ(INTRINSICCV_OK, sobel_3x3_horizontal()( + src, sizeof(src), dst, sizeof(dst), 1, 0, 1)); +} + +TYPED_TEST(Sobel, OversizeImageHorizontal) { MockMallocToFail::enable(); using KernelTestParams = SobelKernelTestParams; typename KernelTestParams::InputType src[1] = {}; @@ -172,7 +183,18 @@ TYPED_TEST(Sobel, ImageSizeHorizontal) { MockMallocToFail::disable(); } -TYPED_TEST(Sobel, ImageSizeVertical) { +TYPED_TEST(Sobel, ZeroImageSizeVertical) { + using KernelTestParams = SobelKernelTestParams; + typename KernelTestParams::InputType src[1] = {}; + typename KernelTestParams::OutputType dst[1]; + + EXPECT_EQ(INTRINSICCV_OK, sobel_3x3_vertical()( + src, sizeof(src), dst, sizeof(dst), 0, 1, 1)); + EXPECT_EQ(INTRINSICCV_OK, sobel_3x3_vertical()( + src, sizeof(src), dst, sizeof(dst), 1, 0, 1)); +} + +TYPED_TEST(Sobel, OversizeImageVertical) { MockMallocToFail::enable(); using KernelTestParams = SobelKernelTestParams; typename KernelTestParams::InputType src[1] = {}; diff --git a/test/api/test_split.cpp b/test/api/test_split.cpp index af095db80..3e750b23e 100644 --- a/test/api/test_split.cpp +++ b/test/api/test_split.cpp @@ -225,7 +225,22 @@ TYPED_TEST(Split, Misalignment) { } } -TYPED_TEST(Split, ImageSize) { +TYPED_TEST(Split, ZeroImageSize) { + const size_t kChannels = 2; + TypeParam src[1] = {}, dst1[1], dst2[1]; + const size_t src_stride = kChannels * sizeof(TypeParam); + void* dsts[kChannels] = {dst1, dst2}; + size_t dst_strides[kChannels] = {sizeof(TypeParam), sizeof(TypeParam)}; + + EXPECT_EQ(INTRINSICCV_OK, + intrinsiccv_split(src, src_stride, dsts, dst_strides, 0, 1, + kChannels, sizeof(TypeParam))); + EXPECT_EQ(INTRINSICCV_OK, + intrinsiccv_split(src, src_stride, dsts, dst_strides, 1, 0, + kChannels, sizeof(TypeParam))); +} + +TYPED_TEST(Split, OversizeImage) { const size_t kChannels = 2; TypeParam src[1] = {}, dst1[1], dst2[1]; const size_t src_stride = kChannels * sizeof(TypeParam); diff --git a/test/api/test_threshold_binary.cpp b/test/api/test_threshold_binary.cpp index f0d325aa7..50205ff75 100644 --- a/test/api/test_threshold_binary.cpp +++ b/test/api/test_threshold_binary.cpp @@ -146,7 +146,17 @@ TYPED_TEST(ThresholdBinary, Misalignment) { sizeof(TypeParam) + 1, 1, 1, 1, 1)); } -TYPED_TEST(ThresholdBinary, ImageSize) { +TYPED_TEST(ThresholdBinary, ZeroImageSize) { + TypeParam src[1] = {}, dst[1]; + EXPECT_EQ(INTRINSICCV_OK, + threshold_binary()(src, sizeof(TypeParam), dst, + sizeof(TypeParam), 0, 1, 1, 1)); + EXPECT_EQ(INTRINSICCV_OK, + threshold_binary()(src, sizeof(TypeParam), dst, + sizeof(TypeParam), 1, 0, 1, 1)); +} + +TYPED_TEST(ThresholdBinary, OversizeImage) { TypeParam src[1] = {}, dst[1]; EXPECT_EQ(INTRINSICCV_ERROR_RANGE, threshold_binary()( diff --git a/test/api/test_transpose.cpp b/test/api/test_transpose.cpp index 1da53a059..e2fe7740f 100644 --- a/test/api/test_transpose.cpp +++ b/test/api/test_transpose.cpp @@ -223,7 +223,17 @@ TYPED_TEST(Transpose, Misalignment) { 1, 1, sizeof(TypeParam))); } -TYPED_TEST(Transpose, ImageSize) { +TYPED_TEST(Transpose, ZeroImageSize) { + TypeParam src[1] = {}, dst[1]; + EXPECT_EQ(INTRINSICCV_OK, + intrinsiccv_transpose(src, sizeof(TypeParam), dst, + sizeof(TypeParam), 0, 1, sizeof(TypeParam))); + EXPECT_EQ(INTRINSICCV_OK, + intrinsiccv_transpose(src, sizeof(TypeParam), dst, + sizeof(TypeParam), 1, 0, sizeof(TypeParam))); +} + +TYPED_TEST(Transpose, OversizeImage) { TypeParam src[1] = {}, dst[1]; EXPECT_EQ(INTRINSICCV_ERROR_RANGE, intrinsiccv_transpose( diff --git a/test/api/test_yuv_to_rgb.cpp b/test/api/test_yuv_to_rgb.cpp index 8e0924a9f..32cbf48c3 100644 --- a/test/api/test_yuv_to_rgb.cpp +++ b/test/api/test_yuv_to_rgb.cpp @@ -69,6 +69,15 @@ class YuvTest final { actual.stride(), expected.width() / channel_number_, expected.height(), is_nv21); + EXPECT_EQ( + INTRINSICCV_OK, + impl(input_y.data(), input_y.stride(), input_uv.data(), + input_uv.stride(), actual.data(), actual.stride(), 0, 1, is_nv21)); + EXPECT_EQ( + INTRINSICCV_OK, + impl(input_y.data(), input_y.stride(), input_uv.data(), + input_uv.stride(), actual.data(), actual.stride(), 1, 0, is_nv21)); + EXPECT_EQ(INTRINSICCV_ERROR_RANGE, impl(input_y.data(), input_y.stride(), input_uv.data(), input_uv.stride(), actual.data(), actual.stride(), -- GitLab