From 95e86cbf0dfad2a37f5d8523d6cf755cde579030 Mon Sep 17 00:00:00 2001 From: Pavel Krajcevski Date: Thu, 23 Jan 2014 14:43:05 -0500 Subject: [PATCH] Add KTX loaders --- IO/CMakeLists.txt | 4 + IO/src/ImageLoaderKTX.cpp | 274 ++++++++++++++++++++++++++++++++++++++ IO/src/ImageLoaderKTX.h | 75 +++++++++++ 3 files changed, 353 insertions(+) create mode 100644 IO/src/ImageLoaderKTX.cpp create mode 100644 IO/src/ImageLoaderKTX.h diff --git a/IO/CMakeLists.txt b/IO/CMakeLists.txt index 72491a5..414a8dc 100644 --- a/IO/CMakeLists.txt +++ b/IO/CMakeLists.txt @@ -87,6 +87,10 @@ INCLUDE_DIRECTORIES( ${FasTC_SOURCE_DIR}/IO/third_party/tga ) SET( SOURCES ${SOURCES} "src/ImageLoaderTGA.cpp" ) SET( HEADERS ${HEADERS} "src/ImageLoaderTGA.h" ) +# Add KTX loaders +SET( SOURCES ${SOURCES} "src/ImageLoaderKTX.cpp" ) +SET( HEADERS ${HEADERS} "src/ImageLoaderKTX.h" ) + FIND_PACKAGE( OpenGL ) IF(OPENGL_FOUND) INCLUDE_DIRECTORIES( ${OPENGL_INCLUDE_DIRS} ) diff --git a/IO/src/ImageLoaderKTX.cpp b/IO/src/ImageLoaderKTX.cpp new file mode 100644 index 0000000..55de436 --- /dev/null +++ b/IO/src/ImageLoaderKTX.cpp @@ -0,0 +1,274 @@ +/* FasTC + * Copyright (c) 2014 University of North Carolina at Chapel Hill. + * All rights reserved. + * + * Permission to use, copy, modify, and distribute this software and its + * documentation for educational, research, and non-profit purposes, without + * fee, and without a written agreement is hereby granted, provided that the + * above copyright notice, this paragraph, and the following four paragraphs + * appear in all copies. + * + * Permission to incorporate this software into commercial products may be + * obtained by contacting the authors or the Office of Technology Development + * at the University of North Carolina at Chapel Hill . + * + * This software program and documentation are copyrighted by the University of + * North Carolina at Chapel Hill. The software program and documentation are + * supplied "as is," without any accompanying services from the University of + * North Carolina at Chapel Hill or the authors. The University of North + * Carolina at Chapel Hill and the authors do not warrant that the operation of + * the program will be uninterrupted or error-free. The end-user understands + * that the program was developed for research purposes and is advised not to + * rely exclusively on the program for any reason. + * + * IN NO EVENT SHALL THE UNIVERSITY OF NORTH CAROLINA AT CHAPEL HILL OR THE + * AUTHORS BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, + * OR CONSEQUENTIAL DAMAGES, INCLUDING LOST PROFITS, ARISING OUT OF THE USE OF + * THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF NORTH CAROLINA + * AT CHAPEL HILL OR THE AUTHORS HAVE BEEN ADVISED OF THE POSSIBILITY OF SUCH + * DAMAGE. + * + * THE UNIVERSITY OF NORTH CAROLINA AT CHAPEL HILL AND THE AUTHORS SPECIFICALLY + * DISCLAIM ANY WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE AND ANY + * STATUTORY WARRANTY OF NON-INFRINGEMENT. THE SOFTWARE PROVIDED HEREUNDER IS ON + * AN "AS IS" BASIS, AND THE UNIVERSITY OF NORTH CAROLINA AT CHAPEL HILL AND + * THE AUTHORS HAVE NO OBLIGATIONS TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, + * ENHANCEMENTS, OR MODIFICATIONS. + * + * Please send all BUG REPORTS to . + * + * The authors may be contacted via: + * + * Pavel Krajcevski + * Dept of Computer Science + * 201 S Columbia St + * Frederick P. Brooks, Jr. Computer Science Bldg + * Chapel Hill, NC 27599-3175 + * USA + * + * + */ + +#include "ImageLoaderKTX.h" + +#include +#include +#include +#include +#include + +#include "TexCompTypes.h" +#include "ScopedAllocator.h" + +#include "GLDefines.h" + +class ByteReader { + private: + const uint8 *m_Data; + uint32 m_BytesLeft; + public: + ByteReader(const uint8 *data, uint32 bytesExpected) + : m_Data(data), m_BytesLeft(bytesExpected) + { } + + bool Advance(uint32 nBytes) { + if(nBytes < m_BytesLeft) { + assert(!"Cannot read any more, unexpected bytes!"); + return false; + } + + m_Data += nBytes; + m_BytesLeft -= nBytes; + return true; + } + + operator const uint8 *() { + return m_Data; + } + + const uint8 *GetData() const { return m_Data; } + uint32 GetBytesLeft() const { return m_BytesLeft; } +}; + +class IntLoader { + public: + virtual uint32 ReadInt(const uint8 *data) const = 0; + bool LoadInt(ByteReader &data, uint32 &result) const { + result = ReadInt(data); + data.Advance(4); + return true; + } +}; + +class BigEndianIntLoader : public IntLoader { + public: + virtual uint32 ReadInt(const uint8 *data) const { + uint32 ret = 0; + ret |= data[0]; + for(uint32 i = 1; i < 4; i++) { + ret <<= 8; + ret |= data[i]; + } + return ret; + } +}; +static const BigEndianIntLoader gBEldr; + +class LittleEndianIntLoader : public IntLoader { + public: + virtual uint32 ReadInt(const uint8 *data) const { + uint32 ret = 0; + ret |= data[3]; + for(uint32 i = 3; i >= 0; i--) { + ret <<= 8; + ret |= data[i]; + } + return ret; + } +}; +static const LittleEndianIntLoader gLEldr; + +ImageLoaderKTX::ImageLoaderKTX(const uint8 *rawData, const int32 rawDataSz) + : ImageLoader(rawData, rawDataSz), m_Processor(NULL) +{ } + +ImageLoaderKTX::~ImageLoaderKTX() { } + +bool ImageLoaderKTX::ReadData() { + + ByteReader rdr (m_RawData, m_NumRawDataBytes); + + // First, check to make sure that the identifier is present... + static const uint8 kKTXID[12] = { + 0xAB, 0x4B, 0x54, 0x58, 0x20, 0x31, 0x31, 0xBB, 0x0D, 0x0A, 0x1A, 0x0A + }; + + if(memcmp(rdr.GetData(), kKTXID, 12) == 0) { + rdr.Advance(12); + } else { + return false; + } + + const IntLoader *ldr = NULL; + if(rdr.GetData()[0] == 0x04) { + ldr = &gBEldr; + } else { + ldr = &gLEldr; + } + rdr.Advance(4); + + #define LOAD(x) uint32 x; do { if(!ldr->LoadInt(rdr, x)) { return false; } } while(0) + LOAD(glType); + LOAD(glTypeSize); + LOAD(glFormat); + LOAD(glInternalFormat); + LOAD(glBaseInternalFormat); + LOAD(pixelWidth); + LOAD(pixelHeight); + LOAD(pixelDepth); + LOAD(numberOfArrayElements); + LOAD(numberOfFaces); + LOAD(numberOfMipmapLevels); + LOAD(bytesOfKeyValueData); + + // Do we need to read the data? + if(m_Processor) { + const uint8 *imgData = rdr.GetData() + bytesOfKeyValueData; + while(rdr.GetData() < imgData) { + LOAD(keyAndValueByteSize); + FasTC::ScopedAllocator keyValueData = + FasTC::ScopedAllocator::Create(keyAndValueByteSize); + if(!keyValueData) { + fprintf(stderr, "KTX loader - out of memory.\n"); + return false; + } + + // Read the bytes... + memcpy(keyValueData, rdr.GetData(), keyAndValueByteSize); + const char *key = reinterpret_cast((const uint8 *)keyValueData); + const char *value = key; + while(value != '\0') { + value++; + } + value++; // consume the null byte + + m_Processor(key, value); + rdr.Advance((keyAndValueByteSize + 3) & ~0x3); + } + } else { + rdr.Advance(bytesOfKeyValueData); + } + + // The following code only supports a limited subset of + // image types, the full spec (if we choose to support it) + // is here: + // http://www.khronos.org/opengles/sdk/tools/KTX/file_format_spec + + // Read image data... + if(numberOfMipmapLevels != 1) { + fprintf(stderr, "KTX loader - unsupported mipmap levels: %d\n", numberOfMipmapLevels); + return false; + } + + LOAD(imageSize); + + if(numberOfArrayElements > 1) { + fprintf(stderr, + "KTX loader - unsupported number of array elements: %d\n", + numberOfArrayElements); + return false; + } + + if(numberOfFaces != 1) { + fprintf(stderr, + "KTX loader - unsupported number of faces: %d\n" + "This likely means that we are trying to load a cube map.\n", + numberOfFaces); + return false; + } + + if(pixelDepth != 0) { + fprintf(stderr, "KTX loader - 3D textures not supported\n"); + return false; + } + + if(pixelHeight == 0) { + fprintf(stderr, "KTX loader - 1D textures not supported\n"); + return false; + } + + if(pixelWidth == 0) { + fprintf(stderr, "KTX loader - nonzero pixel width??\n"); + return false; + } + + if(glType == 0 && + glFormat == 0 && + glInternalFormat == GL_COMPRESSED_RGBA_BPTC_UNORM) { + fprintf(stderr, "KTX loader - BPTC compressed textures unsupported!\n"); + return false; + // Load compressed texture... + // rdr.Advance(pixelWidth * pixelHeight); + } else { + + if(glType != GL_BYTE) { + fprintf(stderr, "KTX loader - unsupported OpenGL type: 0x%x\n", glType); + return false; + } + + if(glInternalFormat != GL_RGBA8) { + fprintf(stderr, "KTX loader - unsupported internal format: 0x%x\n", glFormat); + return false; + } + + // We should have RGBA8 data here so we can simply load it + // as we normally would. + m_Width = pixelWidth; + m_Height = pixelHeight; + LoadFromPixelBuffer(reinterpret_cast(rdr.GetData())); + rdr.Advance(pixelWidth * pixelHeight * 4); + } + return rdr.GetBytesLeft() == 0; +} + diff --git a/IO/src/ImageLoaderKTX.h b/IO/src/ImageLoaderKTX.h new file mode 100644 index 0000000..42df221 --- /dev/null +++ b/IO/src/ImageLoaderKTX.h @@ -0,0 +1,75 @@ +/* FasTC + * Copyright (c) 2014 University of North Carolina at Chapel Hill. + * All rights reserved. + * + * Permission to use, copy, modify, and distribute this software and its + * documentation for educational, research, and non-profit purposes, without + * fee, and without a written agreement is hereby granted, provided that the + * above copyright notice, this paragraph, and the following four paragraphs + * appear in all copies. + * + * Permission to incorporate this software into commercial products may be + * obtained by contacting the authors or the Office of Technology Development + * at the University of North Carolina at Chapel Hill . + * + * This software program and documentation are copyrighted by the University of + * North Carolina at Chapel Hill. The software program and documentation are + * supplied "as is," without any accompanying services from the University of + * North Carolina at Chapel Hill or the authors. The University of North + * Carolina at Chapel Hill and the authors do not warrant that the operation of + * the program will be uninterrupted or error-free. The end-user understands + * that the program was developed for research purposes and is advised not to + * rely exclusively on the program for any reason. + * + * IN NO EVENT SHALL THE UNIVERSITY OF NORTH CAROLINA AT CHAPEL HILL OR THE + * AUTHORS BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, + * OR CONSEQUENTIAL DAMAGES, INCLUDING LOST PROFITS, ARISING OUT OF THE USE OF + * THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF NORTH CAROLINA + * AT CHAPEL HILL OR THE AUTHORS HAVE BEEN ADVISED OF THE POSSIBILITY OF SUCH + * DAMAGE. + * + * THE UNIVERSITY OF NORTH CAROLINA AT CHAPEL HILL AND THE AUTHORS SPECIFICALLY + * DISCLAIM ANY WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE AND ANY + * STATUTORY WARRANTY OF NON-INFRINGEMENT. THE SOFTWARE PROVIDED HEREUNDER IS ON + * AN "AS IS" BASIS, AND THE UNIVERSITY OF NORTH CAROLINA AT CHAPEL HILL AND + * THE AUTHORS HAVE NO OBLIGATIONS TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, + * ENHANCEMENTS, OR MODIFICATIONS. + * + * Please send all BUG REPORTS to . + * + * The authors may be contacted via: + * + * Pavel Krajcevski + * Dept of Computer Science + * 201 S Columbia St + * Frederick P. Brooks, Jr. Computer Science Bldg + * Chapel Hill, NC 27599-3175 + * USA + * + * + */ + +#ifndef _IO_SRC_IMAGE_LOADER_KTX_H_ +#define _IO_SRC_IMAGE_LOADER_KTX_H_ + +#include "ImageLoader.h" + +class ImageLoaderKTX : public ImageLoader { + public: + typedef void (*KTXKeyValueProcessor)(const char *key, const char *value); + + ImageLoaderKTX(const uint8 *rawData, const int32 rawDataSz); + virtual ~ImageLoaderKTX(); + + virtual bool ReadData(); + + void SetProcessor(KTXKeyValueProcessor proc) { + m_Processor = proc; + } + + private: + KTXKeyValueProcessor m_Processor; +}; + +#endif // _IO_SRC_IMAGE_LOADER_KTX_H_