KTX2-File-Format-Support-Technical-Details

This content was automatically converted from the project's wiki Markdown to HTML. See the Basis Universal GitHub wiki for the latest content.

This document is up to date as of Basis Universal v2.1. There is also the previous v2.0 version.

Table of Contents

Intro

KTX™ is a trademark of The Khronos Group Inc.

The Basis Universal transcoder only supports reading compressed texture data from .KTX2 container files in the below specific formats. Our transcoder is not yet a general purpose .KTX2 reader. However, for standard ASTC LDR 4x4-12x12 (all 14 standard ASTC block sizes, UNORM or sRGB variants), and standard ASTC HDR 6x6, the transcoder fully supports ASTC LDR/HDR blocks: i.e. blocks created by our encoder or external encoders such as ARM's astcenc, Intel's ispc_texcomp, etc.

Important Note: As of 3/7/2026, KTX-Software (and the ktx command line tool) does not correctly pass through HDR codec related "effort" level parameters due to simple bugs, which we have pointed out. (Specifically, they parse the --uastc-quality and --uastc-hdr-6x6i-level options, but they aren't properly hooked up to anything and are silently ignored.) We can't yet recommend using KTX-Software for any compression until these issues are fixed, but it can still be useful for basic validation of already compressed files created by our software.

In the mean time, we have forked the KTX-Software repository on GitHub. Our fork fixes these key bugs, has live security fixes merged from this repo, and will be periodically sync'd with the Khronos repo as needed. We will be maintaining this fork with v1.6 related HDR fixes, and we'll be integrating Basis Universal v2.1 with XUASTC LDR support into this forked repo very soon. At this point, we suspect we'll be maintaining this fork of KTX-Software for the foreseeable future.


Useful External References


Khronos KTX-Software Codec Support Status

KTX-Software supports the following supercompressed codecs:

BasisU Codec Name KTX-Software Name
ETC1S "basis-lz"
UASTC LDR 4x4 "uastc" or "uastc-ldr-4x4"
UASTC HDR 4x4 "uastc-hdr-4x4"
UASTC HDR 6x6i "uastc-hdr-6x6i"

Note, as of 3/7/2026, KTX doesn't properly pass through key HDR effort related parameters (see above), so we can't yet recommend using their software for any compression purposes, just basic information/validation. However, our fork of the KTX-Software repository fixes the problem.

Our non-supercompressed ASTC formats, such as ASTC LDR 4x4-12x12 and ASTC HDR 6x6, are also supported for validation (using the info command) or extraction by ktx (using the extract command), although as of 2/26/2026 extracting plain ASTC HDR 6x6 isn't supported by ktx yet (it sounds like this feature is coming soon).

See the ktx tool's create command help text:

>ktx create --help

...

      --encode <codec>          Encode the created KTX file. Case insensitive.
                                Possible options are: basis-lz | uastc | uastc-ldr-4x4 |
                                uastc-hdr-4x4 | uastc-hdr-6x6i

The ktx tool's info command can validate our generated .KTX2 files in all formats except for XUASTC LDR (which is expected), and basisu can introspect, transcode and unpack .KTX2 files generated by ktx (in the codec formats we support).

Our XUASTC LDR supercompressed format is not yet standardized yet, as of late Feb. 2026.

Example ktx command lines for UASTC HDR 4x4 and UASTC HDR 6x6i:

ktx create --format R16G16B16_SFLOAT --generate-mipmap --zstd 2 --encode uastc-hdr-4x4 desk.exr 1.ktx2
ktx create --format R16G16B16_SFLOAT --generate-mipmap --encode uastc-hdr-6x6i desk.exr 2.ktx2

For LDR sRGB images using the ktx tool, be sure to use --format R8G8B8_SRGB, not the UNORM variants which can cause a destructive sRGB->linear conversion before compression (which in 8-bit loses an enormous amount of quality, essentially making the results unusable in practice).

Note if you want to build KTX-Software under Windows with Visual Studio/MSVC using cmake to create the .SLN, we had to pass in -D KTX_FEATURE_TOOLS=ON to cmake to get the command line tools (like ktx) to build. (Otherwise the command line tools won't be in the generated solution.)

The extract command (or extract --all) can be used to unpack a KTX2 file to individual image files.

KTX2 Validation, DFD's, and vk_format values

This document assumes familiarity with the KTX2 container format, Khronos Data Format Descriptors (DFDs), and GPU block-compressed texture formats. The Khronos KTX-Software ktx (or btx in our fork with fixes) "info" command can be used to validate and display detailed file information about our written .KTX2 files. Alternatively, basisu -validate file.ktx2 can be used too.

To see exactly how the compressor creates the output KTX2 file's DFD, see encoder/basisu_comp.cpp, method basis_compressor::get_dfd().

In the KTX2 header, the vk_format field must be KTX2_UNDEFINED (0), or one of these values:

// vk_format's basisu v2.0/v2.1 supports:

// ASTC HDR 4x4 (also see the DFD, or Data Format Descriptor, as our usage is constrained for fast transcoding to BC6H) - this is used for UASTC HDR 4x4
uint32_t KTX2_FORMAT_ASTC_4x4_SFLOAT_BLOCK = 1000066000;

// ASTC HDR 6x6
uint32_t KTX2_FORMAT_ASTC_6x6_SFLOAT_BLOCK = 1000066004;

// ASTC LDR 4x4-12x12 (UNORM and sRGB variants)
uint32_t KTX2_FORMAT_ASTC_4x4_UNORM_BLOCK = 157, KTX2_FORMAT_ASTC_4x4_SRGB_BLOCK = 158;
uint32_t KTX2_FORMAT_ASTC_5x4_UNORM_BLOCK = 159, KTX2_FORMAT_ASTC_5x4_SRGB_BLOCK = 160;
uint32_t KTX2_FORMAT_ASTC_5x5_UNORM_BLOCK = 161, KTX2_FORMAT_ASTC_5x5_SRGB_BLOCK = 162;
uint32_t KTX2_FORMAT_ASTC_6x5_UNORM_BLOCK = 163, KTX2_FORMAT_ASTC_6x5_SRGB_BLOCK = 164;
uint32_t KTX2_FORMAT_ASTC_6x6_UNORM_BLOCK = 165, KTX2_FORMAT_ASTC_6x6_SRGB_BLOCK = 166;
uint32_t KTX2_FORMAT_ASTC_8x5_UNORM_BLOCK = 167, KTX2_FORMAT_ASTC_8x5_SRGB_BLOCK = 168;
uint32_t KTX2_FORMAT_ASTC_8x6_UNORM_BLOCK = 169, KTX2_FORMAT_ASTC_8x6_SRGB_BLOCK = 170;
uint32_t KTX2_FORMAT_ASTC_10x5_UNORM_BLOCK = 173, KTX2_FORMAT_ASTC_10x5_SRGB_BLOCK = 174;
uint32_t KTX2_FORMAT_ASTC_10x6_UNORM_BLOCK = 175, KTX2_FORMAT_ASTC_10x6_SRGB_BLOCK = 176;
uint32_t KTX2_FORMAT_ASTC_8x8_UNORM_BLOCK = 171, KTX2_FORMAT_ASTC_8x8_SRGB_BLOCK = 172;  // note the ASTC block size order is off in the vkFormat definitions
uint32_t KTX2_FORMAT_ASTC_10x8_UNORM_BLOCK = 177, KTX2_FORMAT_ASTC_10x8_SRGB_BLOCK = 178;
uint32_t KTX2_FORMAT_ASTC_10x10_UNORM_BLOCK = 179, KTX2_FORMAT_ASTC_10x10_SRGB_BLOCK = 180;
uint32_t KTX2_FORMAT_ASTC_12x10_UNORM_BLOCK = 181, KTX2_FORMAT_ASTC_12x10_SRGB_BLOCK = 182;
uint32_t KTX2_FORMAT_ASTC_12x12_UNORM_BLOCK = 183, KTX2_FORMAT_ASTC_12x12_SRGB_BLOCK = 184;

If vk_format is not KTX2_UNDEFINED, the transcoder expects the block data to be bit-compatible with the corresponding Vulkan/Khronos texture format, and the DFD must not contradict it. (Also, as a side note: in practice we've seen at least one major KTX2 reader ignore the DFD entirely, and only pay attention to the vk_format.)


The supercompression field must be:

uint32_t KTX2_SS_NONE = 0; // data is raw
uint32_t KTX2_SS_BASISLZ = 1; // ETC1S, file must have global supercompressed data (sgd_byte_offset/sgd_byte_length must be valid)
uint32_t KTX2_SS_ZSTANDARD = 2; // data is Zstd compressed
uint32_t KTX2_SS_UASTC_HDR_6x6I = 4, // UASTC HDR 6x6i (assigned by Khronos in early 2026)
uint32_t KTX2_SS_XUASTC_LDR = 5 // XUASTC LDR 4x4-12x12 (assignment in progress with Khronos as of early 2026)

Basis Universal doesn't currently support supercompression ID 3 (Deflate).

The transcoder supports 2D or cubemap textures, with or without mipmaps. Array textures of any type (2D/cubemap/texture video, with or without mipmaps) are supported. 3D textures are not supported (i.e. the header's pixel_depth must be 0). Cubemaps must have square dimensions.

Basis Universal Formats

1. ETC1S

The vk_format field must be KTX2_UNDEFINED, and the DFD color model must be:

uint32_t KTX2_KDF_DF_MODEL_ETC1S = 163; // 0xA3

The block dimension fields in the DFD must be set to 4x4.

ETC1S textures may have an alpha channel (see below).

The supercompression type must be KTX2_SS_BASISLZ.

The supercompression global data contains compressed codebooks. See the ETC1S spec for details on the format.

2. UASTC LDR 4x4

The vk_format field must be KTX2_UNDEFINED, and the DFD color model must be:

uint32_t KTX2_KDF_DF_MODEL_UASTC_LDR_4X4 = 166; // 0xA6

The block dimension fields in the DFD must be set to 4x4.

UASTC LDR 4x4 textures may have an alpha channel. Here's the UASTC LDR 4x4 spec. Internally UASTC LDR 4x4 uses a conservative union of both the ASTC LDR 4x4 and BC7 latents, but the block packing is simplified to free up space for hint values to accelerate transcoding to other formats.

UASTC LDR 4x4 data may be supercompressed with Zstd.

UASTC LDR 4x4 has no supercompressed global data.

3. UASTC HDR 4x4

The vk_format field must be KTX2_FORMAT_ASTC_4x4_SFLOAT_BLOCK (see above), and the DFD color model must be:

uint32_t KTX2_KDF_DF_MODEL_UASTC_HDR_4X4 = 167; // 0xA7

The block dimension fields in the DFD must be set to 4x4.

UASTC HDR 4x4 data is 100% standard ASTC HDR 4x4 data, but constrained for fast transcoding to BC6H (unsigned variant only - ASTC HDR is unsigned). The UASTC HDR 4x4 spec describes the exact configurations supported. The texture data is standard ASTC HDR, but it cannot utilize configurations that are not supported by the UASTC HDR 4x4 spec, otherwise fast latent to latent transcoding from ASTC HDR to BC6H wouldn't be practical.

UASTC HDR 4x4 textures do not support alpha channels. ASTC HDR 4x4 does, but the constrained subset of ASTC HDR we support to enable fast, simple transcoding to BC6H does not. (BC6H doesn't support alpha.)

UASTC HDR 4x4 data may be supercompressed with Zstd.

UASTC HDR 4x4 has no supercompressed global data.

4. ASTC HDR 6x6

The vk_format field must be KTX2_FORMAT_ASTC_6x6_SFLOAT_BLOCK (see above), and the DFD color model must be:

uint32_t KTX2_KDF_DF_MODEL_ASTC = 162; // 0xA2

The block dimension fields in the DFD must be set to 6x6.

The transcoder uses a fully compliant ASTC HDR decoder whenever it has to decode this format to plain texels. If the ASTC HDR 6x6 block data has alpha, it will be decoded correctly but the alpha data may be ignored depending on the output transcode format. (BC6H doesn't support alpha.)

ASTC HDR 6x6 data may be supercompressed with Zstd.

ASTC HDR 6x6 has no supercompressed global data.

5. UASTC HDR 6x6i (intermediate)

The vk_format field must be KTX2_UNDEFINED, and the DFD color model must be:

uint32_t KTX2_KDF_DF_MODEL_UASTC_HDR_6X6_INTERMEDIATE = 168; // 0xA8

The supercompression type must be KTX2_SS_UASTC_HDR_6x6I (4).

The supercompressed global data contains a seek table: an array of ktx2_slice_offset_len_desc_std struct's, one per KTX2 "image" (the image count = max(header.layer_count, 1) * header.face_count * header.m_level_count):

struct ktx2_slice_offset_len_desc_std
{
    uint32_t m_slice_byte_offset; // mipmap relative offset (NOT the absolute file offset)
    uint32_t m_slice_byte_length; // byte length of this image's data
    uint32_t m_profile; // for UASTC HDR 6x6i: first 2 bytes from the mipmap level's data (header magic+variant ID field)
};

Here's how to compute the index to use within this array, given the mipmap level_index, the array layer_index, and the cubemap face_index:

const uint32_t image_index =
    (level_index * basisu::maximum<uint32_t>(m_header.m_layer_count, 1) * m_header.m_face_count) +
    layer_index * m_header.m_face_count +
    face_index;

The block dimension fields in the DFD must be set to 6x6.

UASTC HDR 6x6i doesn't support alpha channels. Here's the UASTC HDR 6x6i spec.

Note: UASTC HDR 6x6i is the "Codec". Each mipmap level has a small header or marker which defines the exact "version" (or variant, or semantic contract) used by that mipmap level. Each mipmap level may in theory use a different version. In practice, they'll very likely all use the same version. The version field allows Binomial to signal to the transcoder exactly which semantics should be used during transcoding. Binomial will always keep transcoder compatibility with all versions whenever possible. Currently there are 2 stream versions (those written by v1.6, and later by v2.0).

6. ASTC LDR 4x4-12x12

ASTC LDR data may be supercompressed with Zstd.

The vk_format field in the header must be between [KTX2_FORMAT_ASTC_4x4_UNORM_BLOCK, KTX2_FORMAT_ASTC_12x12_SRGB_BLOCK] (this range includes the linear and sRGB variants). During compression when computing candidate distortions, our encoder will configure its ASTC decoder to be compatible with this vk_format (sRGB or linear).

The DFD's model color field must be:

uint32_t KTX2_KDF_DF_MODEL_ASTC = 162; // 0xA2

The block dimension fields in the DFD must be set correctly and match the vk_format field.

The UNORM vk_format's will be emitted if the encoder was in linear mode, otherwise sRGB. This field slightly modifies how ASTC LDR blocks will be decoded by the transcoder (see the ASTC LDR specification).

The transcoder uses a fully compliant ASTC LDR decoder whenever it has to decode these formats.

ASTC LDR 4x4-12x12 may have an alpha channel.

ASTC LDR 4x4-12x12 data may be supercompressed with Zstd.

ASTC LDR 4x4-12x12 has no supercompressed global data.

7. XUASTC LDR 4x4-12x12

The vk_format field must be KTX2_UNDEFINED, and the DFD color model must be:

uint32_t KTX2_KDF_DF_MODEL_XUASTC_LDR_INTERMEDIATE = 169; // 0xA9

The standard ASTC/XUASTC block dimensions are written into the DFD.

The supercompression type must be KTX2_SS_XUASTC_LDR (5).

The supercompression global data contains the same format seek tables as UASTC HDR 6x6i. See the ktx2_slice_offset_len_desc_std struct above. This structure's profile field's lowest 8 bits will be the entropy profile used (arithmetic, hybrid, or full Zstd), and the next 8 bits (starting at bit position 8 relative to the LSB) contain the profile codec variant (currently always 0x01, as there are no variants). See the xuastc_ldr_syntax profile enum in the XUASTC LDR specification.

XUASTC LDR 4x4-12x12 may have an alpha channel.

Each mipmap level may use a different entropy profile. The encoder's default behavior is to always use the arithmetic profile on mipmap levels containing DISABLE_FASTER_FORMAT_TOTAL_BLOCKS_THRESH (64) total blocks or less. The Zstd profile's header overhead is too high for the smallest mipmap levels. The arithmetic profile is slower to transcode, but has very little header overhead. This behavior will likely be changing (and become more configurable) in future versions of the library.

XUASTC LDR is our newest format. Khronos standardization efforts are ongoing as of early 2026. We have aligned the global supercompression seek tables used by XUASTC LDR to be the same as UASTC HDR 6x6i's to assist standardization. It's likely we will be also standardizing several simple deblocking pixel shaders, and also adding at least one key value field that indicates the type of deblocking to apply (if any).

Note: XUASTC LDR is the "Codec". Each mipmap level has a small header which defines the exact XUASTC LDR entropy "profile" (arithmetic, hybrid, or full Zstd), and the "version" (or variant, or semantic contract) used by that mipmap level. Each mipmap level may use a different profile, and (in theory) a different version. (In practice, they'll very likely all use the same profile version.) The version field allows Binomial to signal to the transcoder exactly which semantics should be used during transcoding. Binomial will always keep transcoder compatibility with all versions whenever possible. Currently there is only a single version of XUASTC LDR for all profiles.


DFD - Linear vs. sRGB Determination

For LDR formats, the DFD's transfer function field will be set to either LINEAR or sRGB, which indicates which ASTC LDR decoding profile was used during encoding. The HDR, it'll always be LINEAR (i.e. no transfer function).

uint32_t KTX2_KHR_DF_TRANSFER_LINEAR = 1;
uint32_t KTX2_KHR_DF_TRANSFER_SRGB = 2;

DFD - REC 2020/BT2100 Color Gamut Determination

The C++ compressor API has numerous low-level settings (in struct basis_compressor_params) controlling compression and KTX2 file format generation. If the m_astc_hdr_6x6_options.m_rec2020_bt2100_color_gamut bool flag was set to true, the DFD's color primary field will be set to BC2020 (4). This is done even if the output format isn't ASTC HDR 6x6 or UASTC HDR 6x6i. (We'll be improving how this is handled in the future.)

This corresponds to the cFlagREC2020 in the simplified C++ API basis_compress(), or the BU_COMP_FLAGS_REC2020 compressor flag in the C API.

enum ktx2_df_color_primaries
{
    KTX2_DF_PRIMARIES_UNSPECIFIED = 0,
    KTX2_DF_PRIMARIES_BT709 = 1,
    KTX2_DF_PRIMARIES_SRGB = 1,
    KTX2_DF_PRIMARIES_BT601_EBU = 2,
    KTX2_DF_PRIMARIES_BT601_SMPTE = 3,
    KTX2_DF_PRIMARIES_BT2020 = 4,
    KTX2_DF_PRIMARIES_CIEXYZ = 5,
    KTX2_DF_PRIMARIES_ACES = 6,
    KTX2_DF_PRIMARIES_ACESCC = 7,
    KTX2_DF_PRIMARIES_NTSC1953 = 8,
    KTX2_DF_PRIMARIES_PAL525 = 9,
    KTX2_DF_PRIMARIES_DISPLAYP3 = 10,
    KTX2_DF_PRIMARIES_ADOBERGB = 11
};

Important note about the REC 2020/BT2100 flag: The ASTC HDR 6x6 and UASTC HDR 6x6i's encoder uses different formulas to convert the input HDR linear RGB pixels to ICtCp/Delta E ITP space if the input is known to be REC 2020/BT 2100 vs. the default REC 709. It's important this flag is set correctly, otherwise the encoder will be internally computing distortions in the wrong color space.


DFD - Alpha Channel Determination

For ETC1S: The texture is assumed to have alpha if the DFD's length is 60 bytes (2 samples), otherwise it's assumed to be RGB only.

For UASTC LDR 4x4, ASTC LDR 4x4-12x12, or XUASTC LDR 4x4-12x12, the DFD's channelType field (at uint32_t offset 7 relative to the beginning of the DFD or the initial DFD totalSize field, bit offset 24, 4-bits length) is interpreted to determine if the texture has alpha:

uint32_t KTX2_DF_CHANNEL_UASTC_RGBA = 3U;
uint32_t KTX2_DF_CHANNEL_UASTC_RRRG = 5U;

If channelType is either of these values, it's assumed the texture has an alpha channel. See the Khronos Data Format Specification v1.4.0, "Section 5.6.14 KHR_DF_MODEL_UASTC" for the table of UASTC channel names.

Our other formats don't support alpha channels.

Key Value Fields

HDR Range (ktx_map_range)

For HDR files we always write the KTXmapRange structure, which can be used by a pixel shader to reconstruct the actual float range used in the original source .EXR/.HDR/.DDS file(s):

// always little endian
struct ktx_map_range 
{
   float m_scale;  // scale to multiply the sampled values by, default=1.0
   float m_offset; // offset to add after multiplication, always 0.0
};

This information is necessary because our compressor will automatically rescale input HDR images that use extreme dynamic ranges beyond values representable using ASTC HDR (which is slightly less than MAX_HALF):

// If the input has values higher than this, they need to be linearly scaled so all values are between [0,ASTC_HDR_MAX_VAL], and the linear scaling inverted in the shader.
const float ASTC_HDR_MAX_VAL = 65216.0f; // actually MAX_QLOG12_VAL

The compressor prints a warning (currently to stdout) when this rescaling occurs. Note rescaling only ever occurs on images where any texels have RGB channel values larger than ASTC_HDR_MAX_VAL.

Compressor Version

The key KTXwriter will be set to the string Basis Universal 2.10. The format for our library will always be "Basis Universal X.YY", where X is the major version, and YY is the minor version.

HDR Upconversion Nit Multiplier

The ldrHDRUpconversionNitMultiplier key indicates the HDR texture was automatically upconverted from a 24-bpp SDR/LDR asset. Upconversion is performed by converting the input to linear light (undoing the sRGB transfer function), and then multiplying the normalized linear [0.0, 1.0] intensity range by typically 80–100 nits (where ~100 nits corresponds to SDR reference white).

The value is written as an ASCII decimal number, typically "100" unless changed by the user at compression time. This maps SDR white to a physically meaningful absolute luminance level.

This value can be used in a shader to convert sampled HDR values back to a normalized [0,1] linear range by dividing by the multiplier. The resulting normalized value can then be converted from linear to sRGB, as needed.

This scaling is required because the ASTC HDR 6x6 / UASTC HDR 6x6i compressor converts input data to ICtCp and expects the input to be in linear absolute luminance (nits), not normalized relative intensity.

HDR Upconversion sRGB to Linear Flag

The LDRUpconversionSRGBToLinear key indicates whether the input LDR/SDR asset was converted from sRGB to linear light during upconversion. The value written will always be "1", or the key won't be written at all.

Using the basisu command line tool to dump basic KTX2 header info

Our command line tool can examine our generated .KTX2 files. Example on bik158.ktx2:

C:\dev\bin>wasmtime --wasm threads=yes --wasi threads=yes --dir=. basisu_mt.wasm -info bik158.ktx2

Basis Universal LDR/HDR GPU Texture Supercompression System v2.00.0 (WASI Threaded)
Copyright (C) 2019-2026 Binomial LLC, All rights reserved
No SSE, Multithreading: 1, Zstandard support: 1, OpenCL: 0

Input file "bik158.ktx2", KTX2: 1
Resolution: 960x960
Block size: 6x6
Mipmap Levels: 1
Texture Array Size (layers): 0
Total Faces: 1 (2D)
Is Texture Video: 0
Supercompression Format: XUASTC_LDR_6x6
Supercompression Scheme: BASISLZ
Has Alpha: 0

KTX2 header vk_format: 0x0 (decimal 0)

Data Format Descriptor (DFD):
DFD length in bytes: 44
DFD color model: 169
DFD color primaries: 1 (BT709)
DFD transfer func: 2 (SRGB)
DFD flags: 0
DFD samples: 1
DFD chan0: RGB
DFD hex values:
0x2C,0x0,0x0,0x0,
0x0,0x0,0x0,0x0,
0x2,0x0,0x28,0x0,
0xA9,0x1,0x2,0x0,
0x5,0x5,0x0,0x0,
0x0,0x0,0x0,0x0,
0x0,0x0,0x0,0x0,
0x0,0x0,0x7F,0x0,
0x0,0x0,0x0,0x0,
0x0,0x0,0x0,0x0,
0xFF,0xFF,0xFF,0xFF

Total key values: 1
0. Key: "KTXwriter", Value length in bytes: 22 Value Bytes: 0x42,0x61,0x73,0x69,0x73,0x20,0x55,0x6E,0x69,0x76,0x65,0x72,0x73,0x61,0x6C,0x20,0x32,0x2E,0x30,0x30,0x0,0x0
Levels:
0. Offset: 192, Length: 149083, Uncompressed Length: 0
Image level info:
--- Level Index: 0, Layer Index: 0, Face Index: 0
Orig width/height: 960x960
Width/height: 960x960
Block width/height: 6x6
Num blocks: 160x160, Total blocks: 25600
Alpha flag: false, I-frame flag: false

Success

Using the KTX command line tool to validate KTX2 files

This tool was built from the KTX-Software repo as of 2/24/2026. Here's an example on a UASTC HDR 6x6i file generated using Basis Universal v2.1:

C:\dev\ktx2_2\KTX-Software-main\build\Debug>ktx info c:\dev\bu_2_13\basis_universal\bin\uastc_hdr_6x6i\Desk.ktx2
Validation successful

Header

identifier: «KTX 20»\r\n\x1A\n
vkFormat: VK_FORMAT_UNDEFINED
typeSize: 1
pixelWidth: 644
pixelHeight: 874
pixelDepth: 0
layerCount: 0
faceCount: 1
levelCount: 1
supercompressionScheme: KTX_SS_UASTC_HDR_6x6_INTERMEDIATE
dataFormatDescriptor.byteOffset: 0x68
dataFormatDescriptor.byteLength: 44
keyValueData.byteOffset: 0x94
keyValueData.byteLength: 60
supercompressionGlobalData.byteOffset: 0xd0
supercompressionGlobalData.byteLength: 12

Level Index

Level0.byteOffset: 0xdc
Level0.byteLength: 205424
Level0.uncompressedByteLength: 0

Data Format Descriptor

DFD total bytes: 44
Vendor ID: KHR_DF_VENDORID_KHRONOS
Descriptor type: KHR_DF_KHR_DESCRIPTORTYPE_BASICFORMAT
Version: KHR_DF_VERSIONNUMBER_1_3
Descriptor block size: 40
Flags: 0x0 (KHR_DF_FLAG_ALPHA_STRAIGHT)
Transfer: KHR_DF_TRANSFER_LINEAR
Primaries: KHR_DF_PRIMARIES_BT709
Model: KHR_DF_MODEL_UASTC_HDR_6x6
Dimensions: 6, 6, 1, 1
Plane bytes: 16, 0, 0, 0, 0, 0, 0, 0
Sample 0:
    Qualifiers: 0x80 (KHR_DF_SAMPLE_DATATYPE_FLOAT)
    Channel Type: 0x0 (KHR_DF_CHANNEL_UASTC_HDR_6x6_RGB)
    Length: 128 bits Offset: 0
    Position: 0, 0, 0, 0
    Lower: 0x00000000
    Upper: 0x3f800000

Key/Value Data

KTXmapRange:
    scale: 1.000000
    offset: 0.000000
KTXwriter: Basis Universal 2.10

UASTC HDR6X6 Intermediate Supercompression Global Data


rgbSliceByteLength: 205424
rgbSliceByteOffset: 0
rgbSliceType: 0xabcd

Another example, this time a mipmapped texture array with 2 slices, UASTC HDR 6x6i:

C:\dev\bu_2_28\basis_universal\example>c:\dev\ktx2_2\KTX-Software-main\build\Debug\ktx info test_uastc_hdr_6x6i_array_custom_mips.ktx2
Validation successful

Header

identifier: «KTX 20»\r\n\x1A\n
vkFormat: VK_FORMAT_UNDEFINED
typeSize: 1
pixelWidth: 384
pixelHeight: 256
pixelDepth: 0
layerCount: 2
faceCount: 1
levelCount: 8
supercompressionScheme: KTX_SS_UASTC_HDR_6x6_INTERMEDIATE
dataFormatDescriptor.byteOffset: 0x110
dataFormatDescriptor.byteLength: 44
keyValueData.byteOffset: 0x13c
keyValueData.byteLength: 60
supercompressionGlobalData.byteOffset: 0x178
supercompressionGlobalData.byteLength: 192

Level Index

Level0.byteOffset: 0xb2b
Level0.byteLength: 869
Level0.uncompressedByteLength: 0
Level1.byteOffset: 0x7d2
Level1.byteLength: 857
Level1.uncompressedByteLength: 0
Level2.byteOffset: 0x597
Level2.byteLength: 571
Level2.uncompressedByteLength: 0
Level3.byteOffset: 0x352
Level3.byteLength: 581
Level3.uncompressedByteLength: 0
Level4.byteOffset: 0x290
Level4.byteLength: 194
Level4.uncompressedByteLength: 0
Level5.byteOffset: 0x270
Level5.byteLength: 32
Level5.uncompressedByteLength: 0
Level6.byteOffset: 0x254
Level6.byteLength: 28
Level6.uncompressedByteLength: 0
Level7.byteOffset: 0x238
Level7.byteLength: 28
Level7.uncompressedByteLength: 0

Data Format Descriptor

DFD total bytes: 44
Vendor ID: KHR_DF_VENDORID_KHRONOS
Descriptor type: KHR_DF_KHR_DESCRIPTORTYPE_BASICFORMAT
Version: KHR_DF_VERSIONNUMBER_1_3
Descriptor block size: 40
Flags: 0x0 (KHR_DF_FLAG_ALPHA_STRAIGHT)
Transfer: KHR_DF_TRANSFER_LINEAR
Primaries: KHR_DF_PRIMARIES_BT709
Model: KHR_DF_MODEL_UASTC_HDR_6x6
Dimensions: 6, 6, 1, 1
Plane bytes: 16, 0, 0, 0, 0, 0, 0, 0
Sample 0:
    Qualifiers: 0x80 (KHR_DF_SAMPLE_DATATYPE_FLOAT)
    Channel Type: 0x0 (KHR_DF_CHANNEL_UASTC_HDR_6x6_RGB)
    Length: 128 bits Offset: 0
    Position: 0, 0, 0, 0
    Lower: 0x00000000
    Upper: 0x3f800000

Key/Value Data

KTXmapRange:
    scale: 1.000000
    offset: 0.000000
KTXwriter: Basis Universal 2.10

UASTC HDR6X6 Intermediate Supercompression Global Data


rgbSliceByteLength: 440
rgbSliceByteOffset: 0
rgbSliceType: 0xabcd

rgbSliceByteLength: 429
rgbSliceByteOffset: 0x1b8
rgbSliceType: 0xabcd

rgbSliceByteLength: 434
rgbSliceByteOffset: 0
rgbSliceType: 0xabcd

rgbSliceByteLength: 423
rgbSliceByteOffset: 0x1b2
rgbSliceType: 0xabcd

rgbSliceByteLength: 291
rgbSliceByteOffset: 0
rgbSliceType: 0xabcd

rgbSliceByteLength: 280
rgbSliceByteOffset: 0x123
rgbSliceType: 0xabcd

rgbSliceByteLength: 296
rgbSliceByteOffset: 0
rgbSliceType: 0xabcd

rgbSliceByteLength: 285
rgbSliceByteOffset: 0x128
rgbSliceType: 0xabcd

rgbSliceByteLength: 105
rgbSliceByteOffset: 0
rgbSliceType: 0xabcd

rgbSliceByteLength: 89
rgbSliceByteOffset: 0x69
rgbSliceType: 0xabcd

rgbSliceByteLength: 16
rgbSliceByteOffset: 0
rgbSliceType: 0xabcd

rgbSliceByteLength: 16
rgbSliceByteOffset: 0x10
rgbSliceType: 0xabcd

rgbSliceByteLength: 14
rgbSliceByteOffset: 0
rgbSliceType: 0xabcd

rgbSliceByteLength: 14
rgbSliceByteOffset: 0xe
rgbSliceType: 0xabcd

rgbSliceByteLength: 14
rgbSliceByteOffset: 0
rgbSliceType: 0xabcd

rgbSliceByteLength: 14
rgbSliceByteOffset: 0xe
rgbSliceType: 0xabcd