KleidiCV Coverage Report


Directory: ./
File: kleidicv/include/kleidicv/workspace/blur_and_downsample_ws.h
Date: 2026-03-05 15:57:40
Exec Total Coverage
Lines: 52 52 100.0%
Functions: 15 15 100.0%
Branches: 8 8 100.0%

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_WORKSPACE_BLUR_AND_DOWNSAMPLE_WS_H
6 #define KLEIDICV_WORKSPACE_BLUR_AND_DOWNSAMPLE_WS_H
7
8 #include "separable.h"
9
10 namespace KLEIDICV_TARGET_NAMESPACE {
11
12 // Alter SeparableFilterWorkspace's behavior to only process elements in even
13 // rows and columns
14 class BlurAndDownsampleFilterWorkspace final : public SeparableFilterWorkspace {
15 public:
16 // Only constructible with create().
17 BlurAndDownsampleFilterWorkspace() = delete;
18
19 static std::variant<BlurAndDownsampleFilterWorkspace, kleidicv_error_t>
20 552 create(Rectangle rect, size_t channels,
21 size_t intermediate_size) KLEIDICV_STREAMING {
22 1104 auto [allocation, buffer_rows_stride] =
23 552 allocate(rect, channels, intermediate_size);
24
25
2/2
✓ Branch 0 taken 548 times.
✓ Branch 1 taken 4 times.
552 if (!allocation) {
26 4 return KLEIDICV_ERROR_ALLOCATION;
27 }
28
29 1096 return BlurAndDownsampleFilterWorkspace{rect, channels, allocation,
30 548 buffer_rows_stride};
31 552 }
32
33 private:
34 548 BlurAndDownsampleFilterWorkspace(Rectangle rect, size_t channels,
35 uint8_t *allocation,
36 size_t buffer_rows_stride) KLEIDICV_STREAMING
37 1096 : SeparableFilterWorkspace(rect, channels, allocation,
38 1096 buffer_rows_stride) {}
39
40 public:
41 template <typename FilterType>
42 548 void process(size_t y_begin, size_t y_end,
43 Rows<const typename FilterType::SourceType> src_rows,
44 Rows<typename FilterType::DestinationType> dst_rows,
45 typename FilterType::BorderType border_type,
46 FilterType filter) KLEIDICV_STREAMING {
47 // Border helper which calculates border offsets.
48 1096 typename FilterType::BorderInfoType vertical_border{rect_.height(),
49 548 border_type};
50 1096 typename FilterType::BorderInfoType horizontal_border{rect_.width(),
51 548 border_type};
52
53 // Buffer rows which hold intermediate widened data.
54 548 auto buffer_rows =
55 1096 Rows{reinterpret_cast<typename FilterType::BufferType *>(buffer_.get()),
56 548 buffer_rows_stride_, channels_};
57
58 // Vertical processing loop.
59
2/2
✓ Branch 0 taken 548 times.
✓ Branch 1 taken 10044 times.
10592 for (size_t vertical_index = align_up(y_begin, 2); vertical_index < y_end;
60 10044 vertical_index += 2) {
61 // Recalculate vertical border offsets.
62 10044 auto offsets = vertical_border.offsets_with_border(vertical_index);
63 // Process in the vertical direction first.
64 20088 filter.process_vertical(rect_.width(), src_rows.at(vertical_index),
65 10044 buffer_rows, offsets);
66 // Process in the horizontal direction last.
67 20088 process_horizontal(rect_.width(), buffer_rows,
68 10044 dst_rows.at(vertical_index / 2), filter,
69 10044 horizontal_border);
70 10044 }
71 548 }
72
73 private:
74 template <typename FilterType>
75 10044 void process_horizontal(size_t width,
76 Rows<typename FilterType::BufferType> buffer_rows,
77 Rows<typename FilterType::DestinationType> dst_rows,
78 FilterType filter,
79 typename FilterType::BorderInfoType horizontal_border)
80 KLEIDICV_STREAMING {
81 // Margin associated with the filter.
82 10044 constexpr size_t margin = filter.margin;
83
84 // Process data affected by left border.
85 KLEIDICV_FORCE_LOOP_UNROLL
86
2/2
✓ Branch 0 taken 10044 times.
✓ Branch 1 taken 10044 times.
20088 for (size_t horizontal_index = 0; horizontal_index < margin;
87 10044 horizontal_index += 2) {
88 10044 auto offsets =
89 10044 horizontal_border.offsets_with_left_border(horizontal_index);
90 20088 filter.process_horizontal_borders(buffer_rows.at(0, horizontal_index),
91 10044 dst_rows.at(0, horizontal_index / 2),
92 10044 offsets);
93 10044 }
94
95 // Process data which is not affected by any borders in bulk.
96 {
97 10044 size_t width_without_borders = width - (2 * margin);
98 10044 auto offsets = horizontal_border.offsets_without_border();
99 10044 size_t start = align_up(margin, 2);
100 20088 filter.process_horizontal(width_without_borders, buffer_rows.at(0, start),
101 10044 dst_rows.at(0, start / 2), offsets);
102 10044 }
103
104 // Process data affected by right border.
105
2/2
✓ Branch 0 taken 10044 times.
✓ Branch 1 taken 10044 times.
20088 for (size_t index = align_up(width - margin, 2); index < width;
106 10044 index += 2) {
107 10044 auto offsets = horizontal_border.offsets_with_right_border(index);
108 20088 filter.process_horizontal_borders(buffer_rows.at(0, index),
109 10044 dst_rows.at(0, index / 2), offsets);
110 10044 }
111 10044 }
112 }; // end of class BlurAndDownsampleFilterWorkspace
113
114 } // namespace KLEIDICV_TARGET_NAMESPACE
115
116 #endif // KLEIDICV_WORKSPACE_BLUR_AND_DOWNSAMPLE_WS_H
117