/* * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at https://mozilla.org/MPL/2.0/. */ #include "ImageLoaderKtx.hpp" #include #include #include #include #include namespace OpenVulkano::Image { std::unique_ptr ImageLoaderKtx::loadFromFile(const std::string& filePath) { ktxTexture* texture; KTX_error_code result = ktxTexture_CreateFromNamedFile(filePath.c_str(), KTX_TEXTURE_CREATE_LOAD_IMAGE_DATA_BIT, &texture); if (result != KTX_SUCCESS) { throw std::runtime_error("Failed to load KTX texture: " + std::string(ktxErrorString(result))); } auto image = ExtractImage(texture); ktxTexture_Destroy(texture); return image; } std::unique_ptr ImageLoaderKtx::loadFromMemory(const std::vector& buffer) { ktxTexture* texture; KTX_error_code result = ktxTexture_CreateFromMemory(buffer.data(), buffer.size(), KTX_TEXTURE_CREATE_LOAD_IMAGE_DATA_BIT, &texture); if (result != KTX_SUCCESS) { throw std::runtime_error("Failed to load KTX texture from memory: " + std::string(ktxErrorString(result))); } auto image = ExtractImage(texture); ktxTexture_Destroy(texture); return image; } Math::Vector2i ImageLoaderKtx::GetImageDimensions(const std::string& filename) { ktxTexture* texture; KTX_error_code result = ktxTexture_CreateFromNamedFile(filename.c_str(), KTX_TEXTURE_CREATE_LOAD_IMAGE_DATA_BIT, &texture); if (result != KTX_SUCCESS) { throw std::runtime_error("Failed to load KTX texture for dimensions: " + std::string(ktxErrorString(result))); } Math::Vector2i dimensions(texture->baseWidth, texture->baseHeight); ktxTexture_Destroy(texture); return dimensions; } std::unique_ptr ImageLoaderKtx::ExtractImage(ktxTexture* texture) { if (!texture->pData) { throw std::runtime_error("No image data found in KTX texture."); } auto width = static_cast(texture->baseWidth); auto height = static_cast(texture->baseHeight); auto image = std::make_unique(); image->resolution.x = width; image->resolution.y = height; image->resolution.z = 1; if (texture->classId == ktxTexture1_c) { ktxTexture1* tx = reinterpret_cast(texture); DataFormat format = DataFormat::Format::UNDEFINED; switch (tx->glInternalformat) { case 0x8051: /* GL_RGB8_EXT */ format = DataFormat::Format::R8G8B8_UNORM; break; case 0x8054: /* GL_RGB16_EXT */ format = DataFormat::Format::R16G16B16_UNORM; break; case 0x8057: /* GL_RGB5_A1_EXT */ format = DataFormat::Format::R5G5B5A1_UNORM_PACK16; break; case 0x8058: /* GL_RGBA8_EXT */ format = DataFormat::Format::R8G8B8A8_UNORM; break; case 0x8059: /* GL_RGB10_A2_EXT */ format = DataFormat::Format::A2R10G10B10_UNORM_PACK32; break; case 0x805B: /* GL_RGBA16_EXT */ format = DataFormat::Format::R16G16B16A16_UNORM; break; default: throw std::runtime_error("Unhandled texture1 format: " + tx->glInternalformat); } image->dataFormat = format; } else if (texture->classId == ktxTexture2_c) { ktxTexture2* tx = reinterpret_cast(texture); image->dataFormat = *reinterpret_cast(&tx->vkFormat); } image->data = Array(texture->dataSize); memcpy(image->data.Data(), texture->pData, image->data.Size()); return image; } }