Ktx library + ImageLoaderKtx

This commit is contained in:
Vladyslav Baranovskyi
2024-12-06 17:24:48 +02:00
parent 1abfb22b08
commit f6ee1de342
6 changed files with 158 additions and 2 deletions

View File

@@ -42,3 +42,4 @@ if(ENABLE_TEST)
endif()
add_subdirectory(tinyusdz)
add_subdirectory(ktx-software)

19
3rdParty/ktx-software/CMakeLists.txt vendored Normal file
View File

@@ -0,0 +1,19 @@
include(FetchContent)
if(NOT DEFINED KTX_REPO)
set(KTX_REPO https://github.com/KhronosGroup/KTX-Software.git)
endif ()
FetchContent_Declare(
ktx
EXCLUDE_FROM_ALL
GIT_REPOSITORY ${KTX_REPO}
GIT_TAG v4.3.2
GIT_SHALLOW TRUE
)
set(LIB_TYPE_DEFAULT OFF CACHE BOOL "" FORCE)
set(BUILD_SHARED_LIBS OFF CACHE BOOL "" FORCE)
set(KTX_FEATURE_STATIC_LIBRARY ON CACHE BOOL "" FORCE)
FetchContent_MakeAvailable(ktx)

View File

@@ -67,7 +67,7 @@ if (NOT ANDROID AND NOT IOS)
endif()
endif()
target_link_libraries(openVulkanoCpp PUBLIC magic_enum yaml-cpp fmt spdlog glm pugixml stb eigen utf8cpp imgui_internal TracyClient stud-uuid ryml unordered_dense units)
target_link_libraries(openVulkanoCpp PUBLIC magic_enum yaml-cpp fmt spdlog glm pugixml stb eigen utf8cpp imgui_internal TracyClient stud-uuid ryml unordered_dense units ktx)
LinkAssimp(openVulkanoCpp)
LinkLibArchive(openVulkanoCpp)
LinkLibJpegTurbo(openVulkanoCpp)

View File

@@ -17,6 +17,8 @@ namespace OpenVulkano::Image
JPEG,
PNG,
BMP,
KTX,
DDS,
};
struct Image

View File

@@ -0,0 +1,109 @@
/*
* 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 <ktx.h>
#include <memory>
#include <vector>
#include <iostream>
#include <stdexcept>
namespace OpenVulkano::Image
{
std::unique_ptr<Image> 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<Image> ImageLoaderKtx::loadFromMemory(const std::vector<uint8_t>& 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<Image> ImageLoaderKtx::ExtractImage(ktxTexture* texture)
{
if (!texture->pData)
{
throw std::runtime_error("No image data found in KTX texture.");
}
auto width = static_cast<int>(texture->baseWidth);
auto height = static_cast<int>(texture->baseHeight);
auto image = std::make_unique<Image>();
image->resolution.x = width;
image->resolution.y = height;
image->resolution.z = 1;
if (texture->classId == ktxTexture1_c)
{
ktxTexture1* tx = reinterpret_cast<ktxTexture1*>(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<ktxTexture2*>(texture);
image->dataFormat = *reinterpret_cast<DataFormat::Format*>(&tx->vkFormat);
}
image->data = Array<uint8_t>(texture->dataSize);
memcpy(image->data.Data(), texture->pData, image->data.Size());
return image;
}
}

View File

@@ -0,0 +1,25 @@
/*
* 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/.
*/
#pragma once
#include "ImageLoader.hpp"
struct ktxTexture;
namespace OpenVulkano::Image
{
class ImageLoaderKtx : public IImageLoader
{
public:
std::unique_ptr<Image> loadFromFile(const std::string& filePath) override;
std::unique_ptr<Image> loadFromMemory(const std::vector<uint8_t>& buffer) override;
Math::Vector2i GetImageDimensions(const std::string& filename) override;
protected:
std::unique_ptr<Image> ExtractImage(ktxTexture* texture);
};
}