3#include <BufferStream.h>
11 : vtf(std::move(vtf_))
12 , aspectRatioType(3) {
18TTX::TTX(std::span<const std::byte> tthData, std::span<const std::byte> ttzData) {
19 BufferStreamReadOnly header{tthData.data(), tthData.size()};
26 if (this->
majorVersion != 1 || this->minorVersion != 0) {
30 const auto mipCount = header.read<uint8_t>();
32 const auto vtfChunkSize = header.read<uint32_t>();
34 header.read(this->
mipFlags, mipCount);
36 mz_ulong ttzUncompressedSize = header.read<uint32_t>() - vtfChunkSize;
37 const mz_ulong ttzCompressedSize = header.read<uint32_t>();
39 std::vector<std::byte> vtfData;
40 BufferStream vtfStream{vtfData};
41 vtfStream << header.read_bytes(vtfChunkSize);
42 if (ttzCompressedSize > 0) {
43 if (ttzCompressedSize > ttzData.size()) {
46 std::vector<std::byte> additionalDataUncompressed(ttzUncompressedSize);
47 if (mz_uncompress(
reinterpret_cast<unsigned char*
>(additionalDataUncompressed.data()), &ttzUncompressedSize,
reinterpret_cast<const unsigned char*
>(ttzData.data()), ttzCompressedSize) != MZ_OK) {
50 vtfStream << additionalDataUncompressed;
52 vtfData.resize(vtfStream.size());
61TTX::TTX(
const std::string& tthPath,
const std::string& ttzPath)
62 :
TTX(fs::readFileBuffer(tthPath), fs::readFileBuffer(ttzPath)) {}
64TTX::operator bool()
const {
121std::pair<std::vector<std::byte>, std::vector<std::byte>>
TTX::bake()
const {
122 std::pair<std::vector<std::byte>, std::vector<std::byte>> data;
123 BufferStream streamTTH{data.first};
130 <<
static_cast<uint8_t
>(this->
mipFlags.size())
134 const auto vtfData = this->
vtf.
bake();
135 if (vtfData.empty()) {
138 uint32_t vtfChunkLength;
140 BufferStreamReadOnly streamVTF{vtfData.data(), vtfData.size()};
141 vtfChunkLength = streamVTF.skip<uint32_t>(3).read<uint32_t>();
146 const auto vtfTheRestLength =
static_cast<uint32_t
>(vtfData.size() - vtfChunkLength);
147 streamTTH << vtfChunkLength << this->mipFlags << static_cast<uint32_t>(vtfData.size());
148 const auto vtfTTZLengthPos = streamTTH.tell();
149 streamTTH.write<uint32_t>(0).write(vtfData.data(), vtfChunkLength);
152 mz_ulong compressedSize = mz_compressBound(vtfTheRestLength);
153 data.second.resize(compressedSize);
155 while ((status = mz_compress2(
reinterpret_cast<unsigned char*
>(data.second.data()), &compressedSize,
reinterpret_cast<const unsigned char*
>(vtfData.data() + vtfChunkLength), vtfTheRestLength, this->compressionLevel)) == MZ_BUF_ERROR) {
157 data.second.resize(compressedSize);
159 if (status != MZ_OK) {
162 data.second.resize(compressedSize);
165 streamTTH.seek_u(vtfTTZLengthPos).write<uint32_t>(data.second.size());
166 data.first.resize(streamTTH.size());
171bool TTX::bake(
const std::string& tthPath,
const std::string& ttzPath)
const {
172 const auto data = this->
bake();
174 if (!data.second.empty()) {
const VTF & getVTF() const
const std::vector< uint64_t > & getMipFlags() const
uint8_t getMinorVersion() const
std::vector< uint64_t > mipFlags
uint8_t getMajorVersion() const
uint8_t getAspectRatioType() const
void setVersion(uint8_t newMajorVersion, uint8_t newMinorVersion)
void setMinorVersion(uint8_t newMinorVersion)
int16_t getCompressionLevel() const
void setAspectRatioType(uint8_t newAspectRatioType)
std::pair< std::vector< std::byte >, std::vector< std::byte > > bake() const
void setCompressionLevel(int16_t newCompressionLevel)
void setMajorVersion(uint8_t newMajorVersion)
bool hasThumbnailData() const
std::vector< std::byte > bake() const
uint8_t getMipCount() const
std::span< const std::byte > getThumbnailDataRaw() const
bool writeFileBuffer(const std::string &filepath, std::span< const std::byte > buffer)
constexpr uint32_t TTH_SIGNATURE