载入中...
搜索中...
未找到
SourceTga.cpp
浏览该文件的文档.
1#include "asset/SourceTga.h"
2#include <algorithm>
3#include <array>
4#include <string_view>
5
6namespace eve::asset::detail {
7Result<TgaPixels> decodeTgaRgba8(std::span<const std::uint8_t> b, std::uint64_t budget) {
8 auto fail = [](DiagnosticCode code, const char* message) {
9 return Result<TgaPixels>::failure(Diagnostic::error(code, message, {}, {}, "asset.image.tga"));
10 };
11 if (b.size() < 18) return fail(DiagnosticCode::ParseError, "truncated TGA header");
12 auto u16 = [&](std::size_t p) { return std::uint32_t(b[p]) | (std::uint32_t(b[p + 1]) << 8); };
13 auto u32 = [&](std::size_t p) { return u16(p) | (u16(p + 2) << 16); };
14 const auto w = u16(12), h = u16(14);
15 const unsigned channels = b[16] / 8, attributes = b[17] & 15;
16 if (b[1] != 0 || (b[2] != 2 && b[2] != 10) || (b[16] != 24 && b[16] != 32) || (b[17] & 192) != 0 ||
17 (attributes != 0 && !(channels == 4 && attributes == 8)))
18 return fail(DiagnosticCode::Unsupported, "TGA requires non-interleaved 24/32-bit true-color raw or RLE pixels");
19 const std::uint64_t count = std::uint64_t(w) * h;
20 if (!w || !h || budget < 24 || count > (budget - 24) / 4)
21 return fail(DiagnosticCode::InvalidArgument, "TGA dimensions exceed decoded budget");
22 std::size_t end = b.size(), cursor = 18 + b[0];
23 constexpr std::string_view signature("TRUEVISION-XFILE.\0", 18);
24 if (b.size() >= 26 && std::equal(signature.begin(), signature.end(), b.end() - 18)) {
25 end = b.size() - 26;
26 const auto extension = u32(end), developer = u32(end + 4);
27 if (extension) {
28 if (extension < cursor || extension > end || end - extension < 495 || u16(extension) != 495)
29 return fail(DiagnosticCode::ParseError, "invalid TGA extension area");
30 if (b[extension + 494] > 3)
31 return fail(DiagnosticCode::Unsupported, "premultiplied or unknown TGA alpha semantics");
32 end = extension;
33 }
34 if (developer) {
35 if (developer < cursor || developer > b.size() - 26 || b.size() - 26 - developer < 2)
36 return fail(DiagnosticCode::ParseError, "invalid TGA developer area");
37 end = std::min(end, std::size_t(developer));
38 }
39 }
40 if (cursor > end) return fail(DiagnosticCode::ParseError, "truncated TGA image ID");
41 TgaPixels out{w, h, std::vector<std::uint8_t>(std::size_t(count) * 4)};
42 std::size_t written = 0;
43 auto pixel = [&](std::size_t p) {
44 const std::size_t x = written % w, y = written / w;
45 const auto dx = (b[17] & 16) ? w - 1 - x : x, dy = (b[17] & 32) ? y : h - 1 - y;
46 const auto dst = (dy * w + dx) * 4;
47 out.rgba[dst] = b[p + 2];
48 out.rgba[dst + 1] = b[p + 1];
49 out.rgba[dst + 2] = b[p];
50 out.rgba[dst + 3] = channels == 4 ? b[p + 3] : 255;
51 ++written;
52 };
53 while (written < count) {
54 std::size_t run = 1;
55 bool repeated = false;
56 if (b[2] == 10) {
57 if (cursor == end) return fail(DiagnosticCode::ParseError, "truncated TGA RLE packet");
58 auto header = b[cursor++];
59 run = (header & 127) + 1;
60 repeated = (header & 128) != 0;
61 }
62 if (run > count - written || (repeated ? channels : run * channels) > end - cursor)
63 return fail(DiagnosticCode::ParseError, "TGA packet exceeds image or source bounds");
64 for (std::size_t i = 0; i < run; ++i) pixel(cursor + (repeated ? 0 : i * channels));
65 cursor += (repeated ? 1 : run) * channels;
66 }
67 return Result<TgaPixels>::success(std::move(out));
68}
69} // namespace eve::asset::detail
float w
Definition AnimClip.cpp:738
float y
Definition AnimClip.cpp:738
float x
Definition AnimClip.cpp:738
std::map< std::string, std::vector< Key >, std::less<> > channels
glm::vec4 p[6]
std::string message
DiagnosticCode code
int h
MeleePoint3 b
Definition MeleeHit.cpp:41
std::weak_ptr< Run > run
Definition OnnxGpgpu.cpp:25
float dy
float dx
std::uint32_t count
std::size_t cursor
static Diagnostic error(DiagnosticCode code, std::string message, std::string path={}, DiagnosticDetails details={}, std::string source={})
Construct an error diagnostic with the standard error severity.
Definition Diagnostic.h:125
Move-only operation result carrying either a value or Status.
Definition Result.h:155
static Result success(T value)
Construct a successful result owning value.
Definition Result.h:164
static Result failure(Status status)
Construct a failed result from a structured status.
Definition Result.h:175
Result< TgaPixels > decodeTgaRgba8(std::span< const std::uint8_t > b, std::uint64_t budget)
Decode true-color 24/32-bit raw or RLE TGA with bounded allocation.
Definition SourceTga.cpp:7
DiagnosticCode
Stable machine-readable diagnostic codes.
Definition Diagnostic.h:47
Owning top-down RGBA8 pixels decoded from a TGA source.
Definition SourceTga.h:10