KleidiCV Coverage Report


Directory: ./
File: kleidicv/include/kleidicv/filters/gaussian_blur.h
Date: 2025-09-25 14:13:34
Exec Total Coverage
Lines: 38 38 100.0%
Functions: 4 4 100.0%
Branches: 48 48 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 #ifndef KLEIDICV_FILTERS_GAUSSIAN_BLUR_H
6 #define KLEIDICV_FILTERS_GAUSSIAN_BLUR_H
7
8 #include "kleidicv/config.h"
9 #include "kleidicv/kleidicv.h"
10 #include "kleidicv/types.h"
11 #include "kleidicv/utils.h"
12 #include "kleidicv/workspace/border_types.h"
13 #include "kleidicv/workspace/separable.h"
14
15 extern "C" {
16 // For internal use only. See instead kleidicv_gaussian_blur_u8.
17 // Blur a horizontal stripe across an image. The stripe is defined by the
18 // range (y_begin, y_end].
19 KLEIDICV_API_DECLARATION(kleidicv_gaussian_blur_fixed_stripe_u8,
20 const uint8_t *src, size_t src_stride, uint8_t *dst,
21 size_t dst_stride, size_t width, size_t height,
22 size_t y_begin, size_t y_end, size_t channels,
23 size_t kernel_width, size_t kernel_height,
24 float sigma_x, float sigma_y,
25 kleidicv::FixedBorderType border_type,
26 kleidicv_filter_context_t *context);
27
28 KLEIDICV_API_DECLARATION(kleidicv_gaussian_blur_arbitrary_stripe_u8,
29 const uint8_t *src, size_t src_stride, uint8_t *dst,
30 size_t dst_stride, size_t width, size_t height,
31 size_t y_begin, size_t y_end, size_t channels,
32 size_t kernel_width, size_t kernel_height,
33 float sigma_x, float sigma_y,
34 kleidicv::FixedBorderType border_type,
35 kleidicv_filter_context_t *context);
36 }
37
38 namespace kleidicv {
39
40 1455 inline bool gaussian_blur_is_implemented(
41 size_t width, size_t height, size_t kernel_width, size_t kernel_height,
42 float sigma_x, float sigma_y, size_t channels,
43 kleidicv::FixedBorderType border_type) {
44
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 1452 times.
1455 if (kernel_width != kernel_height) {
45 3 return false;
46 }
47
48
4/4
✓ Branch 0 taken 1449 times.
✓ Branch 1 taken 3 times.
✓ Branch 2 taken 3 times.
✓ Branch 3 taken 1446 times.
1452 if (kernel_width < 3 || kernel_width > 255) {
49 6 return false;
50 }
51
52
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 1440 times.
1446 if ((kernel_width & 1) != 1) {
53 6 return false;
54 }
55
56
2/2
✓ Branch 0 taken 9 times.
✓ Branch 1 taken 1431 times.
1440 if (sigma_x != sigma_y) {
57 9 return false;
58 }
59
60
4/4
✓ Branch 0 taken 1140 times.
✓ Branch 1 taken 291 times.
✓ Branch 2 taken 30 times.
✓ Branch 3 taken 1110 times.
1431 if (width < kernel_width - 1 || height < kernel_width - 1) {
61 321 return false;
62 }
63
64
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 1107 times.
1110 if (channels > KLEIDICV_MAXIMUM_CHANNEL_COUNT) {
65 3 return false;
66 }
67
68
6/6
✓ Branch 0 taken 402 times.
✓ Branch 1 taken 705 times.
✓ Branch 2 taken 228 times.
✓ Branch 3 taken 174 times.
✓ Branch 4 taken 144 times.
✓ Branch 5 taken 84 times.
1107 if (kernel_width > 7 && kernel_width != 15 && kernel_width != 21) {
69
2/2
✓ Branch 0 taken 9 times.
✓ Branch 1 taken 75 times.
84 if (border_type != FixedBorderType::REPLICATE) {
70 9 return false;
71 }
72
73 75 size_t margin = kernel_width / 2;
74 // Number of 16bit elements in a 128-bit vector
75 75 size_t max_border_length = 8;
76 225 size_t aligned_margin = (margin + max_border_length - 1) /
77 150 max_border_length * max_border_length;
78
2/2
✓ Branch 0 taken 12 times.
✓ Branch 1 taken 63 times.
75 if (width < aligned_margin + margin) {
79 12 return false;
80 }
81 75 }
82
83 1086 return true;
84 1455 }
85
86 // Does not include checks for whether the operation is implemented.
87 // This must be done earlier, by gaussian_blur_is_implemented.
88 template <typename T>
89 1101 kleidicv_error_t gaussian_blur_checks(
90 const T *src, size_t src_stride, T *dst, size_t dst_stride, size_t width,
91 size_t height, size_t channels,
92 const KLEIDICV_TARGET_NAMESPACE::SeparableFilterWorkspace *workspace)
93 KLEIDICV_STREAMING {
94
2/2
✓ Branch 0 taken 12 times.
✓ Branch 1 taken 1089 times.
1101 CHECK_POINTERS(workspace);
95
96
4/4
✓ Branch 0 taken 12 times.
✓ Branch 1 taken 1077 times.
✓ Branch 2 taken 12 times.
✓ Branch 3 taken 1077 times.
1089 CHECK_POINTER_AND_STRIDE(src, src_stride, height);
97
4/4
✓ Branch 0 taken 12 times.
✓ Branch 1 taken 1065 times.
✓ Branch 2 taken 12 times.
✓ Branch 3 taken 1065 times.
1077 CHECK_POINTER_AND_STRIDE(dst, dst_stride, height);
98
6/6
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 1062 times.
✓ Branch 2 taken 6 times.
✓ Branch 3 taken 1056 times.
✓ Branch 4 taken 9 times.
✓ Branch 5 taken 1056 times.
1065 CHECK_IMAGE_SIZE(width, height);
99
100
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 1050 times.
1056 if (workspace->channels() < channels) {
101 6 return KLEIDICV_ERROR_CONTEXT_MISMATCH;
102 }
103
104 2100 const KLEIDICV_TARGET_NAMESPACE::Rectangle &context_rect =
105 1050 workspace->image_size();
106
4/4
✓ Branch 0 taken 1038 times.
✓ Branch 1 taken 12 times.
✓ Branch 2 taken 6 times.
✓ Branch 3 taken 1032 times.
1050 if (context_rect.width() < width || context_rect.height() < height) {
107 18 return KLEIDICV_ERROR_CONTEXT_MISMATCH;
108 }
109
110 1032 return KLEIDICV_OK;
111 1101 }
112
113 namespace neon {
114
115 kleidicv_error_t gaussian_blur_fixed_stripe_u8(
116 const uint8_t *src, size_t src_stride, uint8_t *dst, size_t dst_stride,
117 size_t width, size_t height, size_t y_begin, size_t y_end, size_t channels,
118 size_t kernel_width, size_t kernel_height, float sigma_x, float sigma_y,
119 FixedBorderType border_type, kleidicv_filter_context_t *context);
120
121 kleidicv_error_t gaussian_blur_arbitrary_stripe_u8(
122 const uint8_t *src, size_t src_stride, uint8_t *dst, size_t dst_stride,
123 size_t width, size_t height, size_t y_begin, size_t y_end, size_t channels,
124 size_t kernel_width, size_t kernel_height, float sigma_x, float sigma_y,
125 FixedBorderType border_type, kleidicv_filter_context_t *context);
126
127 } // namespace neon
128
129 namespace sve2 {
130
131 kleidicv_error_t gaussian_blur_fixed_stripe_u8(
132 const uint8_t *src, size_t src_stride, uint8_t *dst, size_t dst_stride,
133 size_t width, size_t height, size_t y_begin, size_t y_end, size_t channels,
134 size_t kernel_width, size_t kernel_height, float sigma_x, float sigma_y,
135 FixedBorderType border_type, kleidicv_filter_context_t *context);
136
137 } // namespace sve2
138
139 namespace sme {
140
141 kleidicv_error_t gaussian_blur_fixed_stripe_u8(
142 const uint8_t *src, size_t src_stride, uint8_t *dst, size_t dst_stride,
143 size_t width, size_t height, size_t y_begin, size_t y_end, size_t channels,
144 size_t kernel_width, size_t kernel_height, float sigma_x, float sigma_y,
145 FixedBorderType border_type, kleidicv_filter_context_t *context);
146
147 } // namespace sme
148
149 } // namespace kleidicv
150
151 #endif // KLEIDICV_FILTERS_GAUSSIAN_BLUR_H
152