1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
// SPDX-License-Identifier: BSD-3-Clause
// Copyright (c) 2026 Fernando Sahmkow
/// @file bc3.cpp
/// @brief BC3 (DXT5) encode and decode implementation.
#include "bc1.h"
#include "bc3.h"
#include "bc4.h"
#include <array>
namespace whiteout::textures {
namespace bc3 {
// ============================================================================
// Decode
// ============================================================================
namespace {
void decode_block(const u8* block, u8* out) {
// ---- Decode colour from the BC1 sub-block (bytes 8..15) ----
bc1::decode_block(block + 8, out);
// ---- Decode alpha from the BC4-style sub-block (bytes 0..7) ----
std::array<u8, 16> alpha_vals{};
bc4::decode_block(block, alpha_vals.data());
for (u32 i = 0; i < 16; ++i)
out[i * 4 + 3] = alpha_vals[i];
}
} // anonymous namespace
std::optional<Texture> decodeTexture(const Texture& src, std::string* out_error,
interfaces::WorkerPool* pool) {
return transform_texture_impl(
src, PixelFormat::BC3, PixelFormat::RGBA8, "bc3::decodeTexture",
[pool](std::span<const u8> data, u32 w, u32 h) {
return decode_image_rgba8<16>(data, w, h, decode_block, pool);
},
out_error);
}
// ============================================================================
// Encode
// ============================================================================
namespace {
void encode_block(const u8* rgba, u8* out) {
// ---- Alpha: extract alpha channel, encode as BC4 block ----
std::array<u8, 16> alpha_vals{};
for (u32 i = 0; i < 16; ++i)
alpha_vals[i] = rgba[i * 4 + 3];
bc4::encode_block(alpha_vals.data(), out);
// ---- Colour: encode as a BC1 opaque block ----
bc1::encode_block(rgba, out + 8, /*alpha=*/false);
}
} // anonymous namespace
std::optional<Texture> encodeTexture(const Texture& src, std::string* out_error,
interfaces::WorkerPool* pool) {
return transform_texture_impl(
src, PixelFormat::RGBA8, PixelFormat::BC3, "bc3::encodeTexture",
[pool](std::span<const u8> data, u32 w, u32 h) {
return encode_image_rgba8<16>(data, w, h, encode_block, pool);
},
out_error);
}
} // namespace bc3
} // namespace whiteout::textures