KleidiCV Coverage Report


Directory: ./
File: kleidicv/include/kleidicv/filters/gaussian_blur.h
Date: 2026-01-20 20:58:59
Exec Total Coverage
Lines: 31 31 100.0%
Functions: 2 2 100.0%
Branches: 40 40 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
27 KLEIDICV_API_DECLARATION(kleidicv_gaussian_blur_arbitrary_stripe_u8,
28 const uint8_t *src, size_t src_stride, uint8_t *dst,
29 size_t dst_stride, size_t width, size_t height,
30 size_t y_begin, size_t y_end, size_t channels,
31 size_t kernel_width, size_t kernel_height,
32 float sigma_x, float sigma_y,
33 kleidicv::FixedBorderType border_type);
34 }
35
36 namespace kleidicv {
37
38 1900 inline bool gaussian_blur_is_implemented(
39 size_t width, size_t height, size_t kernel_width, size_t kernel_height,
40 float sigma_x, float sigma_y, size_t channels,
41 kleidicv::FixedBorderType border_type) {
42
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 1896 times.
1900 if (kernel_width != kernel_height) {
43 4 return false;
44 }
45
46
4/4
✓ Branch 0 taken 1892 times.
✓ Branch 1 taken 4 times.
✓ Branch 2 taken 4 times.
✓ Branch 3 taken 1888 times.
1896 if (kernel_width < 3 || kernel_width > 255) {
47 8 return false;
48 }
49
50
2/2
✓ Branch 0 taken 8 times.
✓ Branch 1 taken 1880 times.
1888 if ((kernel_width & 1) != 1) {
51 8 return false;
52 }
53
54
2/2
✓ Branch 0 taken 12 times.
✓ Branch 1 taken 1868 times.
1880 if (sigma_x != sigma_y) {
55 12 return false;
56 }
57
58
4/4
✓ Branch 0 taken 1480 times.
✓ Branch 1 taken 388 times.
✓ Branch 2 taken 40 times.
✓ Branch 3 taken 1440 times.
1868 if (width < kernel_width - 1 || height < kernel_width - 1) {
59 428 return false;
60 }
61
62
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 1436 times.
1440 if (channels > KLEIDICV_MAXIMUM_CHANNEL_COUNT) {
63 4 return false;
64 }
65
66
6/6
✓ Branch 0 taken 504 times.
✓ Branch 1 taken 932 times.
✓ Branch 2 taken 296 times.
✓ Branch 3 taken 208 times.
✓ Branch 4 taken 192 times.
✓ Branch 5 taken 104 times.
1436 if (kernel_width > 7 && kernel_width != 15 && kernel_width != 21) {
67
2/2
✓ Branch 0 taken 12 times.
✓ Branch 1 taken 92 times.
104 if (border_type != FixedBorderType::REPLICATE) {
68 12 return false;
69 }
70
71 92 size_t margin = kernel_width / 2;
72 // Number of 16bit elements in a 128-bit vector
73 92 size_t max_border_length = 8;
74 276 size_t aligned_margin = (margin + max_border_length - 1) /
75 184 max_border_length * max_border_length;
76
2/2
✓ Branch 0 taken 16 times.
✓ Branch 1 taken 76 times.
92 if (width < aligned_margin + margin) {
77 16 return false;
78 }
79 92 }
80
81 1408 return true;
82 1900 }
83
84 // Does not include checks for whether the operation is implemented.
85 // This must be done earlier, by gaussian_blur_is_implemented.
86 template <typename T>
87 1480 kleidicv_error_t gaussian_blur_checks(const T *src, size_t src_stride, T *dst,
88 size_t dst_stride, size_t width,
89 size_t height) KLEIDICV_STREAMING {
90
4/4
✓ Branch 0 taken 16 times.
✓ Branch 1 taken 1464 times.
✓ Branch 2 taken 16 times.
✓ Branch 3 taken 1464 times.
1480 CHECK_POINTER_AND_STRIDE(src, src_stride, height);
91
4/4
✓ Branch 0 taken 16 times.
✓ Branch 1 taken 1448 times.
✓ Branch 2 taken 16 times.
✓ Branch 3 taken 1448 times.
1464 CHECK_POINTER_AND_STRIDE(dst, dst_stride, height);
92
6/6
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 1444 times.
✓ Branch 2 taken 8 times.
✓ Branch 3 taken 1436 times.
✓ Branch 4 taken 12 times.
✓ Branch 5 taken 1436 times.
1448 CHECK_IMAGE_SIZE(width, height);
93
94 1436 return KLEIDICV_OK;
95 1480 }
96
97 namespace neon {
98
99 kleidicv_error_t gaussian_blur_fixed_stripe_u8(
100 const uint8_t *src, size_t src_stride, uint8_t *dst, size_t dst_stride,
101 size_t width, size_t height, size_t y_begin, size_t y_end, size_t channels,
102 size_t kernel_width, size_t kernel_height, float sigma_x, float sigma_y,
103 FixedBorderType border_type);
104
105 kleidicv_error_t gaussian_blur_arbitrary_stripe_u8(
106 const uint8_t *src, size_t src_stride, uint8_t *dst, size_t dst_stride,
107 size_t width, size_t height, size_t y_begin, size_t y_end, size_t channels,
108 size_t kernel_width, size_t kernel_height, float sigma_x, float sigma_y,
109 FixedBorderType border_type);
110
111 } // namespace neon
112
113 namespace sve2 {
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);
120
121 } // namespace sve2
122
123 namespace sme {
124
125 kleidicv_error_t gaussian_blur_fixed_stripe_u8(
126 const uint8_t *src, size_t src_stride, uint8_t *dst, size_t dst_stride,
127 size_t width, size_t height, size_t y_begin, size_t y_end, size_t channels,
128 size_t kernel_width, size_t kernel_height, float sigma_x, float sigma_y,
129 FixedBorderType border_type);
130
131 } // namespace sme
132
133 } // namespace kleidicv
134
135 #endif // KLEIDICV_FILTERS_GAUSSIAN_BLUR_H
136