GCC Code Coverage Report


Directory: ./
File: tasks/shakirova_e_sobel_edge_detection/common/include/img_container.hpp
Date: 2026-04-02 17:12:27
Exec Total Coverage
Lines: 40 46 87.0%
Functions: 4 4 100.0%
Branches: 28 70 40.0%

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 72 times.
✗ Branch 2 not taken.
360 struct ImgContainer {
19 int width{0};
20 int height{0};
21 std::vector<int> pixels;
22
23 72 ImgContainer() = default;
24
1/2
✓ Branch 1 taken 36 times.
✗ Branch 2 not taken.
36 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
3/6
✓ Branch 0 taken 72 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 72 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 72 times.
72 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 72 static ImgContainer FromFile(const std::string &path) {
43
1/2
✗ Branch 2 not taken.
✓ Branch 3 taken 72 times.
144 if (!std::filesystem::exists(path)) {
44 throw std::runtime_error("File not found: " + path);
45 }
46 72 const std::string ext = GetExt(path);
47
5/8
✓ Branch 0 taken 36 times.
✓ Branch 1 taken 36 times.
✓ Branch 2 taken 36 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 36 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✓ Branch 7 taken 36 times.
72 if (ext == ".png" || ext == ".jpg" || ext == ".jpeg" || ext == ".bmp") {
48
1/2
✓ Branch 1 taken 36 times.
✗ Branch 2 not taken.
36 return LoadRaster(path);
49 }
50
1/2
✓ Branch 0 taken 36 times.
✗ Branch 1 not taken.
36 if (ext == ".txt") {
51
1/2
✓ Branch 1 taken 36 times.
✗ Branch 2 not taken.
36 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 9849600 return static_cast<int>((0.299 * r) + (0.587 * g) + (0.114 * b));
59 }
60
61
1/2
✓ Branch 0 taken 72 times.
✗ Branch 1 not taken.
72 static std::string GetExt(const std::string &path) {
62 const auto pos = path.rfind('.');
63
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 72 times.
72 if (pos == std::string::npos) {
64 return "";
65 }
66 72 std::string ext = path.substr(pos);
67 288 std::ranges::transform(ext, ext.begin(), [](unsigned char c) { return std::tolower(c); });
68 72 return ext;
69 }
70
71 36 static ImgContainer LoadRaster(const std::string &path) {
72 36 int w = 0;
73 36 int h = 0;
74 36 int ch = 0;
75 36 uint8_t *data = stbi_load(path.c_str(), &w, &h, &ch, STBI_rgb);
76
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 36 times.
36 if (data == nullptr) {
77 throw std::runtime_error("stb_image failed to load: " + path);
78 }
79 36 ImgContainer img(w, h);
80
2/2
✓ Branch 0 taken 9849600 times.
✓ Branch 1 taken 36 times.
9849636 for (int i = 0; i < w * h; ++i) {
81 9849600 img.pixels[i] = ToGray(data[static_cast<ptrdiff_t>(i) * 3], data[(static_cast<ptrdiff_t>(i) * 3) + 1],
82 9849600 data[(static_cast<ptrdiff_t>(i) * 3) + 2]);
83 }
84
1/2
✓ Branch 1 taken 36 times.
✗ Branch 2 not taken.
36 stbi_image_free(data);
85 36 return img;
86 }
87
88 36 static ImgContainer LoadTXT(const std::string &path) {
89 36 std::ifstream f(path);
90
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 36 times.
36 if (!f.is_open()) {
91 throw std::runtime_error("Cannot open file: " + path);
92 }
93 36 int w = 0;
94 36 int h = 0;
95
2/4
✓ Branch 1 taken 36 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 36 times.
✗ Branch 5 not taken.
36 f >> w >> h;
96
2/4
✓ Branch 0 taken 36 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 36 times.
36 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 684 times.
✓ Branch 1 taken 36 times.
720 for (int i = 0; i < w * h; ++i) {
101
1/2
✓ Branch 1 taken 684 times.
✗ Branch 2 not taken.
684 f >> img.pixels[i];
102 }
103 36 return img;
104 36 }
105 };
106
107 } // namespace shakirova_e_sobel_edge_detection
108