Grammar for KTX files Spec: https://www.khronos.org/opengles/sdk/tools/KTX/file_format_spec/ Example files: https://github.com/KhronosGroup/KTX NOTES: * Arrays not implemented yet The file identifier is a unique set of bytes that will differentiate the file from other types of files. It consists of 12 bytes, as follows: Byte[12] FileIdentifier = { 0xAB, 0x4B, 0x54, 0x58, 0x20, 0x31, 0x31, 0xBB, 0x0D, 0x0A, 0x1A, 0x0A } This can also be expressed using C-style character definitions as: Byte[12] FileIdentifier = { '«', 'K', 'T', 'X', ' ', '1', '1', '»', '\r', '\n', '\x1A', '\n' } The rationale behind the choice values in the identifier is based on the rationale for the identifier in the PNG specification. This identifier both identifies the file as a KTX file and provides for immediate detection of common file-transfer problems. Byte [0] is chosen as a non-ASCII value to reduce the probability that a text file may be misrecognized as a KTX file. Byte [0] also catches bad file transfers that clear bit 7. Bytes [1..6] identify the format, and are the ascii values for the string "KTX 11". Byte [7] is for aesthetic balance with byte 1 (they are a matching pair of double-angle quotation marks). Bytes [8..9] form a CR-LF sequence which catches bad file transfers that alter newline sequences. Byte [10] is a control-Z character, which stops file display under MS-DOS, and further reduces the chance that a text file will be falsely recognised. Byte [11] is a final line feed, which checks for the inverse of the CR-LF translation problem. endianness contains the number 0x04030201 written as a 32 bit integer. If the file is little endian then this is represented as the bytes 0x01 0x02 0x03 0x04. If the file is big endian then this is represented as the bytes 0x04 0x03 0x02 0x01. When reading endianness as a 32 bit integer produces the value 0x04030201 then the endianness of the file matches the the endianness of the program that is reading the file and no conversion is necessary. When reading endianness as a 32 bit integer produces the value 0x01020304 then the endianness of the file is opposite the endianness of the program that is reading the file, and in that case the program reading the file must endian convert all header bytes to the endianness of the program (i.e. a little endian program must convert from big endian, and a big endian program must convert to little endian). For compressed textures, glType must equal 0. For uncompressed textures, glType specifies the type parameter passed to glTex{,Sub}Image*D, usually one of the values from table 8.2 of the OpenGL 4.4 specification [OPENGL44] (UNSIGNED_BYTE, UNSIGNED_SHORT_5_6_5, etc.) glTypeSize specifies the data type size that should be used when endianness conversion is required for the texture data stored in the file. If glType is not 0, this should be the size in bytes corresponding to glType. For texture data which does not depend on platform endianness, including compressed texture data, glTypeSize must equal 1. For compressed textures, glFormat must equal 0. For uncompressed textures, glFormat specifies the format parameter passed to glTex{,Sub}Image*D, usually one of the values from table 8.3 of the OpenGL 4.4 specification [OPENGL44] (RGB, RGBA, BGRA, etc.) For compressed textures, glInternalFormat must equal the compressed internal format, usually one of the values from table 8.14 of the OpenGL 4.4 specification [OPENGL44]. For uncompressed textures, glInternalFormat specifies the internalformat parameter passed to glTexStorage*D or glTexImage*D, usually one of the sized internal formats from tables 8.12 & 8.13 of the OpenGL 4.4 specification [OPENGL44]. The sized format should be chosen to match the bit depth of the data provided. glInternalFormat is used when loading both compressed and uncompressed textures, except when loading into a context that does not support sized formats, such as an unextended OpenGL ES 2.0 context where the internalformat parameter is required to have the same value as the format parameter. For both compressed and uncompressed textures, glBaseInternalFormat specifies the base internal format of the texture, usually one of the values from table 8.11 of the OpenGL 4.4 specification [OPENGL44] (RGB, RGBA, ALPHA, etc.). For uncompressed textures, this value will be the same as glFormat and is used as the internalformat parameter when loading into a context that does not support sized formats, such as an unextended OpenGL ES 2.0 context. The size of the texture image for level 0, in pixels. No rounding to block sizes should be applied for block compressed textures. For 1D textures pixelHeight and pixelDepth must be 0. For 2D and cube textures pixelDepth must be 0. numberOfArrayElements specifies the number of array elements. If the texture is not an array texture, numberOfArrayElements must equal 0. numberOfFaces specifies the number of cubemap faces. For cubemaps and cubemap arrays this should be 6. For non cubemaps this should be 1. Cube map faces are stored in the order: +X, -X, +Y, -Y, +Z, -Z. numberOfMipmapLevels must equal 1 for non-mipmapped textures. For mipmapped textures, it equals the number of mipmaps. Mipmaps are stored in order from largest size to smallest size. The first mipmap level is always level 0. A KTX file does not need to contain a complete mipmap pyramid. If numberOfMipmapLevels equals 0, it indicates that a full mipmap pyramid should be generated from level 0 at load time (this is usually not allowed for compressed formats). An arbitrary number of key/value pairs may follow the header. This can be used to encode any arbitrary data. The bytesOfKeyValueData field indicates the total number of bytes of key/value data including all keyAndValueByteSize fields, all keyAndValue fields, and all valuePadding fields. The file offset of the first imageSize field is located at the file offset of the bytesOfKeyValueData field plus the value of the bytesOfKeyValueData field plus 4. keyAndValue contains 2 separate sections. First it contains a key encoded in UTF-8. The key must be terminated by a NUL character (a single 0x00 byte). Keys that begin with the 3 ascii characters 'KTX' or 'ktx' are reserved and must not be used except as described by this spec (this version of the KTX spec defines a single key). Immediately following the NUL character that terminates the key is the Value data. The Value data may consist of any arbitrary data bytes. Any byte value is allowed. It is encouraged that the value be a NUL terminated UTF-8 string, but this is not required. If the Value data is binary, it is a sequence of bytes rather than of words. It is up to the vendor defining the key to specify how those bytes are to be interpreted (including the endianness of any encoded numbers). If the Value data is a string of bytes then the NUL termination should be included in the keyAndValueByteSize byte count (but programs that read KTX files must not rely on this).