A Rust library and CLI for GPU texture compression. ctt provides a unified interface over multiple encoder backends.
ctt binds to established open-source compression libraries and exposes them through a common Encoder trait. Each backend is compiled as an optional feature and can be enabled independently.
| Backend | Prefix | Feature | Description |
|---|---|---|---|
| bc7enc-rdo | bc7e_ |
encoder-bc7enc |
Perceptual BC7 encoder with RDO support. |
| Intel ISPC Texture Compressor | intel_ |
encoder-intel |
SIMD-optimized BCn and ETC encoder. |
| etcpak | etcpak_ |
encoder-etcpak |
Fast ETC/EAC and BCn encoder. |
| AMD Compressonator | amd_ |
encoder-amd |
AMD's BCn encoder suite. |
| astcenc | astcenc_ |
encoder-astcenc |
ARM ASTC encoder. |
Encoders are listed in priority order — when multiple encoders support the same format (e.g. BC7), the first one in the table is used. To override this, prefix the format with an encoder name (e.g. intel_bc7).
Use ctt --list-encoders to see what's available in your build:
$ ctt --list-encoders
Encoder Priority Formats
------- -------- -------
bc7e 1 bc7
intel 2 bc1, bc3, bc4, bc5, bc6h, bc7, etc1
etcpak 3 etc1, etc2_rgba, eac_r, eac_rg, bc1, bc3, bc4, bc5
amd 4 bc1, bc2, bc3, bc4, bc4s, bc5, bc5s, bc6h, bc6hsf, bc7
astcenc 5 astc
| Format | CLI name | Description |
|---|---|---|
| BC1 | bc1 |
RGB with 1-bit alpha. Opaque textures and simple cutouts. |
| BC2 | bc2 |
RGBA with explicit 4-bit alpha. Sharp alpha transitions. |
| BC3 | bc3 |
RGBA with interpolated alpha. General-purpose transparency. |
| BC4 | bc4 |
Single channel. Grayscale, heightmaps, roughness. |
| BC4S | bc4s |
Single channel, signed. |
| BC5 | bc5 |
Two channels. Normal maps. |
| BC5S | bc5s |
Two channels, signed. |
| BC6H | bc6h |
HDR half-float RGB. Environment maps, HDR textures. |
| BC6H SF | bc6hsf |
HDR signed float RGB. |
| BC7 | bc7 |
High-quality RGBA. Best LDR quality, supports alpha. |
| ETC1 | etc1 |
Mobile-friendly RGB. |
| ETC2 RGBA | etc2_rgba |
Mobile-friendly RGBA. |
| EAC R | eac_r |
Single channel 11-bit. |
| EAC RG | eac_rg |
Two channel 11-bit. |
| ASTC | astc_WxH |
Adaptive scalable texture compression. Variable block sizes (4x4 to 12x12). |
All formats support quality presets from ultra-fast to very-slow where the encoder supports them.
Uncompressed formats are also supported using WebGPU names (e.g. rgba8unorm) or Vulkan names (e.g. r8g8b8a8_unorm).
The container format is inferred from the output file extension (.ktx2 or .dds), or can be set explicitly with --container.
- KTX2 — Khronos cross-platform container. Supports all formats. Optional zstd or zlib supercompression.
- DDS — DirectX standard. Does not support ETC/EAC or ASTC formats.
# Install the CLI (includes all encoders)
cargo install ctt-cli
# Or add the library to your project
cargo add cttBy default the library enables all encoders. To select specific encoders:
cargo add ctt --no-default-features --features encoder-bc7enc,encoder-intel,ispc-prebuiltThe library API mirrors the CLI. Build a Surface, wrap it in an Image, and call convert:
use ctt::{convert, ConvertSettings, Container, TargetFormat, Format};
use ctt::{Image, Surface, ColorSpace, AlphaMode};
let surface = Surface {
data: pixel_bytes,
width: 512,
height: 512,
stride: 512 * 4,
format: Format::R8G8B8A8_UNORM,
color_space: ColorSpace::Srgb,
alpha: AlphaMode::Straight,
};
let image = Image { surfaces: vec![vec![surface]], is_cubemap: false };
let ktx2_bytes = convert(image, ConvertSettings {
format: Some(TargetFormat::Compressed {
encoder_name: None,
format: Format::BC7_UNORM_BLOCK,
}),
container: Container::ktx2(),
..Default::default()
})?;See the API documentation for the full ConvertSettings options and the lower-level pipeline API.
ctt <INPUT>... --output <PATH> [--format <FORMAT>] [OPTIONS]
When --format is omitted the input format is preserved without compression.
Compress to BC7 (auto-selects bc7enc-rdo when available):
ctt diffuse.png -o diffuse.ktx2 -f bc7Force the Intel ISPC encoder for BC7:
ctt diffuse.png -o diffuse.ktx2 -f intel_bc7Normal map to BC5 as DDS:
ctt normal.png -o normal.dds -f bc5 --input-color-space linearHigh quality:
ctt diffuse.png -o diffuse.ktx2 -f bc7 --quality slowCubemap from a cross layout:
ctt skybox_cross.png -o skybox.ktx2 -f bc6h --cubemap --cubemap-layout crossCubemap from six separate faces:
ctt px.png nx.png py.png ny.png pz.png nz.png -o skybox.ktx2 -f bc7 --cubemapGenerate mipmaps:
ctt diffuse.png -o diffuse.ktx2 -f bc7 --mipmapWith zstd supercompression:
ctt diffuse.png -o diffuse.ktx2 -f bc7 --zstdSwizzle channels:
ctt input.png -o output.ktx2 -f bc7 --swizzle bgraRun ctt --help for a full list of options.
The MSRV is 1.85 (edition 2024). MSRV bumps are considered breaking changes.
By default, ctt ships prebuilt ISPC static libraries for all supported platforms. A default build requires only a Rust toolchain and a C++ compiler.
Every prebuilt binary has a GitHub Artifact Attestation that cryptographically proves it was produced by this repository's CI. See docs/prebuilt-binaries.md for full details on the build process, attestation guarantees, and how to verify them.
To build from source instead (requires ispc.exe on PATH):
cargo install ctt-cli --no-default-features --features ispc-build-from-sourceLicensed under any of:
- MIT License
- Apache License, Version 2.0
- Zlib License
at your option.