A KTX 1 file is a 64-byte header, key and value data, and the mipmap levels. Every number is a 32-bit unsigned integer in the byte order of the machine that wrote the file; the endianness field tells a reader whether to swap. This page follows the Khronos KTX File Format Specification, version 1.
Header
| Offset | Size | Field | Meaning |
|---|---|---|---|
| 0 | 12 | identifier | AB 4B 54 58 20 31 31 BB 0D 0A 1A 0A: «KTX 11», CR LF, Ctrl-Z, LF. The bytes catch transfers that strip bit 7 or change line ends. |
| 12 | 4 | endianness | 0x04030201 in the writer’s byte order (below). |
| 16 | 4 | glType | The OpenGL type for glTexImage, such as GL_UNSIGNED_BYTE. 0 for compressed textures. |
| 20 | 4 | glTypeSize | Size in bytes of the data type, used to swap byte order. 1 for compressed data and for data that does not depend on byte order. Never 0. |
| 24 | 4 | glFormat | The OpenGL format, such as GL_RGBA. 0 for compressed textures. |
| 28 | 4 | glInternalFormat | The sized internal format (GL_RGBA8) or, for compressed textures, the compressed format (GL_COMPRESSED_RGB8_ETC2). |
| 32 | 4 | glBaseInternalFormat | The base internal format, such as GL_RGB. Equal to glFormat for uncompressed textures; used where sized formats are not supported. |
| 36 | 4 | pixelWidth | Width of level 0 in pixels, not rounded up to whole blocks. |
| 40 | 4 | pixelHeight | Height of level 0. 0 for a 1D texture. |
| 44 | 4 | pixelDepth | Depth of level 0. 0 for 1D, 2D and cube textures. |
| 48 | 4 | numberOfArrayElements | Number of array layers; 0 if the texture is not an array. |
| 52 | 4 | numberOfFaces | 6 for a cube map or cube map array, otherwise 1. |
| 56 | 4 | numberOfMipmapLevels | Levels stored; 1 for no mipmaps. 0 means only level 0 is stored and the loader should generate the rest (usually impossible for compressed formats). |
| 60 | 4 | bytesOfKeyValueData | Bytes of key and value data that follow, including every size field and padding. 0 for none. |
Endianness
| The reader sees | Bytes | Meaning |
|---|---|---|
0x04030201 | Same order as the reader | Read as is |
0x01020304 | Opposite order | Swap every header field, every size field and key/value size, and, when glTypeSize is above 1, every texture value in units of glTypeSize bytes |
A little-endian file has the bytes 01 02 03 04 at offset 12; a big-endian
one has 04 03 02 01.
Key and value data
Starting at offset 64 and filling bytesOfKeyValueData bytes, each pair
is:
| Field | Size | Meaning |
|---|---|---|
| keyAndValueByteSize | 4 | Bytes of key, its terminating 00, and value. Padding not included. |
| key | varies | UTF-8 text with no byte order mark, ended by one 00 byte. |
| value | varies | Any bytes. Often a UTF-8 string ending in 00, but a reader must not assume it. |
| valuePadding | 0–3 | Zero bytes so the next pair starts on a multiple of 4. |
Keys starting with KTX or ktx are reserved for Khronos. The
only key this version defines is KTXorientation, which records how the
texture coordinates map to the picture without changing the data:
| Value | Meaning |
|---|---|
S=r,T=d | S increases to the right, T downwards (the first row is the top) |
S=r,T=u | S to the right, T upwards (the first row is the bottom, OpenGL’s default) |
S=r,T=d,R=i | As the first, and R increases into the screen (3D) |
S=r,T=u,R=o | As the second, and R increases out of the screen (3D) |
Mipmap levels
After the key and value data come max(1, numberOfMipmapLevels) levels,
level 0 (the largest) first. Each level is:
| Field | Size | Meaning |
|---|---|---|
| imageSize | 4 | Bytes of image data in this level, for all layers, faces and slices, without padding. For a cube map that is not an array (6 faces, 0 array elements), the size of one face. |
| data | varies | For each array element, for each face, for each z slice, for each row (or row of blocks), the pixels (or blocks). |
| cubePadding | 0–3 | Only in non-array cube maps, after each face, so each face starts on a multiple of 4. |
| mipPadding | 0–3 | Zero bytes so the next imageSize starts on a multiple of 4. |
- Faces are stored in the order +X, −X, +Y, −Y, +Z, −Z.
- Rows of uncompressed data are padded to a multiple of 4 bytes, as OpenGL does with
GL_UNPACK_ALIGNMENT4. With the formats known today, cube and mip padding are always empty. - Each level is half the size of the one before in each dimension, rounded down, and never less than 1.
- Paletted formats (
GL_PALETTE*) store all levels together with the palette as one block, with one face only.
Common OpenGL values
The OpenGL registry defines hundreds of formats; these are the values most often seen in KTX 1 files.
| Field | Constant | Value |
|---|---|---|
| glType | GL_BYTE, GL_UNSIGNED_BYTE | 0x1400, 0x1401 |
| glType | GL_SHORT, GL_UNSIGNED_SHORT | 0x1402, 0x1403 |
| glType | GL_INT, GL_UNSIGNED_INT | 0x1404, 0x1405 |
| glType | GL_FLOAT, GL_HALF_FLOAT | 0x1406, 0x140B |
| glType | GL_UNSIGNED_SHORT_5_6_5 | 0x8363 |
| glType | GL_UNSIGNED_SHORT_4_4_4_4, GL_UNSIGNED_SHORT_5_5_5_1 | 0x8033, 0x8034 |
| glFormat | GL_RED, GL_RG | 0x1903, 0x8227 |
| glFormat | GL_RGB, GL_RGBA | 0x1907, 0x1908 |
| glFormat | GL_ALPHA, GL_LUMINANCE, GL_LUMINANCE_ALPHA | 0x1906, 0x1909, 0x190A |
| glFormat | GL_BGRA | 0x80E1 |
| glInternalFormat | GL_RGB8, GL_RGBA8 | 0x8051, 0x8058 |
| glInternalFormat | GL_ETC1_RGB8_OES | 0x8D64 |
| glInternalFormat | GL_COMPRESSED_RGB8_ETC2, GL_COMPRESSED_RGBA8_ETC2_EAC | 0x9274, 0x9278 |
| glInternalFormat | GL_COMPRESSED_RGB_S3TC_DXT1_EXT, GL_COMPRESSED_RGBA_S3TC_DXT5_EXT | 0x83F0, 0x83F3 |
| glInternalFormat | GL_COMPRESSED_RGBA_ASTC_4x4_KHR | 0x93B0 |
A complete file
A 1 by 1 pixel 2D texture in GL_RGBA8, one level, no key and value data,
written little-endian. The pixel is opaque red.
00000000 AB 4B 54 58 20 31 31 BB 0D 0A 1A 0A 01 02 03 04
00000010 01 14 00 00 01 00 00 00 08 19 00 00 58 80 00 00
00000020 08 19 00 00 01 00 00 00 01 00 00 00 00 00 00 00
00000030 00 00 00 00 01 00 00 00 01 00 00 00 00 00 00 00
00000040 04 00 00 00 FF 00 00 FF
GL_UNSIGNED_BYTE, size 1, GL_RGBA, GL_RGBA8, GL_RGBA; 1 × 1 × 0; 0 arrays, 1 face, 1 level, 0 bytes of key data; then imageSize 4 and the pixel