Introduce KtxBundle to libimage and add unit test.

KtxBundle is basically an in-memory representation of a KTX file.
Our primary motivation for introducing this class is to have a
structured container for block-compressed textures.

Note that this class is defined in libimage rather than libimageio.
There are several reasons for this:

1. The texel data in a KtxBundle is not meant to be decoded by the CPU.
2. It has no dependendencies on any libraries (stb_image tinyexr etc).
3. We wish to use it with WebGL, which needs to avoid using imageio.
This commit is contained in:
Philip Rideout
2018-09-13 16:07:00 -07:00
parent c1793b09bc
commit e4b60e47cb
6 changed files with 419 additions and 6 deletions

View File

@@ -15,6 +15,7 @@
*/
#include <image/ColorTransform.h>
#include <image/KtxBundle.h>
#include <image/ImageOps.h>
#include <image/ImageSampler.h>
#include <image/LinearImage.h>
@@ -34,10 +35,12 @@
#include <fstream>
#include <string>
#include <sstream>
#include <vector>
using std::istringstream;
using std::string;
using std::swap;
using std::vector;
using math::float3;
using math::float4;
@@ -287,7 +290,7 @@ TEST_F(ImageTest, Mipmaps) { // NOLINT
"44444 41014 40704 41014 44444 44444 41014 40704 41014 44444");
uint32_t count = getMipmapCount(src);
ASSERT_EQ(count, 3);
std::vector<LinearImage> mips(count);
vector<LinearImage> mips(count);
generateMipmaps(src, filter, mips.data(), count);
updateOrCompare(src, "mip0_5x10.png");
for (uint32_t index = 0; index < count; ++index) {
@@ -307,6 +310,58 @@ TEST_F(ImageTest, Mipmaps) { // NOLINT
}
}
TEST_F(ImageTest, Ktx) { // NOLINT
uint8_t foo[] = {1, 2, 3};
uint8_t* data;
uint32_t size;
KtxBundle nascent(2, 1, true);
ASSERT_EQ(nascent.getNumMipLevels(), 2);
ASSERT_EQ(nascent.getArrayLength(), 1);
ASSERT_TRUE(nascent.isCubemap());
ASSERT_FALSE(nascent.getBlob({0, 0, 0}, &data, &size));
ASSERT_TRUE(nascent.setBlob({0, 0, 0}, foo, sizeof(foo)));
ASSERT_TRUE(nascent.getBlob({0, 0, 0}, &data, &size));
ASSERT_EQ(size, sizeof(foo));
const uint32_t KTX_HEADER_SIZE = 16 * 4;
auto getFileSize = [](const char* filename) {
std::ifstream in(filename, std::ifstream::ate | std::ifstream::binary);
return in.tellg();
};
if (g_comparisonMode == ComparisonMode::COMPARE) {
const auto path = g_comparisonPath + "conftestimage_R11_EAC.ktx";
const auto fileSize = getFileSize(path.c_str());
ASSERT_GT(fileSize, 0);
vector<uint8_t> buffer(fileSize);
std::ifstream in(path, std::ifstream::in);
ASSERT_TRUE(in.read((char*) buffer.data(), fileSize));
KtxBundle deserialized(buffer.data(), buffer.size());
ASSERT_EQ(deserialized.getNumMipLevels(), 1);
ASSERT_EQ(deserialized.getArrayLength(), 1);
ASSERT_EQ(deserialized.isCubemap(), false);
ASSERT_EQ(deserialized.getInfo().pixelWidth, 64);
ASSERT_EQ(deserialized.getInfo().pixelHeight, 32);
ASSERT_EQ(deserialized.getInfo().pixelDepth, 0);
data = nullptr;
size = 0;
ASSERT_TRUE(deserialized.getBlob({0, 0, 0}, &data, &size));
ASSERT_EQ(size, 1024);
ASSERT_NE(data, nullptr);
uint32_t serializedSize = deserialized.getSerializedLength();
ASSERT_EQ(serializedSize, KTX_HEADER_SIZE + sizeof(uint32_t) + 1024);
ASSERT_EQ(serializedSize, fileSize);
vector<uint8_t> reserialized(serializedSize);
ASSERT_TRUE(deserialized.serialize(reserialized.data(), serializedSize));
ASSERT_EQ(reserialized, buffer);
}
}
static void printUsage(const char* name) {
string exec_name(utils::Path(name).getName());
string usage(