| /* |
| * Copyright 2014 Google Inc. |
| * |
| * Use of this source code is governed by a BSD-style license that can be |
| * found in the LICENSE file. |
| */ |
| |
| |
| #ifndef SkKTXFile_DEFINED |
| #define SkKTXFile_DEFINED |
| |
| #include "SkData.h" |
| #include "SkTextureCompressor.h" |
| #include "SkTypes.h" |
| #include "SkTDArray.h" |
| #include "SkString.h" |
| #include "SkRefCnt.h" |
| |
| class SkPixmap; |
| class SkStreamRewindable; |
| class SkWStream; |
| |
| // KTX Image File |
| // --- |
| // KTX is a general texture data storage file format ratified by the Khronos Group. As an |
| // overview, a KTX file contains all of the appropriate values needed to fully specify a |
| // texture in an OpenGL application, including the use of compressed data. |
| // |
| // A full format specification can be found here: |
| // http://www.khronos.org/opengles/sdk/tools/KTX/file_format_spec/ |
| |
| class SkKTXFile { |
| public: |
| // The ownership of the data remains with the caller. This class is intended |
| // to be used as a logical wrapper around the data in order to properly |
| // access the pixels. |
| SkKTXFile(SkData* data) : fData(data), fSwapBytes(false) { |
| data->ref(); |
| fValid = this->readKTXFile(fData->bytes(), fData->size()); |
| } |
| |
| bool valid() const { return fValid; } |
| |
| int width() const { return static_cast<int>(fHeader.fPixelWidth); } |
| int height() const { return static_cast<int>(fHeader.fPixelHeight); } |
| |
| const uint8_t *pixelData(int mipmap = 0) const { |
| SkASSERT(!this->valid() || mipmap < fPixelData.count()); |
| return this->valid() ? fPixelData[mipmap].data() : NULL; |
| } |
| |
| // If the decoded KTX file has the following key, then it will |
| // return the associated value. If not found, the empty string |
| // is returned. |
| SkString getValueForKey(const SkString& key) const; |
| |
| int numMipmaps() const { return static_cast<int>(fHeader.fNumberOfMipmapLevels); } |
| |
| bool isCompressedFormat(SkTextureCompressor::Format fmt) const; |
| bool isRGBA8() const; |
| bool isRGB8() const; |
| |
| static bool is_ktx(const uint8_t data[], size_t size); |
| static bool is_ktx(SkStreamRewindable* stream); |
| |
| static bool WriteETC1ToKTX(SkWStream* stream, const uint8_t *etc1Data, |
| uint32_t width, uint32_t height); |
| static bool WritePixmapToKTX(SkWStream* stream, const SkPixmap& bitmap); |
| private: |
| |
| // The blob holding the file data. |
| sk_sp<SkData> fData; |
| |
| // This header captures all of the data that describes the format |
| // of the image data in a KTX file. |
| struct Header { |
| uint32_t fGLType; |
| uint32_t fGLTypeSize; |
| uint32_t fGLFormat; |
| uint32_t fGLInternalFormat; |
| uint32_t fGLBaseInternalFormat; |
| uint32_t fPixelWidth; |
| uint32_t fPixelHeight; |
| uint32_t fPixelDepth; |
| uint32_t fNumberOfArrayElements; |
| uint32_t fNumberOfFaces; |
| uint32_t fNumberOfMipmapLevels; |
| uint32_t fBytesOfKeyValueData; |
| |
| Header() { memset(this, 0, sizeof(*this)); } |
| } fHeader; |
| |
| // A Key Value pair stored in the KTX file. There may be |
| // arbitrarily many of these. |
| class KeyValue { |
| public: |
| KeyValue(size_t size) : fDataSz(size) { } |
| bool readKeyAndValue(const uint8_t *data); |
| size_t size() const { return fDataSz; } |
| const SkString& key() const { return fKey; } |
| const SkString& value() const { return fValue; } |
| bool writeKeyAndValueForKTX(SkWStream* strm); |
| private: |
| const size_t fDataSz; |
| SkString fKey; |
| SkString fValue; |
| }; |
| |
| static KeyValue CreateKeyValue(const char *key, const char *value); |
| |
| // The pixel data for a single mipmap level in an image. Based on how |
| // the rest of the data is stored, this may be compressed, a cubemap, etc. |
| // The header will describe the format of this data. |
| class PixelData { |
| public: |
| PixelData(const uint8_t *ptr, size_t sz) : fDataSz(sz), fDataPtr(ptr) { } |
| const uint8_t *data() const { return fDataPtr; } |
| size_t dataSize() const { return fDataSz; } |
| private: |
| const size_t fDataSz; |
| const uint8_t *fDataPtr; |
| }; |
| |
| // This function is only called once from the constructor. It loads the data |
| // and populates the appropriate fields of this class |
| // (fKeyValuePairs, fPixelData, fSwapBytes) |
| bool readKTXFile(const uint8_t *data, size_t dataLen); |
| |
| SkTArray<KeyValue> fKeyValuePairs; |
| SkTDArray<PixelData> fPixelData; |
| bool fValid; |
| |
| // If the endianness of the platform is different than the file, |
| // then we need to do proper byte swapping. |
| bool fSwapBytes; |
| |
| // Read an integer from a buffer, advance the buffer, and swap |
| // bytes if fSwapBytes is set |
| uint32_t readInt(const uint8_t** buf, size_t* bytesLeft) const; |
| }; |
| |
| #endif // SkKTXFile_DEFINED |