diff --git a/Doxyfile b/Doxyfile index 62304fa21269fabf8a3f1e31071a71bf315d427f..45c67eafd59ffe836c045b8672819a4e5d8c14cb 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/ctypes.h b/intrinsiccv/include/intrinsiccv/ctypes.h index 98efb3324b451f88b396d62ff58fa7b22378d6c9..22be39c1a7f93d853613c4d349df2b8d14cef1dd 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 @@ -26,28 +26,42 @@ 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 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 +91,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 diff --git a/intrinsiccv/include/intrinsiccv/intrinsiccv.h b/intrinsiccv/include/intrinsiccv/intrinsiccv.h index e1a59e75a80ac444b8d6c3e217604621c6346d40..d75cb646963f78bc63511bec1f7e70f4ca0850cf 100644 --- a/intrinsiccv/include/intrinsiccv/intrinsiccv.h +++ b/intrinsiccv/include/intrinsiccv/intrinsiccv.h @@ -26,6 +26,24 @@ #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 + +/// 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 @@ -47,7 +65,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 +108,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 +151,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 +188,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,26 +232,30 @@ 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 /// 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); @@ -241,6 +267,9 @@ intrinsiccv_error_t intrinsiccv_saturating_add_abs_with_threshold( /// 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. @@ -248,8 +277,8 @@ intrinsiccv_error_t intrinsiccv_saturating_add_abs_with_threshold( /// @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). -/// @param width Number of elements in a row. +/// 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. /// intrinsiccv_error_t intrinsiccv_gray_to_rgb_u8(const uint8_t *src, @@ -264,6 +293,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. @@ -271,8 +303,8 @@ 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). -/// @param width Number of elements in a row. +/// 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. /// intrinsiccv_error_t intrinsiccv_gray_to_rgba_u8(const uint8_t *src, @@ -287,15 +319,18 @@ 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. -/// 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). -/// @param width Number of elements in a row. +/// 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. /// intrinsiccv_error_t intrinsiccv_rgb_to_bgr_u8(const uint8_t *src, @@ -306,15 +341,18 @@ 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. -/// 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). -/// @param width Number of elements in a row. +/// 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. /// intrinsiccv_error_t intrinsiccv_rgb_to_rgb_u8(const uint8_t *src, @@ -329,15 +367,18 @@ 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. -/// 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). -/// @param width Number of elements in a row. +/// 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. /// intrinsiccv_error_t intrinsiccv_rgba_to_bgra_u8(const uint8_t *src, @@ -348,15 +389,18 @@ 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. -/// 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). -/// @param width Number of elements in a row. +/// 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. /// intrinsiccv_error_t intrinsiccv_rgba_to_rgba_u8(const uint8_t *src, @@ -372,15 +416,18 @@ 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. -/// 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). -/// @param width Number of elements in a row. +/// 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. /// intrinsiccv_error_t intrinsiccv_rgb_to_bgra_u8(const uint8_t *src, @@ -396,15 +443,18 @@ 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. -/// 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). -/// @param width Number of elements in a row. +/// 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. /// intrinsiccv_error_t intrinsiccv_rgb_to_rgba_u8(const uint8_t *src, @@ -420,15 +470,18 @@ 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. -/// 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). -/// @param width Number of elements in a row. +/// 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. /// intrinsiccv_error_t intrinsiccv_rgba_to_bgr_u8(const uint8_t *src, @@ -444,15 +497,18 @@ 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. -/// 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). -/// @param width Number of elements in a row. +/// 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. /// intrinsiccv_error_t intrinsiccv_rgba_to_rgb_u8(const uint8_t *src, @@ -469,6 +525,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. @@ -483,8 +542,8 @@ 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). -/// @param width Number of elements in a row. +/// 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 /// as NV12. @@ -503,6 +562,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. @@ -517,8 +579,8 @@ 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). -/// @param width Number of elements in a row. +/// 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 /// as NV12. @@ -536,6 +598,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. @@ -550,8 +615,8 @@ 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). -/// @param width Number of elements in a row. +/// 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 /// as NV12. @@ -569,6 +634,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. @@ -583,8 +651,8 @@ 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). -/// @param width Number of elements in a row. +/// 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 /// as NV12. @@ -598,6 +666,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 @@ -620,22 +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 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. +/// 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 image Image dimensions. +/// @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. /// intrinsiccv_error_t intrinsiccv_morphology_create( intrinsiccv_morphology_context_t **context, intrinsiccv_rectangle_t kernel, @@ -643,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. @@ -655,7 +734,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. @@ -670,22 +751,21 @@ 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 intrinsiccv_morphology_release. -/// -/// Note: from border types only these are supported: \n -/// - \ref INTRINSICCV_BORDER_TYPE_REPLICATE \n -/// - \ref INTRINSICCV_BORDER_TYPE_CONSTANT +/// @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. /// /// @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 +779,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 +803,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 +831,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 +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 ::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 @@ -787,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. /// @@ -804,7 +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 ::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 @@ -819,14 +908,16 @@ 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. +/// 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 @@ -861,18 +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 elements for each pixel. -/// @param type_size Element size in bytes. -/// @param image Image dimensions. +/// @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. /// 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. @@ -897,16 +991,21 @@ 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 -/// 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 +/// 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 +/// - @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 @@ -921,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. /// @@ -939,7 +1039,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. @@ -961,8 +1063,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, @@ -982,6 +1085,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 @@ -997,14 +1102,16 @@ 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, 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,10 +1130,12 @@ 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. +/// @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, @@ -1034,7 +1143,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 +1185,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 +1212,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/morphology/workspace.h b/intrinsiccv/include/intrinsiccv/morphology/workspace.h index dba777b623d3e1efa9998c8ba45771b4094f24dd..32623301f57eaa107238ce4dc42bfec9835416a7 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 b341980a689f758fd8f960098425343e59533d20..41510e10985d14865f074e26f2f3ef0167b793df 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/include/intrinsiccv/utils.h b/intrinsiccv/include/intrinsiccv/utils.h index 4aec291eb9139407c894d2eec420169de824f45b..785c5a1ca8ea6024148d2f0aa52b8e4137c92367 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/include/intrinsiccv/workspace/separable.h b/intrinsiccv/include/intrinsiccv/workspace/separable.h index 1d456838f4f0de13b4aba4e0b504b9345befd1a3..4b7f80007f93312a20eb63d644d8e912e6a58491 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/analysis/canny_neon.cpp b/intrinsiccv/src/analysis/canny_neon.cpp index d2de6a235c7cace1bd7a6e340522073378778124..94b99d696b9bef6f4f25007c1df10b884aa7edc7 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 @@ -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}; @@ -507,7 +508,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/analysis/count_nonzeros_neon.cpp b/intrinsiccv/src/analysis/count_nonzeros_neon.cpp index e54f789cc4fc7028ec69194497e256522f38318b..32c3b541860955b81c33bf0a71578af14bb76aa9 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 b88a5b714555b0507847c47e817ed68f06982824..99b355836a9da465c89a2dbdaef2dce05cc4ebb5 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 a935f5a9f04688286bb77b532f87bed734cb1ec0..8d9b4583465a38343da4806d77b2bbb956341118 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 5bcdabe521db346e8e407e52f8f59028f264a938..43d3e7cd8ad83c258e3e2770b971b102b3320f37 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 9cae9c71764660eb43fbde7c489c861479aa7fc5..29895f1a06a5beb47374b6f05459ea2f41f0c288 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 57691923382d264c4ab9327c10fb3ea8a78597e2..94753bd6753857e7e37b106a925ec0232454554e 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_api.cpp b/intrinsiccv/src/arithmetics/add_abs_with_threshold_api.cpp index 36c575f75e412c1ff11f71bfce5f00873b90b252..e4c24b563c627a26cd620d51e40971dfd9813bfd 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/intrinsiccv/src/arithmetics/add_abs_with_threshold_neon.cpp b/intrinsiccv/src/arithmetics/add_abs_with_threshold_neon.cpp index c7715587c31405336517d7596831943d8ee18e59..23ff6e9d8f9ac62745de1218cba040f2860af8fc 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 2cc065065a971bf9b4ad85543efa5fc341257f12..b9d3176c2bcd6d4711b3c83e166f4c8db1827ff8 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 d738e576ac46c16ed4bd30ea8a911f68504e32bc..c78ad5a89e9887d5cd64b2fa389ae381d917a7b8 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 af9a3d36d9e6b0b8c9a8ff8b42f974421c6ab935..11cc62908cd95ddf063f17ed96090f7b455dc7da 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 76b4073e34b807fac402f274f16fa90f865f3c06..dd37d62595797bb1f2ec6b8f5544964ecf2e0588 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 5999c78c37d24b1f2aae606a5f257213de65f065..431e137167e21eb6a98f21d41a43cfa7c6553a3c 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 9a6c3f3a660b83e6e8e3b9438adc9f8eb39c7049..615dcd17a6ca6461c5e0b876127d4e7c90887731 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 7ad8538e2f5068b6d937268f23047c300d560fd2..abc00b964eab753156654bd2bcea99557befb30c 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 e673b8fd66ebe71c2ab89f48baf7dc69f9c8db6c..1310a28d1c602799c54ecc9bb592b263f32bd1a7 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 549969a3c94325723d2ffc8499731e526bf36bdf..312b512f63d00be1508ebf6a75799f3ec8bfe3b8 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 7af4be3ce3fe4d4fc3513d83fdcb99cfdd36a93e..c1aebeaaa50a9db4d0bae471588cc31300467c3c 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 4dea3c681ead19448ccd06f9d3d081aaf4003789..ceb8b0bb2c714cd18071408c047cd038fe1e540b 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 4a1a3862d4ec708b508b6788f159dc9bf787d9f4..fba99cc6e24842fc1fce5c711bad9e57302bd00d 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 a793ad4b76abeaaa761764ae3698ac070a6ac894..736300d1826685f47d4bdf5e6abc082cc1d21f9b 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 7fc5833b912d6defd479f0a0fc69df12e4cf8eb3..235836a51089c3f92bdd85bc2a24c76c7ce4da99 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 b0d5fadb503e179a0794f392739307b8294c67cf..00fd0696db482adbdfc743b7bc9499d1e9566809 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 3d15e9fc03ea2201036494bff5da6483499459b6..41402fbaf4d222fb32ee470e623d2b3a4582f461 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 ecf63bdecdd4b9feac50933402e8c56ff9016501..8f2906f4d78b7fed906b9da2be4ce532317051c8 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 75b75f1c3233e63ecee12ce6b1cddfbad9b87e56..401abbc8c0c6484ad17af53a70478c3dbb0f10b7 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 ad06c5edb3ad9eb8e851647c23a88c903e09915e..864cbe57824bd6b42211d51a7201240c5957ecfc 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 9fa8d4ab2ce176111cf99fad4a8a15ab64331c54..b0d7aeeeced349760a0045df178c4b611403c415 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 2ba481906ed21470bc1a01a748d38282e0cbe079..0b6102b888fa4217602f17356af5be2929ec1277 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 a7c7b41330b782a197db798c468b58524ce434c8..5d935ca9500285c5c27b9e880ec74c24ee3d8eed 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 0db22f4e24373a466c78c50f029e602fa714bb45..7ef7e9725a5135e671379477791fc52ed64ddcd3 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,16 @@ 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); + + 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 7659cabcabb48e51e1076d47079e544207b3d28f..6622da370bf66283a2ccf44685dcb741146cf758 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,11 @@ 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); + + if (channels > INTRINSICCV_MAXIMUM_CHANNEL_COUNT) { + return INTRINSICCV_ERROR_RANGE; + } Rectangle rect{width, height}; Rows src_rows{src, src_stride, channels}; @@ -160,6 +165,18 @@ intrinsiccv_error_t discrete_gaussian_blur( 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 be87e4671ebb5f117c50ef36b0ca4e09a2f2c5fc..62f6588c6b9f1a9b77b42aa27c4e6f4342d24b4d 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,11 @@ 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); + + if (channels > INTRINSICCV_MAXIMUM_CHANNEL_COUNT) { + return INTRINSICCV_ERROR_RANGE; + } Rectangle rect{width, height}; Rows src_rows{src, src_stride, channels}; @@ -100,6 +105,18 @@ intrinsiccv_error_t discrete_gaussian_blur( 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/intrinsiccv/src/filters/sobel_neon.cpp b/intrinsiccv/src/filters/sobel_neon.cpp index 4ceb9def89a0e434c880ff8e5b5bff4a6bc030f8..9ed8cc9cc87b032c1421ea3ca0ec8630eec66ed6 100644 --- a/intrinsiccv/src/filters/sobel_neon.cpp +++ b/intrinsiccv/src/filters/sobel_neon.cpp @@ -134,6 +134,11 @@ 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); + + if (channels > INTRINSICCV_MAXIMUM_CHANNEL_COUNT) { + return INTRINSICCV_ERROR_RANGE; + } Rectangle rect{width, height}; Rows src_rows{src, src_stride, channels}; @@ -159,6 +164,11 @@ 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); + + if (channels > INTRINSICCV_MAXIMUM_CHANNEL_COUNT) { + return INTRINSICCV_ERROR_RANGE; + } 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 493c3816339bd9b3be780ae389a1af879d59a579..c9cd893a203d588d44f32786a687d3e5c5fb30d4 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,11 @@ 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); + + if (channels > INTRINSICCV_MAXIMUM_CHANNEL_COUNT) { + return INTRINSICCV_ERROR_RANGE; + } Rectangle rect{width, height}; Rows src_rows{src, src_stride, channels}; @@ -150,6 +155,11 @@ 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); + + if (channels > INTRINSICCV_MAXIMUM_CHANNEL_COUNT) { + return INTRINSICCV_ERROR_RANGE; + } 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 05bd288d77db76b28728f7bddd3567ffc28ee27f..19e9922f318f92be9a2477308de3963b95176688 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,17 @@ 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); @@ -66,12 +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) { - *context = nullptr; - 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 bccce645bc28239cf7ea08e1a6a6dbd39c62ef96..2bca15c6d4283759f9adf168380a1145220e109a 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,10 +493,19 @@ 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); + 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()}; @@ -548,10 +557,18 @@ 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); + 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 39dd7d0a5dae5ae75f047de3c48b7419ac73d5f0..40791e939f98b33c3debec6961f90e5fd43408b2 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,10 +456,19 @@ 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); + 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()}; @@ -516,10 +525,19 @@ 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); + 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/resize/resize_neon.cpp b/intrinsiccv/src/resize/resize_neon.cpp index da3c7787a580f2121855bd3e9e9b8c49c0214902..55c5e7317ec524f35e66879f7f93069301c9d07c 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 b46cc56006dd8a158618d4b27c6d48c71fed0312..8c881010fd35ac51e2e5dacc196afeedd440a8f5 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 ef5bdd66be0c328879c85e47b1331eee79b5542d..9ae7de8fd4caab81906e39d50f2c4259ab494999 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(), @@ -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) { @@ -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,28 @@ 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)); } + +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 65c3c90c69ea05beb470c9121f169a90f867bfd3..71b23c81d0fea0762c418f2d135d7c356179d42c 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 35d15a0f592a1f36a5492d4523db35a26d7289cf..077622777ef70e4fd5843fab2b287ebaad327d35 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 8988ffbeca0d0f3c694359b3e024f1c3829f35c8..e8d2798b88410fd9344307944495aa103cde372c 100644 --- a/test/api/test_gaussian_blur.cpp +++ b/test/api/test_gaussian_blur.cpp @@ -88,3 +88,136 @@ 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)); +} + +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; + + 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); + } +} + +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); +} diff --git a/test/api/test_merge.cpp b/test/api/test_merge.cpp index 0ea2aa7a65bfc553e2837128d27b10b544cc8b48..61d8be67d5107a6fb616eb99b8fb8a1bb28c81de 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 816feb7f6a9bca20572639a7cdf30a0ee1aa180f..d44d5e97421e917f092ffbd326dc3386946d8e9f 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 72a06cade899cd98841e2da15a0481d29aba274e..065b75f3f8fe894806d88f62773e76fa57df5f39 100644 --- a/test/api/test_morphology.cpp +++ b/test/api/test_morphology.cpp @@ -49,6 +49,70 @@ 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); + } +} + +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( @@ -111,3 +175,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 64207b83d7d669d280669c63e9af399267b7375d..a9e7030483582be9514676cea937510300318ee9 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 3dc8550efed8fb0f8e32466b0a4f71986a88c628..24ee251f9bb863da018554544f576e2b6d5d9ef9 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 f4c58c26369a3535e0d41062b0dc720541b44cc1..54852878f9ebe44be4129ada9b927c574e995831 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(); @@ -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 f5a1844b3d645ab531b566e32a3bb9aa484bf63f..74607e8607261f4f9a5274eb0a8c05d91e0d32ab 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(); @@ -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 0c1007acc92156d0096ce1fdafac732755eee1a7..6e3f33c5927dd14739d38eb0737c3f667b091bea 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(); @@ -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 16c52f47532d305987b2efe2a5e1d486995ce6c9..b60060a16246267c71fadebdc5021d8c346ac70b 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(); @@ -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 46ed272a1e3cca39ea6c6060fac650ccd3aabc70..310ee5abb1256ff9d9f17cffa57ffd51793c5a94 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) { @@ -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 7245a902eddfa871d61efbf10d079bc23fbdfd9f..34cd6b73c61c289d9fdbae0f00ccff67a6377311 100644 --- a/test/api/test_sobel.cpp +++ b/test/api/test_sobel.cpp @@ -144,3 +144,55 @@ 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)); +} + +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)); +} diff --git a/test/api/test_split.cpp b/test/api/test_split.cpp index 4be8db95f64bf9e2864ed39f454f254219677612..7d9f37393adba8e62da063264a553f8c0c0924be 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 a4cd9cfead3b31ab664f54deaa289d486dc292f9..42ef20532f457844973064e6810ceca2712c325d 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 7a7725bd5c8461fbc5a9cc309c0ad8310fd886a3..7c5c1c1c0242c945a356760af5beb70c784cfede 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 387b1d828dae3bc1527b0739dc6796fd4a98a3c6..a7854d8eccf7e82e21ee2cb2e24cfd7e2888c717 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, diff --git a/test/framework/array.h b/test/framework/array.h index ba72b4a3a8f8722b1fd5a16836dee81cd3669e16..e702cfad03ba459debb09564d9fa2c545a7977f1 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()) \