载入中...
搜索中...
未找到
SourceBc3.cpp
浏览该文件的文档.
1#include "asset/SourceBc3.h"
2#include <array>
3#include <limits>
4
6Result<std::vector<std::uint8_t>> decodeBc3Rgba8(std::span<const std::uint8_t> bytes, std::uint32_t width,
7 std::uint32_t height, std::uint64_t maximumDecodedBytes) {
8 const auto pixels = std::uint64_t(width) * height;
9 const auto columns = (std::uint64_t(width) + 3) / 4;
10 const auto rows = (std::uint64_t(height) + 3) / 4;
11 if (!width || !height || pixels > maximumDecodedBytes / 4 || pixels > std::numeric_limits<std::size_t>::max() / 4 ||
12 columns * rows > std::numeric_limits<std::uint64_t>::max() / 16 || columns * rows * 16 != bytes.size())
13 return Result<std::vector<std::uint8_t>>::failure(
14 Diagnostic::error(DiagnosticCode::InvalidArgument, "BC3 dimensions, byte count or decoded budget invalid",
15 {}, {}, "asset.bc3"));
16 std::vector<std::uint8_t> output(std::size_t(pixels * 4));
17 for (std::uint64_t by = 0; by < rows; ++by) {
18 for (std::uint64_t bx = 0; bx < columns; ++bx) {
19 const auto block = bytes.subspan(std::size_t((by * columns + bx) * 16), 16);
20 std::array<unsigned, 8> alpha{block[0], block[1]};
21 if (alpha[0] > alpha[1]) {
22 for (unsigned i = 1; i <= 6; ++i) alpha[i + 1] = ((7 - i) * alpha[0] + i * alpha[1]) / 7;
23 } else {
24 for (unsigned i = 1; i <= 4; ++i) alpha[i + 1] = ((5 - i) * alpha[0] + i * alpha[1]) / 5;
25 alpha[6] = 0;
26 alpha[7] = 255;
27 }
28 std::array<std::array<unsigned, 3>, 4> color{};
29 for (unsigned i = 0; i < 2; ++i) {
30 const unsigned rgb = block[8 + i * 2] | (unsigned(block[9 + i * 2]) << 8);
31 const unsigned r = rgb >> 11, g = (rgb >> 5) & 63, b = rgb & 31;
32 color[i] = {(r << 3) | (r >> 2), (g << 2) | (g >> 4), (b << 3) | (b >> 2)};
33 }
34 for (unsigned c = 0; c < 3; ++c) {
35 color[2][c] = (2 * color[0][c] + color[1][c]) / 3;
36 color[3][c] = (color[0][c] + 2 * color[1][c]) / 3;
37 }
38 std::uint64_t alphaIndices = 0;
39 std::uint32_t colorIndices = 0;
40 for (unsigned i = 0; i < 6; ++i) alphaIndices |= std::uint64_t(block[2 + i]) << (8 * i);
41 for (unsigned i = 0; i < 4; ++i) colorIndices |= std::uint32_t(block[12 + i]) << (8 * i);
42 for (unsigned i = 0; i < 16; ++i) {
43 const auto x = bx * 4 + i % 4, y = by * 4 + i / 4;
44 if (x >= width || y >= height) continue;
45 const auto at = std::size_t((y * width + x) * 4);
46 for (unsigned c = 0; c < 3; ++c) output[at + c] = std::uint8_t(color[(colorIndices >> (2 * i)) & 3][c]);
47 output[at + 3] = std::uint8_t(alpha[(alphaIndices >> (3 * i)) & 7]);
48 }
49 }
50 }
51 return Result<std::vector<std::uint8_t>>::success(std::move(output));
52}
53} // namespace eve::asset::detail
float y
Definition AnimClip.cpp:738
float x
Definition AnimClip.cpp:738
std::string output
int bx
Definition CaveMesh.cpp:114
int by
Definition CaveMesh.cpp:114
int rows
tensor::Graph g
Definition GpuGraph.cpp:7
double r
std::int32_t c
std::uint32_t height
std::uint32_t width
std::uint64_t bytes
MeleePoint3 b
Definition MeleeHit.cpp:41
uint8_t * pixels
int columns
std::size_t at
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
Result< std::vector< std::uint8_t > > decodeBc3Rgba8(std::span< const std::uint8_t > bytes, std::uint32_t width, std::uint32_t height, std::uint64_t maximumDecodedBytes)
Decode one BC3/DXT5 mip level into tightly packed RGBA8 in source row order.
Definition SourceBc3.cpp:6
glm::vec4 color