diff --git a/adapters/opencv/kleidicv_hal.cpp b/adapters/opencv/kleidicv_hal.cpp index df03a09f52f5c0d8cce9c9a0d8e216d5b8d27f89..618cffcff56019508905cc6438a0d081bddcc093 100644 --- a/adapters/opencv/kleidicv_hal.cpp +++ b/adapters/opencv/kleidicv_hal.cpp @@ -83,7 +83,8 @@ int gray_to_bgr(const uchar *src_data, size_t src_step, uchar *dst_data, if (dcn == 3) { return convert_error(kleidicv_gray_to_rgb_u8( reinterpret_cast(src_data), src_step, - reinterpret_cast(dst_data), dst_step, width, height)); + reinterpret_cast(dst_data), dst_step, width, height, + KLEIDICV_BACKEND_AUTO)); } return convert_error(kleidicv_gray_to_rgba_u8( reinterpret_cast(src_data), src_step, diff --git a/benchmark/benchmark.cpp b/benchmark/benchmark.cpp index 3b881ccd30e754a14cc50974cdab8a1755b40fda..95bb46942925a29594574db88e58d38485991649 100644 --- a/benchmark/benchmark.cpp +++ b/benchmark/benchmark.cpp @@ -119,7 +119,7 @@ BENCH_UNARY_OP_DIFFERENT_CHANNEL_NUMBER(rgba_to_yuv_u8, 4, 3, uint8_t); BENCH_UNARY_OP_DIFFERENT_CHANNEL_NUMBER(bgr_to_yuv_u8, 3, 3, uint8_t); BENCH_UNARY_OP_DIFFERENT_CHANNEL_NUMBER(bgra_to_yuv_u8, 4, 3, uint8_t); -BENCH_UNARY_OP_DIFFERENT_CHANNEL_NUMBER(gray_to_rgb_u8, 1, 3, uint8_t); +// BENCH_UNARY_OP_DIFFERENT_CHANNEL_NUMBER(gray_to_rgb_u8, 1, 3, uint8_t); BENCH_UNARY_OP_DIFFERENT_CHANNEL_NUMBER(gray_to_rgba_u8, 1, 4, uint8_t); BENCH_UNARY_OP_DIFFERENT_CHANNEL_NUMBER(rgb_to_bgr_u8, 3, 3, uint8_t); diff --git a/kleidicv/include/kleidicv/ctypes.h b/kleidicv/include/kleidicv/ctypes.h index 0349db0a409195752ca09ef3ed0e638bfd528e0e..5d9d6cc8e46617e3ba198a84402577c1c3c0c822 100644 --- a/kleidicv/include/kleidicv/ctypes.h +++ b/kleidicv/include/kleidicv/ctypes.h @@ -87,6 +87,22 @@ typedef enum { KLEIDICV_BORDER_TYPE_NONE, } kleidicv_border_type_t; +/// KleidiCV backends +typedef enum { + /// Let KleidiCV choose the backend. + KLEIDICV_BACKEND_AUTO, + /// NEON backend. + KLEIDICV_BACKEND_NEON, +#ifdef KLEIDICV_HAVE_SVE2 + /// SVE2 backend. + KLEIDICV_BACKEND_SVE2, +#endif +#ifdef KLEIDICV_HAVE_SME2 + /// SME2 backend. + KLEIDICV_BACKEND_SME2, +#endif +} kleidicv_backend_t; + /// Internal structure where morphology operations store their state typedef struct kleidicv_morphology_context_t_ kleidicv_morphology_context_t; diff --git a/kleidicv/include/kleidicv/kleidicv.h b/kleidicv/include/kleidicv/kleidicv.h index 54d8cc4bcd4c31cb925fd93bd7964c4e7874e247..c4f236d2228f4da8c64604ef89d9b5f205fb1337 100644 --- a/kleidicv/include/kleidicv/kleidicv.h +++ b/kleidicv/include/kleidicv/kleidicv.h @@ -313,10 +313,12 @@ KLEIDICV_BINARY_OP(kleidicv_bitwise_and, uint8_t); /// images. /// @param width Number of pixels in a row. /// @param height Number of rows in the data. +/// @param backend SIMD backend to be used. /// -KLEIDICV_API_DECLARATION(kleidicv_gray_to_rgb_u8, const uint8_t *src, - size_t src_stride, uint8_t *dst, size_t dst_stride, - size_t width, size_t height); +kleidicv_error_t kleidicv_gray_to_rgb_u8(const uint8_t *src, size_t src_stride, + uint8_t *dst, size_t dst_stride, + size_t width, size_t height, + kleidicv_backend_t backend); /// Converts a grayscale image to RGBA. All channels are 8-bit wide. /// diff --git a/kleidicv/src/conversions/gray_to_rgb_api.cpp b/kleidicv/src/conversions/gray_to_rgb_api.cpp index 6d40ef5a4dd10e0a8f0760c903a5d612047d75ca..dd4362963dfcf03e2c5c3852a132e0ea3e6c7fe7 100644 --- a/kleidicv/src/conversions/gray_to_rgb_api.cpp +++ b/kleidicv/src/conversions/gray_to_rgb_api.cpp @@ -12,5 +12,32 @@ KLEIDICV_SVE2_IMPL_IF(&kleidicv::sve2::partialname), \ &kleidicv::sme2::partialname) -KLEIDICV_DEFINE_C_API(kleidicv_gray_to_rgb_u8, gray_to_rgb_u8); +KLEIDICV_DEFINE_C_API(kleidicv_auto_backend_gray_to_rgb_u8, gray_to_rgb_u8); KLEIDICV_DEFINE_C_API(kleidicv_gray_to_rgba_u8, gray_to_rgba_u8); + +kleidicv_error_t kleidicv_gray_to_rgb_u8(const uint8_t *src, size_t src_stride, + uint8_t *dst, size_t dst_stride, + size_t width, size_t height, + kleidicv_backend_t backend) { + switch (backend) { + case KLEIDICV_BACKEND_AUTO: + return kleidicv_auto_backend_gray_to_rgb_u8(src, src_stride, dst, + dst_stride, width, height); + case KLEIDICV_BACKEND_NEON: + return kleidicv::neon::gray_to_rgb_u8(src, src_stride, dst, dst_stride, + width, height); +#ifdef KLEIDICV_HAVE_SVE2 + case KLEIDICV_BACKEND_SVE2: + return kleidicv::sve2::gray_to_rgb_u8(src, src_stride, dst, dst_stride, + width, height); +#endif + +#ifdef KLEIDICV_HAVE_SME2 + case KLEIDICV_BACKEND_SME2: + return kleidicv::sme2::gray_to_rgb_u8(src, src_stride, dst, dst_stride, + width, height); +#endif + default: + return KLEIDICV_ERROR_NOT_IMPLEMENTED; + } +} diff --git a/test/api/test_rgb_and_gray.cpp b/test/api/test_rgb_and_gray.cpp index cdffcea9047e5fd0237df4015537bf07eff853c8..da1e559e96c4b15b2090637a6cef2cb4ea2ffc71 100644 --- a/test/api/test_rgb_and_gray.cpp +++ b/test/api/test_rgb_and_gray.cpp @@ -166,12 +166,19 @@ class ColorTest final { bool swapBlue_; }; +static kleidicv_error_t kleidicv_gray_to_rgb_u8_wrapper( + const uint8_t *src, size_t src_stride, uint8_t *dst, size_t dst_stride, + size_t width, size_t height) { + return kleidicv_gray_to_rgb_u8(src, src_stride, dst, dst_stride, width, + height, KLEIDICV_BACKEND_AUTO); +} + TEST(GRAY2, RGB) { - GrayTest{false}.execute_test(kleidicv_gray_to_rgb_u8); - GrayTest{false}.with_padding(1).execute_test(kleidicv_gray_to_rgb_u8); + GrayTest{false}.execute_test(kleidicv_gray_to_rgb_u8_wrapper); + GrayTest{false}.with_padding(1).execute_test(kleidicv_gray_to_rgb_u8_wrapper); GrayTest{false} .with_width(2 * test::Options::vector_lanes()) - .execute_test(kleidicv_gray_to_rgb_u8); + .execute_test(kleidicv_gray_to_rgb_u8_wrapper); } TEST(GRAY2, RGBA) {