KleidiCV Coverage Report


Directory: ./
File: kleidicv/include/kleidicv/filters/gaussian_blur.h
Date: 2025-11-25 17:23:32
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 1940 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 4 times.
✓ Branch 1 taken 1936 times.
1940 if (kernel_width != kernel_height) {
45 4 return false;
46 }
47
48
4/4
✓ Branch 0 taken 1932 times.
✓ Branch 1 taken 4 times.
✓ Branch 2 taken 4 times.
✓ Branch 3 taken 1928 times.
1936 if (kernel_width < 3 || kernel_width > 255) {
49 8 return false;
50 }
51
52
2/2
✓ Branch 0 taken 8 times.
✓ Branch 1 taken 1920 times.
1928 if ((kernel_width & 1) != 1) {
53 8 return false;
54 }
55
56
2/2
✓ Branch 0 taken 12 times.
✓ Branch 1 taken 1908 times.
1920 if (sigma_x != sigma_y) {
57 12 return false;
58 }
59
60
4/4
✓ Branch 0 taken 1520 times.
✓ Branch 1 taken 388 times.
✓ Branch 2 taken 40 times.
✓ Branch 3 taken 1480 times.
1908 if (width < kernel_width - 1 || height < kernel_width - 1) {
61 428 return false;
62 }
63
64
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 1476 times.
1480 if (channels > KLEIDICV_MAXIMUM_CHANNEL_COUNT) {
65 4 return false;
66 }
67
68
6/6
✓ Branch 0 taken 536 times.
✓ Branch 1 taken 940 times.
✓ Branch 2 taken 304 times.
✓ Branch 3 taken 232 times.
✓ Branch 4 taken 192 times.
✓ Branch 5 taken 112 times.
1476 if (kernel_width > 7 && kernel_width != 15 && kernel_width != 21) {
69
2/2
✓ Branch 0 taken 12 times.
✓ Branch 1 taken 100 times.
112 if (border_type != FixedBorderType::REPLICATE) {
70 12 return false;
71 }
72
73 100 size_t margin = kernel_width / 2;
74 // Number of 16bit elements in a 128-bit vector
75 100 size_t max_border_length = 8;
76 300 size_t aligned_margin = (margin + max_border_length - 1) /
77 200 max_border_length * max_border_length;
78
2/2
✓ Branch 0 taken 16 times.
✓ Branch 1 taken 84 times.
100 if (width < aligned_margin + margin) {
79 16 return false;
80 }
81 100 }
82
83 1448 return true;
84 1940 }
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 1468 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 16 times.
✓ Branch 1 taken 1452 times.
1468 CHECK_POINTERS(workspace);
95
96
4/4
✓ Branch 0 taken 16 times.
✓ Branch 1 taken 1436 times.
✓ Branch 2 taken 16 times.
✓ Branch 3 taken 1436 times.
1452 CHECK_POINTER_AND_STRIDE(src, src_stride, height);
97
4/4
✓ Branch 0 taken 16 times.
✓ Branch 1 taken 1420 times.
✓ Branch 2 taken 16 times.
✓ Branch 3 taken 1420 times.
1436 CHECK_POINTER_AND_STRIDE(dst, dst_stride, height);
98
6/6
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 1416 times.
✓ Branch 2 taken 8 times.
✓ Branch 3 taken 1408 times.
✓ Branch 4 taken 12 times.
✓ Branch 5 taken 1408 times.
1420 CHECK_IMAGE_SIZE(width, height);
99
100
2/2
✓ Branch 0 taken 8 times.
✓ Branch 1 taken 1400 times.
1408 if (workspace->channels() < channels) {
101 8 return KLEIDICV_ERROR_CONTEXT_MISMATCH;
102 }
103
104 2800 const KLEIDICV_TARGET_NAMESPACE::Rectangle &context_rect =
105 1400 workspace->image_size();
106
4/4
✓ Branch 0 taken 1384 times.
✓ Branch 1 taken 16 times.
✓ Branch 2 taken 8 times.
✓ Branch 3 taken 1376 times.
1400 if (context_rect.width() < width || context_rect.height() < height) {
107 24 return KLEIDICV_ERROR_CONTEXT_MISMATCH;
108 }
109
110 1376 return KLEIDICV_OK;
111 1468 }
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