| Line | Branch | Exec | Source |
|---|---|---|---|
| 1 | // SPDX-FileCopyrightText: 2024 - 2025 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 | template <typename FilterType> | ||
| 17 | 172 | void process(Rectangle rect, size_t y_begin, size_t y_end, | |
| 18 | Rows<const typename FilterType::SourceType> src_rows, | ||
| 19 | Rows<typename FilterType::DestinationType> dst_rows, | ||
| 20 | size_t channels, typename FilterType::BorderType border_type, | ||
| 21 | FilterType filter) KLEIDICV_STREAMING { | ||
| 22 | // Border helper which calculates border offsets. | ||
| 23 | 344 | typename FilterType::BorderInfoType vertical_border{rect.height(), | |
| 24 | 172 | border_type}; | |
| 25 | 344 | typename FilterType::BorderInfoType horizontal_border{rect.width(), | |
| 26 | 172 | border_type}; | |
| 27 | |||
| 28 | // Buffer rows which hold intermediate widened data. | ||
| 29 | 344 | auto buffer_rows = Rows{reinterpret_cast<typename FilterType::BufferType *>( | |
| 30 | 172 | &data_[buffer_rows_offset_]), | |
| 31 | 172 | buffer_rows_stride_, channels}; | |
| 32 | |||
| 33 | // Vertical processing loop. | ||
| 34 |
2/2✓ Branch 0 taken 172 times.
✓ Branch 1 taken 1836 times.
|
2008 | for (size_t vertical_index = y_begin; vertical_index < y_end; |
| 35 | 1836 | vertical_index += 2) { | |
| 36 | // Recalculate vertical border offsets. | ||
| 37 | 1836 | auto offsets = vertical_border.offsets_with_border(vertical_index); | |
| 38 | // Process in the vertical direction first. | ||
| 39 | 3672 | filter.process_vertical(rect.width(), src_rows.at(vertical_index), | |
| 40 | 1836 | buffer_rows, offsets); | |
| 41 | // Process in the horizontal direction last. | ||
| 42 | 3672 | process_horizontal(rect.width(), buffer_rows, | |
| 43 | 1836 | dst_rows.at(vertical_index / 2), filter, | |
| 44 | 1836 | horizontal_border); | |
| 45 | 1836 | } | |
| 46 | 172 | } | |
| 47 | |||
| 48 | private: | ||
| 49 | template <typename FilterType> | ||
| 50 | 1836 | void process_horizontal(size_t width, | |
| 51 | Rows<typename FilterType::BufferType> buffer_rows, | ||
| 52 | Rows<typename FilterType::DestinationType> dst_rows, | ||
| 53 | FilterType filter, | ||
| 54 | typename FilterType::BorderInfoType horizontal_border) | ||
| 55 | KLEIDICV_STREAMING { | ||
| 56 | // Margin associated with the filter. | ||
| 57 | 1836 | constexpr size_t margin = filter.margin; | |
| 58 | |||
| 59 | // Process data affected by left border. | ||
| 60 | KLEIDICV_FORCE_LOOP_UNROLL | ||
| 61 |
2/2✓ Branch 0 taken 1836 times.
✓ Branch 1 taken 1836 times.
|
3672 | for (size_t horizontal_index = 0; horizontal_index < margin; |
| 62 | 1836 | horizontal_index += 2) { | |
| 63 | 1836 | auto offsets = | |
| 64 | 1836 | horizontal_border.offsets_with_left_border(horizontal_index); | |
| 65 | 3672 | filter.process_horizontal_borders(buffer_rows.at(0, horizontal_index), | |
| 66 | 1836 | dst_rows.at(0, horizontal_index / 2), | |
| 67 | 1836 | offsets); | |
| 68 | 1836 | } | |
| 69 | |||
| 70 | // Process data which is not affected by any borders in bulk. | ||
| 71 | { | ||
| 72 | 1836 | size_t width_without_borders = width - (2 * margin); | |
| 73 | 1836 | auto offsets = horizontal_border.offsets_without_border(); | |
| 74 | 1836 | size_t start = align_up(margin, 2); | |
| 75 | 3672 | filter.process_horizontal(width_without_borders, buffer_rows.at(0, start), | |
| 76 | 1836 | dst_rows.at(0, start / 2), offsets); | |
| 77 | 1836 | } | |
| 78 | |||
| 79 | // Process data affected by right border. | ||
| 80 |
2/2✓ Branch 0 taken 1836 times.
✓ Branch 1 taken 1836 times.
|
3672 | for (size_t index = align_up(width - margin, 2); index < width; |
| 81 | 1836 | index += 2) { | |
| 82 | 1836 | auto offsets = horizontal_border.offsets_with_right_border(index); | |
| 83 | 3672 | filter.process_horizontal_borders(buffer_rows.at(0, index), | |
| 84 | 1836 | dst_rows.at(0, index / 2), offsets); | |
| 85 | 1836 | } | |
| 86 | 1836 | } | |
| 87 | }; // end of class BlurAndDownsampleFilterWorkspace | ||
| 88 | |||
| 89 | // BlurAndDownsampleFilterWorkspace and SeparableFilterWorkspace must have the | ||
| 90 | // same size because through the API of this library only | ||
| 91 | // SeparableFilterWorkspace can be created. So, child classes of | ||
| 92 | // SeparableFilterWorkspace can only add functionality but cannot add member | ||
| 93 | // variables. | ||
| 94 | static_assert(sizeof(BlurAndDownsampleFilterWorkspace) == | ||
| 95 | sizeof(SeparableFilterWorkspace)); | ||
| 96 | |||
| 97 | } // namespace KLEIDICV_TARGET_NAMESPACE | ||
| 98 | |||
| 99 | #endif // KLEIDICV_WORKSPACE_BLUR_AND_DOWNSAMPLE_WS_H | ||
| 100 |