From a1b6067a154001a219c4e51a706430c7654ae036 Mon Sep 17 00:00:00 2001 From: Mark Horvath Date: Wed, 14 Feb 2024 13:49:00 +0100 Subject: [PATCH 1/9] Add _s16 suffix to add_abs_with_threshold --- intrinsiccv/include/intrinsiccv/intrinsiccv.h | 2 +- intrinsiccv/src/analysis/canny_neon.cpp | 4 ++-- .../src/arithmetics/add_abs_with_threshold_api.cpp | 4 ++-- test/api/test_add_abs_with_threshold.cpp | 10 +++++----- 4 files changed, 10 insertions(+), 10 deletions(-) diff --git a/intrinsiccv/include/intrinsiccv/intrinsiccv.h b/intrinsiccv/include/intrinsiccv/intrinsiccv.h index e1a59e75a..7cc2d326a 100644 --- a/intrinsiccv/include/intrinsiccv/intrinsiccv.h +++ b/intrinsiccv/include/intrinsiccv/intrinsiccv.h @@ -229,7 +229,7 @@ INTRINSICCV_BINARY_OP_SCALE(intrinsiccv_saturating_multiply_s32, int32_t, /// @param threshold The value that the elements of the addition result /// are compared to. /// -intrinsiccv_error_t intrinsiccv_saturating_add_abs_with_threshold( +intrinsiccv_error_t intrinsiccv_saturating_add_abs_with_threshold_s16( const int16_t *src_a, size_t src_a_stride, const int16_t *src_b, size_t src_b_stride, int16_t *dst, size_t dst_stride, size_t width, size_t height, int16_t threshold); diff --git a/intrinsiccv/src/analysis/canny_neon.cpp b/intrinsiccv/src/analysis/canny_neon.cpp index d2de6a235..f21095365 100644 --- a/intrinsiccv/src/analysis/canny_neon.cpp +++ b/intrinsiccv/src/analysis/canny_neon.cpp @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: 2023 Arm Limited and/or its affiliates +// SPDX-FileCopyrightText: 2023 - 2024 Arm Limited and/or its affiliates // // SPDX-License-Identifier: Apache-2.0 @@ -507,7 +507,7 @@ extern "C" INTRINSICCV_TARGET_FN_ATTRS intrinsiccv_error_t intrinsiccv_canny_u8( // Calculate magnitude from the horizontal and vertical derivatives, and apply // lower threshold. - if (auto err = intrinsiccv_saturating_add_abs_with_threshold( + if (auto err = intrinsiccv_saturating_add_abs_with_threshold_s16( &horizontal_gradient.rows()[0], horizontal_gradient.rows().stride(), &vertical_gradient.rows()[0], vertical_gradient.rows().stride(), &magnitudes.rows_without_margin()[0], diff --git a/intrinsiccv/src/arithmetics/add_abs_with_threshold_api.cpp b/intrinsiccv/src/arithmetics/add_abs_with_threshold_api.cpp index 36c575f75..e4c24b563 100644 --- a/intrinsiccv/src/arithmetics/add_abs_with_threshold_api.cpp +++ b/intrinsiccv/src/arithmetics/add_abs_with_threshold_api.cpp @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: 2023 Arm Limited and/or its affiliates +// SPDX-FileCopyrightText: 2023 - 2024 Arm Limited and/or its affiliates // // SPDX-License-Identifier: Apache-2.0 @@ -41,7 +41,7 @@ intrinsiccv_error_t saturating_add_abs_with_threshold( const type *, size_t, const type *, size_t, type *, size_t, size_t, \ size_t, type) -INTRINSICCV_DEFINE_C_API(intrinsiccv_saturating_add_abs_with_threshold, +INTRINSICCV_DEFINE_C_API(intrinsiccv_saturating_add_abs_with_threshold_s16, int16_t); } // namespace intrinsiccv diff --git a/test/api/test_add_abs_with_threshold.cpp b/test/api/test_add_abs_with_threshold.cpp index ef5bdd66b..eabab027d 100644 --- a/test/api/test_add_abs_with_threshold.cpp +++ b/test/api/test_add_abs_with_threshold.cpp @@ -13,7 +13,7 @@ class SaturatingAddAbsWithThresholdTestBase protected: // Calls the API-under-test in the appropriate way. intrinsiccv_error_t call_api() override { - return intrinsiccv_saturating_add_abs_with_threshold( + return intrinsiccv_saturating_add_abs_with_threshold_s16( this->inputs_[0].data(), this->inputs_[0].stride(), this->inputs_[1].data(), this->inputs_[1].stride(), this->actual_[0].data(), this->actual_[0].stride(), this->width(), @@ -152,7 +152,7 @@ TYPED_TEST(SaturatingAddAbsWithThresholdTest, TestMax) { TYPED_TEST(SaturatingAddAbsWithThresholdTest, NullPointer) { TypeParam src[1], dst[1]; - test::test_null_args(intrinsiccv_saturating_add_abs_with_threshold, src, + test::test_null_args(intrinsiccv_saturating_add_abs_with_threshold_s16, src, sizeof(TypeParam), src, sizeof(TypeParam), dst, sizeof(TypeParam), 1, 1, 1); } @@ -164,15 +164,15 @@ TYPED_TEST(SaturatingAddAbsWithThresholdTest, Misalignment) { } TypeParam src[1] = {}, dst[1] = {}; EXPECT_EQ(INTRINSICCV_ERROR_ALIGNMENT, - intrinsiccv_saturating_add_abs_with_threshold( + intrinsiccv_saturating_add_abs_with_threshold_s16( src, sizeof(TypeParam) + 1, src, sizeof(TypeParam), dst, sizeof(TypeParam), 1, 1, 1)); EXPECT_EQ(INTRINSICCV_ERROR_ALIGNMENT, - intrinsiccv_saturating_add_abs_with_threshold( + intrinsiccv_saturating_add_abs_with_threshold_s16( src, sizeof(TypeParam), src, sizeof(TypeParam) + 1, dst, sizeof(TypeParam), 1, 1, 1)); EXPECT_EQ(INTRINSICCV_ERROR_ALIGNMENT, - intrinsiccv_saturating_add_abs_with_threshold( + intrinsiccv_saturating_add_abs_with_threshold_s16( src, sizeof(TypeParam), src, sizeof(TypeParam), dst, sizeof(TypeParam) + 1, 1, 1, 1)); } -- GitLab From af2979aa8be87da20937ffd2983be9241e93893e Mon Sep 17 00:00:00 2001 From: Mark Horvath Date: Fri, 9 Feb 2024 15:53:20 +0100 Subject: [PATCH 2/9] Add checks for maximum image size --- Doxyfile | 1 + intrinsiccv/include/intrinsiccv/intrinsiccv.h | 184 +++++++++++++----- intrinsiccv/include/intrinsiccv/utils.h | 18 +- intrinsiccv/src/analysis/canny_neon.cpp | 1 + .../src/analysis/count_nonzeros_neon.cpp | 4 +- intrinsiccv/src/analysis/min_max_loc_neon.cpp | 3 +- intrinsiccv/src/analysis/min_max_neon.cpp | 4 +- intrinsiccv/src/arithmetics/absdiff_neon.cpp | 3 +- intrinsiccv/src/arithmetics/absdiff_sme2.cpp | 3 +- intrinsiccv/src/arithmetics/absdiff_sve2.cpp | 3 +- .../add_abs_with_threshold_neon.cpp | 3 +- .../arithmetics/add_abs_with_threshold_sc.h | 3 +- intrinsiccv/src/arithmetics/add_neon.cpp | 3 +- intrinsiccv/src/arithmetics/add_sme2.cpp | 3 +- intrinsiccv/src/arithmetics/add_sve2.cpp | 3 +- intrinsiccv/src/arithmetics/multiply_neon.cpp | 3 +- intrinsiccv/src/arithmetics/multiply_sve2.cpp | 3 +- intrinsiccv/src/arithmetics/scale_neon.cpp | 3 +- intrinsiccv/src/arithmetics/sub_neon.cpp | 3 +- intrinsiccv/src/arithmetics/sub_sme2.cpp | 3 +- intrinsiccv/src/arithmetics/sub_sve2.cpp | 3 +- .../src/arithmetics/threshold_neon.cpp | 3 +- intrinsiccv/src/arithmetics/threshold_sc.h | 3 +- .../src/arithmetics/transpose_neon.cpp | 3 +- .../src/conversions/gray_to_rgb_neon.cpp | 6 +- intrinsiccv/src/conversions/gray_to_rgb_sc.h | 6 +- intrinsiccv/src/conversions/merge_neon.cpp | 3 +- .../src/conversions/rgb_to_rgb_api.cpp | 6 +- .../src/conversions/rgb_to_rgb_neon.cpp | 14 +- intrinsiccv/src/conversions/rgb_to_rgb_sc.h | 14 +- intrinsiccv/src/conversions/split_neon.cpp | 3 +- .../src/conversions/yuv_to_rgb_neon.cpp | 4 +- intrinsiccv/src/conversions/yuv_to_rgb_sc.h | 4 +- intrinsiccv/src/filters/gaussian_blur_api.cpp | 4 +- .../src/filters/gaussian_blur_neon.cpp | 3 +- intrinsiccv/src/filters/gaussian_blur_sc.h | 3 +- intrinsiccv/src/filters/sobel_neon.cpp | 2 + intrinsiccv/src/filters/sobel_sc.h | 4 +- intrinsiccv/src/morphology/morphology_api.cpp | 5 +- .../src/morphology/morphology_neon.cpp | 4 +- intrinsiccv/src/morphology/morphology_sc.h | 4 +- intrinsiccv/src/resize/resize_neon.cpp | 45 ++++- intrinsiccv/src/resize/resize_sc.h | 29 ++- test/api/test_add_abs_with_threshold.cpp | 13 ++ test/api/test_canny.cpp | 11 ++ test/api/test_count_nonzeros.cpp | 15 +- test/api/test_gaussian_blur.cpp | 43 ++++ test/api/test_merge.cpp | 18 ++ test/api/test_min_max.cpp | 26 +++ test/api/test_morphology.cpp | 96 +++++++++ test/api/test_resize_to_quarter.cpp | 26 +++ test/api/test_rgb_and_gray.cpp | 16 ++ test/api/test_saturating_absdiff.cpp | 13 ++ test/api/test_saturating_add.cpp | 13 ++ test/api/test_saturating_multiply.cpp | 13 ++ test/api/test_saturating_sub.cpp | 13 ++ test/api/test_scale.cpp | 11 ++ test/api/test_sobel.cpp | 30 +++ test/api/test_split.cpp | 18 ++ test/api/test_threshold_binary.cpp | 13 ++ test/api/test_transpose.cpp | 13 ++ test/api/test_yuv_to_rgb.cpp | 10 + 62 files changed, 751 insertions(+), 89 deletions(-) diff --git a/Doxyfile b/Doxyfile index 62304fa21..45c67eafd 100644 --- a/Doxyfile +++ b/Doxyfile @@ -17,3 +17,4 @@ HTML_TIMESTAMP = YES GENERATE_LATEX = NO MACRO_EXPANSION = YES DIRECTORY_GRAPH = NO +PREDEFINED = __aarch64__= diff --git a/intrinsiccv/include/intrinsiccv/intrinsiccv.h b/intrinsiccv/include/intrinsiccv/intrinsiccv.h index 7cc2d326a..360366cef 100644 --- a/intrinsiccv/include/intrinsiccv/intrinsiccv.h +++ b/intrinsiccv/include/intrinsiccv/intrinsiccv.h @@ -26,6 +26,18 @@ #include "intrinsiccv/config.h" #include "intrinsiccv/ctypes.h" +#ifndef __aarch64__ +#error "IntrinsicCV is only supported for aarch64" +#endif + +#ifdef __aarch64__ +/// Maximum image size in pixels the library accepts. +/// +/// In case of AArch64 it is limited to (almost) 256 terapixels. This way 16 bit +/// is left for any arithmetic operations around image size or width or height. +#define INTRINSICCV_MAX_IMAGE_PIXELS ((1ULL << 48) - 1) +#endif + #ifdef __cplusplus extern "C" { #endif // __cplusplus @@ -47,7 +59,8 @@ extern "C" { /// The addition is saturated, i.e. the result is the largest number of the /// type of the element if the addition result would overflow. Source data /// length (in bytes) is `stride` * `height`. Width and height are the same -/// for the two sources. +/// for the two sources and for the destination. Number of elements is limited +/// to \ref INTRINSICCV_MAX_IMAGE_PIXELS. /// /// @param src_a Pointer to the first source data. Must be non-null. /// @param src_b Pointer to the second source data. Must be non-null. @@ -89,7 +102,8 @@ INTRINSICCV_BINARY_OP(intrinsiccv_saturating_add_u64, uint64_t); /// The subtraction is saturated, i.e. the result is 0 (unsigned) or the /// smallest possible value of the type of the element if the subtraction result /// would underflow. Source data length (in bytes) is `stride` * `height`. -/// Width and height are the same for the two sources. +/// Width and height are the same for the two sources and for the destination. +/// Number of elements is limited to \ref INTRINSICCV_MAX_IMAGE_PIXELS. /// /// @param src_a Pointer to the first source data. Must be non-null. /// @param src_b Pointer to the second source data. Must be non-null. @@ -131,7 +145,8 @@ INTRINSICCV_BINARY_OP(intrinsiccv_saturating_sub_u64, uint64_t); /// The subtraction is saturated, i.e. the result is the largest number of the /// type of the element if the result would overflow (it is only possible with /// signed types). Source data length (in bytes) is `stride` * `height`. Width -/// and height are the same for the two sources. +/// and height are the same for the two sources and for the destination. Number +/// of elements is limited to \ref INTRINSICCV_MAX_IMAGE_PIXELS. /// /// @param src_a Pointer to the first source data. Must be non-null. /// @param src_b Pointer to the second source data. Must be non-null. @@ -167,7 +182,8 @@ INTRINSICCV_BINARY_OP(intrinsiccv_saturating_absdiff_s32, int32_t); /// The multiplication is saturated, i.e. the result is the largest number of /// the type of the element if the multiplication result would overflow. Source /// data length (in bytes) is `stride` * `height`. Width and height are the -/// same for the two sources. +/// same for the two sources and for the destination. Number of elements is +/// limited to \ref INTRINSICCV_MAX_IMAGE_PIXELS. /// /// @param src_a Pointer to the first source data. Must be non-null. /// @param src_b Pointer to the second source data. Must be non-null. @@ -210,20 +226,24 @@ INTRINSICCV_BINARY_OP_SCALE(intrinsiccv_saturating_multiply_s32, int32_t, /// The addition is saturated, i.e. the result is the largest number of the /// type of the element if the addition result would overflow. Source data /// length (in bytes) is `stride` * `height`. Width and height are the same -/// for the two sources. +/// for the two sources and for the destination. Number of elements is limited +/// to \ref INTRINSICCV_MAX_IMAGE_PIXELS. /// /// @param src_a Pointer to the first source data. Must be non-null. /// @param src_b Pointer to the second source data. Must be non-null. /// @param src_a_stride Distance in bytes from the start of one row to the /// start of the next row for the first source data. /// Must not be less than width * sizeof(type). +/// Must be a multiple of sizeof(type). /// @param src_b_stride Distance in bytes from the start of one row to the /// start of the next row for the second source data. /// Must not be less than width * sizeof(type). +/// Must be a multiple of sizeof(type). /// @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 for the destination 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 threshold The value that the elements of the addition result @@ -241,6 +261,9 @@ intrinsiccv_error_t intrinsiccv_saturating_add_abs_with_threshold_s16( /// where each letter represents one byte of data, and one pixel is represented /// by 3 bytes. There is no padding between the pixels. /// +/// Width and height are the same for the source and for the destination. Number +/// of pixels is limited to \ref INTRINSICCV_MAX_IMAGE_PIXELS. +/// /// @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 for the source data. @@ -249,7 +272,7 @@ intrinsiccv_error_t intrinsiccv_saturating_add_abs_with_threshold_s16( /// @param dst_stride Distance in bytes from the start of one row to the /// start of the next row for the destination data. /// Must not be less than width * sizeof(uint8). -/// @param width Number of elements in a row. +/// @param width Number of pixels in a row. /// @param height Number of rows in the data. /// intrinsiccv_error_t intrinsiccv_gray_to_rgb_u8(const uint8_t *src, @@ -264,6 +287,9 @@ intrinsiccv_error_t intrinsiccv_gray_to_rgb_u8(const uint8_t *src, /// where each letter represents one byte of data, and one pixel is represented /// by 4 bytes. There is no padding between the pixels. /// +/// Width and height are the same for the source and for the destination. Number +/// of pixels is limited to \ref INTRINSICCV_MAX_IMAGE_PIXELS. +/// /// @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 for the source data. @@ -272,7 +298,7 @@ intrinsiccv_error_t intrinsiccv_gray_to_rgb_u8(const uint8_t *src, /// @param dst_stride Distance in bytes from the start of one row to the /// start of the next row for the destination data. /// Must not be less than width * sizeof(uint8). -/// @param width Number of elements in a row. +/// @param width Number of pixels in a row. /// @param height Number of rows in the data. /// intrinsiccv_error_t intrinsiccv_gray_to_rgba_u8(const uint8_t *src, @@ -287,6 +313,9 @@ intrinsiccv_error_t intrinsiccv_gray_to_rgba_u8(const uint8_t *src, /// Each letter represents one byte of data, and one pixel is represented /// by 3 bytes. There is no padding between the pixels. /// +/// Width and height are the same for the source and for the destination. Number +/// of pixels is limited to \ref INTRINSICCV_MAX_IMAGE_PIXELS. +/// /// @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 for the source data. @@ -295,7 +324,7 @@ intrinsiccv_error_t intrinsiccv_gray_to_rgba_u8(const uint8_t *src, /// @param dst_stride Distance in bytes from the start of one row to the /// start of the next row for the destination data. /// Must not be less than width * sizeof(uint8). -/// @param width Number of elements in a row. +/// @param width Number of pixels in a row. /// @param height Number of rows in the data. /// intrinsiccv_error_t intrinsiccv_rgb_to_bgr_u8(const uint8_t *src, @@ -306,6 +335,9 @@ intrinsiccv_error_t intrinsiccv_rgb_to_bgr_u8(const uint8_t *src, /// Copies a source RBG image to destination buffer. /// All channels are 8-bit wide. /// +/// Width and height are the same for the source and for the destination. Number +/// of pixels is limited to \ref INTRINSICCV_MAX_IMAGE_PIXELS. +/// /// @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 for the source data. @@ -314,7 +346,7 @@ intrinsiccv_error_t intrinsiccv_rgb_to_bgr_u8(const uint8_t *src, /// @param dst_stride Distance in bytes from the start of one row to the /// start of the next row for the destination data. /// Must not be less than width * sizeof(uint8). -/// @param width Number of elements in a row. +/// @param width Number of pixels in a row. /// @param height Number of rows in the data. /// intrinsiccv_error_t intrinsiccv_rgb_to_rgb_u8(const uint8_t *src, @@ -329,6 +361,9 @@ intrinsiccv_error_t intrinsiccv_rgb_to_rgb_u8(const uint8_t *src, /// Each letter represents one byte of data, and one pixel is represented /// by 4 bytes. There is no padding between the pixels. /// +/// Width and height are the same for the source and for the destination. Number +/// of pixels is limited to \ref INTRINSICCV_MAX_IMAGE_PIXELS. +/// /// @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 for the source data. @@ -337,7 +372,7 @@ intrinsiccv_error_t intrinsiccv_rgb_to_rgb_u8(const uint8_t *src, /// @param dst_stride Distance in bytes from the start of one row to the /// start of the next row for the destination data. /// Must not be less than width * sizeof(uint8). -/// @param width Number of elements in a row. +/// @param width Number of pixels in a row. /// @param height Number of rows in the data. /// intrinsiccv_error_t intrinsiccv_rgba_to_bgra_u8(const uint8_t *src, @@ -348,6 +383,9 @@ intrinsiccv_error_t intrinsiccv_rgba_to_bgra_u8(const uint8_t *src, /// Copies a source RBGA image to destination buffer. /// All channels are 8-bit wide. /// +/// Width and height are the same for the source and for the destination. Number +/// of pixels is limited to \ref INTRINSICCV_MAX_IMAGE_PIXELS. +/// /// @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 for the source data. @@ -356,7 +394,7 @@ intrinsiccv_error_t intrinsiccv_rgba_to_bgra_u8(const uint8_t *src, /// @param dst_stride Distance in bytes from the start of one row to the /// start of the next row for the destination data. /// Must not be less than width * sizeof(uint8). -/// @param width Number of elements in a row. +/// @param width Number of pixels in a row. /// @param height Number of rows in the data. /// intrinsiccv_error_t intrinsiccv_rgba_to_rgba_u8(const uint8_t *src, @@ -372,6 +410,9 @@ intrinsiccv_error_t intrinsiccv_rgba_to_rgba_u8(const uint8_t *src, /// Each letter represents one byte of data, and one pixel is represented /// by 4 bytes. There is no padding between the pixels. /// +/// Width and height are the same for the source and for the destination. Number +/// of pixels is limited to \ref INTRINSICCV_MAX_IMAGE_PIXELS. +/// /// @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 for the source data. @@ -380,7 +421,7 @@ intrinsiccv_error_t intrinsiccv_rgba_to_rgba_u8(const uint8_t *src, /// @param dst_stride Distance in bytes from the start of one row to the /// start of the next row for the destination data. /// Must not be less than width * sizeof(uint8). -/// @param width Number of elements in a row. +/// @param width Number of pixels in a row. /// @param height Number of rows in the data. /// intrinsiccv_error_t intrinsiccv_rgb_to_bgra_u8(const uint8_t *src, @@ -396,6 +437,9 @@ intrinsiccv_error_t intrinsiccv_rgb_to_bgra_u8(const uint8_t *src, /// Each letter represents one byte of data, and one pixel is represented /// by 4 bytes. There is no padding between the pixels. /// +/// Width and height are the same for the source and for the destination. Number +/// of pixels is limited to \ref INTRINSICCV_MAX_IMAGE_PIXELS. +/// /// @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 for the source data. @@ -404,7 +448,7 @@ intrinsiccv_error_t intrinsiccv_rgb_to_bgra_u8(const uint8_t *src, /// @param dst_stride Distance in bytes from the start of one row to the /// start of the next row for the destination data. /// Must not be less than width * sizeof(uint8). -/// @param width Number of elements in a row. +/// @param width Number of pixels in a row. /// @param height Number of rows in the data. /// intrinsiccv_error_t intrinsiccv_rgb_to_rgba_u8(const uint8_t *src, @@ -420,6 +464,9 @@ intrinsiccv_error_t intrinsiccv_rgb_to_rgba_u8(const uint8_t *src, /// Each letter represents one byte of data, and one pixel is represented /// by 3 bytes. There is no padding between the pixels. /// +/// Width and height are the same for the source and for the destination. Number +/// of pixels is limited to \ref INTRINSICCV_MAX_IMAGE_PIXELS. +/// /// @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 for the source data. @@ -428,7 +475,7 @@ intrinsiccv_error_t intrinsiccv_rgb_to_rgba_u8(const uint8_t *src, /// @param dst_stride Distance in bytes from the start of one row to the /// start of the next row for the destination data. /// Must not be less than width * sizeof(uint8). -/// @param width Number of elements in a row. +/// @param width Number of pixels in a row. /// @param height Number of rows in the data. /// intrinsiccv_error_t intrinsiccv_rgba_to_bgr_u8(const uint8_t *src, @@ -444,6 +491,9 @@ intrinsiccv_error_t intrinsiccv_rgba_to_bgr_u8(const uint8_t *src, /// Each letter represents one byte of data, and one pixel is represented /// by 3 bytes. There is no padding between the pixels. /// +/// Width and height are the same for the source and for the destination. Number +/// of pixels is limited to \ref INTRINSICCV_MAX_IMAGE_PIXELS. +/// /// @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 for the source data. @@ -452,7 +502,7 @@ intrinsiccv_error_t intrinsiccv_rgba_to_bgr_u8(const uint8_t *src, /// @param dst_stride Distance in bytes from the start of one row to the /// start of the next row for the destination data. /// Must not be less than width * sizeof(uint8). -/// @param width Number of elements in a row. +/// @param width Number of pixels in a row. /// @param height Number of rows in the data. /// intrinsiccv_error_t intrinsiccv_rgba_to_rgb_u8(const uint8_t *src, @@ -469,6 +519,9 @@ intrinsiccv_error_t intrinsiccv_rgba_to_rgb_u8(const uint8_t *src, /// If 4-byte alignment is required then intrinsiccv_yuv_sp_to_rgba_u8 can be /// used. /// +/// Width and height are the same for the source and for the destination. Number +/// of pixels is limited to \ref INTRINSICCV_MAX_IMAGE_PIXELS. +/// /// @param src_y Pointer to the input's Y component. Must be non-null. /// @param src_y_stride Distance in bytes from the start of one row to the /// start of the next row for the input's Y component. @@ -484,7 +537,7 @@ intrinsiccv_error_t intrinsiccv_rgba_to_rgb_u8(const uint8_t *src, /// @param dst_stride Distance in bytes from the start of one row to the /// start of the next row for the destination data. Must /// not be less than width * sizeof(type). -/// @param width Number of elements in a row. +/// @param width Number of pixels in a row. /// @param height Number of rows in the data. /// @param is_nv21 If true, input is treated as NV21, otherwise treated /// as NV12. @@ -503,6 +556,9 @@ intrinsiccv_error_t intrinsiccv_yuv_sp_to_rgb_u8( /// If 4-byte alignment is required then intrinsiccv_yuv_sp_to_bgra_u8 can be /// used. /// +/// Width and height are the same for the source and for the destination. Number +/// of pixels is limited to \ref INTRINSICCV_MAX_IMAGE_PIXELS. +/// /// @param src_y Pointer to the input's Y component. Must be non-null. /// @param src_y_stride Distance in bytes from the start of one row to the /// start of the next row for the input's Y component. @@ -518,7 +574,7 @@ intrinsiccv_error_t intrinsiccv_yuv_sp_to_rgb_u8( /// @param dst_stride Distance in bytes from the start of one row to the /// start of the next row for the destination data. Must /// not be less than width * sizeof(type). -/// @param width Number of elements in a row. +/// @param width Number of pixels in a row. /// @param height Number of rows in the data. /// @param is_nv21 If true, input is treated as NV21, otherwise treated /// as NV12. @@ -536,6 +592,9 @@ intrinsiccv_error_t intrinsiccv_yuv_sp_to_bgr_u8( /// Where each letter represents one byte of data, and one pixel is represented /// by 4 bytes. There is no padding between the pixels. /// +/// Width and height are the same for the source and for the destination. Number +/// of pixels is limited to \ref INTRINSICCV_MAX_IMAGE_PIXELS. +/// /// @param src_y Pointer to the input's Y component. Must be non-null. /// @param src_y_stride Distance in bytes from the start of one row to the /// start of the next row for the input's Y component. @@ -551,7 +610,7 @@ intrinsiccv_error_t intrinsiccv_yuv_sp_to_bgr_u8( /// @param dst_stride Distance in bytes from the start of one row to the /// start of the next row for the destination data. Must /// not be less than width * sizeof(type). -/// @param width Number of elements in a row. +/// @param width Number of pixels in a row. /// @param height Number of rows in the data. /// @param is_nv21 If true, input is treated as NV21, otherwise treated /// as NV12. @@ -569,6 +628,9 @@ intrinsiccv_error_t intrinsiccv_yuv_sp_to_rgba_u8( /// Where each letter represents one byte of data, and one pixel is represented /// by 4 bytes. There is no padding between the pixels. /// +/// Width and height are the same for the source and for the destination. Number +/// of pixels is limited to \ref INTRINSICCV_MAX_IMAGE_PIXELS. +/// /// @param src_y Pointer to the input's Y component. Must be non-null. /// @param src_y_stride Distance in bytes from the start of one row to the /// start of the next row for the input's Y component. @@ -584,7 +646,7 @@ intrinsiccv_error_t intrinsiccv_yuv_sp_to_rgba_u8( /// @param dst_stride Distance in bytes from the start of one row to the /// start of the next row for the destination data. Must /// not be less than width * sizeof(type). -/// @param width Number of elements in a row. +/// @param width Number of pixels in a row. /// @param height Number of rows in the data. /// @param is_nv21 If true, input is treated as NV21, otherwise treated /// as NV12. @@ -598,6 +660,9 @@ intrinsiccv_error_t intrinsiccv_yuv_sp_to_bgra_u8( /// caller defined threshold. The strictly larger elements are set to /// `value` and the rest to 0. /// +/// Width and height are the same for the source and for the destination. Number +/// of elements is limited to \ref INTRINSICCV_MAX_IMAGE_PIXELS. +/// /// @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 for the source data. Must @@ -626,7 +691,8 @@ intrinsiccv_error_t intrinsiccv_threshold_binary_u8( /// intrinsiccv_morphology_release. /// /// @param context Pointer where to return the created context's address. -/// @param kernel Width and height of the rectangle +/// @param kernel Width and height of the kernel. Its size must not be +/// more than \ref INTRINSICCV_MAX_IMAGE_PIXELS. /// @param anchor Location in the kernel which is aligned to the actual /// point in the source data /// @param border_type Way of handling the border. @@ -635,7 +701,8 @@ intrinsiccv_error_t intrinsiccv_threshold_binary_u8( /// @param channels Number of elements for each pixel. /// @param iterations Number of times to do the morphology operation. /// @param type_size Element size in bytes. -/// @param image Image dimensions. +/// @param image Image dimensions. Its size must not be more than +/// \ref INTRINSICCV_MAX_IMAGE_PIXELS. /// intrinsiccv_error_t intrinsiccv_morphology_create( intrinsiccv_morphology_context_t **context, intrinsiccv_rectangle_t kernel, @@ -655,7 +722,9 @@ intrinsiccv_error_t intrinsiccv_morphology_release( /// values using a given kernel which has a rectangular shape, and puts the /// result into `dst`. /// -/// Width and height are the same for the source and the destination. +/// Width and height are the same for the source and the destination. Number +/// of pixels is limited to \ref INTRINSICCV_MAX_IMAGE_PIXELS. +/// /// The kernel has an anchor point, it is usually the center of the kernel. /// The algorithm takes a rectangle from the source data using the kernel and /// the anchor, and calculates the max/min value in that rectangle. @@ -678,14 +747,14 @@ intrinsiccv_error_t intrinsiccv_morphology_release( /// - \ref INTRINSICCV_BORDER_TYPE_CONSTANT /// /// @param src Pointer to the source data. Must be non-null. -/// @param src_stride Distance in bytes between the row first elements for -/// the source data. Must not be less than -/// width * (element size in bytes). +/// @param src_stride Distance in bytes from the start of one row to the +/// start of the next row for the source data. +/// Must not be less than width * channels * sizeof(uint8). /// @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 for the destination data. Must -/// not be less than width * (element size in bytes). -/// @param width Number of elements in a row. +/// not be less than width * channels * sizeof(uint8). +/// @param width Number of pixels in a row. /// @param height Number of rows in the data. /// @param context Pointer to morphology context. /// @@ -699,7 +768,8 @@ 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, intrinsiccv_morphology_context_t *context); -/// Counts how many nonzero elements are in the source data. +/// Counts how many nonzero elements are in the source data. Number of elements +/// is limited to \ref INTRINSICCV_MAX_IMAGE_PIXELS. /// /// @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 @@ -722,7 +792,8 @@ intrinsiccv_error_t intrinsiccv_count_nonzeros_u8(const uint8_t *src, /// In case of odd source dimensions `(2*N+1, 2*M+1)` destination /// dimensions could be either `(N+1, M+1)` or `(N, M)` or combination of both. /// For later cases last respective row or column of source data will not be -/// processed. Currently only supports single-channel data. +/// processed. Currently only supports single-channel data. Number of pixels in +/// the source is limited to \ref INTRINSICCV_MAX_IMAGE_PIXELS. /// /// Even dimension example of 2x2 to 1x1 conversion: /// ``` @@ -749,13 +820,13 @@ intrinsiccv_error_t intrinsiccv_count_nonzeros_u8(const uint8_t *src, /// Must be a multiple of sizeof(type). /// Must not be less than width * sizeof(type). /// @param dst_width Number of elements in the destination row. -/// Should be src_width / 2 for even src_width. -/// For odd src_width could be either src_width / 2 -/// or (src_width / 2) + 1 +/// Must be src_width / 2 for even src_width. +/// For odd src_width it must be either src_width / 2 +/// or (src_width / 2) + 1. /// @param dst_height Number of rows in the destination data. -/// Should be src_height / 2 for even src_height. -/// For odd src_height could be either src_height / 2 -/// or (src_height / 2) + 1 +/// Must be src_height / 2 for even src_height. +/// For odd src_height it must be either src_height / 2 +/// or (src_height / 2) + 1. /// intrinsiccv_error_t intrinsiccv_resize_to_quarter_u8( const uint8_t *src, size_t src_stride, size_t src_width, size_t src_height, @@ -772,7 +843,10 @@ intrinsiccv_error_t intrinsiccv_resize_to_quarter_u8( /// Note, that the kernel is mirrored both vertically and horizontally during /// the convolution. /// -/// The only supported border type is ::INTRINSICCV_BORDER_TYPE_REPLICATE +/// The only supported border type is \ref INTRINSICCV_BORDER_TYPE_REPLICATE +/// +/// Width and height are the same for the source and for the destination. Number +/// of pixels is limited to \ref INTRINSICCV_MAX_IMAGE_PIXELS. /// /// @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 @@ -804,7 +878,10 @@ intrinsiccv_error_t intrinsiccv_sobel_3x3_vertical_s16_u8( /// Note, that the kernel is mirrored both vertically and horizontally during /// the convolution. /// -/// The only supported border type is ::INTRINSICCV_BORDER_TYPE_REPLICATE +/// The only supported border type is \ref INTRINSICCV_BORDER_TYPE_REPLICATE +/// +/// Width and height are the same for the source and for the destination. Number +/// of pixels is limited to \ref INTRINSICCV_MAX_IMAGE_PIXELS. /// /// @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 @@ -826,7 +903,8 @@ intrinsiccv_error_t intrinsiccv_sobel_3x3_horizontal_s16_u8( size_t width, size_t height, size_t channel); /// Canny edge detector for uint8_t grayscale input. Output is also a uint8_t -/// grayscale image. Width and height are the same for input and output. +/// grayscale image. Width and height are the same for input and output. Number +/// of pixels is limited to \ref INTRINSICCV_MAX_IMAGE_PIXELS. /// /// The steps: /// - Execute horizontal and vertical Sobel filtering with 3*3 kernels to @@ -866,7 +944,8 @@ intrinsiccv_error_t intrinsiccv_canny_u8(const uint8_t *src, size_t src_stride, /// @param context Pointer where to return the created context's address. /// @param channels Number of elements for each pixel. /// @param type_size Element size in bytes. -/// @param image Image dimensions. +/// @param image Image dimensions. Its size must not be more than +/// \ref INTRINSICCV_MAX_IMAGE_PIXELS. /// intrinsiccv_error_t intrinsiccv_filter_create( intrinsiccv_filter_context_t **context, size_t channels, size_t type_size, @@ -897,8 +976,11 @@ intrinsiccv_error_t intrinsiccv_filter_release( /// [ 4, 16, 24, 16, 4 ] /// [ 1, 4, 6, 4, 1 ] /// ``` -/// Usage: /// +/// Width and height are the same for the source and for the destination. Number +/// of elements is limited to \ref INTRINSICCV_MAX_IMAGE_PIXELS. +/// +/// Usage: \n /// Before using this function, a context must be created using /// intrinsiccv_filter_create, and after finished, it has to be released /// using intrinsiccv_filter_release. Note, from the border types only @@ -939,7 +1021,9 @@ intrinsiccv_error_t intrinsiccv_gaussian_blur_5x5_u8( intrinsiccv_border_type_t border_type, intrinsiccv_filter_context_t *context); -/// Splits a multi channel source stream into separate 1-channel streams. +/// Splits a multi channel source stream into separate 1-channel streams. Width +/// and height are the same for the source stream and for all the destination +/// streams. Number of pixels is limited to \ref INTRINSICCV_MAX_IMAGE_PIXELS. /// /// @param src_data Pointer to the source data. Must be non-null. /// Must be aligned to element_size. @@ -982,6 +1066,8 @@ intrinsiccv_error_t intrinsiccv_split(const void *src_data, size_t src_stride, /// | 2 | 2 | 2 | /// ``` /// +/// Number of elements is limited to \ref INTRINSICCV_MAX_IMAGE_PIXELS. +/// /// @param src Pointer to the source data. Must be non-null. /// Must be aligned to element_size. /// @param src_stride Distance in bytes from the start of one row to the @@ -1004,7 +1090,9 @@ intrinsiccv_error_t intrinsiccv_transpose(const void *src, size_t src_stride, size_t src_width, size_t src_height, size_t element_size); -/// Merges separate 1-channel source streams to one multi channel stream. +/// Merges separate 1-channel source streams to one multi channel stream. Width +/// and height are the same for all the source streams and for the destination. +/// Number of pixels is limited to \ref INTRINSICCV_MAX_IMAGE_PIXELS. /// /// @param srcs A C style array of pointers to the source data. /// Number of pointers in the array must be the same as the @@ -1023,7 +1111,8 @@ intrinsiccv_error_t intrinsiccv_transpose(const void *src, size_t src_stride, /// start of the next row in the destination data. Must not /// be less than width * element_size * channels. /// Must be a multiple of element_size. -/// @param width Number of elements in a row. +/// @param width Number of elements in a row for the source streams, +/// number of pixels in a row for the destination data. /// @param height Number of rows in the data. /// @param channels Number of channels in the destination data. /// @param element_size Size of one element in bytes. @@ -1034,7 +1123,8 @@ intrinsiccv_error_t intrinsiccv_merge(const void **srcs, size_t height, size_t channels, size_t element_size); -/// Calculates minimum and maximum element value across the source data. +/// Calculates minimum and maximum element value across the source data. Number +/// of elements is limited to \ref INTRINSICCV_MAX_IMAGE_PIXELS. /// /// @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 @@ -1075,7 +1165,8 @@ intrinsiccv_error_t intrinsiccv_min_max_s32(const int32_t *src, /// Finds minimum and maximum element value across the source data, /// and returns their location in the source data as offset in bytes -/// from the source beginning. +/// from the source beginning. Number of elements is limited to +/// \ref INTRINSICCV_MAX_IMAGE_PIXELS. /// /// @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 @@ -1101,7 +1192,8 @@ intrinsiccv_error_t intrinsiccv_min_max_loc_u8(const uint8_t *src, /// The result is saturated, i.e. it is the smallest/largest number of the /// type of the element if the result would underflow/overflow. Source data /// length (in bytes) is `stride` * `height`. Width and height are the same -/// for the source and destination. +/// for the source and destination. Number of elements is limited to +/// \ref INTRINSICCV_MAX_IMAGE_PIXELS. /// /// @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 diff --git a/intrinsiccv/include/intrinsiccv/utils.h b/intrinsiccv/include/intrinsiccv/utils.h index 4aec291eb..785c5a1ca 100644 --- a/intrinsiccv/include/intrinsiccv/utils.h +++ b/intrinsiccv/include/intrinsiccv/utils.h @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: 2023 Arm Limited and/or its affiliates +// SPDX-FileCopyrightText: 2023 - 2024 Arm Limited and/or its affiliates // // SPDX-License-Identifier: Apache-2.0 @@ -412,6 +412,22 @@ std::enable_if_t check_pointer_and_stride( } \ ElementType *name = reinterpret_cast(from) +// Check whether the image size is acceptable by limiting it. +#define CHECK_IMAGE_SIZE(width, height) \ + do { \ + size_t image_size = 0; \ + if (__builtin_mul_overflow(width, height, &image_size)) { \ + return INTRINSICCV_ERROR_RANGE; \ + } \ + \ + if (image_size > INTRINSICCV_MAX_IMAGE_PIXELS) { \ + return INTRINSICCV_ERROR_RANGE; \ + } \ + } while (false) + +// Check whether the rectangle size is acceptable by limiting it. +#define CHECK_RECTANGLE_SIZE(rect) CHECK_IMAGE_SIZE(rect.width, rect.height) + } // namespace intrinsiccv #endif // INTRINSICCV_UTILS_H diff --git a/intrinsiccv/src/analysis/canny_neon.cpp b/intrinsiccv/src/analysis/canny_neon.cpp index f21095365..94b99d696 100644 --- a/intrinsiccv/src/analysis/canny_neon.cpp +++ b/intrinsiccv/src/analysis/canny_neon.cpp @@ -471,6 +471,7 @@ extern "C" INTRINSICCV_TARGET_FN_ATTRS intrinsiccv_error_t intrinsiccv_canny_u8( size_t width, size_t height, double low_threshold, double high_threshold) { CHECK_POINTER_AND_STRIDE(src, src_stride); CHECK_POINTER_AND_STRIDE(dst, dst_stride); + CHECK_IMAGE_SIZE(width, height); Rectangle dst_rect{width, height}; diff --git a/intrinsiccv/src/analysis/count_nonzeros_neon.cpp b/intrinsiccv/src/analysis/count_nonzeros_neon.cpp index e54f789cc..32c3b5418 100644 --- a/intrinsiccv/src/analysis/count_nonzeros_neon.cpp +++ b/intrinsiccv/src/analysis/count_nonzeros_neon.cpp @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: 2023 Arm Limited and/or its affiliates +// SPDX-FileCopyrightText: 2023 - 2024 Arm Limited and/or its affiliates // // SPDX-License-Identifier: Apache-2.0 @@ -56,6 +56,8 @@ INTRINSICCV_TARGET_FN_ATTRS static intrinsiccv_error_t count_nonzeros( size_t *count) { CHECK_POINTERS(count); CHECK_POINTER_AND_STRIDE(src, src_stride); + CHECK_IMAGE_SIZE(width, height); + Rectangle rect{width, height}; Rows src_rows{src, src_stride}; *count = neon::count_nonzeros_impl(src_rows, rect); diff --git a/intrinsiccv/src/analysis/min_max_loc_neon.cpp b/intrinsiccv/src/analysis/min_max_loc_neon.cpp index b88a5b714..99b355836 100644 --- a/intrinsiccv/src/analysis/min_max_loc_neon.cpp +++ b/intrinsiccv/src/analysis/min_max_loc_neon.cpp @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: 2023 Arm Limited and/or its affiliates +// SPDX-FileCopyrightText: 2023 - 2024 Arm Limited and/or its affiliates // // SPDX-License-Identifier: Apache-2.0 @@ -311,6 +311,7 @@ intrinsiccv_error_t min_max_loc(const ScalarType *src, size_t src_stride, size_t width, size_t height, size_t *min_offset, size_t *max_offset) { CHECK_POINTER_AND_STRIDE(src, src_stride); + CHECK_IMAGE_SIZE(width, height); Rectangle rect{width, height}; Rows src_rows{src, src_stride}; diff --git a/intrinsiccv/src/analysis/min_max_neon.cpp b/intrinsiccv/src/analysis/min_max_neon.cpp index a935f5a9f..8d9b45834 100644 --- a/intrinsiccv/src/analysis/min_max_neon.cpp +++ b/intrinsiccv/src/analysis/min_max_neon.cpp @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: 2023 Arm Limited and/or its affiliates +// SPDX-FileCopyrightText: 2023 - 2024 Arm Limited and/or its affiliates // // SPDX-License-Identifier: Apache-2.0 @@ -49,6 +49,8 @@ intrinsiccv_error_t min_max(const ScalarType *src, size_t src_stride, size_t width, size_t height, ScalarType *min_value, ScalarType *max_value) { CHECK_POINTER_AND_STRIDE(src, src_stride); + CHECK_IMAGE_SIZE(width, height); + Rectangle rect{width, height}; Rows src_rows{src, src_stride}; MinMax operation; diff --git a/intrinsiccv/src/arithmetics/absdiff_neon.cpp b/intrinsiccv/src/arithmetics/absdiff_neon.cpp index 5bcdabe52..43d3e7cd8 100644 --- a/intrinsiccv/src/arithmetics/absdiff_neon.cpp +++ b/intrinsiccv/src/arithmetics/absdiff_neon.cpp @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: 2023 Arm Limited and/or its affiliates +// SPDX-FileCopyrightText: 2023 - 2024 Arm Limited and/or its affiliates // // SPDX-License-Identifier: Apache-2.0 @@ -43,6 +43,7 @@ intrinsiccv_error_t saturating_absdiff(const T *src_a, size_t src_a_stride, CHECK_POINTER_AND_STRIDE(src_a, src_a_stride); CHECK_POINTER_AND_STRIDE(src_b, src_b_stride); CHECK_POINTER_AND_STRIDE(dst, dst_stride); + CHECK_IMAGE_SIZE(width, height); SaturatingAbsDiff operation; Rectangle rect{width, height}; diff --git a/intrinsiccv/src/arithmetics/absdiff_sme2.cpp b/intrinsiccv/src/arithmetics/absdiff_sme2.cpp index 9cae9c717..29895f1a0 100644 --- a/intrinsiccv/src/arithmetics/absdiff_sme2.cpp +++ b/intrinsiccv/src/arithmetics/absdiff_sme2.cpp @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: 2023 Arm Limited and/or its affiliates +// SPDX-FileCopyrightText: 2023 - 2024 Arm Limited and/or its affiliates // // SPDX-License-Identifier: Apache-2.0 @@ -43,6 +43,7 @@ INTRINSICCV_LOCALLY_STREAMING intrinsiccv_error_t saturating_absdiff( CHECK_POINTER_AND_STRIDE(src_a, src_a_stride); CHECK_POINTER_AND_STRIDE(src_b, src_b_stride); CHECK_POINTER_AND_STRIDE(dst, dst_stride); + CHECK_IMAGE_SIZE(width, height); SaturatingAbsDiff operation; Rectangle rect{width, height}; diff --git a/intrinsiccv/src/arithmetics/absdiff_sve2.cpp b/intrinsiccv/src/arithmetics/absdiff_sve2.cpp index 576919233..94753bd67 100644 --- a/intrinsiccv/src/arithmetics/absdiff_sve2.cpp +++ b/intrinsiccv/src/arithmetics/absdiff_sve2.cpp @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: 2023 Arm Limited and/or its affiliates +// SPDX-FileCopyrightText: 2023 - 2024 Arm Limited and/or its affiliates // // SPDX-License-Identifier: Apache-2.0 @@ -41,6 +41,7 @@ intrinsiccv_error_t saturating_absdiff(const T *src_a, size_t src_a_stride, CHECK_POINTER_AND_STRIDE(src_a, src_a_stride); CHECK_POINTER_AND_STRIDE(src_b, src_b_stride); CHECK_POINTER_AND_STRIDE(dst, dst_stride); + CHECK_IMAGE_SIZE(width, height); SaturatingAbsDiff operation; Rectangle rect{width, height}; diff --git a/intrinsiccv/src/arithmetics/add_abs_with_threshold_neon.cpp b/intrinsiccv/src/arithmetics/add_abs_with_threshold_neon.cpp index c7715587c..23ff6e9d8 100644 --- a/intrinsiccv/src/arithmetics/add_abs_with_threshold_neon.cpp +++ b/intrinsiccv/src/arithmetics/add_abs_with_threshold_neon.cpp @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: 2023 Arm Limited and/or its affiliates +// SPDX-FileCopyrightText: 2023 - 2024 Arm Limited and/or its affiliates // // SPDX-License-Identifier: Apache-2.0 @@ -54,6 +54,7 @@ intrinsiccv_error_t saturating_add_abs_with_threshold( CHECK_POINTER_AND_STRIDE(src_a, src_a_stride); CHECK_POINTER_AND_STRIDE(src_b, src_b_stride); CHECK_POINTER_AND_STRIDE(dst, dst_stride); + CHECK_IMAGE_SIZE(width, height); SaturatingAddAbsWithThreshold operation{threshold}; Rectangle rect{width, height}; diff --git a/intrinsiccv/src/arithmetics/add_abs_with_threshold_sc.h b/intrinsiccv/src/arithmetics/add_abs_with_threshold_sc.h index 2cc065065..b9d3176c2 100644 --- a/intrinsiccv/src/arithmetics/add_abs_with_threshold_sc.h +++ b/intrinsiccv/src/arithmetics/add_abs_with_threshold_sc.h @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: 2023 Arm Limited and/or its affiliates +// SPDX-FileCopyrightText: 2023 - 2024 Arm Limited and/or its affiliates // // SPDX-License-Identifier: Apache-2.0 @@ -42,6 +42,7 @@ intrinsiccv_error_t saturating_add_abs_with_threshold_sc( CHECK_POINTER_AND_STRIDE(src_a, src_a_stride); CHECK_POINTER_AND_STRIDE(src_b, src_b_stride); CHECK_POINTER_AND_STRIDE(dst, dst_stride); + CHECK_IMAGE_SIZE(width, height); SaturatingAddAbsWithThreshold operation{threshold}; Rectangle rect{width, height}; diff --git a/intrinsiccv/src/arithmetics/add_neon.cpp b/intrinsiccv/src/arithmetics/add_neon.cpp index d738e576a..c78ad5a89 100644 --- a/intrinsiccv/src/arithmetics/add_neon.cpp +++ b/intrinsiccv/src/arithmetics/add_neon.cpp @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: 2023 Arm Limited and/or its affiliates +// SPDX-FileCopyrightText: 2023 - 2024 Arm Limited and/or its affiliates // // SPDX-License-Identifier: Apache-2.0 @@ -42,6 +42,7 @@ intrinsiccv_error_t saturating_add(const T *src_a, size_t src_a_stride, CHECK_POINTER_AND_STRIDE(src_a, src_a_stride); CHECK_POINTER_AND_STRIDE(src_b, src_b_stride); CHECK_POINTER_AND_STRIDE(dst, dst_stride); + CHECK_IMAGE_SIZE(width, height); SaturatingAdd operation; Rectangle rect{width, height}; diff --git a/intrinsiccv/src/arithmetics/add_sme2.cpp b/intrinsiccv/src/arithmetics/add_sme2.cpp index af9a3d36d..11cc62908 100644 --- a/intrinsiccv/src/arithmetics/add_sme2.cpp +++ b/intrinsiccv/src/arithmetics/add_sme2.cpp @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: 2023 Arm Limited and/or its affiliates +// SPDX-FileCopyrightText: 2023 - 2024 Arm Limited and/or its affiliates // // SPDX-License-Identifier: Apache-2.0 @@ -29,6 +29,7 @@ INTRINSICCV_LOCALLY_STREAMING intrinsiccv_error_t saturating_add( CHECK_POINTER_AND_STRIDE(src_a, src_a_stride); CHECK_POINTER_AND_STRIDE(src_b, src_b_stride); CHECK_POINTER_AND_STRIDE(dst, dst_stride); + CHECK_IMAGE_SIZE(width, height); SaturatingAdd operation; Rectangle rect{width, height}; diff --git a/intrinsiccv/src/arithmetics/add_sve2.cpp b/intrinsiccv/src/arithmetics/add_sve2.cpp index 76b4073e3..dd37d6259 100644 --- a/intrinsiccv/src/arithmetics/add_sve2.cpp +++ b/intrinsiccv/src/arithmetics/add_sve2.cpp @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: 2023 Arm Limited and/or its affiliates +// SPDX-FileCopyrightText: 2023 - 2024 Arm Limited and/or its affiliates // // SPDX-License-Identifier: Apache-2.0 @@ -29,6 +29,7 @@ intrinsiccv_error_t saturating_add(const T *src_a, size_t src_a_stride, CHECK_POINTER_AND_STRIDE(src_a, src_a_stride); CHECK_POINTER_AND_STRIDE(src_b, src_b_stride); CHECK_POINTER_AND_STRIDE(dst, dst_stride); + CHECK_IMAGE_SIZE(width, height); SaturatingAdd operation; Rectangle rect{width, height}; diff --git a/intrinsiccv/src/arithmetics/multiply_neon.cpp b/intrinsiccv/src/arithmetics/multiply_neon.cpp index 5999c78c3..431e13716 100644 --- a/intrinsiccv/src/arithmetics/multiply_neon.cpp +++ b/intrinsiccv/src/arithmetics/multiply_neon.cpp @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: 2023 Arm Limited and/or its affiliates +// SPDX-FileCopyrightText: 2023 - 2024 Arm Limited and/or its affiliates // // SPDX-License-Identifier: Apache-2.0 @@ -70,6 +70,7 @@ intrinsiccv_error_t saturating_multiply(const T *src_a, size_t src_a_stride, CHECK_POINTER_AND_STRIDE(src_a, src_a_stride); CHECK_POINTER_AND_STRIDE(src_b, src_b_stride); CHECK_POINTER_AND_STRIDE(dst, dst_stride); + CHECK_IMAGE_SIZE(width, height); (void)scale; // TODO: figure out the way to process the scale. SaturatingMultiply operation; diff --git a/intrinsiccv/src/arithmetics/multiply_sve2.cpp b/intrinsiccv/src/arithmetics/multiply_sve2.cpp index 9a6c3f3a6..615dcd17a 100644 --- a/intrinsiccv/src/arithmetics/multiply_sve2.cpp +++ b/intrinsiccv/src/arithmetics/multiply_sve2.cpp @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: 2023 Arm Limited and/or its affiliates +// SPDX-FileCopyrightText: 2023 - 2024 Arm Limited and/or its affiliates // // SPDX-License-Identifier: Apache-2.0 @@ -48,6 +48,7 @@ intrinsiccv_error_t saturating_multiply(const T *src_a, size_t src_a_stride, CHECK_POINTER_AND_STRIDE(src_a, src_a_stride); CHECK_POINTER_AND_STRIDE(src_b, src_b_stride); CHECK_POINTER_AND_STRIDE(dst, dst_stride); + CHECK_IMAGE_SIZE(width, height); (void)scale; // TODO: figure out the way to process the scale. SaturatingMultiply operation; diff --git a/intrinsiccv/src/arithmetics/scale_neon.cpp b/intrinsiccv/src/arithmetics/scale_neon.cpp index 7ad8538e2..abc00b964 100644 --- a/intrinsiccv/src/arithmetics/scale_neon.cpp +++ b/intrinsiccv/src/arithmetics/scale_neon.cpp @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: 2023 Arm Limited and/or its affiliates +// SPDX-FileCopyrightText: 2023 - 2024 Arm Limited and/or its affiliates // // SPDX-License-Identifier: Apache-2.0 @@ -174,6 +174,7 @@ intrinsiccv_error_t scale(const T *src, size_t src_stride, T *dst, float scale, float shift) { CHECK_POINTER_AND_STRIDE(src, src_stride); CHECK_POINTER_AND_STRIDE(dst, dst_stride); + CHECK_IMAGE_SIZE(width, height); Rectangle rect{width, height}; Rows src_rows{src, src_stride}; diff --git a/intrinsiccv/src/arithmetics/sub_neon.cpp b/intrinsiccv/src/arithmetics/sub_neon.cpp index e673b8fd6..1310a28d1 100644 --- a/intrinsiccv/src/arithmetics/sub_neon.cpp +++ b/intrinsiccv/src/arithmetics/sub_neon.cpp @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: 2023 Arm Limited and/or its affiliates +// SPDX-FileCopyrightText: 2023 - 2024 Arm Limited and/or its affiliates // // SPDX-License-Identifier: Apache-2.0 @@ -42,6 +42,7 @@ intrinsiccv_error_t saturating_sub(const T *src_a, size_t src_a_stride, CHECK_POINTER_AND_STRIDE(src_a, src_a_stride); CHECK_POINTER_AND_STRIDE(src_b, src_b_stride); CHECK_POINTER_AND_STRIDE(dst, dst_stride); + CHECK_IMAGE_SIZE(width, height); SaturatingSub operation; Rectangle rect{width, height}; diff --git a/intrinsiccv/src/arithmetics/sub_sme2.cpp b/intrinsiccv/src/arithmetics/sub_sme2.cpp index 549969a3c..312b512f6 100644 --- a/intrinsiccv/src/arithmetics/sub_sme2.cpp +++ b/intrinsiccv/src/arithmetics/sub_sme2.cpp @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: 2023 Arm Limited and/or its affiliates +// SPDX-FileCopyrightText: 2023 - 2024 Arm Limited and/or its affiliates // // SPDX-License-Identifier: Apache-2.0 @@ -29,6 +29,7 @@ INTRINSICCV_LOCALLY_STREAMING intrinsiccv_error_t saturating_sub( CHECK_POINTER_AND_STRIDE(src_a, src_a_stride); CHECK_POINTER_AND_STRIDE(src_b, src_b_stride); CHECK_POINTER_AND_STRIDE(dst, dst_stride); + CHECK_IMAGE_SIZE(width, height); SaturatingSub operation; Rectangle rect{width, height}; diff --git a/intrinsiccv/src/arithmetics/sub_sve2.cpp b/intrinsiccv/src/arithmetics/sub_sve2.cpp index 7af4be3ce..c1aebeaaa 100644 --- a/intrinsiccv/src/arithmetics/sub_sve2.cpp +++ b/intrinsiccv/src/arithmetics/sub_sve2.cpp @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: 2023 Arm Limited and/or its affiliates +// SPDX-FileCopyrightText: 2023 - 2024 Arm Limited and/or its affiliates // // SPDX-License-Identifier: Apache-2.0 @@ -29,6 +29,7 @@ intrinsiccv_error_t saturating_sub(const T *src_a, size_t src_a_stride, CHECK_POINTER_AND_STRIDE(src_a, src_a_stride); CHECK_POINTER_AND_STRIDE(src_b, src_b_stride); CHECK_POINTER_AND_STRIDE(dst, dst_stride); + CHECK_IMAGE_SIZE(width, height); SaturatingSub operation; Rectangle rect{width, height}; diff --git a/intrinsiccv/src/arithmetics/threshold_neon.cpp b/intrinsiccv/src/arithmetics/threshold_neon.cpp index 4dea3c681..ceb8b0bb2 100644 --- a/intrinsiccv/src/arithmetics/threshold_neon.cpp +++ b/intrinsiccv/src/arithmetics/threshold_neon.cpp @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: 2023 Arm Limited and/or its affiliates +// SPDX-FileCopyrightText: 2023 - 2024 Arm Limited and/or its affiliates // // SPDX-License-Identifier: Apache-2.0 @@ -43,6 +43,7 @@ intrinsiccv_error_t threshold_binary(const T *src, size_t src_stride, T *dst, size_t height, T threshold, T value) { CHECK_POINTER_AND_STRIDE(src, src_stride); CHECK_POINTER_AND_STRIDE(dst, dst_stride); + CHECK_IMAGE_SIZE(width, height); Rectangle rect{width, height}; Rows src_rows{src, src_stride}; diff --git a/intrinsiccv/src/arithmetics/threshold_sc.h b/intrinsiccv/src/arithmetics/threshold_sc.h index 4a1a3862d..fba99cc6e 100644 --- a/intrinsiccv/src/arithmetics/threshold_sc.h +++ b/intrinsiccv/src/arithmetics/threshold_sc.h @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: 2023 Arm Limited and/or its affiliates +// SPDX-FileCopyrightText: 2023 - 2024 Arm Limited and/or its affiliates // // SPDX-License-Identifier: Apache-2.0 @@ -39,6 +39,7 @@ intrinsiccv_error_t threshold_binary_sc( size_t height, T threshold, T value) INTRINSICCV_STREAMING_COMPATIBLE { CHECK_POINTER_AND_STRIDE(src, src_stride); CHECK_POINTER_AND_STRIDE(dst, dst_stride); + CHECK_IMAGE_SIZE(width, height); Rectangle rect{width, height}; Rows src_rows{src, src_stride}; diff --git a/intrinsiccv/src/arithmetics/transpose_neon.cpp b/intrinsiccv/src/arithmetics/transpose_neon.cpp index a793ad4b7..736300d18 100644 --- a/intrinsiccv/src/arithmetics/transpose_neon.cpp +++ b/intrinsiccv/src/arithmetics/transpose_neon.cpp @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: 2023 Arm Limited and/or its affiliates +// SPDX-FileCopyrightText: 2023 - 2024 Arm Limited and/or its affiliates // // SPDX-License-Identifier: Apache-2.0 @@ -204,6 +204,7 @@ static intrinsiccv_error_t transpose(const void *src_void, size_t src_stride, MAKE_POINTER_CHECK_ALIGNMENT(T, dst, dst_void); CHECK_POINTER_AND_STRIDE(src, src_stride); CHECK_POINTER_AND_STRIDE(dst, dst_stride); + CHECK_IMAGE_SIZE(src_width, src_height); Rectangle rect{src_width, src_height}; Rows dst_rows{dst, dst_stride}; diff --git a/intrinsiccv/src/conversions/gray_to_rgb_neon.cpp b/intrinsiccv/src/conversions/gray_to_rgb_neon.cpp index 7fc5833b9..235836a51 100644 --- a/intrinsiccv/src/conversions/gray_to_rgb_neon.cpp +++ b/intrinsiccv/src/conversions/gray_to_rgb_neon.cpp @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: 2023 Arm Limited and/or its affiliates +// SPDX-FileCopyrightText: 2023 - 2024 Arm Limited and/or its affiliates // // SPDX-License-Identifier: Apache-2.0 @@ -110,6 +110,8 @@ intrinsiccv_error_t gray_to_rgb_u8(const uint8_t *src, size_t src_stride, size_t width, size_t height) { CHECK_POINTER_AND_STRIDE(src, src_stride); CHECK_POINTER_AND_STRIDE(dst, dst_stride); + CHECK_IMAGE_SIZE(width, height); + Rectangle rect{width, height}; Rows src_rows{src, src_stride}; Rows dst_rows{dst, dst_stride, 3 /* RGB */}; @@ -124,6 +126,8 @@ intrinsiccv_error_t gray_to_rgba_u8(const uint8_t *src, size_t src_stride, size_t width, size_t height) { CHECK_POINTER_AND_STRIDE(src, src_stride); CHECK_POINTER_AND_STRIDE(dst, dst_stride); + CHECK_IMAGE_SIZE(width, height); + Rectangle rect{width, height}; Rows src_rows{src, src_stride}; Rows dst_rows{dst, dst_stride, 4 /* RGBA */}; diff --git a/intrinsiccv/src/conversions/gray_to_rgb_sc.h b/intrinsiccv/src/conversions/gray_to_rgb_sc.h index b0d5fadb5..00fd0696d 100644 --- a/intrinsiccv/src/conversions/gray_to_rgb_sc.h +++ b/intrinsiccv/src/conversions/gray_to_rgb_sc.h @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: 2023 Arm Limited and/or its affiliates +// SPDX-FileCopyrightText: 2023 - 2024 Arm Limited and/or its affiliates // // SPDX-License-Identifier: Apache-2.0 @@ -201,6 +201,8 @@ INTRINSICCV_TARGET_FN_ATTRS static intrinsiccv_error_t gray_to_rgb_u8_sc( size_t width, size_t height) INTRINSICCV_STREAMING_COMPATIBLE { CHECK_POINTER_AND_STRIDE(src, src_stride); CHECK_POINTER_AND_STRIDE(dst, dst_stride); + CHECK_IMAGE_SIZE(width, height); + Rectangle rect{width, height}; Rows src_rows{src, src_stride}; Rows dst_rows{dst, dst_stride, 3 /* RGB */}; @@ -219,6 +221,8 @@ INTRINSICCV_TARGET_FN_ATTRS static intrinsiccv_error_t gray_to_rgba_u8_sc( size_t width, size_t height) INTRINSICCV_STREAMING_COMPATIBLE { CHECK_POINTER_AND_STRIDE(src, src_stride); CHECK_POINTER_AND_STRIDE(dst, dst_stride); + CHECK_IMAGE_SIZE(width, height); + Rectangle rect{width, height}; Rows src_rows{src, src_stride}; Rows dst_rows{dst, dst_stride, 4 /* RGBA */}; diff --git a/intrinsiccv/src/conversions/merge_neon.cpp b/intrinsiccv/src/conversions/merge_neon.cpp index 3d15e9fc0..41402fbaf 100644 --- a/intrinsiccv/src/conversions/merge_neon.cpp +++ b/intrinsiccv/src/conversions/merge_neon.cpp @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: 2023 Arm Limited and/or its affiliates +// SPDX-FileCopyrightText: 2023 - 2024 Arm Limited and/or its affiliates // // SPDX-License-Identifier: Apache-2.0 @@ -383,6 +383,7 @@ intrinsiccv_error_t merge(const void **srcs, const size_t *src_strides, CHECK_POINTER_AND_STRIDE(src0, src_strides[0]); CHECK_POINTER_AND_STRIDE(src1, src_strides[1]); CHECK_POINTER_AND_STRIDE(dst, dst_stride); + CHECK_IMAGE_SIZE(width, height); Rectangle rect{width, height}; Rows src_a_rows{src0, src_strides[0]}; diff --git a/intrinsiccv/src/conversions/rgb_to_rgb_api.cpp b/intrinsiccv/src/conversions/rgb_to_rgb_api.cpp index ecf63bdec..8f2906f4d 100644 --- a/intrinsiccv/src/conversions/rgb_to_rgb_api.cpp +++ b/intrinsiccv/src/conversions/rgb_to_rgb_api.cpp @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: 2023 Arm Limited and/or its affiliates +// SPDX-FileCopyrightText: 2023 - 2024 Arm Limited and/or its affiliates // // SPDX-License-Identifier: Apache-2.0 @@ -31,6 +31,8 @@ intrinsiccv_error_t intrinsiccv_rgb_to_rgb_u8(const uint8_t *src, size_t height) { CHECK_POINTER_AND_STRIDE(src, src_stride); CHECK_POINTER_AND_STRIDE(dst, dst_stride); + CHECK_IMAGE_SIZE(width, height); + Rectangle rect{width, height}; Rows src_rows{src, src_stride, 3 /* RGB */}; Rows dst_rows{dst, dst_stride, 3 /* BGR */}; @@ -44,6 +46,8 @@ intrinsiccv_error_t intrinsiccv_rgba_to_rgba_u8(const uint8_t *src, size_t height) { CHECK_POINTER_AND_STRIDE(src, src_stride); CHECK_POINTER_AND_STRIDE(dst, dst_stride); + CHECK_IMAGE_SIZE(width, height); + Rectangle rect{width, height}; Rows src_rows{src, src_stride, 4 /* RGBA */}; Rows dst_rows{dst, dst_stride, 4 /* RGBA */}; diff --git a/intrinsiccv/src/conversions/rgb_to_rgb_neon.cpp b/intrinsiccv/src/conversions/rgb_to_rgb_neon.cpp index 75b75f1c3..401abbc8c 100644 --- a/intrinsiccv/src/conversions/rgb_to_rgb_neon.cpp +++ b/intrinsiccv/src/conversions/rgb_to_rgb_neon.cpp @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: 2023 Arm Limited and/or its affiliates +// SPDX-FileCopyrightText: 2023 - 2024 Arm Limited and/or its affiliates // // SPDX-License-Identifier: Apache-2.0 @@ -193,6 +193,8 @@ intrinsiccv_error_t rgb_to_bgr_u8(const uint8_t *src, size_t src_stride, size_t height) { CHECK_POINTER_AND_STRIDE(src, src_stride); CHECK_POINTER_AND_STRIDE(dst, dst_stride); + CHECK_IMAGE_SIZE(width, height); + Rectangle rect{width, height}; Rows src_rows{src, src_stride, 3 /* RGB */}; Rows dst_rows{dst, dst_stride, 3 /* BGR */}; @@ -207,6 +209,8 @@ intrinsiccv_error_t rgba_to_bgra_u8(const uint8_t *src, size_t src_stride, size_t width, size_t height) { CHECK_POINTER_AND_STRIDE(src, src_stride); CHECK_POINTER_AND_STRIDE(dst, dst_stride); + CHECK_IMAGE_SIZE(width, height); + Rectangle rect{width, height}; Rows src_rows{src, src_stride, 4 /* RGBA */}; Rows dst_rows{dst, dst_stride, 4 /* BGRA */}; @@ -220,6 +224,8 @@ rgb_to_bgra_u8(const uint8_t *src, size_t src_stride, uint8_t *dst, size_t dst_stride, size_t width, size_t height) { CHECK_POINTER_AND_STRIDE(src, src_stride); CHECK_POINTER_AND_STRIDE(dst, dst_stride); + CHECK_IMAGE_SIZE(width, height); + Rectangle rect{width, height}; Rows src_rows{src, src_stride, 3 /* RGB */}; Rows dst_rows{dst, dst_stride, 4 /* BGRA */}; @@ -233,6 +239,8 @@ rgb_to_rgba_u8(const uint8_t *src, size_t src_stride, uint8_t *dst, size_t dst_stride, size_t width, size_t height) { CHECK_POINTER_AND_STRIDE(src, src_stride); CHECK_POINTER_AND_STRIDE(dst, dst_stride); + CHECK_IMAGE_SIZE(width, height); + Rectangle rect{width, height}; Rows src_rows{src, src_stride, 3 /* RGB */}; Rows dst_rows{dst, dst_stride, 4 /* RGBA */}; @@ -247,6 +255,8 @@ intrinsiccv_error_t rgba_to_bgr_u8(const uint8_t *src, size_t src_stride, size_t width, size_t height) { CHECK_POINTER_AND_STRIDE(src, src_stride); CHECK_POINTER_AND_STRIDE(dst, dst_stride); + CHECK_IMAGE_SIZE(width, height); + Rectangle rect{width, height}; Rows src_rows{src, src_stride, 4 /* RGBA */}; Rows dst_rows{dst, dst_stride, 3 /* BGR */}; @@ -261,6 +271,8 @@ intrinsiccv_error_t rgba_to_rgb_u8(const uint8_t *src, size_t src_stride, size_t width, size_t height) { CHECK_POINTER_AND_STRIDE(src, src_stride); CHECK_POINTER_AND_STRIDE(dst, dst_stride); + CHECK_IMAGE_SIZE(width, height); + Rectangle rect{width, height}; Rows src_rows{src, src_stride, 4 /* RGBA */}; Rows dst_rows{dst, dst_stride, 3 /* RGB */}; diff --git a/intrinsiccv/src/conversions/rgb_to_rgb_sc.h b/intrinsiccv/src/conversions/rgb_to_rgb_sc.h index ad06c5edb..864cbe578 100644 --- a/intrinsiccv/src/conversions/rgb_to_rgb_sc.h +++ b/intrinsiccv/src/conversions/rgb_to_rgb_sc.h @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: 2023 Arm Limited and/or its affiliates +// SPDX-FileCopyrightText: 2023 - 2024 Arm Limited and/or its affiliates // // SPDX-License-Identifier: Apache-2.0 @@ -186,6 +186,8 @@ INTRINSICCV_TARGET_FN_ATTRS static intrinsiccv_error_t rgb_to_bgr_u8_sc( size_t width, size_t height) INTRINSICCV_STREAMING_COMPATIBLE { CHECK_POINTER_AND_STRIDE(src, src_stride); CHECK_POINTER_AND_STRIDE(dst, dst_stride); + CHECK_IMAGE_SIZE(width, height); + Rectangle rect{width, height}; Rows src_rows{src, src_stride, 3 /* RGB */}; Rows dst_rows{dst, dst_stride, 3 /* BGR */}; @@ -205,6 +207,8 @@ static intrinsiccv_error_t rgba_to_bgra_u8_sc( size_t width, size_t height) INTRINSICCV_STREAMING_COMPATIBLE { CHECK_POINTER_AND_STRIDE(src, src_stride); CHECK_POINTER_AND_STRIDE(dst, dst_stride); + CHECK_IMAGE_SIZE(width, height); + Rectangle rect{width, height}; Rows src_rows{src, src_stride, 4 /* RGBA */}; Rows dst_rows{dst, dst_stride, 4 /* BGRA */}; @@ -219,6 +223,8 @@ static intrinsiccv_error_t rgb_to_bgra_u8_sc( size_t width, size_t height) INTRINSICCV_STREAMING_COMPATIBLE { CHECK_POINTER_AND_STRIDE(src, src_stride); CHECK_POINTER_AND_STRIDE(dst, dst_stride); + CHECK_IMAGE_SIZE(width, height); + Rectangle rect{width, height}; Rows src_rows{src, src_stride, 3 /* RGB */}; Rows dst_rows{dst, dst_stride, 4 /* BGRA */}; @@ -233,6 +239,8 @@ static intrinsiccv_error_t rgb_to_rgba_u8_sc( size_t width, size_t height) INTRINSICCV_STREAMING_COMPATIBLE { CHECK_POINTER_AND_STRIDE(src, src_stride); CHECK_POINTER_AND_STRIDE(dst, dst_stride); + CHECK_IMAGE_SIZE(width, height); + Rectangle rect{width, height}; Rows src_rows{src, src_stride, 3 /* RGB */}; Rows dst_rows{dst, dst_stride, 4 /* RGBA */}; @@ -247,6 +255,8 @@ static intrinsiccv_error_t rgba_to_bgr_u8_sc( size_t width, size_t height) INTRINSICCV_STREAMING_COMPATIBLE { CHECK_POINTER_AND_STRIDE(src, src_stride); CHECK_POINTER_AND_STRIDE(dst, dst_stride); + CHECK_IMAGE_SIZE(width, height); + Rectangle rect{width, height}; Rows src_rows{src, src_stride, 4 /* RGBA */}; Rows dst_rows{dst, dst_stride, 3 /* BGR */}; @@ -261,6 +271,8 @@ static intrinsiccv_error_t rgba_to_rgb_u8_sc( size_t width, size_t height) INTRINSICCV_STREAMING_COMPATIBLE { CHECK_POINTER_AND_STRIDE(src, src_stride); CHECK_POINTER_AND_STRIDE(dst, dst_stride); + CHECK_IMAGE_SIZE(width, height); + Rectangle rect{width, height}; Rows src_rows{src, src_stride, 4 /* RGBA */}; Rows dst_rows{dst, dst_stride, 3 /* RGB */}; diff --git a/intrinsiccv/src/conversions/split_neon.cpp b/intrinsiccv/src/conversions/split_neon.cpp index 9fa8d4ab2..b0d7aeeec 100644 --- a/intrinsiccv/src/conversions/split_neon.cpp +++ b/intrinsiccv/src/conversions/split_neon.cpp @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: 2023 Arm Limited and/or its affiliates +// SPDX-FileCopyrightText: 2023 - 2024 Arm Limited and/or its affiliates // // SPDX-License-Identifier: Apache-2.0 @@ -269,6 +269,7 @@ intrinsiccv_error_t split(const void *src_void, const size_t src_stride, CHECK_POINTER_AND_STRIDE(src_data, src_stride); CHECK_POINTER_AND_STRIDE(dst0, dst_strides[0]); CHECK_POINTER_AND_STRIDE(dst1, dst_strides[1]); + CHECK_IMAGE_SIZE(width, height); Rectangle rect{width, height}; Rows src_rows{const_cast(src_data), src_stride, diff --git a/intrinsiccv/src/conversions/yuv_to_rgb_neon.cpp b/intrinsiccv/src/conversions/yuv_to_rgb_neon.cpp index 2ba481906..0b6102b88 100644 --- a/intrinsiccv/src/conversions/yuv_to_rgb_neon.cpp +++ b/intrinsiccv/src/conversions/yuv_to_rgb_neon.cpp @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: 2023 Arm Limited and/or its affiliates +// SPDX-FileCopyrightText: 2023 - 2024 Arm Limited and/or its affiliates // // SPDX-License-Identifier: Apache-2.0 @@ -295,6 +295,8 @@ intrinsiccv_error_t yuv2rgbx_operation( CHECK_POINTER_AND_STRIDE(src_y, src_y_stride); CHECK_POINTER_AND_STRIDE(src_uv, src_uv_stride); CHECK_POINTER_AND_STRIDE(dst, dst_stride); + CHECK_IMAGE_SIZE(width, height); + Rectangle rect{width, height}; ParallelRows y_rows{src_y, src_y_stride}; Rows uv_rows{src_uv, src_uv_stride}; diff --git a/intrinsiccv/src/conversions/yuv_to_rgb_sc.h b/intrinsiccv/src/conversions/yuv_to_rgb_sc.h index a7c7b4133..5d935ca95 100644 --- a/intrinsiccv/src/conversions/yuv_to_rgb_sc.h +++ b/intrinsiccv/src/conversions/yuv_to_rgb_sc.h @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: 2023 Arm Limited and/or its affiliates +// SPDX-FileCopyrightText: 2023 - 2024 Arm Limited and/or its affiliates // // SPDX-License-Identifier: Apache-2.0 @@ -196,6 +196,8 @@ intrinsiccv_error_t yuv2rgbx_operation( CHECK_POINTER_AND_STRIDE(src_y, src_y_stride); CHECK_POINTER_AND_STRIDE(src_uv, src_uv_stride); CHECK_POINTER_AND_STRIDE(dst, dst_stride); + CHECK_IMAGE_SIZE(width, height); + Rectangle rect{width, height}; ParallelRows y_rows{src_y, src_y_stride}; Rows uv_rows{src_uv, src_uv_stride}; diff --git a/intrinsiccv/src/filters/gaussian_blur_api.cpp b/intrinsiccv/src/filters/gaussian_blur_api.cpp index 0db22f4e2..2f922939d 100644 --- a/intrinsiccv/src/filters/gaussian_blur_api.cpp +++ b/intrinsiccv/src/filters/gaussian_blur_api.cpp @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: 2023 Arm Limited and/or its affiliates +// SPDX-FileCopyrightText: 2023 - 2024 Arm Limited and/or its affiliates // // SPDX-License-Identifier: Apache-2.0 @@ -15,6 +15,8 @@ intrinsiccv_error_t intrinsiccv_filter_create( intrinsiccv_filter_context_t **context, size_t channels, size_t type_size, intrinsiccv_rectangle_t image) { CHECK_POINTERS(context); + CHECK_RECTANGLE_SIZE(image); + auto workspace = SeparableFilterWorkspace::create(Rectangle{image}, channels, type_size); if (!workspace) { diff --git a/intrinsiccv/src/filters/gaussian_blur_neon.cpp b/intrinsiccv/src/filters/gaussian_blur_neon.cpp index 7659cabca..6f1567345 100644 --- a/intrinsiccv/src/filters/gaussian_blur_neon.cpp +++ b/intrinsiccv/src/filters/gaussian_blur_neon.cpp @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: 2023 Arm Limited and/or its affiliates +// SPDX-FileCopyrightText: 2023 - 2024 Arm Limited and/or its affiliates // // SPDX-License-Identifier: Apache-2.0 @@ -153,6 +153,7 @@ intrinsiccv_error_t discrete_gaussian_blur( CHECK_POINTERS(context); CHECK_POINTER_AND_STRIDE(src, src_stride); CHECK_POINTER_AND_STRIDE(dst, dst_stride); + CHECK_IMAGE_SIZE(width, height); Rectangle rect{width, height}; Rows src_rows{src, src_stride, channels}; diff --git a/intrinsiccv/src/filters/gaussian_blur_sc.h b/intrinsiccv/src/filters/gaussian_blur_sc.h index be87e4671..9ab684f23 100644 --- a/intrinsiccv/src/filters/gaussian_blur_sc.h +++ b/intrinsiccv/src/filters/gaussian_blur_sc.h @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: 2023 Arm Limited and/or its affiliates +// SPDX-FileCopyrightText: 2023 - 2024 Arm Limited and/or its affiliates // // SPDX-License-Identifier: Apache-2.0 @@ -93,6 +93,7 @@ intrinsiccv_error_t discrete_gaussian_blur( CHECK_POINTERS(context); CHECK_POINTER_AND_STRIDE(src, src_stride); CHECK_POINTER_AND_STRIDE(dst, dst_stride); + CHECK_IMAGE_SIZE(width, height); Rectangle rect{width, height}; Rows src_rows{src, src_stride, channels}; diff --git a/intrinsiccv/src/filters/sobel_neon.cpp b/intrinsiccv/src/filters/sobel_neon.cpp index 4ceb9def8..e5c26d41c 100644 --- a/intrinsiccv/src/filters/sobel_neon.cpp +++ b/intrinsiccv/src/filters/sobel_neon.cpp @@ -134,6 +134,7 @@ intrinsiccv_error_t sobel_3x3_horizontal_s16_u8(const uint8_t *src, size_t channels) { CHECK_POINTER_AND_STRIDE(src, src_stride); CHECK_POINTER_AND_STRIDE(dst, dst_stride); + CHECK_IMAGE_SIZE(width, height); Rectangle rect{width, height}; Rows src_rows{src, src_stride, channels}; @@ -159,6 +160,7 @@ intrinsiccv_error_t sobel_3x3_vertical_s16_u8(const uint8_t *src, size_t height, size_t channels) { CHECK_POINTER_AND_STRIDE(src, src_stride); CHECK_POINTER_AND_STRIDE(dst, dst_stride); + CHECK_IMAGE_SIZE(width, height); Rectangle rect{width, height}; Rows src_rows{src, src_stride, channels}; diff --git a/intrinsiccv/src/filters/sobel_sc.h b/intrinsiccv/src/filters/sobel_sc.h index 493c38163..77c3e5564 100644 --- a/intrinsiccv/src/filters/sobel_sc.h +++ b/intrinsiccv/src/filters/sobel_sc.h @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: 2023 Arm Limited and/or its affiliates +// SPDX-FileCopyrightText: 2023 - 2024 Arm Limited and/or its affiliates // // SPDX-License-Identifier: Apache-2.0 @@ -124,6 +124,7 @@ static intrinsiccv_error_t sobel_3x3_horizontal_s16_u8_sc( size_t channels) INTRINSICCV_STREAMING_COMPATIBLE { CHECK_POINTER_AND_STRIDE(src, src_stride); CHECK_POINTER_AND_STRIDE(dst, dst_stride); + CHECK_IMAGE_SIZE(width, height); Rectangle rect{width, height}; Rows src_rows{src, src_stride, channels}; @@ -150,6 +151,7 @@ static intrinsiccv_error_t sobel_3x3_vertical_s16_u8_sc( size_t channels) INTRINSICCV_STREAMING_COMPATIBLE { CHECK_POINTER_AND_STRIDE(src, src_stride); CHECK_POINTER_AND_STRIDE(dst, dst_stride); + CHECK_IMAGE_SIZE(width, height); Rectangle rect{width, height}; Rows src_rows{src, src_stride, channels}; diff --git a/intrinsiccv/src/morphology/morphology_api.cpp b/intrinsiccv/src/morphology/morphology_api.cpp index 05bd288d7..83fd156b4 100644 --- a/intrinsiccv/src/morphology/morphology_api.cpp +++ b/intrinsiccv/src/morphology/morphology_api.cpp @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: 2023 Arm Limited and/or its affiliates +// SPDX-FileCopyrightText: 2023 - 2024 Arm Limited and/or its affiliates // // SPDX-License-Identifier: Apache-2.0 @@ -58,6 +58,8 @@ intrinsiccv_error_t intrinsiccv_morphology_create( intrinsiccv_border_values_t border_values, size_t channels, size_t iterations, size_t type_size, intrinsiccv_rectangle_t image) { CHECK_POINTERS(context); + CHECK_RECTANGLE_SIZE(kernel); + CHECK_RECTANGLE_SIZE(image); auto morphology_border_type = MorphologyWorkspace::get_border_type(border_type); @@ -70,7 +72,6 @@ intrinsiccv_error_t intrinsiccv_morphology_create( kernel, anchor, *morphology_border_type, border_values, channels, iterations, type_size, image); if (!workspace) { - *context = nullptr; return INTRINSICCV_ERROR_ALLOCATION; } diff --git a/intrinsiccv/src/morphology/morphology_neon.cpp b/intrinsiccv/src/morphology/morphology_neon.cpp index bccce645b..21af80cd1 100644 --- a/intrinsiccv/src/morphology/morphology_neon.cpp +++ b/intrinsiccv/src/morphology/morphology_neon.cpp @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: 2023 Arm Limited and/or its affiliates +// SPDX-FileCopyrightText: 2023 - 2024 Arm Limited and/or its affiliates // // SPDX-License-Identifier: Apache-2.0 @@ -493,6 +493,7 @@ intrinsiccv_error_t dilate(const T *src, size_t src_stride, T *dst, CHECK_POINTERS(context); CHECK_POINTER_AND_STRIDE(src, src_stride); CHECK_POINTER_AND_STRIDE(dst, dst_stride); + CHECK_IMAGE_SIZE(width, height); auto *workspace = reinterpret_cast(context); @@ -548,6 +549,7 @@ intrinsiccv_error_t erode(const T *src, size_t src_stride, T *dst, CHECK_POINTERS(context); CHECK_POINTER_AND_STRIDE(src, src_stride); CHECK_POINTER_AND_STRIDE(dst, dst_stride); + CHECK_IMAGE_SIZE(width, height); auto *workspace = reinterpret_cast(context); diff --git a/intrinsiccv/src/morphology/morphology_sc.h b/intrinsiccv/src/morphology/morphology_sc.h index 39dd7d0a5..d49a3da76 100644 --- a/intrinsiccv/src/morphology/morphology_sc.h +++ b/intrinsiccv/src/morphology/morphology_sc.h @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: 2023 Arm Limited and/or its affiliates +// SPDX-FileCopyrightText: 2023 - 2024 Arm Limited and/or its affiliates // // SPDX-License-Identifier: Apache-2.0 @@ -456,6 +456,7 @@ static intrinsiccv_error_t dilate_sc(const T *src, size_t src_stride, T *dst, CHECK_POINTERS(context); CHECK_POINTER_AND_STRIDE(src, src_stride); CHECK_POINTER_AND_STRIDE(dst, dst_stride); + CHECK_IMAGE_SIZE(width, height); auto *workspace = reinterpret_cast(context); @@ -516,6 +517,7 @@ static intrinsiccv_error_t erode_sc(const T *src, size_t src_stride, T *dst, CHECK_POINTERS(context); CHECK_POINTER_AND_STRIDE(src, src_stride); CHECK_POINTER_AND_STRIDE(dst, dst_stride); + CHECK_IMAGE_SIZE(width, height); auto *workspace = reinterpret_cast(context); diff --git a/intrinsiccv/src/resize/resize_neon.cpp b/intrinsiccv/src/resize/resize_neon.cpp index da3c7787a..55c5e7317 100644 --- a/intrinsiccv/src/resize/resize_neon.cpp +++ b/intrinsiccv/src/resize/resize_neon.cpp @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: 2023 Arm Limited and/or its affiliates +// SPDX-FileCopyrightText: 2023 - 2024 Arm Limited and/or its affiliates // // SPDX-License-Identifier: Apache-2.0 @@ -8,13 +8,52 @@ namespace intrinsiccv::neon { +INTRINSICCV_TARGET_FN_ATTRS +static intrinsiccv_error_t check_dimensions(size_t src_dim, size_t dst_dim) { + size_t half_src_dim = src_dim / 2; + + if ((src_dim % 2) == 0) { + if (dst_dim == half_src_dim) { + return INTRINSICCV_OK; + } + } else { + if (dst_dim == half_src_dim || dst_dim == (half_src_dim + 1)) { + return INTRINSICCV_OK; + } + } + + return INTRINSICCV_ERROR_RANGE; +} + +INTRINSICCV_TARGET_FN_ATTRS +static intrinsiccv_error_t check_resize_args( + const uint8_t *src, size_t src_stride, size_t src_width, size_t src_height, + uint8_t *dst, size_t dst_stride, size_t dst_width, size_t dst_height) { + CHECK_POINTER_AND_STRIDE(src, src_stride); + CHECK_POINTER_AND_STRIDE(dst, dst_stride); + CHECK_IMAGE_SIZE(src_width, src_height); + + if (intrinsiccv_error_t ret = check_dimensions(src_width, dst_width)) { + return ret; + } + + if (intrinsiccv_error_t ret = check_dimensions(src_height, dst_height)) { + return ret; + } + + return INTRINSICCV_OK; +} + INTRINSICCV_TARGET_FN_ATTRS intrinsiccv_error_t resize_to_quarter_u8(const uint8_t *src, size_t src_stride, size_t src_width, size_t src_height, uint8_t *dst, size_t dst_stride, size_t dst_width, size_t dst_height) { - CHECK_POINTER_AND_STRIDE(src, src_stride); - CHECK_POINTER_AND_STRIDE(dst, dst_stride); + if (intrinsiccv_error_t ret = + check_resize_args(src, src_stride, src_width, src_height, dst, + dst_stride, dst_width, dst_height)) { + return ret; + } for (; src_height >= 2; src_height -= 2, src += (src_stride * 2), --dst_height, dst += dst_stride) { diff --git a/intrinsiccv/src/resize/resize_sc.h b/intrinsiccv/src/resize/resize_sc.h index b46cc5600..8c881010f 100644 --- a/intrinsiccv/src/resize/resize_sc.h +++ b/intrinsiccv/src/resize/resize_sc.h @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: 2023 Arm Limited and/or its affiliates +// SPDX-FileCopyrightText: 2023 - 2024 Arm Limited and/or its affiliates // // SPDX-License-Identifier: Apache-2.0 @@ -139,12 +139,39 @@ static inline void process_single_row( } } +INTRINSICCV_TARGET_FN_ATTRS +static intrinsiccv_error_t check_dimensions(size_t src_dim, size_t dst_dim) + INTRINSICCV_STREAMING_COMPATIBLE { + size_t half_src_dim = src_dim / 2; + + if ((src_dim % 2) == 0) { + if (dst_dim == half_src_dim) { + return INTRINSICCV_OK; + } + } else { + if (dst_dim == half_src_dim || dst_dim == (half_src_dim + 1)) { + return INTRINSICCV_OK; + } + } + + return INTRINSICCV_ERROR_RANGE; +} + INTRINSICCV_TARGET_FN_ATTRS static intrinsiccv_error_t resize_to_quarter_u8_sc( const uint8_t *src, size_t src_stride, size_t src_width, size_t src_height, uint8_t *dst, size_t dst_stride, size_t dst_width, size_t dst_height) INTRINSICCV_STREAMING_COMPATIBLE { CHECK_POINTER_AND_STRIDE(src, src_stride); CHECK_POINTER_AND_STRIDE(dst, dst_stride); + CHECK_IMAGE_SIZE(src_width, src_height); + + if (intrinsiccv_error_t ret = check_dimensions(src_width, dst_width)) { + return ret; + } + + if (intrinsiccv_error_t ret = check_dimensions(src_height, dst_height)) { + return ret; + } Rows src_rows{src, src_stride, /* channels*/ 1}; Rows dst_rows{dst, dst_stride, /* channels*/ 1}; diff --git a/test/api/test_add_abs_with_threshold.cpp b/test/api/test_add_abs_with_threshold.cpp index eabab027d..384657090 100644 --- a/test/api/test_add_abs_with_threshold.cpp +++ b/test/api/test_add_abs_with_threshold.cpp @@ -176,3 +176,16 @@ TYPED_TEST(SaturatingAddAbsWithThresholdTest, Misalignment) { src, sizeof(TypeParam), src, sizeof(TypeParam), dst, sizeof(TypeParam) + 1, 1, 1, 1)); } + +TYPED_TEST(SaturatingAddAbsWithThresholdTest, ImageSize) { + TypeParam src[1], dst[1]; + EXPECT_EQ(INTRINSICCV_ERROR_RANGE, + intrinsiccv_saturating_add_abs_with_threshold_s16( + src, sizeof(TypeParam), src, sizeof(TypeParam), dst, + sizeof(TypeParam), INTRINSICCV_MAX_IMAGE_PIXELS + 1, 1, 1)); + EXPECT_EQ(INTRINSICCV_ERROR_RANGE, + intrinsiccv_saturating_add_abs_with_threshold_s16( + src, sizeof(TypeParam), src, sizeof(TypeParam), dst, + sizeof(TypeParam), INTRINSICCV_MAX_IMAGE_PIXELS, + INTRINSICCV_MAX_IMAGE_PIXELS, 1)); +} diff --git a/test/api/test_canny.cpp b/test/api/test_canny.cpp index 65c3c90c6..71b23c81d 100644 --- a/test/api/test_canny.cpp +++ b/test/api/test_canny.cpp @@ -38,3 +38,14 @@ TYPED_TEST(CannyTest, Misalignment) { canny()(src, sizeof(TypeParam), dst, sizeof(TypeParam) + 1, 1, 1, 0.0, 1.0)); } + +TYPED_TEST(CannyTest, ImageSize) { + TypeParam src[1], dst[1]; + EXPECT_EQ(INTRINSICCV_ERROR_RANGE, + canny()(src, sizeof(TypeParam), dst, sizeof(TypeParam), + INTRINSICCV_MAX_IMAGE_PIXELS + 1, 1, 0.0, 1.0)); + EXPECT_EQ(INTRINSICCV_ERROR_RANGE, + canny()(src, sizeof(TypeParam), dst, sizeof(TypeParam), + INTRINSICCV_MAX_IMAGE_PIXELS, + INTRINSICCV_MAX_IMAGE_PIXELS, 0.0, 1.0)); +} diff --git a/test/api/test_count_nonzeros.cpp b/test/api/test_count_nonzeros.cpp index 35d15a0f5..077622777 100644 --- a/test/api/test_count_nonzeros.cpp +++ b/test/api/test_count_nonzeros.cpp @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: 2023 Arm Limited and/or its affiliates +// SPDX-FileCopyrightText: 2023 - 2024 Arm Limited and/or its affiliates // // SPDX-License-Identifier: Apache-2.0 @@ -129,3 +129,16 @@ TYPED_TEST(CountNonZeros, Misalignment) { INTRINSICCV_ERROR_ALIGNMENT, count_nonzeros()(src, sizeof(TypeParam) + 1, 1, 1, &count)); } + +TYPED_TEST(CountNonZeros, ImageSize) { + TypeParam src[1]; + size_t count = 0; + EXPECT_EQ( + INTRINSICCV_ERROR_RANGE, + count_nonzeros()(src, sizeof(TypeParam), + INTRINSICCV_MAX_IMAGE_PIXELS + 1, 1, &count)); + EXPECT_EQ(INTRINSICCV_ERROR_RANGE, + count_nonzeros()(src, sizeof(TypeParam), + INTRINSICCV_MAX_IMAGE_PIXELS, + INTRINSICCV_MAX_IMAGE_PIXELS, &count)); +} diff --git a/test/api/test_gaussian_blur.cpp b/test/api/test_gaussian_blur.cpp index 8988ffbec..8e5fc91fb 100644 --- a/test/api/test_gaussian_blur.cpp +++ b/test/api/test_gaussian_blur.cpp @@ -88,3 +88,46 @@ TYPED_TEST(GaussianBlurTest, Misalignment) { INTRINSICCV_BORDER_TYPE_REFLECT, context)); EXPECT_EQ(INTRINSICCV_OK, intrinsiccv_filter_release(context)); } + +TYPED_TEST(GaussianBlurTest, ImageSize) { + 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]; + EXPECT_EQ(INTRINSICCV_ERROR_RANGE, + gaussian_blur_3x3()( + src, sizeof(TypeParam), dst, sizeof(TypeParam), + INTRINSICCV_MAX_IMAGE_PIXELS + 1, 1, 1, + INTRINSICCV_BORDER_TYPE_REFLECT, context)); + EXPECT_EQ(INTRINSICCV_ERROR_RANGE, + gaussian_blur_3x3()( + src, sizeof(TypeParam), dst, sizeof(TypeParam), + INTRINSICCV_MAX_IMAGE_PIXELS, INTRINSICCV_MAX_IMAGE_PIXELS, 1, + INTRINSICCV_BORDER_TYPE_REFLECT, context)); + EXPECT_EQ(INTRINSICCV_ERROR_RANGE, + gaussian_blur_5x5()( + src, sizeof(TypeParam), dst, sizeof(TypeParam), + INTRINSICCV_MAX_IMAGE_PIXELS + 1, 1, 1, + INTRINSICCV_BORDER_TYPE_REFLECT, context)); + EXPECT_EQ(INTRINSICCV_ERROR_RANGE, + gaussian_blur_5x5()( + src, sizeof(TypeParam), dst, sizeof(TypeParam), + INTRINSICCV_MAX_IMAGE_PIXELS, INTRINSICCV_MAX_IMAGE_PIXELS, 1, + INTRINSICCV_BORDER_TYPE_REFLECT, context)); + EXPECT_EQ(INTRINSICCV_OK, intrinsiccv_filter_release(context)); +} + +TEST(FilterCreate, ImageSize) { + intrinsiccv_filter_context_t *context = nullptr; + + for (intrinsiccv_rectangle_t rect : { + intrinsiccv_rectangle_t{INTRINSICCV_MAX_IMAGE_PIXELS + 1, 1}, + intrinsiccv_rectangle_t{INTRINSICCV_MAX_IMAGE_PIXELS, + INTRINSICCV_MAX_IMAGE_PIXELS}, + }) { + EXPECT_EQ(INTRINSICCV_ERROR_RANGE, + intrinsiccv_filter_create(&context, 1, 1, rect)); + ASSERT_EQ(nullptr, context); + } +} diff --git a/test/api/test_merge.cpp b/test/api/test_merge.cpp index 0ea2aa7a6..61d8be67d 100644 --- a/test/api/test_merge.cpp +++ b/test/api/test_merge.cpp @@ -223,3 +223,21 @@ TYPED_TEST(Merge, Misalignment) { } } } + +TYPED_TEST(Merge, ImageSize) { + 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_ERROR_RANGE, + intrinsiccv_merge(srcs, src_strides, dst, dst_stride, + INTRINSICCV_MAX_IMAGE_PIXELS + 1, 1, kChannels, + sizeof(TypeParam))); + EXPECT_EQ(INTRINSICCV_ERROR_RANGE, + intrinsiccv_merge(srcs, src_strides, dst, dst_stride, + INTRINSICCV_MAX_IMAGE_PIXELS, + INTRINSICCV_MAX_IMAGE_PIXELS, kChannels, + sizeof(TypeParam))); +} diff --git a/test/api/test_min_max.cpp b/test/api/test_min_max.cpp index 816feb7f6..d44d5e974 100644 --- a/test/api/test_min_max.cpp +++ b/test/api/test_min_max.cpp @@ -310,6 +310,18 @@ TYPED_TEST(MinMax, Misalignment) { &max_value)); } +TYPED_TEST(MinMax, ImageSize) { + TypeParam src[1], min_value, max_value; + EXPECT_EQ(INTRINSICCV_ERROR_RANGE, + min_max()(src, sizeof(TypeParam), + INTRINSICCV_MAX_IMAGE_PIXELS + 1, 1, + &min_value, &max_value)); + EXPECT_EQ(INTRINSICCV_ERROR_RANGE, + min_max()( + src, sizeof(TypeParam), INTRINSICCV_MAX_IMAGE_PIXELS, + INTRINSICCV_MAX_IMAGE_PIXELS, &min_value, &max_value)); +} + template class MinMaxLoc : public testing::Test {}; @@ -320,3 +332,17 @@ TYPED_TEST(MinMaxLoc, API) { MinMaxLocTest{}.test(); MinMaxLocTest{}.test(); } + +TYPED_TEST(MinMaxLoc, ImageSize) { + TypeParam src[1]; + size_t min_offset = 0, max_offset = 8; + + EXPECT_EQ(INTRINSICCV_ERROR_RANGE, + min_max_loc()(src, sizeof(TypeParam), + INTRINSICCV_MAX_IMAGE_PIXELS + 1, 1, + &min_offset, &max_offset)); + EXPECT_EQ(INTRINSICCV_ERROR_RANGE, + min_max_loc()( + src, sizeof(TypeParam), INTRINSICCV_MAX_IMAGE_PIXELS, + INTRINSICCV_MAX_IMAGE_PIXELS, &min_offset, &max_offset)); +} diff --git a/test/api/test_morphology.cpp b/test/api/test_morphology.cpp index 72a06cade..825984207 100644 --- a/test/api/test_morphology.cpp +++ b/test/api/test_morphology.cpp @@ -49,6 +49,32 @@ TYPED_TEST(MorphologyTest, UnsupportedBorderType) { } } +TYPED_TEST(MorphologyTest, UnsupportedSize) { + intrinsiccv_morphology_context_t *context = nullptr; + + for (intrinsiccv_rectangle_t rect : { + intrinsiccv_rectangle_t{INTRINSICCV_MAX_IMAGE_PIXELS + 1, 1}, + intrinsiccv_rectangle_t{INTRINSICCV_MAX_IMAGE_PIXELS, + INTRINSICCV_MAX_IMAGE_PIXELS}, + }) { + EXPECT_EQ(INTRINSICCV_ERROR_RANGE, + intrinsiccv_morphology_create( + &context, rect, 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, 1})); + ASSERT_EQ(nullptr, context); + + EXPECT_EQ(INTRINSICCV_ERROR_RANGE, + 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), rect)); + ASSERT_EQ(nullptr, context); + } +} + static intrinsiccv_error_t make_minimal_context( intrinsiccv_morphology_context_t **context, size_t type_size) { return intrinsiccv_morphology_create( @@ -111,3 +137,73 @@ TYPED_TEST(ErodeTest, Misalignment) { sizeof(TypeParam) + 1, 1, 1, context)); EXPECT_EQ(INTRINSICCV_OK, intrinsiccv_morphology_release(context)); } + +TYPED_TEST(DilateTest, ImageSize) { + intrinsiccv_morphology_context_t *context = nullptr; + ASSERT_EQ(INTRINSICCV_OK, make_minimal_context(&context, sizeof(TypeParam))); + TypeParam src[1], dst[1]; + EXPECT_EQ(INTRINSICCV_ERROR_RANGE, + dilate()(src, sizeof(TypeParam), dst, sizeof(TypeParam), + INTRINSICCV_MAX_IMAGE_PIXELS + 1, 1, context)); + EXPECT_EQ(INTRINSICCV_ERROR_RANGE, + dilate()(src, sizeof(TypeParam), dst, sizeof(TypeParam), + INTRINSICCV_MAX_IMAGE_PIXELS, + INTRINSICCV_MAX_IMAGE_PIXELS, context)); + EXPECT_EQ(INTRINSICCV_OK, intrinsiccv_morphology_release(context)); +} + +TYPED_TEST(ErodeTest, ImageSize) { + intrinsiccv_morphology_context_t *context = nullptr; + ASSERT_EQ(INTRINSICCV_OK, make_minimal_context(&context, sizeof(TypeParam))); + TypeParam src[1], dst[1]; + EXPECT_EQ(INTRINSICCV_ERROR_RANGE, + erode()(src, sizeof(TypeParam), dst, sizeof(TypeParam), + INTRINSICCV_MAX_IMAGE_PIXELS + 1, 1, context)); + EXPECT_EQ(INTRINSICCV_ERROR_RANGE, + erode()(src, sizeof(TypeParam), dst, sizeof(TypeParam), + INTRINSICCV_MAX_IMAGE_PIXELS, + INTRINSICCV_MAX_IMAGE_PIXELS, context)); + EXPECT_EQ(INTRINSICCV_OK, intrinsiccv_morphology_release(context)); +} + +TYPED_TEST(DilateTest, InvalidContextSizeType) { + intrinsiccv_morphology_context_t *context = nullptr; + ASSERT_EQ(INTRINSICCV_OK, + make_minimal_context(&context, sizeof(TypeParam) + 1)); + TypeParam src[1], dst[1]; + EXPECT_EQ(INTRINSICCV_ERROR_CONTEXT_MISMATCH, + dilate()(src, sizeof(TypeParam), dst, sizeof(TypeParam), + 1, 1, context)); + EXPECT_EQ(INTRINSICCV_OK, intrinsiccv_morphology_release(context)); +} + +TYPED_TEST(ErodeTest, InvalidContextSizeType) { + intrinsiccv_morphology_context_t *context = nullptr; + ASSERT_EQ(INTRINSICCV_OK, + make_minimal_context(&context, sizeof(TypeParam) + 1)); + TypeParam src[1], dst[1]; + EXPECT_EQ(INTRINSICCV_ERROR_CONTEXT_MISMATCH, + erode()(src, sizeof(TypeParam), dst, sizeof(TypeParam), + 1, 1, context)); + EXPECT_EQ(INTRINSICCV_OK, intrinsiccv_morphology_release(context)); +} + +TYPED_TEST(DilateTest, InvalidContextImageSize) { + intrinsiccv_morphology_context_t *context = nullptr; + ASSERT_EQ(INTRINSICCV_OK, make_minimal_context(&context, sizeof(TypeParam))); + TypeParam src[1], dst[1]; + EXPECT_EQ(INTRINSICCV_ERROR_CONTEXT_MISMATCH, + dilate()(src, sizeof(TypeParam), dst, sizeof(TypeParam), + 2, 1, context)); + EXPECT_EQ(INTRINSICCV_OK, intrinsiccv_morphology_release(context)); +} + +TYPED_TEST(ErodeTest, InvalidContextImageSize) { + intrinsiccv_morphology_context_t *context = nullptr; + ASSERT_EQ(INTRINSICCV_OK, make_minimal_context(&context, sizeof(TypeParam))); + TypeParam src[1], dst[1]; + EXPECT_EQ(INTRINSICCV_ERROR_CONTEXT_MISMATCH, + erode()(src, sizeof(TypeParam), dst, sizeof(TypeParam), + 2, 1, context)); + EXPECT_EQ(INTRINSICCV_OK, intrinsiccv_morphology_release(context)); +} diff --git a/test/api/test_resize_to_quarter.cpp b/test/api/test_resize_to_quarter.cpp index 64207b83d..a9e703048 100644 --- a/test/api/test_resize_to_quarter.cpp +++ b/test/api/test_resize_to_quarter.cpp @@ -218,3 +218,29 @@ TEST(ResizeToQuarter, NullPointer) { test::test_null_args(intrinsiccv_resize_to_quarter_u8, src, 2, 2, 2, dst, 1, 1, 1); } + +TEST(ResizeToQuarter, ImageSize) { + const uint8_t src[1] = {}; + uint8_t dst[1]; + + EXPECT_EQ(INTRINSICCV_ERROR_RANGE, + intrinsiccv_resize_to_quarter_u8( + src, 1, INTRINSICCV_MAX_IMAGE_PIXELS + 1, 1, dst, 1, 1, 1)); + + EXPECT_EQ(INTRINSICCV_ERROR_RANGE, + intrinsiccv_resize_to_quarter_u8( + src, 1, INTRINSICCV_MAX_IMAGE_PIXELS, + INTRINSICCV_MAX_IMAGE_PIXELS, dst, 1, 1, 1)); + + EXPECT_EQ(INTRINSICCV_ERROR_RANGE, + intrinsiccv_resize_to_quarter_u8(src, 1, 8, 8, dst, 1, 4, 3)); + + EXPECT_EQ(INTRINSICCV_ERROR_RANGE, + intrinsiccv_resize_to_quarter_u8(src, 1, 8, 8, dst, 1, 3, 4)); + + EXPECT_EQ(INTRINSICCV_ERROR_RANGE, + intrinsiccv_resize_to_quarter_u8(src, 1, 9, 9, dst, 1, 4, 1)); + + EXPECT_EQ(INTRINSICCV_ERROR_RANGE, + intrinsiccv_resize_to_quarter_u8(src, 1, 9, 9, dst, 1, 7, 5)); +} diff --git a/test/api/test_rgb_and_gray.cpp b/test/api/test_rgb_and_gray.cpp index 3dc8550ef..24ee251f9 100644 --- a/test/api/test_rgb_and_gray.cpp +++ b/test/api/test_rgb_and_gray.cpp @@ -36,6 +36,14 @@ class GrayTest final { test::test_null_args(impl, source.data(), source.stride(), actual.data(), actual.stride(), logical_width, actual.height()); + + EXPECT_EQ(INTRINSICCV_ERROR_RANGE, + impl(source.data(), source.stride(), actual.data(), + actual.stride(), INTRINSICCV_MAX_IMAGE_PIXELS + 1, 1)); + EXPECT_EQ( + INTRINSICCV_ERROR_RANGE, + impl(source.data(), source.stride(), actual.data(), actual.stride(), + INTRINSICCV_MAX_IMAGE_PIXELS, INTRINSICCV_MAX_IMAGE_PIXELS)); } private: @@ -91,6 +99,14 @@ class ColourTest final { test::test_null_args(impl, source.data(), source.stride(), actual.data(), actual.stride(), logical_width, actual.height()); + + EXPECT_EQ(INTRINSICCV_ERROR_RANGE, + impl(source.data(), source.stride(), actual.data(), + actual.stride(), INTRINSICCV_MAX_IMAGE_PIXELS + 1, 1)); + EXPECT_EQ( + INTRINSICCV_ERROR_RANGE, + impl(source.data(), source.stride(), actual.data(), actual.stride(), + INTRINSICCV_MAX_IMAGE_PIXELS, INTRINSICCV_MAX_IMAGE_PIXELS)); } private: diff --git a/test/api/test_saturating_absdiff.cpp b/test/api/test_saturating_absdiff.cpp index f4c58c263..82ed17665 100644 --- a/test/api/test_saturating_absdiff.cpp +++ b/test/api/test_saturating_absdiff.cpp @@ -122,3 +122,16 @@ TYPED_TEST(SaturatingAbsDiff, Misalignment) { sizeof(TypeParam), dst, sizeof(TypeParam) + 1, 1, 1)); } + +TYPED_TEST(SaturatingAbsDiff, ImageSize) { + TypeParam src[1], dst[1]; + EXPECT_EQ(INTRINSICCV_ERROR_RANGE, + saturating_absdiff()( + src, sizeof(TypeParam), src, sizeof(TypeParam), dst, + sizeof(TypeParam), INTRINSICCV_MAX_IMAGE_PIXELS + 1, 1)); + EXPECT_EQ(INTRINSICCV_ERROR_RANGE, + saturating_absdiff()( + src, sizeof(TypeParam), src, sizeof(TypeParam), dst, + sizeof(TypeParam), INTRINSICCV_MAX_IMAGE_PIXELS, + INTRINSICCV_MAX_IMAGE_PIXELS)); +} diff --git a/test/api/test_saturating_add.cpp b/test/api/test_saturating_add.cpp index f5a1844b3..c5cc01c92 100644 --- a/test/api/test_saturating_add.cpp +++ b/test/api/test_saturating_add.cpp @@ -114,3 +114,16 @@ TYPED_TEST(SaturatingAdd, Misalignment) { sizeof(TypeParam), dst, sizeof(TypeParam) + 1, 1, 1)); } + +TYPED_TEST(SaturatingAdd, ImageSize) { + TypeParam src[1], dst[1]; + EXPECT_EQ(INTRINSICCV_ERROR_RANGE, + saturating_add()( + src, sizeof(TypeParam), src, sizeof(TypeParam), dst, + sizeof(TypeParam), INTRINSICCV_MAX_IMAGE_PIXELS + 1, 1)); + EXPECT_EQ(INTRINSICCV_ERROR_RANGE, + saturating_add()( + src, sizeof(TypeParam), src, sizeof(TypeParam), dst, + sizeof(TypeParam), INTRINSICCV_MAX_IMAGE_PIXELS, + INTRINSICCV_MAX_IMAGE_PIXELS)); +} diff --git a/test/api/test_saturating_multiply.cpp b/test/api/test_saturating_multiply.cpp index 0c1007acc..51df8e366 100644 --- a/test/api/test_saturating_multiply.cpp +++ b/test/api/test_saturating_multiply.cpp @@ -122,3 +122,16 @@ TYPED_TEST(SaturatingMultiply, Misalignment) { sizeof(TypeParam), dst, sizeof(TypeParam) + 1, 1, 1, 1)); } + +TYPED_TEST(SaturatingMultiply, ImageSize) { + TypeParam src[1], dst[1]; + EXPECT_EQ(INTRINSICCV_ERROR_RANGE, + saturating_multiply()( + src, sizeof(TypeParam), src, sizeof(TypeParam), dst, + sizeof(TypeParam), INTRINSICCV_MAX_IMAGE_PIXELS + 1, 1, 1)); + EXPECT_EQ(INTRINSICCV_ERROR_RANGE, + saturating_multiply()( + src, sizeof(TypeParam), src, sizeof(TypeParam), dst, + sizeof(TypeParam), INTRINSICCV_MAX_IMAGE_PIXELS, + INTRINSICCV_MAX_IMAGE_PIXELS, 1)); +} diff --git a/test/api/test_saturating_sub.cpp b/test/api/test_saturating_sub.cpp index 16c52f475..3618a4e01 100644 --- a/test/api/test_saturating_sub.cpp +++ b/test/api/test_saturating_sub.cpp @@ -116,3 +116,16 @@ TYPED_TEST(SaturatingSub, Misalignment) { sizeof(TypeParam), dst, sizeof(TypeParam) + 1, 1, 1)); } + +TYPED_TEST(SaturatingSub, ImageSize) { + TypeParam src[1], dst[1]; + EXPECT_EQ(INTRINSICCV_ERROR_RANGE, + saturating_sub()( + src, sizeof(TypeParam), src, sizeof(TypeParam), dst, + sizeof(TypeParam), INTRINSICCV_MAX_IMAGE_PIXELS + 1, 1)); + EXPECT_EQ(INTRINSICCV_ERROR_RANGE, + saturating_sub()( + src, sizeof(TypeParam), src, sizeof(TypeParam), dst, + sizeof(TypeParam), INTRINSICCV_MAX_IMAGE_PIXELS, + INTRINSICCV_MAX_IMAGE_PIXELS)); +} diff --git a/test/api/test_scale.cpp b/test/api/test_scale.cpp index 46ed272a1..a0eddade3 100644 --- a/test/api/test_scale.cpp +++ b/test/api/test_scale.cpp @@ -387,3 +387,14 @@ TYPED_TEST(ScaleTest, Misalignment) { scale()(src, sizeof(TypeParam), dst, sizeof(TypeParam) + 1, 1, 1, 2, 0)); } + +TYPED_TEST(ScaleTest, ImageSize) { + TypeParam src[1], dst[1]; + EXPECT_EQ(INTRINSICCV_ERROR_RANGE, + scale()(src, sizeof(TypeParam), dst, sizeof(TypeParam), + INTRINSICCV_MAX_IMAGE_PIXELS + 1, 1, 2, 0)); + EXPECT_EQ(INTRINSICCV_ERROR_RANGE, + scale()(src, sizeof(TypeParam), dst, sizeof(TypeParam), + INTRINSICCV_MAX_IMAGE_PIXELS, + INTRINSICCV_MAX_IMAGE_PIXELS, 2, 0)); +} diff --git a/test/api/test_sobel.cpp b/test/api/test_sobel.cpp index 7245a902e..dce2430c2 100644 --- a/test/api/test_sobel.cpp +++ b/test/api/test_sobel.cpp @@ -144,3 +144,33 @@ TYPED_TEST(Sobel, MisalignmentVertical) { sizeof(dst) + 1, 1, 1, 1)); } } + +TYPED_TEST(Sobel, ImageSizeHorizontal) { + using KernelTestParams = SobelKernelTestParams; + typename KernelTestParams::InputType src[1] = {}; + typename KernelTestParams::OutputType dst[1]; + + EXPECT_EQ(INTRINSICCV_ERROR_RANGE, + sobel_3x3_horizontal()( + src, sizeof(src), dst, sizeof(dst), + INTRINSICCV_MAX_IMAGE_PIXELS + 1, 1, 1)); + EXPECT_EQ(INTRINSICCV_ERROR_RANGE, + sobel_3x3_horizontal()( + src, sizeof(src), dst, sizeof(dst), + INTRINSICCV_MAX_IMAGE_PIXELS, INTRINSICCV_MAX_IMAGE_PIXELS, 1)); +} + +TYPED_TEST(Sobel, ImageSizeVertical) { + using KernelTestParams = SobelKernelTestParams; + typename KernelTestParams::InputType src[1] = {}; + typename KernelTestParams::OutputType dst[1]; + + EXPECT_EQ( + INTRINSICCV_ERROR_RANGE, + sobel_3x3_vertical()(src, sizeof(src), dst, sizeof(dst), + INTRINSICCV_MAX_IMAGE_PIXELS + 1, 1, 1)); + EXPECT_EQ(INTRINSICCV_ERROR_RANGE, + sobel_3x3_vertical()(src, sizeof(src), dst, sizeof(dst), + INTRINSICCV_MAX_IMAGE_PIXELS, + INTRINSICCV_MAX_IMAGE_PIXELS, 1)); +} diff --git a/test/api/test_split.cpp b/test/api/test_split.cpp index 4be8db95f..7d9f37393 100644 --- a/test/api/test_split.cpp +++ b/test/api/test_split.cpp @@ -224,3 +224,21 @@ TYPED_TEST(Split, Misalignment) { } } } + +TYPED_TEST(Split, ImageSize) { + 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_ERROR_RANGE, + intrinsiccv_split(src, src_stride, dsts, dst_strides, + INTRINSICCV_MAX_IMAGE_PIXELS + 1, 1, kChannels, + sizeof(TypeParam))); + EXPECT_EQ(INTRINSICCV_ERROR_RANGE, + intrinsiccv_split(src, src_stride, dsts, dst_strides, + INTRINSICCV_MAX_IMAGE_PIXELS, + INTRINSICCV_MAX_IMAGE_PIXELS, kChannels, + sizeof(TypeParam))); +} diff --git a/test/api/test_threshold_binary.cpp b/test/api/test_threshold_binary.cpp index a4cd9cfea..42ef20532 100644 --- a/test/api/test_threshold_binary.cpp +++ b/test/api/test_threshold_binary.cpp @@ -145,3 +145,16 @@ TYPED_TEST(ThresholdBinary, Misalignment) { threshold_binary()(src, sizeof(TypeParam), dst, sizeof(TypeParam) + 1, 1, 1, 1, 1)); } + +TYPED_TEST(ThresholdBinary, ImageSize) { + TypeParam src[1], dst[1]; + EXPECT_EQ(INTRINSICCV_ERROR_RANGE, + threshold_binary()( + src, sizeof(TypeParam), dst, sizeof(TypeParam), + INTRINSICCV_MAX_IMAGE_PIXELS + 1, 1, 1, 1)); + EXPECT_EQ(INTRINSICCV_ERROR_RANGE, + threshold_binary()(src, sizeof(TypeParam), dst, + sizeof(TypeParam), + INTRINSICCV_MAX_IMAGE_PIXELS, + INTRINSICCV_MAX_IMAGE_PIXELS, 1, 1)); +} diff --git a/test/api/test_transpose.cpp b/test/api/test_transpose.cpp index 7a7725bd5..7c5c1c1c0 100644 --- a/test/api/test_transpose.cpp +++ b/test/api/test_transpose.cpp @@ -187,3 +187,16 @@ TYPED_TEST(Transpose, Misalignment) { intrinsiccv_transpose(src, sizeof(TypeParam), dst, sizeof(TypeParam) + 1, 1, 1, sizeof(TypeParam))); } + +TYPED_TEST(Transpose, ImageSize) { + TypeParam src[1], dst[1]; + EXPECT_EQ(INTRINSICCV_ERROR_RANGE, + intrinsiccv_transpose( + src, sizeof(TypeParam), dst, sizeof(TypeParam), + INTRINSICCV_MAX_IMAGE_PIXELS + 1, 1, sizeof(TypeParam))); + EXPECT_EQ( + INTRINSICCV_ERROR_RANGE, + intrinsiccv_transpose(src, sizeof(TypeParam), dst, sizeof(TypeParam), + INTRINSICCV_MAX_IMAGE_PIXELS, + INTRINSICCV_MAX_IMAGE_PIXELS, sizeof(TypeParam))); +} diff --git a/test/api/test_yuv_to_rgb.cpp b/test/api/test_yuv_to_rgb.cpp index 387b1d828..a7854d8ec 100644 --- a/test/api/test_yuv_to_rgb.cpp +++ b/test/api/test_yuv_to_rgb.cpp @@ -67,6 +67,16 @@ class YuvTest final { input_uv.data(), input_uv.stride(), actual.data(), actual.stride(), expected.width() / channel_number_, expected.height(), is_nv21); + + EXPECT_EQ(INTRINSICCV_ERROR_RANGE, + impl(input_y.data(), input_y.stride(), input_uv.data(), + input_uv.stride(), actual.data(), actual.stride(), + INTRINSICCV_MAX_IMAGE_PIXELS + 1, 1, is_nv21)); + EXPECT_EQ(INTRINSICCV_ERROR_RANGE, + impl(input_y.data(), input_y.stride(), input_uv.data(), + input_uv.stride(), actual.data(), actual.stride(), + INTRINSICCV_MAX_IMAGE_PIXELS, INTRINSICCV_MAX_IMAGE_PIXELS, + is_nv21)); } void calculate_expected(test::Array2D &y_arr, -- GitLab From a39cb5b2eeb43a5a400caefed98316e253a55059 Mon Sep 17 00:00:00 2001 From: Mark Horvath Date: Wed, 14 Feb 2024 15:19:11 +0100 Subject: [PATCH 3/9] Add missing doxygen docs for ctypes.h --- intrinsiccv/include/intrinsiccv/ctypes.h | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/intrinsiccv/include/intrinsiccv/ctypes.h b/intrinsiccv/include/intrinsiccv/ctypes.h index 98efb3324..8f676e998 100644 --- a/intrinsiccv/include/intrinsiccv/ctypes.h +++ b/intrinsiccv/include/intrinsiccv/ctypes.h @@ -3,7 +3,7 @@ // SPDX-License-Identifier: Apache-2.0 /// @file ctypes.h -/// Helper type definitions +/// @brief Helper type definitions #ifndef INTRINSICCV_CTYPES_H #define INTRINSICCV_CTYPES_H @@ -34,20 +34,31 @@ typedef enum INTRINSICCV_NODISCARD { INTRINSICCV_ERROR_ALIGNMENT, } intrinsiccv_error_t; +/// Struct to represent a point typedef struct { + /// x coordinate size_t x; + /// y coordinate size_t y; } intrinsiccv_point_t; +/// Struct to represent a rectangle typedef struct { + /// Width of the rectangle size_t width; + /// Height of the rectangle size_t height; } intrinsiccv_rectangle_t; +/// Struct to store border values typedef struct { + /// Top border value double top; + /// Left border value double left; + /// Bottom border value double bottom; + /// Right border value double right; } intrinsiccv_border_values_t; @@ -77,6 +88,7 @@ typedef enum { typedef struct intrinsiccv_morphology_context_t_ intrinsiccv_morphology_context_t; +/// Internal structure where filter operations store their state typedef struct intrinsiccv_filter_context_t_ intrinsiccv_filter_context_t; #endif // INTRINSICCV_CTYPES_H -- GitLab From 846e10a951874bdb2c6c93466f1074a7a80aa965 Mon Sep 17 00:00:00 2001 From: Mark Horvath Date: Wed, 14 Feb 2024 17:06:24 +0100 Subject: [PATCH 4/9] Add morphology related constraint checks --- intrinsiccv/include/intrinsiccv/ctypes.h | 5 ++- intrinsiccv/include/intrinsiccv/intrinsiccv.h | 31 ++++++++++----- .../intrinsiccv/morphology/workspace.h | 33 ++++++++++------ intrinsiccv/include/intrinsiccv/types.h | 8 ++++ intrinsiccv/src/morphology/morphology_api.cpp | 19 +++++++--- .../src/morphology/morphology_neon.cpp | 15 ++++++++ intrinsiccv/src/morphology/morphology_sc.h | 16 ++++++++ test/api/test_morphology.cpp | 38 +++++++++++++++++++ 8 files changed, 137 insertions(+), 28 deletions(-) diff --git a/intrinsiccv/include/intrinsiccv/ctypes.h b/intrinsiccv/include/intrinsiccv/ctypes.h index 8f676e998..20f651050 100644 --- a/intrinsiccv/include/intrinsiccv/ctypes.h +++ b/intrinsiccv/include/intrinsiccv/ctypes.h @@ -26,12 +26,15 @@ typedef enum INTRINSICCV_NODISCARD { INTRINSICCV_ERROR_NOT_IMPLEMENTED, /// Null pointer was passed as an argument. INTRINSICCV_ERROR_NULL_POINTER, - /// A value was encountered outside the representable range. + /// A value was encountered outside the representable or valid range. INTRINSICCV_ERROR_RANGE, /// Could not allocate memory. INTRINSICCV_ERROR_ALLOCATION, /// A value did not meet alignment requirements. INTRINSICCV_ERROR_ALIGNMENT, + /// The provided context (like \ref intrinsiccv_morphology_context_t) is not + /// compatible with the operation. + INTRINSICCV_ERROR_CONTEXT_MISMATCH, } intrinsiccv_error_t; /// Struct to represent a point diff --git a/intrinsiccv/include/intrinsiccv/intrinsiccv.h b/intrinsiccv/include/intrinsiccv/intrinsiccv.h index 360366cef..6ebeef17a 100644 --- a/intrinsiccv/include/intrinsiccv/intrinsiccv.h +++ b/intrinsiccv/include/intrinsiccv/intrinsiccv.h @@ -38,6 +38,12 @@ #define INTRINSICCV_MAX_IMAGE_PIXELS ((1ULL << 48) - 1) #endif +/// Size in bytes of the largest possible element type +#define INTRINSICCV_MAXIMUM_TYPE_SIZE (8) + +/// Maximum number of channels +#define INTRINSICCV_MAXIMUM_CHANNEL_COUNT (8) + #ifdef __cplusplus extern "C" { #endif // __cplusplus @@ -694,13 +700,19 @@ intrinsiccv_error_t intrinsiccv_threshold_binary_u8( /// @param kernel Width and height of the kernel. Its size must not be /// more than \ref INTRINSICCV_MAX_IMAGE_PIXELS. /// @param anchor Location in the kernel which is aligned to the actual -/// point in the source data -/// @param border_type Way of handling the border. +/// point in the source data. Must not point out of the +/// kernel. +/// @param border_type Way of handling the border. The supported border types +/// are: \n +/// - \ref INTRINSICCV_BORDER_TYPE_CONSTANT \n +/// - \ref INTRINSICCV_BORDER_TYPE_REPLICATE /// @param border_values Border values if the border_type is -/// ::INTRINSICCV_BORDER_TYPE_CONSTANT. -/// @param channels Number of elements for each pixel. +/// \ref INTRINSICCV_BORDER_TYPE_CONSTANT. +/// @param channels Number of channels in the data. Must be not more than +/// \ref INTRINSICCV_MAXIMUM_CHANNEL_COUNT. /// @param iterations Number of times to do the morphology operation. -/// @param type_size Element size in bytes. +/// @param type_size Element size in bytes. Must not be more than +/// \ref INTRINSICCV_MAXIMUM_TYPE_SIZE. /// @param image Image dimensions. Its size must not be more than /// \ref INTRINSICCV_MAX_IMAGE_PIXELS. /// @@ -740,11 +752,10 @@ intrinsiccv_error_t intrinsiccv_morphology_release( /// /// Before using this function, a context must be created using /// \ref intrinsiccv_morphology_create, and after finished, it has to be -/// released using intrinsiccv_morphology_release. -/// -/// Note: from border types only these are supported: \n -/// - \ref INTRINSICCV_BORDER_TYPE_REPLICATE \n -/// - \ref INTRINSICCV_BORDER_TYPE_CONSTANT +/// released using \ref intrinsiccv_morphology_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. /// /// @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 diff --git a/intrinsiccv/include/intrinsiccv/morphology/workspace.h b/intrinsiccv/include/intrinsiccv/morphology/workspace.h index dba777b62..32623301f 100644 --- a/intrinsiccv/include/intrinsiccv/morphology/workspace.h +++ b/intrinsiccv/include/intrinsiccv/morphology/workspace.h @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: 2023 Arm Limited and/or its affiliates +// SPDX-FileCopyrightText: 2023 - 2024 Arm Limited and/or its affiliates // // SPDX-License-Identifier: Apache-2.0 @@ -59,22 +59,28 @@ class MorphologyWorkspace final { MorphologyWorkspace() = delete; // Creates a workspace on the heap. - static Pointer create( - intrinsiccv_rectangle_t kernel, intrinsiccv_point_t anchor, - BorderType border_type, intrinsiccv_border_values_t border_values, - size_t channels, size_t iterations, size_t type_size, + static intrinsiccv_error_t create( + Pointer &workspace, intrinsiccv_rectangle_t kernel, + intrinsiccv_point_t anchor, 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); // To avoid load/store penalties. const size_t kAlignment = 16; - Rectangle rect{image}; + if (anchor.x >= kernel.width || anchor.y >= kernel.height) { + return INTRINSICCV_ERROR_RANGE; + } + + Rectangle image_size{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(); + size_t wide_rows_width = + margin.left() + image_size.width() + margin.right(); size_t wide_rows_stride = wide_rows_width * channels; wide_rows_stride = __builtin_align_up(wide_rows_stride, kAlignment); size_t wide_rows_height = 1UL; // There is only one wide row. @@ -82,7 +88,7 @@ class MorphologyWorkspace final { wide_rows_size += kAlignment - 1; // Multiple buffer rows to hold rows without any borders. - size_t buffer_rows_width = type_size * rect.width(); + size_t buffer_rows_width = type_size * image_size.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,14 +103,14 @@ class MorphologyWorkspace final { indirect_row_storage_size + buffer_rows_size + wide_rows_size; void *allocation = std::malloc(allocation_size); - auto workspace = MorphologyWorkspace::Pointer{ + workspace = MorphologyWorkspace::Pointer{ reinterpret_cast(allocation)}; if (!workspace) { - return workspace; + return INTRINSICCV_ERROR_ALLOCATION; } workspace->rows_per_iteration_ = rows_per_iteration; - workspace->wide_rows_src_width_ = rect.width(); + workspace->wide_rows_src_width_ = image_size.width(); workspace->channels_ = channels; auto *buffer_rows_address = &workspace->data_[indirect_row_storage_size]; @@ -127,8 +133,9 @@ class MorphologyWorkspace final { workspace->channels_ = channels; workspace->iterations_ = iterations; workspace->type_size_ = type_size; + workspace->image_size_ = image_size; - return workspace; + return INTRINSICCV_OK; } intrinsiccv_rectangle_t kernel() const { return kernel_; } @@ -138,6 +145,7 @@ class MorphologyWorkspace final { size_t channels() const { return channels_; } size_t iterations() const { return iterations_; } size_t type_size() const { return type_size_; } + Rectangle image_size() const { return image_size_; } // This function is too complex, but disable the warning for now. // NOLINTBEGIN(readability-function-cognitive-complexity) @@ -371,6 +379,7 @@ class MorphologyWorkspace final { intrinsiccv_border_values_t border_values_; size_t iterations_; size_t type_size_; + Rectangle image_size_; // Number of wide rows in this workspace. size_t rows_per_iteration_; diff --git a/intrinsiccv/include/intrinsiccv/types.h b/intrinsiccv/include/intrinsiccv/types.h index b341980a6..41510e109 100644 --- a/intrinsiccv/include/intrinsiccv/types.h +++ b/intrinsiccv/include/intrinsiccv/types.h @@ -54,6 +54,14 @@ class Rectangle final { height_ = 1; } + bool operator==(const Rectangle &rhs) const INTRINSICCV_STREAMING_COMPATIBLE { + return width() == rhs.width() && height() == rhs.height(); + } + + bool operator!=(const Rectangle &rhs) const INTRINSICCV_STREAMING_COMPATIBLE { + return !operator==(rhs); + } + private: size_t width_; size_t height_; diff --git a/intrinsiccv/src/morphology/morphology_api.cpp b/intrinsiccv/src/morphology/morphology_api.cpp index 83fd156b4..19e9922f3 100644 --- a/intrinsiccv/src/morphology/morphology_api.cpp +++ b/intrinsiccv/src/morphology/morphology_api.cpp @@ -58,9 +58,18 @@ intrinsiccv_error_t intrinsiccv_morphology_create( intrinsiccv_border_values_t border_values, size_t channels, size_t iterations, size_t type_size, intrinsiccv_rectangle_t image) { CHECK_POINTERS(context); + *context = nullptr; CHECK_RECTANGLE_SIZE(kernel); CHECK_RECTANGLE_SIZE(image); + if (type_size > INTRINSICCV_MAXIMUM_TYPE_SIZE) { + return INTRINSICCV_ERROR_RANGE; + } + + if (channels > INTRINSICCV_MAXIMUM_CHANNEL_COUNT) { + return INTRINSICCV_ERROR_RANGE; + } + auto morphology_border_type = MorphologyWorkspace::get_border_type(border_type); @@ -68,11 +77,11 @@ intrinsiccv_error_t intrinsiccv_morphology_create( return INTRINSICCV_ERROR_NOT_IMPLEMENTED; } - auto workspace = MorphologyWorkspace::create( - kernel, anchor, *morphology_border_type, border_values, channels, - iterations, type_size, image); - if (!workspace) { - return INTRINSICCV_ERROR_ALLOCATION; + MorphologyWorkspace::Pointer workspace; + if (intrinsiccv_error_t error = MorphologyWorkspace::create( + workspace, kernel, anchor, *morphology_border_type, border_values, + channels, iterations, type_size, image)) { + return error; } *context = diff --git a/intrinsiccv/src/morphology/morphology_neon.cpp b/intrinsiccv/src/morphology/morphology_neon.cpp index 21af80cd1..2bca15c6d 100644 --- a/intrinsiccv/src/morphology/morphology_neon.cpp +++ b/intrinsiccv/src/morphology/morphology_neon.cpp @@ -497,7 +497,15 @@ intrinsiccv_error_t dilate(const T *src, size_t src_stride, T *dst, auto *workspace = reinterpret_cast(context); + if (workspace->type_size() != sizeof(T)) { + return INTRINSICCV_ERROR_CONTEXT_MISMATCH; + } + Rectangle rect{width, height}; + if (workspace->image_size() != rect) { + return INTRINSICCV_ERROR_CONTEXT_MISMATCH; + } + Rectangle kernel{workspace->kernel()}; Rows src_rows{src, src_stride, workspace->channels()}; Rows dst_rows{dst, dst_stride, workspace->channels()}; @@ -552,8 +560,15 @@ intrinsiccv_error_t erode(const T *src, size_t src_stride, T *dst, CHECK_IMAGE_SIZE(width, height); auto *workspace = reinterpret_cast(context); + if (workspace->type_size() != sizeof(T)) { + return INTRINSICCV_ERROR_CONTEXT_MISMATCH; + } Rectangle rect{width, height}; + if (workspace->image_size() != rect) { + return INTRINSICCV_ERROR_CONTEXT_MISMATCH; + } + Rectangle kernel{workspace->kernel()}; Rows src_rows{src, src_stride, workspace->channels()}; Rows dst_rows{dst, dst_stride, workspace->channels()}; diff --git a/intrinsiccv/src/morphology/morphology_sc.h b/intrinsiccv/src/morphology/morphology_sc.h index d49a3da76..40791e939 100644 --- a/intrinsiccv/src/morphology/morphology_sc.h +++ b/intrinsiccv/src/morphology/morphology_sc.h @@ -460,7 +460,15 @@ static intrinsiccv_error_t dilate_sc(const T *src, size_t src_stride, T *dst, auto *workspace = reinterpret_cast(context); + if (workspace->type_size() != sizeof(T)) { + return INTRINSICCV_ERROR_CONTEXT_MISMATCH; + } + Rectangle rect{width, height}; + if (workspace->image_size() != rect) { + return INTRINSICCV_ERROR_CONTEXT_MISMATCH; + } + Rectangle kernel{workspace->kernel()}; Rows src_rows{src, src_stride, workspace->channels()}; Rows dst_rows{dst, dst_stride, workspace->channels()}; @@ -521,7 +529,15 @@ static intrinsiccv_error_t erode_sc(const T *src, size_t src_stride, T *dst, auto *workspace = reinterpret_cast(context); + if (workspace->type_size() != sizeof(T)) { + return INTRINSICCV_ERROR_CONTEXT_MISMATCH; + } + Rectangle rect{width, height}; + if (workspace->image_size() != rect) { + return INTRINSICCV_ERROR_CONTEXT_MISMATCH; + } + Rectangle kernel{workspace->kernel()}; Rows src_rows{src, src_stride, workspace->channels()}; Rows dst_rows{dst, dst_stride, workspace->channels()}; diff --git a/test/api/test_morphology.cpp b/test/api/test_morphology.cpp index 825984207..065b75f3f 100644 --- a/test/api/test_morphology.cpp +++ b/test/api/test_morphology.cpp @@ -75,6 +75,44 @@ TYPED_TEST(MorphologyTest, UnsupportedSize) { } } +TYPED_TEST(MorphologyTest, InvalidAnchor) { + intrinsiccv_morphology_context_t *context = nullptr; + + EXPECT_EQ(INTRINSICCV_ERROR_RANGE, + intrinsiccv_morphology_create( + &context, intrinsiccv_rectangle_t{1, 1}, + intrinsiccv_point_t{1, 0}, INTRINSICCV_BORDER_TYPE_REPLICATE, + intrinsiccv_border_values_t{0, 0, 1, 1}, 1, 1, + sizeof(TypeParam), intrinsiccv_rectangle_t{1, 1})); + ASSERT_EQ(nullptr, context); +} + +TYPED_TEST(MorphologyTest, InvalidTypeSize) { + intrinsiccv_morphology_context_t *context = nullptr; + + EXPECT_EQ( + INTRINSICCV_ERROR_RANGE, + 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, + INTRINSICCV_MAXIMUM_TYPE_SIZE + 1, intrinsiccv_rectangle_t{1, 1})); + ASSERT_EQ(nullptr, context); +} + +TYPED_TEST(MorphologyTest, InvalidChannelNumber) { + intrinsiccv_morphology_context_t *context = nullptr; + + EXPECT_EQ(INTRINSICCV_ERROR_RANGE, + 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}, + INTRINSICCV_MAXIMUM_CHANNEL_COUNT + 1, 1, 1, + 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( -- GitLab From ecb291ad32b4997512d8d66fd7c573bff9dd610c Mon Sep 17 00:00:00 2001 From: Mark Horvath Date: Wed, 14 Feb 2024 22:49:58 +0100 Subject: [PATCH 5/9] Document split, merge, and transpose constraints --- intrinsiccv/include/intrinsiccv/intrinsiccv.h | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/intrinsiccv/include/intrinsiccv/intrinsiccv.h b/intrinsiccv/include/intrinsiccv/intrinsiccv.h index 6ebeef17a..b8487a3c5 100644 --- a/intrinsiccv/include/intrinsiccv/intrinsiccv.h +++ b/intrinsiccv/include/intrinsiccv/intrinsiccv.h @@ -1056,8 +1056,9 @@ intrinsiccv_error_t intrinsiccv_gaussian_blur_5x5_u8( /// @param width Number of pixels in one row of the source data. (One /// pixel consists of 'channels' number of elements.) /// @param height Number of rows in the source data. -/// @param channels Number of channels in the source data. -/// @param element_size Size of one element in bytes. +/// @param channels Number of channels in the source data. Must be 2, 3 or +/// 4. +/// @param element_size Size of one element in bytes. Must be 1, 2, 4 or 8. /// intrinsiccv_error_t intrinsiccv_split(const void *src_data, size_t src_stride, void **dst_data, @@ -1094,7 +1095,7 @@ intrinsiccv_error_t intrinsiccv_split(const void *src_data, size_t src_stride, /// Must not be less than height * element_size. /// @param src_width Number of elements in a row. /// @param src_height Number of rows in the data. -/// @param element_size Size of one element in bytes. +/// @param element_size Size of one element in bytes. Must be 1, 2, 4 or 8. /// intrinsiccv_error_t intrinsiccv_transpose(const void *src, size_t src_stride, void *dst, size_t dst_stride, @@ -1125,8 +1126,9 @@ intrinsiccv_error_t intrinsiccv_transpose(const void *src, size_t src_stride, /// @param width Number of elements in a row for the source streams, /// number of pixels in a row for the destination data. /// @param height Number of rows in the data. -/// @param channels Number of channels in the destination data. -/// @param element_size Size of one element in bytes. +/// @param channels Number of channels in the destination data. Must be 2, +/// 3 or 4. +/// @param element_size Size of one element in bytes. Must be 1, 2, 4 or 8. /// intrinsiccv_error_t intrinsiccv_merge(const void **srcs, const size_t *src_strides, void *dst, -- GitLab From 20aafbb21e7a8fb6a46723d70a95a32624b141a5 Mon Sep 17 00:00:00 2001 From: Mark Horvath Date: Wed, 14 Feb 2024 23:27:14 +0100 Subject: [PATCH 6/9] Fix stride constraints for color conversion --- intrinsiccv/include/intrinsiccv/intrinsiccv.h | 44 +++++++++---------- 1 file changed, 22 insertions(+), 22 deletions(-) diff --git a/intrinsiccv/include/intrinsiccv/intrinsiccv.h b/intrinsiccv/include/intrinsiccv/intrinsiccv.h index b8487a3c5..19f5c7e37 100644 --- a/intrinsiccv/include/intrinsiccv/intrinsiccv.h +++ b/intrinsiccv/include/intrinsiccv/intrinsiccv.h @@ -277,7 +277,7 @@ intrinsiccv_error_t intrinsiccv_saturating_add_abs_with_threshold_s16( /// @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 for the destination data. -/// Must not be less than width * sizeof(uint8). +/// Must not be less than width * 3 * sizeof(uint8). /// @param width Number of pixels in a row. /// @param height Number of rows in the data. /// @@ -303,7 +303,7 @@ intrinsiccv_error_t intrinsiccv_gray_to_rgb_u8(const uint8_t *src, /// @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 for the destination data. -/// Must not be less than width * sizeof(uint8). +/// Must not be less than width * 4 * sizeof(uint8). /// @param width Number of pixels in a row. /// @param height Number of rows in the data. /// @@ -325,11 +325,11 @@ intrinsiccv_error_t intrinsiccv_gray_to_rgba_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 for the source data. -/// Must not be less than width * sizeof(uint8). +/// Must not be less than width * 3 * sizeof(uint8). /// @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 for the destination data. -/// Must not be less than width * sizeof(uint8). +/// Must not be less than width * 3 * sizeof(uint8). /// @param width Number of pixels in a row. /// @param height Number of rows in the data. /// @@ -347,11 +347,11 @@ intrinsiccv_error_t intrinsiccv_rgb_to_bgr_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 for the source data. -/// Must not be less than width * sizeof(uint8). +/// Must not be less than width * 3 * sizeof(uint8). /// @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 for the destination data. -/// Must not be less than width * sizeof(uint8). +/// Must not be less than width * 3 * sizeof(uint8). /// @param width Number of pixels in a row. /// @param height Number of rows in the data. /// @@ -373,11 +373,11 @@ intrinsiccv_error_t intrinsiccv_rgb_to_rgb_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 for the source data. -/// Must not be less than width * sizeof(uint8). +/// Must not be less than width * 4 * sizeof(uint8). /// @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 for the destination data. -/// Must not be less than width * sizeof(uint8). +/// Must not be less than width * 4 * sizeof(uint8). /// @param width Number of pixels in a row. /// @param height Number of rows in the data. /// @@ -395,11 +395,11 @@ intrinsiccv_error_t intrinsiccv_rgba_to_bgra_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 for the source data. -/// Must not be less than width * sizeof(uint8). +/// Must not be less than width * 4 * sizeof(uint8). /// @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 for the destination data. -/// Must not be less than width * sizeof(uint8). +/// Must not be less than width * 4 * sizeof(uint8). /// @param width Number of pixels in a row. /// @param height Number of rows in the data. /// @@ -422,11 +422,11 @@ intrinsiccv_error_t intrinsiccv_rgba_to_rgba_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 for the source data. -/// Must not be less than width * sizeof(uint8). +/// Must not be less than width * 3 * sizeof(uint8). /// @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 for the destination data. -/// Must not be less than width * sizeof(uint8). +/// Must not be less than width * 4 * sizeof(uint8). /// @param width Number of pixels in a row. /// @param height Number of rows in the data. /// @@ -449,11 +449,11 @@ intrinsiccv_error_t intrinsiccv_rgb_to_bgra_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 for the source data. -/// Must not be less than width * sizeof(uint8). +/// Must not be less than width * 3 * sizeof(uint8). /// @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 for the destination data. -/// Must not be less than width * sizeof(uint8). +/// Must not be less than width * 4 * sizeof(uint8). /// @param width Number of pixels in a row. /// @param height Number of rows in the data. /// @@ -476,11 +476,11 @@ intrinsiccv_error_t intrinsiccv_rgb_to_rgba_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 for the source data. -/// Must not be less than width * sizeof(uint8). +/// Must not be less than width * 4 * sizeof(uint8). /// @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 for the destination data. -/// Must not be less than width * sizeof(uint8). +/// Must not be less than width * 3 * sizeof(uint8). /// @param width Number of pixels in a row. /// @param height Number of rows in the data. /// @@ -503,11 +503,11 @@ intrinsiccv_error_t intrinsiccv_rgba_to_bgr_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 for the source data. -/// Must not be less than width * sizeof(uint8). +/// Must not be less than width * 4 * sizeof(uint8). /// @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 for the destination data. -/// Must not be less than width * sizeof(uint8). +/// Must not be less than width * 3 * sizeof(uint8). /// @param width Number of pixels in a row. /// @param height Number of rows in the data. /// @@ -542,7 +542,7 @@ intrinsiccv_error_t intrinsiccv_rgba_to_rgb_u8(const uint8_t *src, /// @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 for the destination data. Must -/// not be less than width * sizeof(type). +/// not be less than width * 3 * sizeof(type). /// @param width Number of pixels in a row. /// @param height Number of rows in the data. /// @param is_nv21 If true, input is treated as NV21, otherwise treated @@ -579,7 +579,7 @@ intrinsiccv_error_t intrinsiccv_yuv_sp_to_rgb_u8( /// @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 for the destination data. Must -/// not be less than width * sizeof(type). +/// not be less than width * 3 * sizeof(type). /// @param width Number of pixels in a row. /// @param height Number of rows in the data. /// @param is_nv21 If true, input is treated as NV21, otherwise treated @@ -615,7 +615,7 @@ intrinsiccv_error_t intrinsiccv_yuv_sp_to_bgr_u8( /// @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 for the destination data. Must -/// not be less than width * sizeof(type). +/// not be less than width * 4 * sizeof(type). /// @param width Number of pixels in a row. /// @param height Number of rows in the data. /// @param is_nv21 If true, input is treated as NV21, otherwise treated @@ -651,7 +651,7 @@ intrinsiccv_error_t intrinsiccv_yuv_sp_to_rgba_u8( /// @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 for the destination data. Must -/// not be less than width * sizeof(type). +/// not be less than width * 4 * sizeof(type). /// @param width Number of pixels in a row. /// @param height Number of rows in the data. /// @param is_nv21 If true, input is treated as NV21, otherwise treated -- GitLab From 3e784913151ed3c1ff84c192e6579d8500615d2f Mon Sep 17 00:00:00 2001 From: Mark Horvath Date: Wed, 14 Feb 2024 23:50:30 +0100 Subject: [PATCH 7/9] Add constraint for Sobel about channel number --- intrinsiccv/include/intrinsiccv/intrinsiccv.h | 10 +++++---- intrinsiccv/src/filters/sobel_neon.cpp | 8 +++++++ intrinsiccv/src/filters/sobel_sc.h | 8 +++++++ test/api/test_sobel.cpp | 22 +++++++++++++++++++ 4 files changed, 44 insertions(+), 4 deletions(-) diff --git a/intrinsiccv/include/intrinsiccv/intrinsiccv.h b/intrinsiccv/include/intrinsiccv/intrinsiccv.h index 19f5c7e37..49de82fe9 100644 --- a/intrinsiccv/include/intrinsiccv/intrinsiccv.h +++ b/intrinsiccv/include/intrinsiccv/intrinsiccv.h @@ -872,11 +872,12 @@ intrinsiccv_error_t intrinsiccv_resize_to_quarter_u8( /// @param width Number of pixels in the data. (One pixel consists of /// 'channels' number of elements.) /// @param height Number of rows in the data. -/// @param channel Number of channels in the data. +/// @param channels Number of channels in the data. Must be not more than +/// \ref INTRINSICCV_MAXIMUM_CHANNEL_COUNT. /// intrinsiccv_error_t intrinsiccv_sobel_3x3_vertical_s16_u8( const uint8_t *src, size_t src_stride, int16_t *dst, size_t dst_stride, - size_t width, size_t height, size_t channel); + size_t width, size_t height, size_t channels); /// Calculates horizontal derivative approximation with Sobel filter. /// @@ -907,11 +908,12 @@ intrinsiccv_error_t intrinsiccv_sobel_3x3_vertical_s16_u8( /// @param width Number of pixels in the data. (One pixel consists of /// 'channels' number of elements.) /// @param height Number of rows in the data. -/// @param channel Number of channels in the data. +/// @param channels Number of channels in the data. Must be not more than +/// \ref INTRINSICCV_MAXIMUM_CHANNEL_COUNT. /// intrinsiccv_error_t intrinsiccv_sobel_3x3_horizontal_s16_u8( const uint8_t *src, size_t src_stride, int16_t *dst, size_t dst_stride, - size_t width, size_t height, size_t channel); + size_t width, size_t height, size_t channels); /// Canny edge detector for uint8_t grayscale input. Output is also a uint8_t /// grayscale image. Width and height are the same for input and output. Number diff --git a/intrinsiccv/src/filters/sobel_neon.cpp b/intrinsiccv/src/filters/sobel_neon.cpp index e5c26d41c..9ed8cc9cc 100644 --- a/intrinsiccv/src/filters/sobel_neon.cpp +++ b/intrinsiccv/src/filters/sobel_neon.cpp @@ -136,6 +136,10 @@ intrinsiccv_error_t sobel_3x3_horizontal_s16_u8(const uint8_t *src, CHECK_POINTER_AND_STRIDE(dst, dst_stride); CHECK_IMAGE_SIZE(width, height); + if (channels > INTRINSICCV_MAXIMUM_CHANNEL_COUNT) { + return INTRINSICCV_ERROR_RANGE; + } + Rectangle rect{width, height}; Rows src_rows{src, src_stride, channels}; Rows dst_rows{dst, dst_stride, channels}; @@ -162,6 +166,10 @@ intrinsiccv_error_t sobel_3x3_vertical_s16_u8(const uint8_t *src, CHECK_POINTER_AND_STRIDE(dst, dst_stride); CHECK_IMAGE_SIZE(width, height); + if (channels > INTRINSICCV_MAXIMUM_CHANNEL_COUNT) { + return INTRINSICCV_ERROR_RANGE; + } + Rectangle rect{width, height}; Rows src_rows{src, src_stride, channels}; Rows dst_rows{dst, dst_stride, channels}; diff --git a/intrinsiccv/src/filters/sobel_sc.h b/intrinsiccv/src/filters/sobel_sc.h index 77c3e5564..c9cd893a2 100644 --- a/intrinsiccv/src/filters/sobel_sc.h +++ b/intrinsiccv/src/filters/sobel_sc.h @@ -126,6 +126,10 @@ static intrinsiccv_error_t sobel_3x3_horizontal_s16_u8_sc( CHECK_POINTER_AND_STRIDE(dst, dst_stride); CHECK_IMAGE_SIZE(width, height); + if (channels > INTRINSICCV_MAXIMUM_CHANNEL_COUNT) { + return INTRINSICCV_ERROR_RANGE; + } + Rectangle rect{width, height}; Rows src_rows{src, src_stride, channels}; Rows dst_rows{dst, dst_stride, channels}; @@ -153,6 +157,10 @@ static intrinsiccv_error_t sobel_3x3_vertical_s16_u8_sc( CHECK_POINTER_AND_STRIDE(dst, dst_stride); CHECK_IMAGE_SIZE(width, height); + if (channels > INTRINSICCV_MAXIMUM_CHANNEL_COUNT) { + return INTRINSICCV_ERROR_RANGE; + } + Rectangle rect{width, height}; Rows src_rows{src, src_stride, channels}; Rows dst_rows{dst, dst_stride, channels}; diff --git a/test/api/test_sobel.cpp b/test/api/test_sobel.cpp index dce2430c2..34cd6b73c 100644 --- a/test/api/test_sobel.cpp +++ b/test/api/test_sobel.cpp @@ -174,3 +174,25 @@ TYPED_TEST(Sobel, ImageSizeVertical) { INTRINSICCV_MAX_IMAGE_PIXELS, INTRINSICCV_MAX_IMAGE_PIXELS, 1)); } + +TYPED_TEST(Sobel, ChannelNumberHorizontal) { + using KernelTestParams = SobelKernelTestParams; + typename KernelTestParams::InputType src[1] = {}; + typename KernelTestParams::OutputType dst[1]; + + EXPECT_EQ(INTRINSICCV_ERROR_RANGE, + sobel_3x3_horizontal()( + src, sizeof(src), dst, sizeof(dst), 1, 1, + INTRINSICCV_MAXIMUM_CHANNEL_COUNT + 1)); +} + +TYPED_TEST(Sobel, ChannelNumberVertical) { + using KernelTestParams = SobelKernelTestParams; + typename KernelTestParams::InputType src[1] = {}; + typename KernelTestParams::OutputType dst[1]; + + EXPECT_EQ( + INTRINSICCV_ERROR_RANGE, + sobel_3x3_vertical()(src, sizeof(src), dst, sizeof(dst), 1, 1, + INTRINSICCV_MAXIMUM_CHANNEL_COUNT + 1)); +} -- GitLab From 08713bdeb3f5165a91af66d139cbc3cea42c6891 Mon Sep 17 00:00:00 2001 From: Mark Horvath Date: Thu, 15 Feb 2024 00:20:42 +0100 Subject: [PATCH 8/9] Add Gaussian related constraint checks --- intrinsiccv/include/intrinsiccv/intrinsiccv.h | 15 ++-- .../include/intrinsiccv/workspace/separable.h | 14 ++- intrinsiccv/src/filters/gaussian_blur_api.cpp | 8 ++ .../src/filters/gaussian_blur_neon.cpp | 16 ++++ intrinsiccv/src/filters/gaussian_blur_sc.h | 16 ++++ test/api/test_gaussian_blur.cpp | 90 +++++++++++++++++++ 6 files changed, 153 insertions(+), 6 deletions(-) diff --git a/intrinsiccv/include/intrinsiccv/intrinsiccv.h b/intrinsiccv/include/intrinsiccv/intrinsiccv.h index 49de82fe9..a4771c498 100644 --- a/intrinsiccv/include/intrinsiccv/intrinsiccv.h +++ b/intrinsiccv/include/intrinsiccv/intrinsiccv.h @@ -955,8 +955,10 @@ intrinsiccv_error_t intrinsiccv_canny_u8(const uint8_t *src, size_t src_stride, /// using \ref intrinsiccv_filter_release. /// /// @param context Pointer where to return the created context's address. -/// @param channels Number of elements for each pixel. -/// @param type_size Element size in bytes. +/// @param channels Number of channels in the data. Must be not more than +/// \ref INTRINSICCV_MAXIMUM_CHANNEL_COUNT. +/// @param type_size Element size in bytes. Must not be more than +/// \ref INTRINSICCV_MAXIMUM_TYPE_SIZE. /// @param image Image dimensions. Its size must not be more than /// \ref INTRINSICCV_MAX_IMAGE_PIXELS. /// @@ -996,8 +998,10 @@ intrinsiccv_error_t intrinsiccv_filter_release( /// Usage: \n /// Before using this function, a context must be created using /// intrinsiccv_filter_create, and after finished, it has to be released -/// using intrinsiccv_filter_release. Note, from the border types only -/// these are supported: \n +/// using intrinsiccv_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 /// - \ref INTRINSICCV_BORDER_TYPE_REPLICATE \n /// - \ref INTRINSICCV_BORDER_TYPE_REFLECT \n /// - \ref INTRINSICCV_BORDER_TYPE_WRAP \n @@ -1016,7 +1020,8 @@ intrinsiccv_error_t intrinsiccv_filter_release( /// @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. +/// @param channels Number of channels in the data. Must be not more than +/// \ref INTRINSICCV_MAXIMUM_CHANNEL_COUNT. /// @param border_type Way of handling the border. /// @param context Pointer to filter context. /// diff --git a/intrinsiccv/include/intrinsiccv/workspace/separable.h b/intrinsiccv/include/intrinsiccv/workspace/separable.h index 1d456838f..4b7f80007 100644 --- a/intrinsiccv/include/intrinsiccv/workspace/separable.h +++ b/intrinsiccv/include/intrinsiccv/workspace/separable.h @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: 2023 Arm Limited and/or its affiliates +// SPDX-FileCopyrightText: 2023 - 2024 Arm Limited and/or its affiliates // // SPDX-License-Identifier: Apache-2.0 @@ -109,10 +109,17 @@ class SeparableFilterWorkspace final { buffer_rows_address = __builtin_align_up(buffer_rows_address, kAlignment); workspace->buffer_rows_offset_ = buffer_rows_address - &workspace->data_[0]; workspace->buffer_rows_stride_ = buffer_rows_stride; + workspace->image_size_ = rect; + workspace->channels_ = channels; + workspace->buffer_type_size_ = buffer_type_size; return workspace; } + size_t channels() const { return channels_; } + Rectangle image_size() const { return image_size_; } + size_t buffer_type_size() const { return buffer_type_size_; } + // Processes rows vertically first along the full width template void process(Rectangle rect, @@ -191,6 +198,11 @@ class SeparableFilterWorkspace final { size_t buffer_rows_offset_; // Stride of the buffer rows. size_t buffer_rows_stride_; + + Rectangle image_size_; + size_t channels_; + size_t buffer_type_size_; + // Workspace area begins here. uint8_t data_[0] INTRINSICCV_ATTR_ALIGNED(kAlignment); }; // end of class SeparableFilterWorkspace diff --git a/intrinsiccv/src/filters/gaussian_blur_api.cpp b/intrinsiccv/src/filters/gaussian_blur_api.cpp index 2f922939d..7ef7e9725 100644 --- a/intrinsiccv/src/filters/gaussian_blur_api.cpp +++ b/intrinsiccv/src/filters/gaussian_blur_api.cpp @@ -17,6 +17,14 @@ intrinsiccv_error_t intrinsiccv_filter_create( CHECK_POINTERS(context); CHECK_RECTANGLE_SIZE(image); + if (type_size > INTRINSICCV_MAXIMUM_TYPE_SIZE) { + return INTRINSICCV_ERROR_RANGE; + } + + if (channels > INTRINSICCV_MAXIMUM_CHANNEL_COUNT) { + return INTRINSICCV_ERROR_RANGE; + } + auto workspace = SeparableFilterWorkspace::create(Rectangle{image}, channels, type_size); if (!workspace) { diff --git a/intrinsiccv/src/filters/gaussian_blur_neon.cpp b/intrinsiccv/src/filters/gaussian_blur_neon.cpp index 6f1567345..6622da370 100644 --- a/intrinsiccv/src/filters/gaussian_blur_neon.cpp +++ b/intrinsiccv/src/filters/gaussian_blur_neon.cpp @@ -155,12 +155,28 @@ intrinsiccv_error_t discrete_gaussian_blur( CHECK_POINTER_AND_STRIDE(dst, dst_stride); CHECK_IMAGE_SIZE(width, height); + if (channels > INTRINSICCV_MAXIMUM_CHANNEL_COUNT) { + return INTRINSICCV_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 (workspace->buffer_type_size() != sizeof(ScalarType)) { + return INTRINSICCV_ERROR_CONTEXT_MISMATCH; + } + + if (workspace->channels() != channels) { + return INTRINSICCV_ERROR_CONTEXT_MISMATCH; + } + + if (workspace->image_size() != rect) { + return INTRINSICCV_ERROR_CONTEXT_MISMATCH; + } + auto fixed_border_type = get_fixed_border_type(border_type); if (!fixed_border_type) { diff --git a/intrinsiccv/src/filters/gaussian_blur_sc.h b/intrinsiccv/src/filters/gaussian_blur_sc.h index 9ab684f23..62f6588c6 100644 --- a/intrinsiccv/src/filters/gaussian_blur_sc.h +++ b/intrinsiccv/src/filters/gaussian_blur_sc.h @@ -95,12 +95,28 @@ intrinsiccv_error_t discrete_gaussian_blur( CHECK_POINTER_AND_STRIDE(dst, dst_stride); CHECK_IMAGE_SIZE(width, height); + if (channels > INTRINSICCV_MAXIMUM_CHANNEL_COUNT) { + return INTRINSICCV_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 (workspace->buffer_type_size() != sizeof(ScalarType)) { + return INTRINSICCV_ERROR_CONTEXT_MISMATCH; + } + + if (workspace->channels() != channels) { + return INTRINSICCV_ERROR_CONTEXT_MISMATCH; + } + + if (workspace->image_size() != rect) { + return INTRINSICCV_ERROR_CONTEXT_MISMATCH; + } + GaussianBlurFilterType blur; SeparableFilter filter{blur}; diff --git a/test/api/test_gaussian_blur.cpp b/test/api/test_gaussian_blur.cpp index 8e5fc91fb..e8d2798b8 100644 --- a/test/api/test_gaussian_blur.cpp +++ b/test/api/test_gaussian_blur.cpp @@ -118,6 +118,76 @@ TYPED_TEST(GaussianBlurTest, ImageSize) { EXPECT_EQ(INTRINSICCV_OK, intrinsiccv_filter_release(context)); } +TYPED_TEST(GaussianBlurTest, ChannelNumber) { + 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]; + EXPECT_EQ(INTRINSICCV_ERROR_RANGE, + gaussian_blur_3x3()( + src, sizeof(TypeParam), dst, sizeof(TypeParam), 1, 1, + INTRINSICCV_MAXIMUM_CHANNEL_COUNT + 1, + INTRINSICCV_BORDER_TYPE_REFLECT, context)); + EXPECT_EQ(INTRINSICCV_ERROR_RANGE, + gaussian_blur_5x5()( + src, sizeof(TypeParam), dst, sizeof(TypeParam), 1, 1, + INTRINSICCV_MAXIMUM_CHANNEL_COUNT + 1, + INTRINSICCV_BORDER_TYPE_REFLECT, context)); + EXPECT_EQ(INTRINSICCV_OK, intrinsiccv_filter_release(context)); +} + +TYPED_TEST(GaussianBlurTest, InvalidContextSizeType) { + intrinsiccv_filter_context_t *context = nullptr; + ASSERT_EQ(INTRINSICCV_OK, + intrinsiccv_filter_create(&context, 1, sizeof(TypeParam) + 1, + intrinsiccv_rectangle_t{1, 1})); + TypeParam src[1], dst[1]; + EXPECT_EQ(INTRINSICCV_ERROR_CONTEXT_MISMATCH, + gaussian_blur_3x3()( + src, sizeof(TypeParam), dst, sizeof(TypeParam), 1, 1, 1, + INTRINSICCV_BORDER_TYPE_REFLECT, context)); + EXPECT_EQ(INTRINSICCV_ERROR_CONTEXT_MISMATCH, + gaussian_blur_5x5()( + src, sizeof(TypeParam), dst, sizeof(TypeParam), 1, 1, 1, + INTRINSICCV_BORDER_TYPE_REFLECT, context)); + EXPECT_EQ(INTRINSICCV_OK, intrinsiccv_filter_release(context)); +} + +TYPED_TEST(GaussianBlurTest, InvalidContextChannelNumber) { + intrinsiccv_filter_context_t *context = nullptr; + ASSERT_EQ(INTRINSICCV_OK, + intrinsiccv_filter_create(&context, 2, sizeof(TypeParam), + intrinsiccv_rectangle_t{1, 1})); + TypeParam src[1], dst[1]; + EXPECT_EQ(INTRINSICCV_ERROR_CONTEXT_MISMATCH, + gaussian_blur_3x3()( + src, sizeof(TypeParam), dst, sizeof(TypeParam), 1, 1, 1, + INTRINSICCV_BORDER_TYPE_REFLECT, context)); + EXPECT_EQ(INTRINSICCV_ERROR_CONTEXT_MISMATCH, + gaussian_blur_5x5()( + src, sizeof(TypeParam), dst, sizeof(TypeParam), 1, 1, 1, + INTRINSICCV_BORDER_TYPE_REFLECT, context)); + EXPECT_EQ(INTRINSICCV_OK, intrinsiccv_filter_release(context)); +} + +TYPED_TEST(GaussianBlurTest, InvalidContextImageSize) { + 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]; + EXPECT_EQ(INTRINSICCV_ERROR_CONTEXT_MISMATCH, + gaussian_blur_3x3()( + src, sizeof(TypeParam), dst, sizeof(TypeParam), 2, 2, 1, + INTRINSICCV_BORDER_TYPE_REFLECT, context)); + EXPECT_EQ(INTRINSICCV_ERROR_CONTEXT_MISMATCH, + gaussian_blur_5x5()( + src, sizeof(TypeParam), dst, sizeof(TypeParam), 2, 2, 1, + INTRINSICCV_BORDER_TYPE_REFLECT, context)); + EXPECT_EQ(INTRINSICCV_OK, intrinsiccv_filter_release(context)); +} + TEST(FilterCreate, ImageSize) { intrinsiccv_filter_context_t *context = nullptr; @@ -131,3 +201,23 @@ TEST(FilterCreate, ImageSize) { ASSERT_EQ(nullptr, context); } } + +TEST(FilterCreate, TypeSize) { + intrinsiccv_filter_context_t *context = nullptr; + + EXPECT_EQ( + INTRINSICCV_ERROR_RANGE, + intrinsiccv_filter_create(&context, 1, INTRINSICCV_MAXIMUM_TYPE_SIZE + 1, + intrinsiccv_rectangle_t{1, 1})); + ASSERT_EQ(nullptr, context); +} + +TEST(FilterCreate, ChannelNumber) { + intrinsiccv_filter_context_t *context = nullptr; + + EXPECT_EQ( + INTRINSICCV_ERROR_RANGE, + intrinsiccv_filter_create(&context, INTRINSICCV_MAXIMUM_CHANNEL_COUNT + 1, + 1, intrinsiccv_rectangle_t{1, 1})); + ASSERT_EQ(nullptr, context); +} -- GitLab From 3471f52f9e161aaa7fc07921ebf2a54f8ba30db9 Mon Sep 17 00:00:00 2001 From: Mark Horvath Date: Thu, 15 Feb 2024 16:54:11 +0100 Subject: [PATCH 9/9] Use @ref instead of \ref in doxygen comments Also removed all \ref from the comments in the test files. --- intrinsiccv/include/intrinsiccv/ctypes.h | 2 +- intrinsiccv/include/intrinsiccv/intrinsiccv.h | 118 +++++++++--------- test/api/test_add_abs_with_threshold.cpp | 2 +- test/api/test_saturating_absdiff.cpp | 2 +- test/api/test_saturating_add.cpp | 2 +- test/api/test_saturating_multiply.cpp | 2 +- test/api/test_saturating_sub.cpp | 2 +- test/api/test_scale.cpp | 2 +- test/framework/array.h | 4 +- 9 files changed, 68 insertions(+), 68 deletions(-) diff --git a/intrinsiccv/include/intrinsiccv/ctypes.h b/intrinsiccv/include/intrinsiccv/ctypes.h index 20f651050..22be39c1a 100644 --- a/intrinsiccv/include/intrinsiccv/ctypes.h +++ b/intrinsiccv/include/intrinsiccv/ctypes.h @@ -32,7 +32,7 @@ typedef enum INTRINSICCV_NODISCARD { INTRINSICCV_ERROR_ALLOCATION, /// A value did not meet alignment requirements. INTRINSICCV_ERROR_ALIGNMENT, - /// The provided context (like \ref intrinsiccv_morphology_context_t) is not + /// The provided context (like @ref intrinsiccv_morphology_context_t) is not /// compatible with the operation. INTRINSICCV_ERROR_CONTEXT_MISMATCH, } intrinsiccv_error_t; diff --git a/intrinsiccv/include/intrinsiccv/intrinsiccv.h b/intrinsiccv/include/intrinsiccv/intrinsiccv.h index a4771c498..d75cb6469 100644 --- a/intrinsiccv/include/intrinsiccv/intrinsiccv.h +++ b/intrinsiccv/include/intrinsiccv/intrinsiccv.h @@ -66,7 +66,7 @@ extern "C" { /// type of the element if the addition result would overflow. Source data /// length (in bytes) is `stride` * `height`. Width and height are the same /// for the two sources and for the destination. Number of elements is limited -/// to \ref INTRINSICCV_MAX_IMAGE_PIXELS. +/// to @ref INTRINSICCV_MAX_IMAGE_PIXELS. /// /// @param src_a Pointer to the first source data. Must be non-null. /// @param src_b Pointer to the second source data. Must be non-null. @@ -109,7 +109,7 @@ INTRINSICCV_BINARY_OP(intrinsiccv_saturating_add_u64, uint64_t); /// smallest possible value of the type of the element if the subtraction result /// would underflow. Source data length (in bytes) is `stride` * `height`. /// Width and height are the same for the two sources and for the destination. -/// Number of elements is limited to \ref INTRINSICCV_MAX_IMAGE_PIXELS. +/// Number of elements is limited to @ref INTRINSICCV_MAX_IMAGE_PIXELS. /// /// @param src_a Pointer to the first source data. Must be non-null. /// @param src_b Pointer to the second source data. Must be non-null. @@ -152,7 +152,7 @@ INTRINSICCV_BINARY_OP(intrinsiccv_saturating_sub_u64, uint64_t); /// type of the element if the result would overflow (it is only possible with /// signed types). Source data length (in bytes) is `stride` * `height`. Width /// and height are the same for the two sources and for the destination. Number -/// of elements is limited to \ref INTRINSICCV_MAX_IMAGE_PIXELS. +/// of elements is limited to @ref INTRINSICCV_MAX_IMAGE_PIXELS. /// /// @param src_a Pointer to the first source data. Must be non-null. /// @param src_b Pointer to the second source data. Must be non-null. @@ -189,7 +189,7 @@ INTRINSICCV_BINARY_OP(intrinsiccv_saturating_absdiff_s32, int32_t); /// the type of the element if the multiplication result would overflow. Source /// data length (in bytes) is `stride` * `height`. Width and height are the /// same for the two sources and for the destination. Number of elements is -/// limited to \ref INTRINSICCV_MAX_IMAGE_PIXELS. +/// limited to @ref INTRINSICCV_MAX_IMAGE_PIXELS. /// /// @param src_a Pointer to the first source data. Must be non-null. /// @param src_b Pointer to the second source data. Must be non-null. @@ -233,7 +233,7 @@ INTRINSICCV_BINARY_OP_SCALE(intrinsiccv_saturating_multiply_s32, int32_t, /// type of the element if the addition result would overflow. Source data /// length (in bytes) is `stride` * `height`. Width and height are the same /// for the two sources and for the destination. Number of elements is limited -/// to \ref INTRINSICCV_MAX_IMAGE_PIXELS. +/// to @ref INTRINSICCV_MAX_IMAGE_PIXELS. /// /// @param src_a Pointer to the first source data. Must be non-null. /// @param src_b Pointer to the second source data. Must be non-null. @@ -268,7 +268,7 @@ intrinsiccv_error_t intrinsiccv_saturating_add_abs_with_threshold_s16( /// by 3 bytes. There is no padding between the pixels. /// /// Width and height are the same for the source and for the destination. Number -/// of pixels is limited to \ref INTRINSICCV_MAX_IMAGE_PIXELS. +/// of pixels is limited to @ref INTRINSICCV_MAX_IMAGE_PIXELS. /// /// @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 @@ -294,7 +294,7 @@ intrinsiccv_error_t intrinsiccv_gray_to_rgb_u8(const uint8_t *src, /// by 4 bytes. There is no padding between the pixels. /// /// Width and height are the same for the source and for the destination. Number -/// of pixels is limited to \ref INTRINSICCV_MAX_IMAGE_PIXELS. +/// of pixels is limited to @ref INTRINSICCV_MAX_IMAGE_PIXELS. /// /// @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 @@ -320,7 +320,7 @@ intrinsiccv_error_t intrinsiccv_gray_to_rgba_u8(const uint8_t *src, /// by 3 bytes. There is no padding between the pixels. /// /// Width and height are the same for the source and for the destination. Number -/// of pixels is limited to \ref INTRINSICCV_MAX_IMAGE_PIXELS. +/// of pixels is limited to @ref INTRINSICCV_MAX_IMAGE_PIXELS. /// /// @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 @@ -342,7 +342,7 @@ intrinsiccv_error_t intrinsiccv_rgb_to_bgr_u8(const uint8_t *src, /// All channels are 8-bit wide. /// /// Width and height are the same for the source and for the destination. Number -/// of pixels is limited to \ref INTRINSICCV_MAX_IMAGE_PIXELS. +/// of pixels is limited to @ref INTRINSICCV_MAX_IMAGE_PIXELS. /// /// @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 @@ -368,7 +368,7 @@ intrinsiccv_error_t intrinsiccv_rgb_to_rgb_u8(const uint8_t *src, /// by 4 bytes. There is no padding between the pixels. /// /// Width and height are the same for the source and for the destination. Number -/// of pixels is limited to \ref INTRINSICCV_MAX_IMAGE_PIXELS. +/// of pixels is limited to @ref INTRINSICCV_MAX_IMAGE_PIXELS. /// /// @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 @@ -390,7 +390,7 @@ intrinsiccv_error_t intrinsiccv_rgba_to_bgra_u8(const uint8_t *src, /// All channels are 8-bit wide. /// /// Width and height are the same for the source and for the destination. Number -/// of pixels is limited to \ref INTRINSICCV_MAX_IMAGE_PIXELS. +/// of pixels is limited to @ref INTRINSICCV_MAX_IMAGE_PIXELS. /// /// @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 @@ -417,7 +417,7 @@ intrinsiccv_error_t intrinsiccv_rgba_to_rgba_u8(const uint8_t *src, /// by 4 bytes. There is no padding between the pixels. /// /// Width and height are the same for the source and for the destination. Number -/// of pixels is limited to \ref INTRINSICCV_MAX_IMAGE_PIXELS. +/// of pixels is limited to @ref INTRINSICCV_MAX_IMAGE_PIXELS. /// /// @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 @@ -444,7 +444,7 @@ intrinsiccv_error_t intrinsiccv_rgb_to_bgra_u8(const uint8_t *src, /// by 4 bytes. There is no padding between the pixels. /// /// Width and height are the same for the source and for the destination. Number -/// of pixels is limited to \ref INTRINSICCV_MAX_IMAGE_PIXELS. +/// of pixels is limited to @ref INTRINSICCV_MAX_IMAGE_PIXELS. /// /// @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 @@ -471,7 +471,7 @@ intrinsiccv_error_t intrinsiccv_rgb_to_rgba_u8(const uint8_t *src, /// by 3 bytes. There is no padding between the pixels. /// /// Width and height are the same for the source and for the destination. Number -/// of pixels is limited to \ref INTRINSICCV_MAX_IMAGE_PIXELS. +/// of pixels is limited to @ref INTRINSICCV_MAX_IMAGE_PIXELS. /// /// @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 @@ -498,7 +498,7 @@ intrinsiccv_error_t intrinsiccv_rgba_to_bgr_u8(const uint8_t *src, /// by 3 bytes. There is no padding between the pixels. /// /// Width and height are the same for the source and for the destination. Number -/// of pixels is limited to \ref INTRINSICCV_MAX_IMAGE_PIXELS. +/// of pixels is limited to @ref INTRINSICCV_MAX_IMAGE_PIXELS. /// /// @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 @@ -526,7 +526,7 @@ intrinsiccv_error_t intrinsiccv_rgba_to_rgb_u8(const uint8_t *src, /// used. /// /// Width and height are the same for the source and for the destination. Number -/// of pixels is limited to \ref INTRINSICCV_MAX_IMAGE_PIXELS. +/// of pixels is limited to @ref INTRINSICCV_MAX_IMAGE_PIXELS. /// /// @param src_y Pointer to the input's Y component. Must be non-null. /// @param src_y_stride Distance in bytes from the start of one row to the @@ -563,7 +563,7 @@ intrinsiccv_error_t intrinsiccv_yuv_sp_to_rgb_u8( /// used. /// /// Width and height are the same for the source and for the destination. Number -/// of pixels is limited to \ref INTRINSICCV_MAX_IMAGE_PIXELS. +/// of pixels is limited to @ref INTRINSICCV_MAX_IMAGE_PIXELS. /// /// @param src_y Pointer to the input's Y component. Must be non-null. /// @param src_y_stride Distance in bytes from the start of one row to the @@ -599,7 +599,7 @@ intrinsiccv_error_t intrinsiccv_yuv_sp_to_bgr_u8( /// by 4 bytes. There is no padding between the pixels. /// /// Width and height are the same for the source and for the destination. Number -/// of pixels is limited to \ref INTRINSICCV_MAX_IMAGE_PIXELS. +/// of pixels is limited to @ref INTRINSICCV_MAX_IMAGE_PIXELS. /// /// @param src_y Pointer to the input's Y component. Must be non-null. /// @param src_y_stride Distance in bytes from the start of one row to the @@ -635,7 +635,7 @@ intrinsiccv_error_t intrinsiccv_yuv_sp_to_rgba_u8( /// by 4 bytes. There is no padding between the pixels. /// /// Width and height are the same for the source and for the destination. Number -/// of pixels is limited to \ref INTRINSICCV_MAX_IMAGE_PIXELS. +/// of pixels is limited to @ref INTRINSICCV_MAX_IMAGE_PIXELS. /// /// @param src_y Pointer to the input's Y component. Must be non-null. /// @param src_y_stride Distance in bytes from the start of one row to the @@ -667,7 +667,7 @@ intrinsiccv_error_t intrinsiccv_yuv_sp_to_bgra_u8( /// `value` and the rest to 0. /// /// Width and height are the same for the source and for the destination. Number -/// of elements is limited to \ref INTRINSICCV_MAX_IMAGE_PIXELS. +/// of elements is limited to @ref INTRINSICCV_MAX_IMAGE_PIXELS. /// /// @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 @@ -691,30 +691,30 @@ intrinsiccv_error_t intrinsiccv_threshold_binary_u8( /// Creates a morphology context according to the parameters. /// -/// Before a \ref intrinsiccv_dilate_u8 "dilate" or \ref intrinsiccv_erode_u8 +/// Before a @ref intrinsiccv_dilate_u8 "dilate" or @ref intrinsiccv_erode_u8 /// "erode" operation, this initialization is needed. After the operation is -/// finished, the context needs to be released using \ref +/// finished, the context needs to be released using @ref /// intrinsiccv_morphology_release. /// /// @param context Pointer where to return the created context's address. /// @param kernel Width and height of the kernel. Its size must not be -/// more than \ref INTRINSICCV_MAX_IMAGE_PIXELS. +/// more than @ref INTRINSICCV_MAX_IMAGE_PIXELS. /// @param anchor Location in the kernel which is aligned to the actual /// point in the source data. Must not point out of the /// kernel. /// @param border_type Way of handling the border. The supported border types /// are: \n -/// - \ref INTRINSICCV_BORDER_TYPE_CONSTANT \n -/// - \ref INTRINSICCV_BORDER_TYPE_REPLICATE +/// - @ref INTRINSICCV_BORDER_TYPE_CONSTANT \n +/// - @ref INTRINSICCV_BORDER_TYPE_REPLICATE /// @param border_values Border values if the border_type is -/// \ref INTRINSICCV_BORDER_TYPE_CONSTANT. +/// @ref INTRINSICCV_BORDER_TYPE_CONSTANT. /// @param channels Number of channels in the data. Must be not more than -/// \ref INTRINSICCV_MAXIMUM_CHANNEL_COUNT. +/// @ref INTRINSICCV_MAXIMUM_CHANNEL_COUNT. /// @param iterations Number of times to do the morphology operation. /// @param type_size Element size in bytes. Must not be more than -/// \ref INTRINSICCV_MAXIMUM_TYPE_SIZE. +/// @ref INTRINSICCV_MAXIMUM_TYPE_SIZE. /// @param image Image dimensions. Its size must not be more than -/// \ref INTRINSICCV_MAX_IMAGE_PIXELS. +/// @ref INTRINSICCV_MAX_IMAGE_PIXELS. /// intrinsiccv_error_t intrinsiccv_morphology_create( intrinsiccv_morphology_context_t **context, intrinsiccv_rectangle_t kernel, @@ -722,7 +722,7 @@ intrinsiccv_error_t intrinsiccv_morphology_create( intrinsiccv_border_values_t border_values, size_t channels, size_t iterations, size_t type_size, intrinsiccv_rectangle_t image); -/// Releases a morphology context that was previously created using \ref +/// Releases a morphology context that was previously created using @ref /// intrinsiccv_morphology_create. /// /// @param context Pointer to morphology context. Must not be nullptr. @@ -735,7 +735,7 @@ intrinsiccv_error_t intrinsiccv_morphology_release( /// result into `dst`. /// /// Width and height are the same for the source and the destination. Number -/// of pixels is limited to \ref INTRINSICCV_MAX_IMAGE_PIXELS. +/// of pixels is limited to @ref INTRINSICCV_MAX_IMAGE_PIXELS. /// /// The kernel has an anchor point, it is usually the center of the kernel. /// The algorithm takes a rectangle from the source data using the kernel and @@ -751,8 +751,8 @@ intrinsiccv_error_t intrinsiccv_morphology_release( /// Usage: /// /// Before using this function, a context must be created using -/// \ref intrinsiccv_morphology_create, and after finished, it has to be -/// released using \ref intrinsiccv_morphology_release. +/// @ref intrinsiccv_morphology_create, and after finished, it has to be +/// released using @ref intrinsiccv_morphology_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. @@ -780,7 +780,7 @@ intrinsiccv_error_t intrinsiccv_erode_u8( size_t width, size_t height, intrinsiccv_morphology_context_t *context); /// Counts how many nonzero elements are in the source data. Number of elements -/// is limited to \ref INTRINSICCV_MAX_IMAGE_PIXELS. +/// is limited to @ref INTRINSICCV_MAX_IMAGE_PIXELS. /// /// @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 @@ -804,7 +804,7 @@ intrinsiccv_error_t intrinsiccv_count_nonzeros_u8(const uint8_t *src, /// dimensions could be either `(N+1, M+1)` or `(N, M)` or combination of both. /// For later cases last respective row or column of source data will not be /// processed. Currently only supports single-channel data. Number of pixels in -/// the source is limited to \ref INTRINSICCV_MAX_IMAGE_PIXELS. +/// the source is limited to @ref INTRINSICCV_MAX_IMAGE_PIXELS. /// /// Even dimension example of 2x2 to 1x1 conversion: /// ``` @@ -854,10 +854,10 @@ intrinsiccv_error_t intrinsiccv_resize_to_quarter_u8( /// Note, that the kernel is mirrored both vertically and horizontally during /// the convolution. /// -/// The only supported border type is \ref INTRINSICCV_BORDER_TYPE_REPLICATE +/// The only supported border type is @ref INTRINSICCV_BORDER_TYPE_REPLICATE /// /// Width and height are the same for the source and for the destination. Number -/// of pixels is limited to \ref INTRINSICCV_MAX_IMAGE_PIXELS. +/// of pixels is limited to @ref INTRINSICCV_MAX_IMAGE_PIXELS. /// /// @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 @@ -873,7 +873,7 @@ intrinsiccv_error_t intrinsiccv_resize_to_quarter_u8( /// '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 INTRINSICCV_MAXIMUM_CHANNEL_COUNT. +/// @ref INTRINSICCV_MAXIMUM_CHANNEL_COUNT. /// intrinsiccv_error_t intrinsiccv_sobel_3x3_vertical_s16_u8( const uint8_t *src, size_t src_stride, int16_t *dst, size_t dst_stride, @@ -890,10 +890,10 @@ intrinsiccv_error_t intrinsiccv_sobel_3x3_vertical_s16_u8( /// Note, that the kernel is mirrored both vertically and horizontally during /// the convolution. /// -/// The only supported border type is \ref INTRINSICCV_BORDER_TYPE_REPLICATE +/// The only supported border type is @ref INTRINSICCV_BORDER_TYPE_REPLICATE /// /// Width and height are the same for the source and for the destination. Number -/// of pixels is limited to \ref INTRINSICCV_MAX_IMAGE_PIXELS. +/// of pixels is limited to @ref INTRINSICCV_MAX_IMAGE_PIXELS. /// /// @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 @@ -909,7 +909,7 @@ intrinsiccv_error_t intrinsiccv_sobel_3x3_vertical_s16_u8( /// '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 INTRINSICCV_MAXIMUM_CHANNEL_COUNT. +/// @ref INTRINSICCV_MAXIMUM_CHANNEL_COUNT. /// intrinsiccv_error_t intrinsiccv_sobel_3x3_horizontal_s16_u8( const uint8_t *src, size_t src_stride, int16_t *dst, size_t dst_stride, @@ -917,7 +917,7 @@ intrinsiccv_error_t intrinsiccv_sobel_3x3_horizontal_s16_u8( /// Canny edge detector for uint8_t grayscale input. Output is also a uint8_t /// grayscale image. Width and height are the same for input and output. Number -/// of pixels is limited to \ref INTRINSICCV_MAX_IMAGE_PIXELS. +/// of pixels is limited to @ref INTRINSICCV_MAX_IMAGE_PIXELS. /// /// The steps: /// - Execute horizontal and vertical Sobel filtering with 3*3 kernels to @@ -952,21 +952,21 @@ intrinsiccv_error_t intrinsiccv_canny_u8(const uint8_t *src, size_t src_stride, /// /// Before a gaussian_blur operation, this initialization is needed. /// After the operation is finished, the context needs to be released -/// using \ref intrinsiccv_filter_release. +/// using @ref intrinsiccv_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 INTRINSICCV_MAXIMUM_CHANNEL_COUNT. +/// @ref INTRINSICCV_MAXIMUM_CHANNEL_COUNT. /// @param type_size Element size in bytes. Must not be more than -/// \ref INTRINSICCV_MAXIMUM_TYPE_SIZE. +/// @ref INTRINSICCV_MAXIMUM_TYPE_SIZE. /// @param image Image dimensions. Its size must not be more than -/// \ref INTRINSICCV_MAX_IMAGE_PIXELS. +/// @ref INTRINSICCV_MAX_IMAGE_PIXELS. /// intrinsiccv_error_t intrinsiccv_filter_create( intrinsiccv_filter_context_t **context, size_t channels, size_t type_size, intrinsiccv_rectangle_t image); -/// Releases a filter context that was previously created using \ref +/// Releases a filter context that was previously created using @ref /// intrinsiccv_filter_create. /// /// @param context Pointer to filter context. Must not be nullptr. @@ -993,7 +993,7 @@ intrinsiccv_error_t intrinsiccv_filter_release( /// ``` /// /// Width and height are the same for the source and for the destination. Number -/// of elements is limited to \ref INTRINSICCV_MAX_IMAGE_PIXELS. +/// of elements is limited to @ref INTRINSICCV_MAX_IMAGE_PIXELS. /// /// Usage: \n /// Before using this function, a context must be created using @@ -1002,10 +1002,10 @@ intrinsiccv_error_t intrinsiccv_filter_release( /// 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 -/// - \ref INTRINSICCV_BORDER_TYPE_REPLICATE \n -/// - \ref INTRINSICCV_BORDER_TYPE_REFLECT \n -/// - \ref INTRINSICCV_BORDER_TYPE_WRAP \n -/// - \ref INTRINSICCV_BORDER_TYPE_REVERSE +/// - @ref INTRINSICCV_BORDER_TYPE_REPLICATE \n +/// - @ref INTRINSICCV_BORDER_TYPE_REFLECT \n +/// - @ref INTRINSICCV_BORDER_TYPE_WRAP \n +/// - @ref INTRINSICCV_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 @@ -1021,7 +1021,7 @@ intrinsiccv_error_t intrinsiccv_filter_release( /// '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 INTRINSICCV_MAXIMUM_CHANNEL_COUNT. +/// @ref INTRINSICCV_MAXIMUM_CHANNEL_COUNT. /// @param border_type Way of handling the border. /// @param context Pointer to filter context. /// @@ -1041,7 +1041,7 @@ intrinsiccv_error_t intrinsiccv_gaussian_blur_5x5_u8( /// Splits a multi channel source stream into separate 1-channel streams. Width /// and height are the same for the source stream and for all the destination -/// streams. Number of pixels is limited to \ref INTRINSICCV_MAX_IMAGE_PIXELS. +/// streams. Number of pixels is limited to @ref INTRINSICCV_MAX_IMAGE_PIXELS. /// /// @param src_data Pointer to the source data. Must be non-null. /// Must be aligned to element_size. @@ -1085,7 +1085,7 @@ intrinsiccv_error_t intrinsiccv_split(const void *src_data, size_t src_stride, /// | 2 | 2 | 2 | /// ``` /// -/// Number of elements is limited to \ref INTRINSICCV_MAX_IMAGE_PIXELS. +/// Number of elements is limited to @ref INTRINSICCV_MAX_IMAGE_PIXELS. /// /// @param src Pointer to the source data. Must be non-null. /// Must be aligned to element_size. @@ -1111,7 +1111,7 @@ intrinsiccv_error_t intrinsiccv_transpose(const void *src, size_t src_stride, /// Merges separate 1-channel source streams to one multi channel stream. Width /// and height are the same for all the source streams and for the destination. -/// Number of pixels is limited to \ref INTRINSICCV_MAX_IMAGE_PIXELS. +/// Number of pixels is limited to @ref INTRINSICCV_MAX_IMAGE_PIXELS. /// /// @param srcs A C style array of pointers to the source data. /// Number of pointers in the array must be the same as the @@ -1144,7 +1144,7 @@ intrinsiccv_error_t intrinsiccv_merge(const void **srcs, size_t element_size); /// Calculates minimum and maximum element value across the source data. Number -/// of elements is limited to \ref INTRINSICCV_MAX_IMAGE_PIXELS. +/// of elements is limited to @ref INTRINSICCV_MAX_IMAGE_PIXELS. /// /// @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 @@ -1186,7 +1186,7 @@ intrinsiccv_error_t intrinsiccv_min_max_s32(const int32_t *src, /// Finds minimum and maximum element value across the source data, /// and returns their location in the source data as offset in bytes /// from the source beginning. Number of elements is limited to -/// \ref INTRINSICCV_MAX_IMAGE_PIXELS. +/// @ref INTRINSICCV_MAX_IMAGE_PIXELS. /// /// @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 @@ -1213,7 +1213,7 @@ intrinsiccv_error_t intrinsiccv_min_max_loc_u8(const uint8_t *src, /// type of the element if the result would underflow/overflow. Source data /// length (in bytes) is `stride` * `height`. Width and height are the same /// for the source and destination. Number of elements is limited to -/// \ref INTRINSICCV_MAX_IMAGE_PIXELS. +/// @ref INTRINSICCV_MAX_IMAGE_PIXELS. /// /// @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 diff --git a/test/api/test_add_abs_with_threshold.cpp b/test/api/test_add_abs_with_threshold.cpp index 384657090..9ae7de8fd 100644 --- a/test/api/test_add_abs_with_threshold.cpp +++ b/test/api/test_add_abs_with_threshold.cpp @@ -127,7 +127,7 @@ class SaturatingAddAbsWithThresholdTest : public testing::Test {}; using ElementTypes = ::testing::Types; -// Tests \ref saturating_add_abs_with_threshold API. +// Tests saturating_add_abs_with_threshold API. TYPED_TEST_SUITE(SaturatingAddAbsWithThresholdTest, ElementTypes); TYPED_TEST(SaturatingAddAbsWithThresholdTest, TestPositive) { diff --git a/test/api/test_saturating_absdiff.cpp b/test/api/test_saturating_absdiff.cpp index 82ed17665..54852878f 100644 --- a/test/api/test_saturating_absdiff.cpp +++ b/test/api/test_saturating_absdiff.cpp @@ -89,7 +89,7 @@ using ElementTypes = ::testing::Types; TYPED_TEST_SUITE(SaturatingAbsDiff, ElementTypes); -// Tests \ref intrinsiccv_saturating_absdiff_ API. +// Tests intrinsiccv_saturating_absdiff_ API. TYPED_TEST(SaturatingAbsDiff, API) { // Test without padding. SaturatingAbsDiffTest{}.test(); diff --git a/test/api/test_saturating_add.cpp b/test/api/test_saturating_add.cpp index c5cc01c92..74607e860 100644 --- a/test/api/test_saturating_add.cpp +++ b/test/api/test_saturating_add.cpp @@ -81,7 +81,7 @@ using ElementTypes = ::testing::Types; TYPED_TEST_SUITE(SaturatingAdd, ElementTypes); -// Tests \ref intrinsiccv_saturating_add_ API. +// Tests intrinsiccv_saturating_add_ API. TYPED_TEST(SaturatingAdd, API) { // Test without padding. SaturatingAddTest{}.test(); diff --git a/test/api/test_saturating_multiply.cpp b/test/api/test_saturating_multiply.cpp index 51df8e366..6e3f33c59 100644 --- a/test/api/test_saturating_multiply.cpp +++ b/test/api/test_saturating_multiply.cpp @@ -89,7 +89,7 @@ using ElementTypes = ::testing::Types; TYPED_TEST_SUITE(SaturatingMultiply, ElementTypes); -// Tests \ref intrinsiccv_saturating_multiply_ API. +// Tests intrinsiccv_saturating_multiply_ API. TYPED_TEST(SaturatingMultiply, API) { // Test without padding. SaturatingMultiplyTest{}.test(); diff --git a/test/api/test_saturating_sub.cpp b/test/api/test_saturating_sub.cpp index 3618a4e01..b60060a16 100644 --- a/test/api/test_saturating_sub.cpp +++ b/test/api/test_saturating_sub.cpp @@ -83,7 +83,7 @@ using ElementTypes = ::testing::Types; TYPED_TEST_SUITE(SaturatingSub, ElementTypes); -// Tests \ref intrinsiccv_saturating_sub_ API. +// Tests intrinsiccv_saturating_sub_ API. TYPED_TEST(SaturatingSub, API) { // Test without padding. SaturatingSubTest{}.test(); diff --git a/test/api/test_scale.cpp b/test/api/test_scale.cpp index a0eddade3..310ee5abb 100644 --- a/test/api/test_scale.cpp +++ b/test/api/test_scale.cpp @@ -318,7 +318,7 @@ class ScaleTest : public testing::Test {}; using ElementTypes = ::testing::Types; -// Tests \ref intrinsiccv_scale_u8 API. +// Tests intrinsiccv_scale_u8 API. TYPED_TEST_SUITE(ScaleTest, ElementTypes); TYPED_TEST(ScaleTest, TestScalar1) { diff --git a/test/framework/array.h b/test/framework/array.h index ba72b4a3a..e702cfad0 100644 --- a/test/framework/array.h +++ b/test/framework/array.h @@ -325,7 +325,7 @@ class Array2D : public TwoDimensional { size_t stride_{0}; }; // end of class Array2D -// Compares two \ref Array2D objects for equality. +// Compares two Array2D objects for equality. #define EXPECT_EQ_ARRAY2D(lhs, rhs) \ do { \ ASSERT_EQ((lhs).width(), (rhs).width()) \ @@ -345,7 +345,7 @@ class Array2D : public TwoDimensional { } \ } while (0 != 0) -// Compares two \ref Array2D objects for inequality. +// Compares two Array2D objects for inequality. #define EXPECT_NE_ARRAY2D(lhs, rhs) \ do { \ ASSERT_EQ((lhs).width(), (rhs).width()) \ -- GitLab