| Line | Branch | Exec | Source |
|---|---|---|---|
| 1 | // SPDX-FileCopyrightText: 2024 - 2026 Arm Limited and/or its affiliates <open-source-office@arm.com> | ||
| 2 | // | ||
| 3 | // SPDX-License-Identifier: Apache-2.0 | ||
| 4 | |||
| 5 | #ifndef KLEIDICV_RESIZE_RESIZE_LINEAR_H | ||
| 6 | #define KLEIDICV_RESIZE_RESIZE_LINEAR_H | ||
| 7 | |||
| 8 | #include <algorithm> | ||
| 9 | #include <array> | ||
| 10 | #include <cstddef> | ||
| 11 | |||
| 12 | #include "kleidicv/kleidicv.h" | ||
| 13 | |||
| 14 | #define KLEIDICV_RESIZE_MAX_WIDTH_OR_HEIGHT ((1ULL << 24) - 1) | ||
| 15 | |||
| 16 | namespace kleidicv { | ||
| 17 | |||
| 18 | 1780 | inline bool resize_linear_u8_is_implemented(size_t src_width, size_t src_height, | |
| 19 | size_t dst_width, size_t dst_height, | ||
| 20 | size_t channels) { | ||
| 21 |
2/2✓ Branch 0 taken 1765 times.
✓ Branch 1 taken 15 times.
|
1780 | if (src_width > KLEIDICV_RESIZE_MAX_WIDTH_OR_HEIGHT || |
| 22 |
2/2✓ Branch 0 taken 1750 times.
✓ Branch 1 taken 15 times.
|
1765 | src_height > KLEIDICV_RESIZE_MAX_WIDTH_OR_HEIGHT || |
| 23 |
4/4✓ Branch 0 taken 1735 times.
✓ Branch 1 taken 15 times.
✓ Branch 2 taken 15 times.
✓ Branch 3 taken 1720 times.
|
1750 | dst_width > KLEIDICV_RESIZE_MAX_WIDTH_OR_HEIGHT || |
| 24 | 1735 | dst_height > KLEIDICV_RESIZE_MAX_WIDTH_OR_HEIGHT) { | |
| 25 | 60 | return false; | |
| 26 | } | ||
| 27 | |||
| 28 |
4/4✓ Branch 0 taken 1715 times.
✓ Branch 1 taken 5 times.
✓ Branch 2 taken 5 times.
✓ Branch 3 taken 1710 times.
|
1720 | if (src_width == 0 || src_height == 0) { |
| 29 | 10 | return true; | |
| 30 | } | ||
| 31 | |||
| 32 |
2/2✓ Branch 0 taken 545 times.
✓ Branch 1 taken 1165 times.
|
1710 | if (channels == 1) { |
| 33 |
4/4✓ Branch 0 taken 840 times.
✓ Branch 1 taken 325 times.
✓ Branch 2 taken 60 times.
✓ Branch 3 taken 780 times.
|
1270 | if ((src_width / 2 == dst_width || (src_width + 1) / 2 == dst_width) && |
| 34 |
2/2✓ Branch 0 taken 105 times.
✓ Branch 1 taken 280 times.
|
385 | (src_height / 2 == dst_height || (src_height + 1) / 2 == dst_height)) { |
| 35 | 385 | return true; | |
| 36 | } | ||
| 37 | |||
| 38 | 780 | const std::array<size_t, 2> implemented_ratios = {2, 4}; | |
| 39 |
4/4✓ Branch 0 taken 510 times.
✓ Branch 1 taken 270 times.
✓ Branch 2 taken 510 times.
✓ Branch 3 taken 270 times.
|
1560 | if (std::any_of(implemented_ratios.begin(), implemented_ratios.end(), |
| 40 | 2035 | [&](size_t ratio) { | |
| 41 |
2/2✓ Branch 0 taken 725 times.
✓ Branch 1 taken 530 times.
|
1785 | return src_width * ratio == dst_width && |
| 42 | 530 | src_height * ratio == dst_height; | |
| 43 | })) { | ||
| 44 | 510 | return true; | |
| 45 | } | ||
| 46 | 780 | } | |
| 47 | |||
| 48 | // Downsize between horizontal ratios of 1/3 and 1/1: a minimal width is | ||
| 49 | // needed to execute vector operations | ||
| 50 |
7/8✓ Branch 0 taken 805 times.
✓ Branch 1 taken 10 times.
✓ Branch 2 taken 805 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 680 times.
✓ Branch 5 taken 125 times.
✓ Branch 6 taken 45 times.
✓ Branch 7 taken 635 times.
|
815 | if (channels <= 3 && dst_width * 3 >= src_width && dst_width < src_width && |
| 51 | 680 | dst_height < src_height) { | |
| 52 |
2/2✓ Branch 0 taken 15 times.
✓ Branch 1 taken 620 times.
|
635 | if (dst_width < 8) { |
| 53 | 15 | return false; | |
| 54 | } | ||
| 55 |
4/4✓ Branch 0 taken 320 times.
✓ Branch 1 taken 300 times.
✓ Branch 2 taken 100 times.
✓ Branch 3 taken 220 times.
|
620 | if ((dst_width * 2 >= src_width) && (channels != 3)) { |
| 56 | 220 | return src_width >= 16; | |
| 57 | } | ||
| 58 | 400 | return src_width >= 32; | |
| 59 | } | ||
| 60 | |||
| 61 | 180 | return false; | |
| 62 | 1780 | } | |
| 63 | |||
| 64 | 815 | inline bool resize_linear_f32_is_implemented(size_t src_width, | |
| 65 | size_t src_height, | ||
| 66 | size_t dst_width, | ||
| 67 | size_t dst_height, | ||
| 68 | size_t channels) { | ||
| 69 |
2/2✓ Branch 0 taken 810 times.
✓ Branch 1 taken 5 times.
|
815 | if (src_width > KLEIDICV_RESIZE_MAX_WIDTH_OR_HEIGHT || |
| 70 |
2/2✓ Branch 0 taken 805 times.
✓ Branch 1 taken 5 times.
|
810 | src_height > KLEIDICV_RESIZE_MAX_WIDTH_OR_HEIGHT || |
| 71 |
4/4✓ Branch 0 taken 800 times.
✓ Branch 1 taken 5 times.
✓ Branch 2 taken 5 times.
✓ Branch 3 taken 795 times.
|
805 | dst_width > KLEIDICV_RESIZE_MAX_WIDTH_OR_HEIGHT || |
| 72 | 800 | dst_height > KLEIDICV_RESIZE_MAX_WIDTH_OR_HEIGHT) { | |
| 73 | 20 | return false; | |
| 74 | } | ||
| 75 | |||
| 76 |
2/2✓ Branch 0 taken 10 times.
✓ Branch 1 taken 785 times.
|
795 | if (channels != 1) { |
| 77 | 10 | return false; | |
| 78 | } | ||
| 79 | |||
| 80 |
2/4✓ Branch 0 taken 785 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 785 times.
|
785 | if (src_width == 0 || src_height == 0) { |
| 81 | ✗ | return true; | |
| 82 | } | ||
| 83 | 785 | const std::array<size_t, 3> implemented_ratios = {2, 4, 8}; | |
| 84 | 1570 | return std::any_of(implemented_ratios.begin(), implemented_ratios.end(), | |
| 85 | 2325 | [&](size_t ratio) { | |
| 86 |
2/2✓ Branch 0 taken 790 times.
✓ Branch 1 taken 750 times.
|
2290 | return src_width * ratio == dst_width && |
| 87 | 750 | src_height * ratio == dst_height; | |
| 88 | }); | ||
| 89 | 815 | } | |
| 90 | |||
| 91 | namespace neon { | ||
| 92 | kleidicv_error_t resize_to_quarter_u8(const uint8_t *src, size_t src_stride, | ||
| 93 | size_t src_width, size_t src_height, | ||
| 94 | uint8_t *dst, size_t dst_stride, | ||
| 95 | size_t dst_width, size_t dst_height); | ||
| 96 | kleidicv_error_t kleidicv_resize_2x2_stripe_u8( | ||
| 97 | const uint8_t *src, size_t src_stride, size_t src_width, size_t src_height, | ||
| 98 | size_t y_begin, size_t y_end, uint8_t *dst, size_t dst_stride); | ||
| 99 | kleidicv_error_t kleidicv_resize_4x4_stripe_u8( | ||
| 100 | const uint8_t *src, size_t src_stride, size_t src_width, size_t src_height, | ||
| 101 | size_t y_begin, size_t y_end, uint8_t *dst, size_t dst_stride); | ||
| 102 | template <ptrdiff_t kRatio, ptrdiff_t kChannels> | ||
| 103 | kleidicv_error_t kleidicv_resize_generic_stripe_u8( | ||
| 104 | const uint8_t *src, size_t src_stride, size_t src_width, size_t src_height, | ||
| 105 | size_t y_begin, size_t y_end, uint8_t *dst, size_t dst_stride, | ||
| 106 | size_t dst_width, size_t dst_height); | ||
| 107 | kleidicv_error_t kleidicv_resize_linear_stripe_f32( | ||
| 108 | const float *src, size_t src_stride, size_t src_width, size_t src_height, | ||
| 109 | size_t y_begin, size_t y_end, float *dst, size_t dst_stride, | ||
| 110 | size_t dst_width, size_t dst_height); | ||
| 111 | } // namespace neon | ||
| 112 | |||
| 113 | namespace sve2 { | ||
| 114 | kleidicv_error_t resize_to_quarter_u8(const uint8_t *src, size_t src_stride, | ||
| 115 | size_t src_width, size_t src_height, | ||
| 116 | uint8_t *dst, size_t dst_stride, | ||
| 117 | size_t dst_width, size_t dst_height); | ||
| 118 | kleidicv_error_t kleidicv_resize_2x2_stripe_u8( | ||
| 119 | const uint8_t *src, size_t src_stride, size_t src_width, size_t src_height, | ||
| 120 | size_t y_begin, size_t y_end, uint8_t *dst, size_t dst_stride); | ||
| 121 | kleidicv_error_t kleidicv_resize_4x4_stripe_u8( | ||
| 122 | const uint8_t *src, size_t src_stride, size_t src_width, size_t src_height, | ||
| 123 | size_t y_begin, size_t y_end, uint8_t *dst, size_t dst_stride); | ||
| 124 | template <ptrdiff_t kRatio, ptrdiff_t kChannels> | ||
| 125 | kleidicv_error_t kleidicv_resize_generic_stripe_u8( | ||
| 126 | const uint8_t *src, size_t src_stride, size_t src_width, size_t src_height, | ||
| 127 | size_t y_begin, size_t y_end, uint8_t *dst, size_t dst_stride, | ||
| 128 | size_t dst_width, size_t dst_height); | ||
| 129 | kleidicv_error_t kleidicv_resize_linear_stripe_f32( | ||
| 130 | const float *src, size_t src_stride, size_t src_width, size_t src_height, | ||
| 131 | size_t y_begin, size_t y_end, float *dst, size_t dst_stride, | ||
| 132 | size_t dst_width, size_t dst_height); | ||
| 133 | } // namespace sve2 | ||
| 134 | |||
| 135 | namespace sme { | ||
| 136 | kleidicv_error_t resize_to_quarter_u8(const uint8_t *src, size_t src_stride, | ||
| 137 | size_t src_width, size_t src_height, | ||
| 138 | uint8_t *dst, size_t dst_stride, | ||
| 139 | size_t dst_width, size_t dst_height); | ||
| 140 | kleidicv_error_t kleidicv_resize_2x2_stripe_u8( | ||
| 141 | const uint8_t *src, size_t src_stride, size_t src_width, size_t src_height, | ||
| 142 | size_t y_begin, size_t y_end, uint8_t *dst, size_t dst_stride); | ||
| 143 | kleidicv_error_t kleidicv_resize_4x4_stripe_u8( | ||
| 144 | const uint8_t *src, size_t src_stride, size_t src_width, size_t src_height, | ||
| 145 | size_t y_begin, size_t y_end, uint8_t *dst, size_t dst_stride); | ||
| 146 | template <ptrdiff_t kRatio, ptrdiff_t kChannels> | ||
| 147 | kleidicv_error_t kleidicv_resize_generic_stripe_u8( | ||
| 148 | const uint8_t *src, size_t src_stride, size_t src_width, size_t src_height, | ||
| 149 | size_t y_begin, size_t y_end, uint8_t *dst, size_t dst_stride, | ||
| 150 | size_t dst_width, size_t dst_height); | ||
| 151 | kleidicv_error_t kleidicv_resize_linear_stripe_f32( | ||
| 152 | const float *src, size_t src_stride, size_t src_width, size_t src_height, | ||
| 153 | size_t y_begin, size_t y_end, float *dst, size_t dst_stride, | ||
| 154 | size_t dst_width, size_t dst_height); | ||
| 155 | } // namespace sme | ||
| 156 | |||
| 157 | namespace sme2 { | ||
| 158 | kleidicv_error_t resize_to_quarter_u8(const uint8_t *src, size_t src_stride, | ||
| 159 | size_t src_width, size_t src_height, | ||
| 160 | uint8_t *dst, size_t dst_stride, | ||
| 161 | size_t dst_width, size_t dst_height); | ||
| 162 | kleidicv_error_t kleidicv_resize_2x2_stripe_u8( | ||
| 163 | const uint8_t *src, size_t src_stride, size_t src_width, size_t src_height, | ||
| 164 | size_t y_begin, size_t y_end, uint8_t *dst, size_t dst_stride); | ||
| 165 | kleidicv_error_t kleidicv_resize_4x4_stripe_u8( | ||
| 166 | const uint8_t *src, size_t src_stride, size_t src_width, size_t src_height, | ||
| 167 | size_t y_begin, size_t y_end, uint8_t *dst, size_t dst_stride); | ||
| 168 | template <ptrdiff_t kRatio, ptrdiff_t kChannels> | ||
| 169 | kleidicv_error_t kleidicv_resize_generic_stripe_u8( | ||
| 170 | const uint8_t *src, size_t src_stride, size_t src_width, size_t src_height, | ||
| 171 | size_t y_begin, size_t y_end, uint8_t *dst, size_t dst_stride, | ||
| 172 | size_t dst_width, size_t dst_height); | ||
| 173 | kleidicv_error_t kleidicv_resize_linear_stripe_f32( | ||
| 174 | const float *src, size_t src_stride, size_t src_width, size_t src_height, | ||
| 175 | size_t y_begin, size_t y_end, float *dst, size_t dst_stride, | ||
| 176 | size_t dst_width, size_t dst_height); | ||
| 177 | } // namespace sme2 | ||
| 178 | |||
| 179 | } // namespace kleidicv | ||
| 180 | |||
| 181 | #ifdef __cplusplus | ||
| 182 | extern "C" { | ||
| 183 | #endif // __cplusplus | ||
| 184 | /// Internal - not part of the public API and its direct use is not supported. | ||
| 185 | /// It is used by the multithreaded function. | ||
| 186 | extern kleidicv_error_t kleidicv_resize_linear_stripe_u8( | ||
| 187 | const uint8_t *src, size_t src_stride, size_t src_width, size_t src_height, | ||
| 188 | size_t y_begin, size_t y_end, uint8_t *dst, size_t dst_stride, | ||
| 189 | size_t dst_width, size_t dst_height, size_t channels); | ||
| 190 | |||
| 191 | /// Internal - not part of the public API and its direct use is not | ||
| 192 | /// supported. It is used by the multithreaded function. | ||
| 193 | extern kleidicv_error_t (*kleidicv_resize_linear_stripe_f32)( | ||
| 194 | const float *src, size_t src_stride, size_t src_width, size_t src_height, | ||
| 195 | size_t y_begin, size_t y_end, float *dst, size_t dst_stride, | ||
| 196 | size_t dst_width, size_t dst_height); | ||
| 197 | |||
| 198 | #ifdef __cplusplus | ||
| 199 | } // extern "C" | ||
| 200 | #endif // __cplusplus | ||
| 201 | |||
| 202 | #endif // KLEIDICV_RESIZE_RESIZE_H | ||
| 203 |