GCC Code Coverage Report


Directory: ./
File: tasks/shakirova_e_sobel_edge_detection/common/include/img_container.hpp
Date: 2026-06-04 20:25:32
Exec Total Coverage
Lines: 40 46 87.0%
Functions: 4 4 100.0%
Branches: 30 76 39.5%

Line Branch Exec Source
1 #pragma once
2
3 #include <stb/stb_image.h>
4
5 #include <algorithm>
6 #include <cctype>
7 #include <cstddef>
8 #include <cstdint>
9 #include <filesystem>
10 #include <fstream>
11 #include <stdexcept>
12 #include <string>
13 #include <utility>
14 #include <vector>
15
16 namespace shakirova_e_sobel_edge_detection {
17
18
1/2
✓ Branch 1 taken 156 times.
✗ Branch 2 not taken.
780 struct ImgContainer {
19 int width{0};
20 int height{0};
21 std::vector<int> pixels;
22
23 156 ImgContainer() = default;
24
1/2
✓ Branch 1 taken 78 times.
✗ Branch 2 not taken.
78 ImgContainer(int w, int h) : width(w), height(h), pixels(static_cast<size_t>(w) * static_cast<size_t>(h), 0) {}
25 ImgContainer(int w, int h, std::vector<int> px) : width(w), height(h), pixels(std::move(px)) {}
26
27 [[nodiscard]] bool IsValid() const {
28
5/12
✓ Branch 0 taken 150 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 6 times.
✓ Branch 3 taken 144 times.
✓ Branch 4 taken 6 times.
✓ Branch 5 taken 144 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
150 return width > 2 && height > 2 && static_cast<int>(pixels.size()) == width * height;
29 }
30
31 [[nodiscard]] int &At(int x, int y) {
32 return pixels[(y * width) + x];
33 }
34 [[nodiscard]] const int &At(int x, int y) const {
35 return pixels[(y * width) + x];
36 }
37
38 friend bool operator==(const ImgContainer &lhs, const ImgContainer &rhs) {
39 return lhs.width == rhs.width && lhs.height == rhs.height && lhs.pixels == rhs.pixels;
40 }
41
42 156 static ImgContainer FromFile(const std::string &path) {
43
1/2
✗ Branch 2 not taken.
✓ Branch 3 taken 156 times.
312 if (!std::filesystem::exists(path)) {
44 throw std::runtime_error("File not found: " + path);
45 }
46 156 const std::string ext = GetExt(path);
47
5/8
✓ Branch 0 taken 78 times.
✓ Branch 1 taken 78 times.
✓ Branch 2 taken 78 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 78 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✓ Branch 7 taken 78 times.
156 if (ext == ".png" || ext == ".jpg" || ext == ".jpeg" || ext == ".bmp") {
48
1/2
✓ Branch 1 taken 78 times.
✗ Branch 2 not taken.
78 return LoadRaster(path);
49 }
50
1/2
✓ Branch 0 taken 78 times.
✗ Branch 1 not taken.
78 if (ext == ".txt") {
51
1/2
✓ Branch 1 taken 78 times.
✗ Branch 2 not taken.
78 return LoadTXT(path);
52 }
53 throw std::runtime_error("Unsupported format: " + ext + " (supported: .png .jpg .bmp .txt)");
54 }
55
56 private:
57 static int ToGray(uint8_t r, uint8_t g, uint8_t b) {
58 21340800 return static_cast<int>((0.299 * r) + (0.587 * g) + (0.114 * b));
59 }
60
61
1/2
✓ Branch 0 taken 156 times.
✗ Branch 1 not taken.
156 static std::string GetExt(const std::string &path) {
62 const auto pos = path.rfind('.');
63
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 156 times.
156 if (pos == std::string::npos) {
64 return "";
65 }
66 156 std::string ext = path.substr(pos);
67 624 std::ranges::transform(ext, ext.begin(), [](unsigned char c) { return std::tolower(c); });
68 156 return ext;
69 }
70
71 78 static ImgContainer LoadRaster(const std::string &path) {
72 78 int w = 0;
73 78 int h = 0;
74 78 int ch = 0;
75 78 uint8_t *data = stbi_load(path.c_str(), &w, &h, &ch, STBI_rgb);
76
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 78 times.
78 if (data == nullptr) {
77 throw std::runtime_error("stb_image failed to load: " + path);
78 }
79 78 ImgContainer img(w, h);
80
2/2
✓ Branch 0 taken 21340800 times.
✓ Branch 1 taken 78 times.
21340878 for (int i = 0; i < w * h; ++i) {
81 21340800 img.pixels[i] = ToGray(data[static_cast<ptrdiff_t>(i) * 3], data[(static_cast<ptrdiff_t>(i) * 3) + 1],
82 21340800 data[(static_cast<ptrdiff_t>(i) * 3) + 2]);
83 }
84
1/2
✓ Branch 1 taken 78 times.
✗ Branch 2 not taken.
78 stbi_image_free(data);
85 78 return img;
86 }
87
88 78 static ImgContainer LoadTXT(const std::string &path) {
89 78 std::ifstream f(path);
90
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 78 times.
78 if (!f.is_open()) {
91 throw std::runtime_error("Cannot open file: " + path);
92 }
93 78 int w = 0;
94 78 int h = 0;
95
2/4
✓ Branch 1 taken 78 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 78 times.
✗ Branch 5 not taken.
78 f >> w >> h;
96
2/4
✓ Branch 0 taken 78 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 78 times.
78 if (w <= 0 || h <= 0) {
97 throw std::runtime_error("Invalid dimensions in: " + path);
98 }
99 ImgContainer img(w, h);
100
2/2
✓ Branch 0 taken 1482 times.
✓ Branch 1 taken 78 times.
1560 for (int i = 0; i < w * h; ++i) {
101
1/2
✓ Branch 1 taken 1482 times.
✗ Branch 2 not taken.
1482 f >> img.pixels[i];
102 }
103 78 return img;
104 78 }
105 };
106
107 } // namespace shakirova_e_sobel_edge_detection
108