Home | History | Annotate | Download | only in ktx
      1 
      2 /*
      3  * Copyright 2014 Google Inc.
      4  *
      5  * Use of this source code is governed by a BSD-style license that can be
      6  * found in the LICENSE file.
      7  */
      8 
      9 
     10 #ifndef SkKTXFile_DEFINED
     11 #define SkKTXFile_DEFINED
     12 
     13 #include "SkData.h"
     14 #include "SkTypes.h"
     15 #include "SkTDArray.h"
     16 #include "SkString.h"
     17 #include "SkRefCnt.h"
     18 
     19 class SkBitmap;
     20 class SkStreamRewindable;
     21 class SkWStream;
     22 
     23 // KTX Image File
     24 // ---
     25 // KTX is a general texture data storage file format ratified by the Khronos Group. As an
     26 // overview, a KTX file contains all of the appropriate values needed to fully specify a
     27 // texture in an OpenGL application, including the use of compressed data.
     28 //
     29 // A full format specification can be found here:
     30 // http://www.khronos.org/opengles/sdk/tools/KTX/file_format_spec/
     31 
     32 class SkKTXFile {
     33 public:
     34     // The ownership of the data remains with the caller. This class is intended
     35     // to be used as a logical wrapper around the data in order to properly
     36     // access the pixels.
     37     SkKTXFile(SkData* data)
     38         : fData(data), fSwapBytes(false)
     39     {
     40         data->ref();
     41         fValid = this->readKTXFile(fData->bytes(), fData->size());
     42     }
     43 
     44     bool valid() const { return fValid; }
     45 
     46     int width() const { return static_cast<int>(fHeader.fPixelWidth); }
     47     int height() const { return static_cast<int>(fHeader.fPixelHeight); }
     48 
     49     const uint8_t *pixelData(int mipmap = 0) const {
     50         SkASSERT(!this->valid() || mipmap < fPixelData.count());
     51         return this->valid() ? fPixelData[mipmap].data() : NULL;
     52     }
     53 
     54     // If the decoded KTX file has the following key, then it will
     55     // return the associated value. If not found, the empty string
     56     // is returned.
     57     SkString getValueForKey(const SkString& key) const;
     58 
     59     int numMipmaps() const { return static_cast<int>(fHeader.fNumberOfMipmapLevels); }
     60 
     61     bool isETC1() const;
     62     bool isRGBA8() const;
     63     bool isRGB8() const;
     64 
     65     static bool is_ktx(const uint8_t *data);
     66     static bool is_ktx(SkStreamRewindable* stream);
     67 
     68     static bool WriteETC1ToKTX(SkWStream* stream, const uint8_t *etc1Data,
     69                                uint32_t width, uint32_t height);
     70     static bool WriteBitmapToKTX(SkWStream* stream, const SkBitmap& bitmap);
     71 private:
     72 
     73     // The blob holding the file data.
     74     SkAutoTUnref<SkData> fData;
     75 
     76     // This header captures all of the data that describes the format
     77     // of the image data in a KTX file.
     78     struct Header {
     79         uint32_t fGLType;
     80         uint32_t fGLTypeSize;
     81         uint32_t fGLFormat;
     82         uint32_t fGLInternalFormat;
     83         uint32_t fGLBaseInternalFormat;
     84         uint32_t fPixelWidth;
     85         uint32_t fPixelHeight;
     86         uint32_t fPixelDepth;
     87         uint32_t fNumberOfArrayElements;
     88         uint32_t fNumberOfFaces;
     89         uint32_t fNumberOfMipmapLevels;
     90         uint32_t fBytesOfKeyValueData;
     91 
     92         Header() { memset(this, 0, sizeof(*this)); }
     93     } fHeader;
     94 
     95     // A Key Value pair stored in the KTX file. There may be
     96     // arbitrarily many of these.
     97     class KeyValue {
     98     public:
     99         KeyValue(size_t size) : fDataSz(size) { }
    100         bool readKeyAndValue(const uint8_t *data);
    101         size_t size() const { return fDataSz; }
    102         const SkString& key() const { return fKey; }
    103         const SkString& value() const { return fValue; }
    104         bool writeKeyAndValueForKTX(SkWStream* strm);
    105     private:
    106         const size_t fDataSz;
    107         SkString     fKey;
    108         SkString     fValue;
    109     };
    110 
    111     static KeyValue CreateKeyValue(const char *key, const char *value);
    112 
    113     // The pixel data for a single mipmap level in an image. Based on how
    114     // the rest of the data is stored, this may be compressed, a cubemap, etc.
    115     // The header will describe the format of this data.
    116     class PixelData {
    117     public:
    118         PixelData(const uint8_t *ptr, size_t sz) : fDataSz(sz), fDataPtr(ptr) { }
    119         const uint8_t *data() const { return fDataPtr; }
    120         size_t dataSize() const { return fDataSz; }
    121     private:
    122         const size_t fDataSz;
    123         const uint8_t *fDataPtr;
    124     };
    125 
    126     // This function is only called once from the constructor. It loads the data
    127     // and populates the appropriate fields of this class
    128     // (fKeyValuePairs, fPixelData, fSwapBytes)
    129     bool readKTXFile(const uint8_t *data, size_t dataLen);
    130 
    131     SkTArray<KeyValue> fKeyValuePairs;
    132     SkTDArray<PixelData> fPixelData;
    133     bool fValid;
    134 
    135     // If the endianness of the platform is different than the file,
    136     // then we need to do proper byte swapping.
    137     bool fSwapBytes;
    138 
    139     // Read an integer from a buffer, advance the buffer, and swap
    140     // bytes if fSwapBytes is set
    141     uint32_t readInt(const uint8_t** buf, size_t* bytesLeft) const;
    142 };
    143 
    144 #endif  // SkKTXFile_DEFINED
    145