GCC Code Coverage Report


Directory: ./
File: tasks/moskaev_v_lin_filt_block_gauss_3/tbb/src/ops_tbb.cpp
Date: 2026-06-04 20:25:32
Exec Total Coverage
Lines: 75 75 100.0%
Functions: 11 11 100.0%
Branches: 29 42 69.0%

Line Branch Exec Source
1 #include "moskaev_v_lin_filt_block_gauss_3/tbb/include/ops_tbb.hpp"
2
3 #include <tbb/blocked_range2d.h>
4 #include <tbb/parallel_for.h>
5
6 #include <algorithm>
7 #include <cmath>
8 #include <cstddef>
9 #include <cstdint>
10 #include <vector>
11
12 #include "moskaev_v_lin_filt_block_gauss_3/common/include/common.hpp"
13
14 namespace moskaev_v_lin_filt_block_gauss_3 {
15
16
1/2
✓ Branch 1 taken 16 times.
✗ Branch 2 not taken.
16 MoskaevVLinFiltBlockGauss3TBB::MoskaevVLinFiltBlockGauss3TBB(const InType &in) {
17 SetTypeOfTask(GetStaticTypeOfTask());
18 GetInput() = in;
19 16 GetOutput() = OutType();
20 16 }
21
22 16 bool MoskaevVLinFiltBlockGauss3TBB::ValidationImpl() {
23 const auto &input = GetInput();
24 16 return !std::get<4>(input).empty();
25 }
26
27 16 bool MoskaevVLinFiltBlockGauss3TBB::PreProcessingImpl() {
28 16 return true;
29 }
30
31 namespace {
32
33 104 inline void ComputeFilteredPixel(const std::vector<uint8_t> &input_block, std::vector<uint8_t> &output_block,
34 int block_width, int inner_width, int channels, int row, int col, int channel) {
35 float sum = 0.0F;
36
2/2
✓ Branch 0 taken 312 times.
✓ Branch 1 taken 104 times.
416 for (int ky = -1; ky <= 1; ++ky) {
37
2/2
✓ Branch 0 taken 936 times.
✓ Branch 1 taken 312 times.
1248 for (int kx = -1; kx <= 1; ++kx) {
38 936 int ny = row + 1 + ky;
39 936 int nx = col + 1 + kx;
40 936 int idx = (((ny * block_width) + nx) * channels) + channel;
41 936 sum += static_cast<float>(input_block[idx]) * kGaussianKernel[((ky + 1) * 3) + (kx + 1)];
42 }
43 }
44 104 int out_idx = (((row * inner_width) + col) * channels) + channel;
45 104 output_block[out_idx] = static_cast<uint8_t>(std::round(sum));
46 104 }
47
48 } // namespace
49
50 16 void MoskaevVLinFiltBlockGauss3TBB::ApplyGaussianFilterToBlock(const std::vector<uint8_t> &input_block,
51 std::vector<uint8_t> &output_block, int block_width,
52 int block_height, int channels) {
53 16 int inner_width = block_width - 2;
54 16 int inner_height = block_height - 2;
55
56 16 tbb::parallel_for(0, inner_height, [&](int row) {
57
2/2
✓ Branch 0 taken 72 times.
✓ Branch 1 taken 32 times.
104 for (int col = 0; col < inner_width; ++col) {
58
2/2
✓ Branch 0 taken 104 times.
✓ Branch 1 taken 72 times.
176 for (int channel = 0; channel < channels; ++channel) {
59 104 ComputeFilteredPixel(input_block, output_block, block_width, inner_width, channels, row, col, channel);
60 }
61 }
62 32 });
63 16 }
64
65 namespace {
66
67 void CopyBlockWithPadding(const std::vector<uint8_t> &source_image, std::vector<uint8_t> &padded_block, int width,
68 int height, int channels, int block_x, int block_y, int current_block_width,
69 int current_block_height, int block_with_padding_width) {
70 int padded_height = current_block_height + 2;
71 16 int padded_width = current_block_width + 2;
72
73 96 tbb::parallel_for(0, padded_height, [&](int row) {
74
2/2
✓ Branch 0 taken 264 times.
✓ Branch 1 taken 64 times.
328 for (int col = 0; col < padded_width; ++col) {
75 264 int src_y = std::clamp(block_y + row - 1, 0, height - 1);
76 264 int src_x = std::clamp(block_x + col - 1, 0, width - 1);
77
2/2
✓ Branch 0 taken 392 times.
✓ Branch 1 taken 264 times.
656 for (int channel = 0; channel < channels; ++channel) {
78 392 int src_idx = (((src_y * width) + src_x) * channels) + channel;
79 392 int dst_idx = (((row * block_with_padding_width) + col) * channels) + channel;
80 392 padded_block[dst_idx] = source_image[src_idx];
81 }
82 }
83 64 });
84 }
85
86 void CopyProcessedBlockToOutput(const std::vector<uint8_t> &processed_block, std::vector<uint8_t> &output_image,
87 int width, int channels, int block_x, int block_y, int current_block_width,
88 int current_block_height) {
89
1/2
✓ Branch 1 taken 16 times.
✗ Branch 2 not taken.
16 tbb::parallel_for(0, current_block_height, [&](int row) {
90
2/2
✓ Branch 0 taken 72 times.
✓ Branch 1 taken 32 times.
104 for (int col = 0; col < current_block_width; ++col) {
91
2/2
✓ Branch 0 taken 104 times.
✓ Branch 1 taken 72 times.
176 for (int channel = 0; channel < channels; ++channel) {
92 104 int src_idx = (((row * current_block_width) + col) * channels) + channel;
93 104 int dst_idx = ((((block_y + row) * width) + (block_x + col)) * channels) + channel;
94 104 output_image[dst_idx] = processed_block[src_idx];
95 }
96 }
97 32 });
98 }
99
100 } // namespace
101
102 16 bool MoskaevVLinFiltBlockGauss3TBB::RunImpl() {
103 const auto &input = GetInput();
104
105 16 int width = std::get<0>(input);
106 16 int height = std::get<1>(input);
107
1/2
✓ Branch 0 taken 16 times.
✗ Branch 1 not taken.
16 int channels = std::get<2>(input);
108 const auto &image_data = std::get<4>(input);
109
110
1/2
✓ Branch 0 taken 16 times.
✗ Branch 1 not taken.
16 if (image_data.empty()) {
111 return false;
112 }
113
114 16 block_size_ = 64;
115 16 int block_size = block_size_;
116
117 16 GetOutput().resize(static_cast<size_t>(width) * static_cast<size_t>(height) * static_cast<size_t>(channels));
118
119 16 int blocks_x = (width + block_size - 1) / block_size;
120 16 int blocks_y = (height + block_size - 1) / block_size;
121
122 16 tbb::parallel_for(0, blocks_y, [&](int by) {
123
2/2
✓ Branch 0 taken 16 times.
✓ Branch 1 taken 16 times.
32 for (int bx = 0; bx < blocks_x; ++bx) {
124 16 int block_x = bx * block_size;
125 16 int block_y = by * block_size;
126
1/2
✓ Branch 0 taken 16 times.
✗ Branch 1 not taken.
16 int current_block_width = std::min(block_size, width - block_x);
127
1/2
✓ Branch 0 taken 16 times.
✗ Branch 1 not taken.
16 int current_block_height = std::min(block_size, height - block_y);
128 16 int block_with_padding_width = current_block_width + 2;
129 16 int block_with_padding_height = current_block_height + 2;
130
131 16 std::vector<uint8_t> input_block(static_cast<size_t>(block_with_padding_width) *
132 16 static_cast<size_t>(block_with_padding_height) *
133 16 static_cast<size_t>(channels),
134 16 0);
135 16 std::vector<uint8_t> output_block(static_cast<size_t>(current_block_width) *
136 16 static_cast<size_t>(current_block_height) * static_cast<size_t>(channels),
137
1/4
✓ Branch 1 taken 16 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
16 0);
138
139
1/2
✓ Branch 1 taken 16 times.
✗ Branch 2 not taken.
16 CopyBlockWithPadding(image_data, input_block, width, height, channels, block_x, block_y, current_block_width,
140 current_block_height, block_with_padding_width);
141
1/2
✓ Branch 1 taken 16 times.
✗ Branch 2 not taken.
16 ApplyGaussianFilterToBlock(input_block, output_block, block_with_padding_width, block_with_padding_height,
142 channels);
143
2/4
✓ Branch 1 taken 16 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 16 times.
✗ Branch 4 not taken.
16 CopyProcessedBlockToOutput(output_block, GetOutput(), width, channels, block_x, block_y, current_block_width,
144 current_block_height);
145 }
146 16 });
147
148 16 return true;
149 }
150
151 16 bool MoskaevVLinFiltBlockGauss3TBB::PostProcessingImpl() {
152 16 return !GetOutput().empty();
153 }
154
155 } // namespace moskaev_v_lin_filt_block_gauss_3
156