109 lines
3.4 KiB
C++
109 lines
3.4 KiB
C++
/*
|
|
* 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;
|
|
}
|
|
} |