KleidiCV Coverage Report


Directory: ./
File: kleidicv/src/conversions/rgb_to_rgb_neon.cpp
Date: 2025-09-25 14:13:34
Exec Total Coverage
Lines: 158 158 100.0%
Functions: 19 19 100.0%
Branches: 84 84 100.0%

Line Branch Exec Source
1 // SPDX-FileCopyrightText: 2023 - 2025 Arm Limited and/or its affiliates <open-source-office@arm.com>
2 //
3 // SPDX-License-Identifier: Apache-2.0
4
5 #include "kleidicv/conversions/rgb_to_rgb.h"
6 #include "kleidicv/kleidicv.h"
7 #include "kleidicv/neon.h"
8
9 namespace kleidicv::neon {
10
11 template <typename ScalarType>
12 class RGBToBGR final : public UnrollTwice {
13 public:
14 using VecTraits = neon::VecTraits<ScalarType>;
15
16 #if !KLEIDICV_PREFER_INTERLEAVING_LOAD_STORE
17 64 RGBToBGR() : indices_{} { VecTraits::load(kRGBToBGRTableIndices, indices_); }
18 #else
19 RGBToBGR() = default;
20 #endif
21
22 430 void vector_path(const ScalarType *src, ScalarType *dst) {
23 #if KLEIDICV_PREFER_INTERLEAVING_LOAD_STORE
24 uint8x16x3_t src_vect = vld3q_u8(src);
25 uint8x16x3_t dst_vect;
26
27 dst_vect.val[0] = src_vect.val[2];
28 dst_vect.val[1] = src_vect.val[1];
29 dst_vect.val[2] = src_vect.val[0];
30
31 vst3q_u8(dst, dst_vect);
32 #else
33
34 430 uint8x16x3_t src_vect;
35 430 VecTraits::load(src, src_vect);
36
37 430 uint8x16x3_t dst_vect;
38
39 430 uint8x16x2_t src_vect_0_1;
40 430 src_vect_0_1.val[0] = src_vect.val[0];
41 430 src_vect_0_1.val[1] = src_vect.val[1];
42
43 430 uint8x16x2_t src_vect_1_2;
44 430 src_vect_1_2.val[0] = src_vect.val[1];
45 430 src_vect_1_2.val[1] = src_vect.val[2];
46
47 430 dst_vect.val[0] = vqtbl2q_u8(src_vect_0_1, indices_.val[0]);
48 430 dst_vect.val[1] = vqtbl3q_u8(src_vect, indices_.val[1]);
49 430 dst_vect.val[2] = vqtbl2q_u8(src_vect_1_2, indices_.val[2]);
50
51 430 VecTraits::store(dst_vect, dst);
52 #endif
53 430 }
54
55 435 void scalar_path(const ScalarType *src, ScalarType *dst) {
56 435 auto tmp = src[0];
57 435 dst[0] = src[2];
58 435 dst[1] = src[1];
59 435 dst[2] = tmp;
60 435 }
61
62 private:
63 #if !KLEIDICV_PREFER_INTERLEAVING_LOAD_STORE
64 static constexpr uint8_t kRGBToBGRTableIndices[48] = {
65 2, 1, 0, 5, 4, 3, 8, 7, 6, 11, 10, 9, 14, 13, 12, 17,
66 16, 15, 20, 19, 18, 23, 22, 21, 26, 25, 24, 29, 28, 27, 32, 31,
67 14, 19, 18, 17, 22, 21, 20, 25, 24, 23, 28, 27, 26, 31, 30, 29};
68 uint8x16x3_t indices_;
69 #endif
70 }; // end of class RGBToBGR<ScalarType>
71
72 template <typename ScalarType>
73 class RGBAToBGRA final : public UnrollTwice {
74 public:
75 using VecTraits = neon::VecTraits<ScalarType>;
76
77 430 void vector_path(const ScalarType *src, ScalarType *dst) {
78 430 uint8x16x4_t src_vect = vld4q_u8(src);
79 430 uint8x16x4_t dst_vect;
80
81 430 dst_vect.val[0] = src_vect.val[2];
82 430 dst_vect.val[1] = src_vect.val[1];
83 430 dst_vect.val[2] = src_vect.val[0];
84 430 dst_vect.val[3] = src_vect.val[3];
85
86 430 vst4q_u8(dst, dst_vect);
87 430 }
88
89 435 void scalar_path(const ScalarType *src, ScalarType *dst) {
90 435 auto tmp = src[0];
91 435 dst[0] = src[2];
92 435 dst[1] = src[1];
93 435 dst[2] = tmp;
94 435 dst[3] = src[3];
95 435 }
96 }; // end of class RGBAToBGRA<ScalarType>
97
98 template <typename ScalarType>
99 class RGBToBGRA final : public UnrollTwice {
100 public:
101 using VecTraits = neon::VecTraits<ScalarType>;
102
103 430 void vector_path(const ScalarType *src, ScalarType *dst) {
104 430 uint8x16x3_t src_vect = vld3q_u8(src);
105 430 uint8x16x4_t dst_vect;
106
107 430 dst_vect.val[0] = src_vect.val[2];
108 430 dst_vect.val[1] = src_vect.val[1];
109 430 dst_vect.val[2] = src_vect.val[0];
110 430 dst_vect.val[3] = vdupq_n_u8(0xff);
111
112 430 vst4q_u8(dst, dst_vect);
113 430 }
114
115 435 void scalar_path(const ScalarType *src, ScalarType *dst) {
116 435 auto tmp = src[0];
117 435 dst[0] = src[2];
118 435 dst[1] = src[1];
119 435 dst[2] = tmp;
120 435 dst[3] = 0xff;
121 435 }
122 }; // end of class RGBToBGRA<ScalarType>
123
124 template <typename ScalarType>
125 class RGBToRGBA final : public UnrollTwice {
126 public:
127 using VecTraits = neon::VecTraits<ScalarType>;
128
129 430 void vector_path(const ScalarType *src, ScalarType *dst) {
130 430 uint8x16x3_t src_vect = vld3q_u8(src);
131 430 uint8x16x4_t dst_vect;
132
133 430 dst_vect.val[0] = src_vect.val[0];
134 430 dst_vect.val[1] = src_vect.val[1];
135 430 dst_vect.val[2] = src_vect.val[2];
136 430 dst_vect.val[3] = vdupq_n_u8(0xff);
137
138 430 vst4q_u8(dst, dst_vect);
139 430 }
140
141 435 void scalar_path(const ScalarType *src, ScalarType *dst) {
142 435 memcpy(static_cast<void *>(dst), static_cast<const void *>(src), 3);
143 435 dst[3] = 0xff;
144 435 }
145 }; // end of class RGBToRGBA<ScalarType>
146
147 template <typename ScalarType>
148 class RGBAToBGR final : public UnrollTwice {
149 public:
150 using VecTraits = neon::VecTraits<ScalarType>;
151
152 430 void vector_path(const ScalarType *src, ScalarType *dst) {
153 430 uint8x16x4_t src_vect = vld4q_u8(src);
154 430 uint8x16x3_t dst_vect;
155
156 430 dst_vect.val[0] = src_vect.val[2];
157 430 dst_vect.val[1] = src_vect.val[1];
158 430 dst_vect.val[2] = src_vect.val[0];
159
160 430 vst3q_u8(dst, dst_vect);
161 430 }
162
163 435 void scalar_path(const ScalarType *src, ScalarType *dst) {
164 435 auto tmp = src[0];
165 435 dst[0] = src[2];
166 435 dst[1] = src[1];
167 435 dst[2] = tmp;
168 435 }
169 }; // end of class RGBAToBGR<ScalarType>
170
171 template <typename ScalarType>
172 class RGBAToRGB final : public UnrollTwice {
173 public:
174 using VecTraits = neon::VecTraits<ScalarType>;
175
176 430 void vector_path(const ScalarType *src, ScalarType *dst) {
177 430 uint8x16x4_t src_vect = vld4q_u8(src);
178 430 uint8x16x3_t dst_vect;
179
180 430 dst_vect.val[0] = src_vect.val[0];
181 430 dst_vect.val[1] = src_vect.val[1];
182 430 dst_vect.val[2] = src_vect.val[2];
183
184 430 vst3q_u8(dst, dst_vect);
185 430 }
186
187 435 void scalar_path(const ScalarType *src, ScalarType *dst) {
188 435 memcpy(static_cast<void *>(dst), static_cast<const void *>(src), 3);
189 435 }
190 }; // end of class RGBAToRGB<ScalarType>
191
192 KLEIDICV_TARGET_FN_ATTRS
193 68 kleidicv_error_t rgb_to_bgr_u8(const uint8_t *src, size_t src_stride,
194 uint8_t *dst, size_t dst_stride, size_t width,
195 size_t height) {
196
4/4
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 67 times.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 67 times.
68 CHECK_POINTER_AND_STRIDE(src, src_stride, height);
197
4/4
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 66 times.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 66 times.
67 CHECK_POINTER_AND_STRIDE(dst, dst_stride, height);
198
6/6
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 65 times.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 64 times.
✓ Branch 4 taken 2 times.
✓ Branch 5 taken 64 times.
66 CHECK_IMAGE_SIZE(width, height);
199
200 64 Rectangle rect{width, height};
201 64 Rows<const uint8_t> src_rows{src, src_stride, 3 /* RGB */};
202 64 Rows<uint8_t> dst_rows{dst, dst_stride, 3 /* BGR */};
203 64 RGBToBGR<uint8_t> operation;
204 64 apply_operation_by_rows(operation, rect, src_rows, dst_rows);
205 64 return KLEIDICV_OK;
206 68 }
207
208 KLEIDICV_TARGET_FN_ATTRS
209 68 kleidicv_error_t rgba_to_bgra_u8(const uint8_t *src, size_t src_stride,
210 uint8_t *dst, size_t dst_stride, size_t width,
211 size_t height) {
212
4/4
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 67 times.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 67 times.
68 CHECK_POINTER_AND_STRIDE(src, src_stride, height);
213
4/4
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 66 times.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 66 times.
67 CHECK_POINTER_AND_STRIDE(dst, dst_stride, height);
214
6/6
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 65 times.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 64 times.
✓ Branch 4 taken 2 times.
✓ Branch 5 taken 64 times.
66 CHECK_IMAGE_SIZE(width, height);
215
216 64 Rectangle rect{width, height};
217 64 Rows<const uint8_t> src_rows{src, src_stride, 4 /* RGBA */};
218 64 Rows<uint8_t> dst_rows{dst, dst_stride, 4 /* BGRA */};
219 64 RGBAToBGRA<uint8_t> operation;
220 64 apply_operation_by_rows(operation, rect, src_rows, dst_rows);
221 64 return KLEIDICV_OK;
222 68 }
223
224 KLEIDICV_TARGET_FN_ATTRS kleidicv_error_t
225 68 rgb_to_bgra_u8(const uint8_t *src, size_t src_stride, uint8_t *dst,
226 size_t dst_stride, size_t width, size_t height) {
227
4/4
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 67 times.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 67 times.
68 CHECK_POINTER_AND_STRIDE(src, src_stride, height);
228
4/4
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 66 times.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 66 times.
67 CHECK_POINTER_AND_STRIDE(dst, dst_stride, height);
229
6/6
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 65 times.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 64 times.
✓ Branch 4 taken 2 times.
✓ Branch 5 taken 64 times.
66 CHECK_IMAGE_SIZE(width, height);
230
231 64 Rectangle rect{width, height};
232 64 Rows<const uint8_t> src_rows{src, src_stride, 3 /* RGB */};
233 64 Rows<uint8_t> dst_rows{dst, dst_stride, 4 /* BGRA */};
234 64 RGBToBGRA<uint8_t> operation;
235 64 apply_operation_by_rows(operation, rect, src_rows, dst_rows);
236 64 return KLEIDICV_OK;
237 68 }
238
239 KLEIDICV_TARGET_FN_ATTRS kleidicv_error_t
240 68 rgb_to_rgba_u8(const uint8_t *src, size_t src_stride, uint8_t *dst,
241 size_t dst_stride, size_t width, size_t height) {
242
4/4
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 67 times.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 67 times.
68 CHECK_POINTER_AND_STRIDE(src, src_stride, height);
243
4/4
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 66 times.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 66 times.
67 CHECK_POINTER_AND_STRIDE(dst, dst_stride, height);
244
6/6
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 65 times.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 64 times.
✓ Branch 4 taken 2 times.
✓ Branch 5 taken 64 times.
66 CHECK_IMAGE_SIZE(width, height);
245
246 64 Rectangle rect{width, height};
247 64 Rows<const uint8_t> src_rows{src, src_stride, 3 /* RGB */};
248 64 Rows<uint8_t> dst_rows{dst, dst_stride, 4 /* RGBA */};
249 64 RGBToRGBA<uint8_t> operation;
250 64 apply_operation_by_rows(operation, rect, src_rows, dst_rows);
251 64 return KLEIDICV_OK;
252 68 }
253
254 KLEIDICV_TARGET_FN_ATTRS
255 68 kleidicv_error_t rgba_to_bgr_u8(const uint8_t *src, size_t src_stride,
256 uint8_t *dst, size_t dst_stride, size_t width,
257 size_t height) {
258
4/4
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 67 times.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 67 times.
68 CHECK_POINTER_AND_STRIDE(src, src_stride, height);
259
4/4
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 66 times.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 66 times.
67 CHECK_POINTER_AND_STRIDE(dst, dst_stride, height);
260
6/6
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 65 times.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 64 times.
✓ Branch 4 taken 2 times.
✓ Branch 5 taken 64 times.
66 CHECK_IMAGE_SIZE(width, height);
261
262 64 Rectangle rect{width, height};
263 64 Rows<const uint8_t> src_rows{src, src_stride, 4 /* RGBA */};
264 64 Rows<uint8_t> dst_rows{dst, dst_stride, 3 /* BGR */};
265 64 RGBAToBGR<uint8_t> operation;
266 64 apply_operation_by_rows(operation, rect, src_rows, dst_rows);
267 64 return KLEIDICV_OK;
268 68 }
269
270 KLEIDICV_TARGET_FN_ATTRS
271 68 kleidicv_error_t rgba_to_rgb_u8(const uint8_t *src, size_t src_stride,
272 uint8_t *dst, size_t dst_stride, size_t width,
273 size_t height) {
274
4/4
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 67 times.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 67 times.
68 CHECK_POINTER_AND_STRIDE(src, src_stride, height);
275
4/4
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 66 times.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 66 times.
67 CHECK_POINTER_AND_STRIDE(dst, dst_stride, height);
276
6/6
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 65 times.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 64 times.
✓ Branch 4 taken 2 times.
✓ Branch 5 taken 64 times.
66 CHECK_IMAGE_SIZE(width, height);
277
278 64 Rectangle rect{width, height};
279 64 Rows<const uint8_t> src_rows{src, src_stride, 4 /* RGBA */};
280 64 Rows<uint8_t> dst_rows{dst, dst_stride, 3 /* RGB */};
281 64 RGBAToRGB<uint8_t> operation;
282 64 apply_operation_by_rows(operation, rect, src_rows, dst_rows);
283 64 return KLEIDICV_OK;
284 68 }
285
286 } // namespace kleidicv::neon
287