• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

Razakhel / RaZ / 18064138724

27 Sep 2025 04:20PM UTC coverage: 74.093% (+0.04%) from 74.05%
18064138724

push

github

Razakhel
[Utils/Logger] Added formatted logging overloads

- Formatted calls to logging functions and made use of std::format() in several other places

100 of 170 new or added lines in 36 files covered. (58.82%)

4 existing lines in 2 files now uncovered.

8334 of 11248 relevant lines covered (74.09%)

1757.71 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

73.85
/src/RaZ/Data/TgaFormat.cpp
1
#include "RaZ/Data/Image.hpp"
2
#include "RaZ/Data/TgaFormat.hpp"
3
#include "RaZ/Utils/FilePath.hpp"
4
#include "RaZ/Utils/Logger.hpp"
5

6
#include "tracy/Tracy.hpp"
7

8
#include <array>
9
#include <fstream>
10
#include <sstream>
11

12
namespace Raz::TgaFormat {
13

14
Image load(const FilePath& filePath, bool flipVertically) {
3✔
15
  ZoneScopedN("TgaFormat::load");
16
  ZoneTextF("Path: %s", filePath.toUtf8().c_str());
17

18
  Logger::debug("[TgaFormat] Loading TGA file ('{}')...", filePath);
3✔
19

20
  std::ifstream file(filePath, std::ios_base::binary);
3✔
21

22
  if (!file)
3✔
NEW
23
    throw std::invalid_argument(std::format("Error: Could not open the PNG file '{}'", filePath));
×
24

25
  // Declaring a single array of unsigned char, reused everywhere later
26
  std::array<unsigned char, 2> bytes {};
3✔
27

28
  // ID length (identifies the number of bytes contained in field 6, the image ID Field. The maximum number
29
  //  of characters is 255. A value of zero indicates that no image ID field is included within the image) - TODO
30
  file.read(reinterpret_cast<char*>(bytes.data()), 1);
3✔
31

32
  // Colormap (0 - no colormap, 1 - colormap)
33
  file.read(reinterpret_cast<char*>(bytes.data()), 1);
3✔
34
  const bool hasColormap = (bytes[0] == 1);
3✔
35

36
  // Image type
37
  file.read(reinterpret_cast<char*>(bytes.data()), 1);
3✔
38

39
  bool runLengthEncoding = false;
3✔
40
  uint8_t channelCount {};
3✔
41
  ImageColorspace colorspace {};
3✔
42

43
  switch (bytes[0]) {
3✔
44
    case 0: // No image data available
×
45
      throw std::runtime_error("Error: Invalid TGA image, no data available");
×
46

47
    case 9:   // RLE color-mapped
×
48
    case 10:  // RLE true-color
49
      runLengthEncoding = true;
×
50
      [[fallthrough]];
51
    case 1:   // Uncompressed color-mapped
3✔
52
    case 2:   // Uncompressed true-color
53
      channelCount = 3;
3✔
54
      colorspace = ImageColorspace::RGB;
3✔
55
      break;
3✔
56

57
    case 11:  // RLE gray
×
58
      runLengthEncoding = true;
×
59
      [[fallthrough]];
60
    case 3:   // Uncompressed gray
×
61
      channelCount = 1;
×
62
      colorspace = ImageColorspace::GRAY;
×
63
      break;
×
64

65
    default:
×
66
      throw std::runtime_error("Error: TGA invalid image type");
×
67
  }
68

69
  // TODO: handle colormap
70
  if (hasColormap) {
3✔
71
    // Colormap specs (size 5)
72
    std::array<char, 5> colorSpecs {};
×
73
    file.read(colorSpecs.data(), 5);
×
74

75
    // First entry index (2 bytes)
76

77
    // Colormap length (2 bytes)
78

79
    // Colormap entry size (1 byte)
80
  } else {
81
    file.ignore(5);
3✔
82
  }
83

84
  // Image specs (10 bytes)
85

86
  // X- & Y-origin (2 bytes each) - TODO: handle origins
87
  // It is expected to have 0 for both origins
88
  uint16_t xOrigin {};
3✔
89
  file.read(reinterpret_cast<char*>(&xOrigin), 2);
3✔
90

91
  uint16_t yOrigin {};
3✔
92
  file.read(reinterpret_cast<char*>(&yOrigin), 2);
3✔
93

94
  // Width & height (2 bytes each)
95
  uint16_t width {};
3✔
96
  file.read(reinterpret_cast<char*>(&width), 2);
3✔
97

98
  uint16_t height {};
3✔
99
  file.read(reinterpret_cast<char*>(&height), 2);
3✔
100

101
  // Bit depth (1 byte)
102
  file.read(reinterpret_cast<char*>(bytes.data()), 1);
3✔
103
  [[maybe_unused]] const uint8_t bitDepth = bytes[0] / channelCount;
3✔
104

105
  // Image descriptor (1 byte) - TODO: handle image descriptor
106
  // Bits 3-0 give the alpha channel depth, bits 5-4 give direction
107
  file.read(reinterpret_cast<char*>(bytes.data()), 1);
3✔
108

109
  Image image(width, height, colorspace, ImageDataType::BYTE);
3✔
110
  auto* imgData = static_cast<uint8_t*>(image.getDataPtr());
3✔
111

112
  if (!runLengthEncoding) {
3✔
113
    std::vector<uint8_t> values(width * height * channelCount);
3✔
114
    file.read(reinterpret_cast<char*>(values.data()), static_cast<std::streamsize>(values.size()));
3✔
115

116
    if (channelCount == 3) { // 3 channels, RGB
3✔
117
      for (std::size_t heightIndex = 0; heightIndex < height; ++heightIndex) {
9✔
118
        const std::size_t finalHeightIndex = (flipVertically ? heightIndex : height - 1 - heightIndex);
6✔
119

120
        for (std::size_t widthIndex = 0; widthIndex < width; ++widthIndex) {
18✔
121
          const std::size_t inPixelIndex = (heightIndex * width + widthIndex) * channelCount;
12✔
122
          const std::size_t outPixelIndex = (finalHeightIndex * width + widthIndex) * channelCount;
12✔
123

124
          // Values are laid out as BGR, they need to be reordered to RGB
125
          imgData[outPixelIndex + 2] = values[inPixelIndex];
12✔
126
          imgData[outPixelIndex + 1] = values[inPixelIndex + 1];
12✔
127
          imgData[outPixelIndex]     = values[inPixelIndex + 2];
12✔
128
        }
129
      }
130
    } else { // 1 channel, grayscale
131
      std::move(values.begin(), values.end(), imgData);
×
132
    }
133
  } else {
3✔
134
    throw std::runtime_error("Error: RLE on TGA images is not handled yet");
×
135
  }
136

137
  Logger::debug("[TgaFormat] Loaded TGA file");
3✔
138

139
  return image;
6✔
140
}
3✔
141

142
} // namespace Raz::TgaFormat
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc