This content was automatically converted from the project's wiki Markdown to HTML. See the Basis Universal GitHub wiki for the latest content.
This documentation is based off Basis Universal v2.10.
struct basis_compressor_params
class basis_compressorThe compression library, located in the encoder subdirectory, defines the types and classes needed to compress .KTX2 or .basis files, given one or more LDR/SDR or HDR images. This document describes the key classes and types needed to directly call the C++ compressor, bypassing our higher level (but less capable) C compression API. The tradeoff: the C++ API has sharper edges, and is a bit more tricky to use correctly because of all the codecs and file formats we've added to the system over time while also preventing older code from breaking.
Originally, when Basis Universal was released, the compressor wasn't a library but a command line tool with some internal classes (which also happened to be directly callable by others). Over time the compressor has evolved into a separate C++ encoder library (with a C API), and the API has grown organically as we've added new codecs and capabilities, but we've kept backwards API compatibility with existing C++ code as much as possible.
The JavaScript emscripten wrapper functions, and the C API (which is used by WASM WASI modules and Python) are both layered on top of this C++ API.
Compression functionality lives in the basisu namespace,
and transcoder functionality lives in the basist namespace.
The transcoder module also has some low-level functionality in the
basisu namespace. The compression library depends on
functionality provided by the transcoder module.
Also see the C++ transcoder module API reference. The compression C API may also be a useful reference, as it's layered directly on top of this C++ API.
The transcoder module also includes numerous other useful features, such as a number of fast real-time analytical GPU texture block encoders.
For LDR content, XUASTC LDR (particularly with larger block sizes such as 8x8 or 12x12) generally produces the smallest files overall. ETC1S can still be competitive for simpler texture video content, but even then XUASTC LDR 12x12 can beat it — even without skip blocks or conditional replenishment.
The minimum HDR input value is 0, and the maximum HDR input value is
basist::ASTC_HDR_MAX_VAL (65216.0), which is slightly less
than MAX_HALF (65504.0). Both are ASTC HDR limitations, ignoring
void-extent block ASTC spec loopholes which we don't exploit.
Signed inputs will be clamped to 0, with a warning printed to stdout.
If an input HDR image has any RGB color components larger than
ASTC_HDR_MAX_VAL, each RGB texel in the input image will be
rescaled linearly, with a warning printed to stdout. The output .KTX2
file's ktx_map_range
key-value entry will contain the proper scale to apply in the pixel
shader (or while decoding) to recover the original linear range.
Currently, the code that enforces the HDR input limits is very simplistic, so it's recommended that all input image(s) or custom mipmap levels be in the ASTC HDR encodable [0, ASTC_HDR_MAX_VAL] range before compressing them. The HDR input clamp code applies the clamping to each input image individually, which works fine if there's only a single input image (the most common case), but not with texture array inputs or if custom HDR mipmap chains are supplied. (This will be improved in the next major release.)
The function basisu::enable_debug_printf(bool enabled),
defined in transcoder/basisu.h,
globally enables or disabled debug printing to stdout. You can then set
the m_debug member of the
basis_compressor_params compression parameter struct to
true (see below) to see verbose debug output.
Enabling debug output can be very useful for verifying that you've
properly initialized the compressor and each codec as expected. This
corresponds to the command line tool's -debug
parameter.
The function basisu::basisu_encoder_init() in encoder/basisu_enc.h
MUST be called before using any other functions or classes inside the
compression library or the transcoder module
(transcoder/basisu_transcoder.cpp). It must be allowed to
complete and return before calling anything else inside the library or
the transcoder module.
This function will also initialize the transcoder by calling
basist::basisu_transcoder_init();.
This function is globally mutexed (with std::mutex).
These macros, located in encoder/basisu_comp.h,
define the library's version:
#define BASISU_LIB_VERSION 210
#define BASISU_LIB_VERSION_STRING "2.10"
The following constants, referenced throughout the
basis_compressor_params documentation, define default
values, ranges, and limits used by the compressor. They are located in
various encoder headers.
| Constant | Value | Description |
|---|---|---|
BASISU_MAX_SUPPORTED_TEXTURE_DIMENSION |
16384 |
Maximum supported texture dimension in texels |
BASISU_MAX_IMAGE_DIMENSION |
16384 |
Maximum image dimension in texels |
BASISU_MAX_SLICES |
0xFFFFFF |
Maximum number of slices |
| Constant | Value | Description |
|---|---|---|
BASISU_QUALITY_MIN |
1 |
Minimum ETC1S quality level (note: 0 is also technically valid but nearly identical to 1) |
BASISU_QUALITY_MAX |
255 |
Maximum ETC1S quality level |
BASISU_DEFAULT_QUALITY |
128 |
Default ETC1S quality level |
BASISU_DEFAULT_ETC1S_COMPRESSION_LEVEL |
2 |
Default ETC1S compression effort level (library default is 2, command line default is 1) |
BASISU_MAX_ETC1S_COMPRESSION_LEVEL |
6 |
Maximum ETC1S compression effort level |
BASISU_MAX_ENDPOINT_CLUSTERS |
16128 |
Maximum endpoint codebook size
(basisu_frontend::cMaxEndpointClusters) |
BASISU_MAX_SELECTOR_CLUSTERS |
16128 |
Maximum selector codebook size
(basisu_frontend::cMaxSelectorClusters) |
BASISU_DEFAULT_ENDPOINT_RDO_THRESH |
1.5 |
Default endpoint RDO threshold (allows block color distance to increase by 1.5 while searching for an alternative nearby endpoint) |
BASISU_DEFAULT_SELECTOR_RDO_THRESH |
1.25 |
Default selector RDO threshold (allows block color distance to increase by 1.25 while searching the selector history buffer) |
BASISU_DEFAULT_HYBRID_SEL_CB_QUALITY_THRESH |
2.0 |
Default hybrid selector codebook quality threshold |
| Constant | Value | Description |
|---|---|---|
BASISU_XUASTC_QUALITY_MIN |
1 |
Minimum XUASTC LDR quality level (in basisu
namespace) |
BASISU_XUASTC_QUALITY_MAX |
100 |
Maximum XUASTC LDR quality level (in basisu
namespace) |
astc_ldr::EFFORT_LEVEL_DEF |
3 |
Default XUASTC LDR effort level (in basisu::astc_ldr
namespace) |
astc_ldr::EFFORT_LEVEL_MIN |
0 |
Minimum XUASTC LDR effort level (in basisu::astc_ldr
namespace) |
astc_ldr::EFFORT_LEVEL_MAX |
10 |
Maximum XUASTC LDR effort level (in basisu::astc_ldr
namespace) |
These constants are defined in encoder/basisu_uastc_enc.h,
in the basisu namespace.
| Constant | Value | Description |
|---|---|---|
BASISU_RDO_UASTC_DICT_SIZE_DEFAULT |
4096 |
Default RDO dictionary size |
BASISU_RDO_UASTC_DICT_SIZE_MIN |
64 |
Minimum RDO dictionary size |
BASISU_RDO_UASTC_DICT_SIZE_MAX |
65536 |
Maximum RDO dictionary size |
UASTC_RDO_DEFAULT_SMOOTH_BLOCK_MAX_ERROR_SCALE |
10.0 |
Default smooth block max error scale. The encoder boosts the error of smooth blocks to suppress distortion on smooth areas; larger values protect smooth blocks more. Set to 1.0 to disable. |
UASTC_RDO_DEFAULT_MAX_SMOOTH_BLOCK_STD_DEV |
18.0 |
Default smooth block max std deviation. The encoder computes a smoothness factor [0,1] per block by dividing the block's max component variance by this value (then clamping). Larger values protect more blocks. |
UASTC_RDO_DEFAULT_MAX_ALLOWED_RMS_INCREASE_RATIO |
10.0 |
Default max allowed RMS increase ratio. How much a block's RMS error may increase before a trial is rejected. |
UASTC_RDO_DEFAULT_SKIP_BLOCK_RMS_THRESH |
8.0 |
Default skip block RMS threshold. Blocks with this much RMS error or more are completely skipped by the RDO encoder. |
cPackUASTC*)These flags are defined in encoder/basisu_uastc_enc.h,
in the basisu namespace. They are passed via
m_pack_uastc_ldr_4x4_flags. The level values occupy the low
4 bits (cPackUASTCLevelMask = 0xF) and can be OR'd with the
optional flags.
| Constant | Value | Description |
|---|---|---|
cPackUASTCLevelFastest |
0 |
Lowest quality, ~1x speed. 5 modes. No BC1 hints. Avg. 43.45 dB |
cPackUASTCLevelFaster |
1 |
~3x slower than fastest. 9 modes. Avg. 46.49 dB |
cPackUASTCLevelDefault |
2 |
~5.5x slower than fastest. 14 modes. Avg. 47.47 dB |
cPackUASTCLevelSlower |
3 |
~14.5x slower than fastest. All 18 modes. Avg. 48.01 dB |
cPackUASTCLevelVerySlow |
4 |
~200x slower than fastest. Best quality. Avg. 48.24 dB |
cPackUASTCLevelMask |
0xF |
Mask for the level bits |
cPackUASTCFavorUASTCError |
8 |
Favor lowest UASTC error over BC7 |
cPackUASTCFavorBC7Error |
16 |
Favor lowest BC7 error over UASTC |
cPackUASTCETC1FasterHints |
64 |
Use faster ETC1 hint generation |
cPackUASTCETC1FastestHints |
128 |
Use fastest ETC1 hint generation |
cPackUASTCETC1DisableFlipAndIndividual |
256 |
Disable ETC1 flip and individual mode |
cPackUASTCFavorSimplerModes |
512 |
Favor UASTC modes 0 and 10 (experimental, useful for RDO) |
These constants are in the basisu::astc_ldr
namespace.
| Constant | Value | Description |
|---|---|---|
astc_ldr::DCT_QUALITY_MIN |
1 |
Minimum DCT quality level |
astc_ldr::DCT_QUALITY_MAX |
100 |
Maximum DCT quality level |
| Constant | Value | Description |
|---|---|---|
LDR_TO_HDR_NITS |
100.0 |
Default luminance in nits for LDR→HDR upconversion |
enum class hdr_modesControls the HDR sub-mode when m_hdr is
true. Used by m_hdr_mode. Located in encoder/basisu_comp.h.
| Value | Description |
|---|---|
cUASTC_HDR_4X4 |
Standard but constrained ASTC HDR 4x4 texture data that can be rapidly transcoded to BC6H |
cASTC_HDR_6X6 |
Standard RDO-optimized or non-RDO (highest quality) ASTC HDR 6x6 texture data that can be rapidly re-encoded to BC6H |
cUASTC_HDR_6X6_INTERMEDIATE |
A custom intermediate format based on ASTC HDR 6x6 that can be rapidly decoded straight to ASTC HDR 6x6 or re-encoded to BC6H |
enum basist::ktx2_supercompressionControls KTX2 supercompression via
m_ktx2_uastc_supercompression. Located in the transcoder
module.
| Value | Int | Description |
|---|---|---|
KTX2_SS_NONE |
0 |
No supercompression |
KTX2_SS_BASISLZ |
1 |
BasisLZ (ETC1S) supercompression |
KTX2_SS_ZSTANDARD |
2 |
Zstandard supercompression |
KTX2_SS_DEFLATE |
3 |
Deflate (currently unsupported) |
KTX2_SS_UASTC_HDR_6x6I |
4 |
UASTC HDR 6x6i (assigned by Khronos, in KTX-Software as of 2/19/2026) |
KTX2_SS_XUASTC_LDR |
5 |
XUASTC LDR 4x4–12x12 (coordinated with Khronos, not yet in KTX-Software as of 2/19/2026) |
enum class basist::astc_ldr_t::xuastc_ldr_syntaxControls the XUASTC LDR syntax mode via
m_xuastc_ldr_syntax. Trades decompression/transcoding speed
against compression ratio.
| Value | Int | Description |
|---|---|---|
cFullArith |
0 |
Full arithmetic coding (best ratio, slowest transcoding) |
cHybridArithZStd |
1 |
Hybrid arithmetic + Zstandard |
cFullZStd |
2 |
Full Zstandard (fastest transcoding, lower ratio) — default |
The compressor uses two small template wrappers —
bool_param<def> and param<T> —
instead of raw types for most member variables. These wrappers track
whether a value has been explicitly changed by the caller (via
was_changed()), which lets the compressor distinguish "the
user set this to X" from "this is still the default." Both types
implicitly convert to their underlying type, so they can be used like
plain bool / int / float values
in most contexts.
bool_param<def> wraps a bool with a
compile-time default. param<T> wraps a value of type
T and additionally stores a default, min, and max —
assignments are automatically clamped to [min, max]. Both are reset to
their defaults (and marked unchanged) by clear().
struct basis_compressor_paramsThis structure holds all the parameters the compressor and each codec
uses. It's located in encoder/basisu_comp.h.
This structure is directly manipulated by the command line tool (basisu_tool.cpp)
while parsing the command line. There's usually a 1:1 correspondence
between command line parameters and members of this structure. However,
note the command line tool's defaults for some codec parameter may
differ from the basis_compressor_params member
variables.
Importantly, the m_pJob_pool member variable
(defined in encoder/basisu_enc.h
MUST be set to a pointer to an initialized job_pool object,
like this:
// num_total_threads is the number of TOTAL threads in the pool, so 1=no extra threads, 2=1 extra thread etc.
job_pool compressor_jpool(num_total_threads);
comp_params.m_pJob_pool = &compressor_jpool;
The compressor will distribute parallel tasks to the supplied job
pool object. Most codecs will utilize threading if the job pool has more
than one thread, regardless of the m_multithreading flag.
The m_multithreading member variable (which defaults to
true) is currently only checked by the ETC1S codec. To
fully disable multithreading across all codecs, create the job pool with
1 thread and set m_multithreading to
false.
| Name | Description |
|---|---|
clear() |
Resets all members to construction-time state |
set_format_mode() |
Sets desired codec and block size |
set_format_mode_and_effort() |
Sets codec format + effort level |
set_format_mode_and_quality_effort() |
Sets codec format + quality + effort |
set_srgb_options() |
Sets sRGB-related options as a group |
is_etc1s() |
Returns true if format is ETC1S |
is_uastc_ldr_4x4() |
Returns true if format is UASTC LDR 4x4 |
is_uastc_hdr_4x4() |
Returns true if format is UASTC HDR 4x4 |
get_format_mode() |
Returns current basis_tex_format |
| Name | Type | Default | Description |
|---|---|---|---|
m_tex_type |
basist::basis_texture_type |
basist::cBASISTexType2D |
Texture type (2D, array, cubemap, video) |
m_quality_level |
int |
-1 |
Unified quality level for ETC1S / XUASTC LDR |
m_perceptual |
bool_param<true> |
true |
Perceptual sRGB colorspace metrics vs. linear |
m_uastc |
bool_param<false> |
false |
(legacy) true for any non-ETC1S format |
m_hdr |
bool_param<false> |
false |
(legacy) true for HDR modes |
m_hdr_mode |
hdr_modes |
cUASTC_HDR_4X4 |
(legacy) Selects HDR sub-mode |
m_xuastc_or_astc_ldr_basis_tex_format |
param<int> |
-1 |
(legacy) XUASTC/ASTC LDR format selector |
| Name | Type | Default | Description |
|---|---|---|---|
m_etc1s_max_endpoint_clusters |
uint32_t |
0 |
Endpoint codebook size |
m_etc1s_max_selector_clusters |
uint32_t |
0 |
Selector codebook size |
m_etc1s_compression_level |
param<int> |
2 |
Compression effort level (0–6) |
m_no_selector_rdo |
bool_param<false> |
false |
Disable selector RDO |
m_selector_rdo_thresh |
param<float> |
1.25 |
Selector RDO threshold |
m_no_endpoint_rdo |
bool_param<false> |
false |
Disable endpoint RDO |
m_endpoint_rdo_thresh |
param<float> |
1.5 |
Endpoint RDO threshold |
m_disable_hierarchical_endpoint_codebooks |
bool_param<false> |
false |
Disable 2-level endpoint codebook searching |
m_use_opencl |
bool_param<false> |
false |
Enables OpenCL in ETC1S mode |
m_pGlobal_codebooks |
const basist::basisu_lowlevel_etc1s_transcoder* |
nullptr |
Global codebook pointer |
| Name | Type | Default | Description |
|---|---|---|---|
m_pack_uastc_ldr_4x4_flags |
uint32_t |
2 |
Packing flags (see cPackUASTC*) |
m_rdo_uastc_ldr_4x4 |
bool_param<false> |
false |
Enable RDO post-process |
m_rdo_uastc_ldr_4x4_quality_scalar |
param<float> |
1.0 |
RDO quality/lambda scalar |
m_rdo_uastc_ldr_4x4_dict_size |
param<int> |
4096 |
RDO dictionary size |
m_rdo_uastc_ldr_4x4_max_smooth_block_error_scale |
param<float> |
10.0 |
Smooth block max error scale |
m_rdo_uastc_ldr_4x4_smooth_block_max_std_dev |
param<float> |
18.0 |
Smooth block max std dev |
m_rdo_uastc_ldr_4x4_max_allowed_rms_increase_ratio |
param<float> |
10.0 |
Max allowed RMS increase ratio |
m_rdo_uastc_ldr_4x4_skip_block_rms_thresh |
param<float> |
8.0 |
Skip block RMS threshold |
m_rdo_uastc_ldr_4x4_favor_simpler_modes_in_rdo_mode |
bool_param<true> |
true |
Favor simpler modes during RDO |
m_rdo_uastc_ldr_4x4_multithreading |
bool_param<true> |
true |
Enable multithreading for RDO |
| Name | Type | Default | Description |
|---|---|---|---|
m_uastc_hdr_4x4_options |
uastc_hdr_4x4_codec_options |
(initialized) | UASTC HDR 4x4 codec options |
m_astc_hdr_6x6_options |
astc_6x6_hdr::astc_hdr_6x6_global_config |
(cleared) | ASTC HDR 6x6 / UASTC HDR 6x6i options |
m_hdr_favor_astc |
bool_param<false> |
false |
Favor ASTC HDR quality over BC6H |
| Name | Type | Default | Description |
|---|---|---|---|
m_xuastc_ldr_effort_level |
param<int> |
3 |
Effort level (0–10) |
m_xuastc_ldr_use_dct |
bool_param<false> |
false |
Enable Weight Grid DCT |
m_xuastc_ldr_use_lossy_supercompression |
bool_param<false> |
false |
Allow bounded distortion for smaller files |
m_xuastc_ldr_force_disable_subsets |
bool_param<false> |
false |
Disable 2-3 subset usage |
m_xuastc_ldr_force_disable_rgb_dual_plane |
bool_param<false> |
false |
Disable RGB dual plane |
m_xuastc_ldr_syntax |
param<int> |
cFullZStd (2) |
Syntax mode (speed vs. ratio) |
m_xuastc_ldr_channel_weights[4] |
uint32_t[4] |
{1,1,1,1} |
Per-channel error weights |
m_xuastc_ldr_blurring |
bool_param<false> |
false |
Experimental blurring (very slow) |
m_ls_min_psnr |
param<float> |
35.0 |
Lossy supercompression min PSNR |
m_ls_min_alpha_psnr |
param<float> |
38.0 |
Lossy supercompression min alpha PSNR |
m_ls_thresh_psnr |
param<float> |
1.5 |
Lossy supercompression threshold PSNR |
m_ls_thresh_alpha_psnr |
param<float> |
0.75 |
Lossy supercompression threshold alpha PSNR |
m_ls_thresh_edge_psnr |
param<float> |
1.0 |
Lossy supercompression edge threshold PSNR |
m_ls_thresh_edge_alpha_psnr |
param<float> |
0.5 |
Lossy supercompression edge threshold alpha PSNR |
| Name | Type | Default | Description |
|---|---|---|---|
m_ldr_hdr_upconversion_srgb_to_linear |
bool_param<true> |
true |
Apply sRGB→linear during upconversion |
m_ldr_hdr_upconversion_nit_multiplier |
param<float> |
0.0 |
Luminance multiplier (0 = default 100 nits) |
m_ldr_hdr_upconversion_black_bias |
param<float> |
0.0 |
sRGB-space black bias |
| Name | Type | Default | Description |
|---|---|---|---|
m_read_source_images |
bool_param<false> |
false |
Read inputs from filenames vs. memory |
m_source_filenames |
basisu::vector<std::string> |
— | Input filenames |
m_source_alpha_filenames |
basisu::vector<std::string> |
— | Input alpha-channel filenames |
m_source_images |
basisu::vector<image> |
— | LDR source images in memory |
m_source_images_hdr |
basisu::vector<imagef> |
— | HDR source images in memory |
m_source_mipmap_images |
basisu::vector<basisu::vector<image>> |
— | Optional LDR mipmap chain |
m_source_mipmap_images_hdr |
basisu::vector<basisu::vector<imagef>> |
— | Optional HDR mipmap chain |
| Name | Type | Default | Description |
|---|---|---|---|
m_resample_width |
param<int> |
0 |
Target resample width in texels |
m_resample_height |
param<int> |
0 |
Target resample height in texels |
m_resample_factor |
param<float> |
0.0 |
Resample scaling factor |
| Name | Type | Default | Description |
|---|---|---|---|
m_mip_gen |
bool_param<false> |
false |
Enable automatic mipmap generation |
m_mip_scale |
param<float> |
1.0 |
Filter kernel scale (<1.0 sharpens, >1.0 blurs) |
m_mip_filter |
std::string |
"kaiser" |
Mipmap filter name |
m_mip_srgb |
bool_param<false> |
false |
Convert sRGB→linear before filtering, then back (use
set_srgb_options()) |
m_mip_premultiplied |
bool_param<true> |
true |
Premultiplied alpha mips (not currently supported) |
m_mip_renormalize |
bool_param<false> |
false |
Renormalize mip texels to unit length (for tangent space normal maps) |
m_mip_wrapping |
bool_param<true> |
true |
Assume wrap UV addressing; if false, clamp |
m_mip_fast |
bool_param<true> |
true |
Generate each mip from previous level (faster but less accurate) |
m_mip_smallest_dimension |
param<int> |
1 |
Smallest mip dimension in texels |
| Name | Type | Default | Description |
|---|---|---|---|
m_out_filename |
std::string |
— | Output filename |
m_write_output_basis_or_ktx2_files |
bool_param<false> |
false |
Write output file(s) to disk |
m_create_ktx2_file |
bool_param<false> |
false |
Also generate KTX2 output |
m_ktx2_uastc_supercompression |
basist::ktx2_supercompression |
KTX2_SS_NONE |
KTX2 supercompression type |
m_ktx2_key_values |
basist::ktx2_transcoder::key_value_vec |
— | Custom KTX2 key-value entries |
m_ktx2_zstd_supercompression_level |
param<int> |
6 |
Zstd supercompression level |
m_ktx2_and_basis_srgb_transfer_function |
bool_param<true> |
true |
sRGB vs. linear transfer function in output DFD |
| Name | Type | Default | Description |
|---|---|---|---|
m_status_output |
bool_param<true> |
true |
Print codec status to stdout |
m_debug |
bool_param<false> |
false |
Print low-level debug info to stdout |
m_debug_images |
bool_param<false> |
false |
Write debug images to disk |
m_validate_etc1s |
bool_param<false> |
false |
Low-level ETC1S data validation (slower) |
m_compute_stats |
bool_param<false> |
false |
Compute codec statistics |
m_print_stats |
bool_param<true> |
true |
Print codec statistics (if computed) |
m_validate_output_data |
bool_param<false> |
false |
Try transcoding output after compression |
m_transcode_flags |
param<uint32_t> |
0 |
Flags for validation transcoding |
| Name | Type | Default | Description |
|---|---|---|---|
m_multithreading |
bool_param<true> |
true |
Enable multithreaded encoding |
m_y_flip |
bool_param<false> |
false |
Flip source images on Y axis |
m_check_for_alpha |
bool_param<true> |
true |
Auto-detect alpha in source images |
m_force_alpha |
bool_param<false> |
false |
Force alpha channel on |
m_swizzle[4] |
uint8_t[4] |
{0,1,2,3} |
Input channel swizzle (0=R, 1=G, 2=B, 3=A) |
m_renormalize |
bool_param<false> |
false |
Renormalize normal-map texels |
m_userdata0 |
uint32_t |
0 |
User data written to .basis header |
m_userdata1 |
uint32_t |
0 |
User data written to .basis header |
m_us_per_frame |
uint32_t |
0 |
Frame timing written to .basis header |
m_pJob_pool |
job_pool* |
nullptr |
MUST be set to a valid job pool |
clear()Resets all member variables to their initial (construction time) state.
void set_format_mode(basist::basis_tex_format m)This method sets the desired codec and block size: ETC1S, UASTC LDR 4x4, XUASTC LDR 4x4-12x12, etc. It's the preferred way of setting the desired codec. The default is the library's original format, ETC1S.
basis_tex_format is documented here.
Use get_format_mode() to retrieve the format mode that was
set.
bool set_format_mode_and_effort(basist::basis_tex_format mode, int effort = -1, bool set_defaults = true)bool set_format_mode_and_quality_effort(basist::basis_tex_format mode, int quality = -1, int effort = -1, bool set_defaults = true)These methods call set_format_mode() to set the desired
codec format, then optionally set the unified effort [0,10] or quality
[1,100] level parameters specific to that codec. They return
true on success. (Note the quality level can also be set to
0 via this API, which is essentially the same as 1, but it's recommended
to only use quality levels [1,100].)
A value of -1 for quality or effort results
in not changing the specified parameter, unless
set_defaults is true. If effort
and/or quality are -1 and set_defaults is
true, the default (construction-time) effort and/or quality
level parameters set.
Note the interpretation of the default setting for quality is codec
dependent. For example, for ETC1S it causes the
m_quality_level member variable to be set to -1, which
causes the codec to use manually specified codebook sizes. For other
formats it results in no DCT, or no RDO, etc.
These methods are the recommended way to set the codec quality and effort levels, however there are lower level methods available to directly set various codec specific configuration parameters, such as "lambda", directly. This can be particularly useful in HDR, because it's tricky for us to compute a RDO lambda setting useable across a wide range of HDR content.
void set_srgb_options(bool srgb_flag)This method sets three key member variables related to sRGB vs. linear sampling as a group:
m_perceptual = srgb_flag;
m_mip_srgb = srgb_flag;
m_ktx2_and_basis_srgb_transfer_function = srgb_flag;
Note: m_ktx2_and_basis_srgb_transfer_function used to be
named m_ktx2_srgb_transfer_func in previous (pre-v2.0)
library versions. We changed the default setting to true to
match m_perceptual, so we renamed the member variable.
This is the recommended way to tell the compressor that the input is sRGB (photographic) or linear content.
m_perceptualm_perceptual is interpreted in a codec specific manner.
It should be set to true if the input is photographic or
sRGB content (like a typical image or albedo map), or false
if the input is not photographic (linear light, such as a normal map)
content. This setting defaults to true.
m_perceptual is used to control sRGB vs. linear
resampling when the m_resample_factor is not 0.
ETC1S will use a simple perceptual colorspace error metric if
m_perceptual is true. For ETC1S, which setting
is best to use may need some experimentation for content which isn't a
typical photo or albedo map.
Some codecs, such as UASTC LDR 4x4, ASTC LDR 4x4-12, and XUASTC LDR 4x4-12x12, always internally use plain linear SSE/MSE/PSNR metrics, ignoring this setting.
For UASTC HDR 4x4: If m_perceptual is true
the RGB channel weights are set to (2,3,1), otherwise they are set to
(1,1,1). If m_perceptual is true, it is
possible to customize the channel weights directly by setting
m_uastc_hdr_4x4_options.m_r_err_scale and
m_uastc_hdr_4x4_options.m_g_err_scale member variables to
the desired RG weights (B is always 1.0).
m_ktx2_and_basis_srgb_transfer_functionm_ktx2_and_basis_srgb_transfer_function controls the
transfer function value written into the DFD of the generated .KTX2
file. It defaults to true. It most likely should match
m_perceptual.
In HDR mode this member variable is ignored and the LINEAR transfer
function is always written to the KTX2's DFD. A warning message will be
printed if m_ktx2_and_basis_srgb_transfer_function is
true in HDR mode.
The ASTC LDR 4x4-12x12 and XUASTC LDR 4x4-12x12 codecs use
m_ktx2_and_basis_srgb_transfer_function to control how
candidate ASTC blocks are decoded (linear vs. sRGB) during compression.
For maximum quality, it's important to match this setting
against how the ASTC texture will be decoded by the GPU. The
transcoder also uses this value — either from the KTX2 DFD or from the
XUASTC per-mipmap header (which this setting controls) — to ensure
consistent decode behavior at transcode time.
m_mip_srgbm_mip_srgb controls whether the automatic mipmap
generator converts the input from sRGB to linear space before filtering
(and then back to sRGB). Note this parameter defaults to
false unless set by the developer. This default
exists for backwards API compatibility with older code that uses the C++
API directly — changing it to true would alter the output
of existing programs that don't explicitly set it. It's recommended
m_mip_srgb match m_perceptual (which is why
set_srgb_options() exists). The command line tool does this
automatically unless -mip_linear or -mip_srgb
were specified.
bool is_etc1s() const,
bool is_uastc_ldr_4x4() const,
bool is_uastc_hdr_4x4() constSimple helper methods that determine which codec mode is active by
querying the legacy member variables. is_etc1s() checks
m_uastc only. is_uastc_ldr_4x4() checks
m_uastc, m_hdr, and
m_xuastc_or_astc_ldr_basis_tex_format.
is_uastc_hdr_4x4() checks m_uastc,
m_hdr, and m_hdr_mode. These exist because the
legacy member variable combinations are easy to get wrong.
basist::basis_tex_format get_format_mode() constReturns the current format mode as a
basist::basis_tex_format, as set by
set_format_mode(). Because of backwards API compatibility
the compressor doesn't use this value directly yet; it's here to aid the
transition to the new API.
basist::basis_texture_type m_tex_typeSets the texture type: 2D, 2D texture array, cubemap array, or texture video frames. See the documentation of this enum here.
This setting impacts the number of source images expected by the compressor. For example, cubemaps require a multiple of 6 images (one for each face), etc.
int m_quality_levelThis member variable was previously named
m_etc1s_quality_level. It was renamed because it's no
longer ETC1S specific.
The m_quality_level member variable allows the developer
to directly set the ETC1S or XUASTC LDR quality levels. It defaults to
-1. It's recommended to use the method
set_format_mode_and_quality_effort() (see above) to set the
codec quality level, instead of directly manipulating this member
variable.
ETC1S: this parameter ranges from [1,255] or
[BASISU_QUALITY_MIN, BASISU_QUALITY_MAX].
(Note 0 is also a valid ETC1S quality level setting, but for all
practical purposes it's the same as 1.) If m_quality_level
is -1, manually set codebook sizes (controlled by the
m_etc1s_max_endpoint_clusters and
m_etc1s_max_selector_clusters member variables, which both
default to 0 after construction) will be used instead.
XUASTC LDR: this parameter, which controls the
Weight Grid DCT's quantization table, ranges from [1,100] or
[BASISU_XUASTC_QUALITY_MIN,
BASISU_XUASTC_QUALITY_MAX]. (Note 0 is also a valid
setting, but it'll be the same quality as 1.) If
m_quality_level is -1, Weight Grid DCT will be disabled,
otherwise it'll be enabled if m_xuastc_ldr_use_dct is also
enabled. This parameter is a libjpeg-style DCT quality setting, where
values 90 or above are very high quality, values 75 or higher are
average quality, and lower values are progressively worse quality.
Values below ~30 (depending on the content and XUASTC LDR block size)
may be unusable without some sort of deblocking.
bool_param<true> m_perceptualUse perceptual sRGB colorspace metrics instead of linear. Defaults to
true. See set_srgb_options()
above for details on how this interacts with other sRGB-related
settings.
m_uastc,
m_hdr, m_hdr_mode, and
m_xuastc_or_astc_ldr_basis_tex_format (legacy)These legacy member variables control which codec the format uses.
It's highly recommended to call set_format_mode() (or
set_format_mode_and_quality_effort(), etc.) instead of
directly manipulating these member variables, which takes care of
setting them correctly for you.
They exist for backwards API compatibility with older code, which manipulates them directly.
By default the library generates LDR ETC1S data. The rules are:
m_uastc is false you get ETC1S (the
default).m_uastc is true, and m_hdr
is not true, and
m_xuastc_or_astc_ldr_basis_tex_format == -1, we generate
UASTC LDR 4x4 data (8bpp with or without RDO).m_uastc is true, and m_hdr
is not true, and
m_xuastc_or_astc_ldr_basis_tex_format != -1, we generate
XUASTC 4x4-12x12 or ASTC 4x4-12x12 LDR data, controlled by
m_xuastc_or_astc_ldr_basis_tex_format.m_uastc is true and m_hdr
is true, we generate 4x4 or 6x6 HDR data, controlled by
m_hdr_mode.uint32_t m_etc1s_max_endpoint_clusters
and uint32_t m_etc1s_max_selector_clustersETC1S: These settings directly control the codebook sizes. They are
only used when m_quality_level is set to -1. The larger the
codebook sizes, the higher the overall quality, but the higher the
bitrate. Larger codebooks also take longer to unpack before
transcoding.
param<int> m_etc1s_compression_levelETC1S compression effort level, ranging from 0 to
BASISU_MAX_ETC1S_COMPRESSION_LEVEL (higher is slower). This
parameter controls numerous internal encoding speed vs. compression
efficiency/performance tradeoffs. Defaults to
BASISU_DEFAULT_ETC1S_COMPRESSION_LEVEL (note: the library
default is 2, which differs from the command line tool's default of
1).
This is not the same as the ETC1S quality level
(m_quality_level), and most users shouldn't need to change
this. It's recommended to use set_format_mode_and_effort()
or set_format_mode_and_quality_effort() to set the effort
level in a unified way across all codecs, rather than setting this
member variable directly.
bool_param<false> m_no_selector_rdo
and param<float> m_selector_rdo_threshControls selector Rate-Distortion Optimization. If
m_no_selector_rdo is true, selector RDO is
disabled, resulting in faster compression but larger files.
m_selector_rdo_thresh sets the RDO threshold (defaults to
BASISU_DEFAULT_SELECTOR_RDO_THRESH).
bool_param<false> m_no_endpoint_rdo
and param<float> m_endpoint_rdo_threshControls endpoint Rate-Distortion Optimization. If
m_no_endpoint_rdo is true, endpoint RDO is
disabled. m_endpoint_rdo_thresh sets the RDO threshold
(defaults to BASISU_DEFAULT_ENDPOINT_RDO_THRESH).
bool_param<false> m_disable_hierarchical_endpoint_codebooksIf true the front end will not use 2-level endpoint
codebook searching, for slightly higher quality but much slower
execution. Note some m_etc1s_compression_level settings
disable this automatically.
bool_param<false> m_use_openclEnables OpenCL usage in ETC1S mode. The compressor will fall back to CPU encoding if something goes wrong.
OpenCL usage is only available if the
BASISU_SUPPORT_OPENCL macro was set to 1 at compile time,
and if a OpenCL v1.2 driver is available.
const basist::basisu_lowlevel_etc1s_transcoder *m_pGlobal_codebooksPointer to an ETC1S global codebook object. Defaults to
nullptr.
uint32_t m_pack_uastc_ldr_4x4_flagsUASTC LDR 4x4 packing/quality flags. Defaults to
cPackUASTCLevelDefault (2). See UASTC LDR 4x4
Packing Level Flags (cPackUASTC*) for all available
values.
The lowest nibble (masked by cPackUASTCLevelMask,
0xF) selects the effort/quality level
(cPackUASTCLevelFastest through
cPackUASTCLevelVerySlow). The remaining bits are optional
flags that can be logically OR'd together with the level, for example:
cPackUASTCLevelSlower | cPackUASTCFavorBC7Error.
It's recommended to use set_format_mode_and_effort() or
set_format_mode_and_quality_effort() to set the effort
level rather than manipulating this member variable directly. If you
need to set additional flags beyond the effort level, you can OR them in
afterward.
bool_param<false> m_rdo_uastc_ldr_4x4Enables UASTC LDR 4x4 Rate-Distortion Optimization post-processing.
Defaults to false. This variable and
m_rdo_uastc_ldr_4x4_quality_scalar will be set
automatically if you use set_format_mode_and_effort() or
set_format_mode_and_quality_effort().
param<float> m_rdo_uastc_ldr_4x4_quality_scalarRDO quality/lambda scalar for UASTC LDR 4x4. Defaults to
1.0. The higher this value, the lower the quality, but the
more compressible the output data will be. It's recommended to use
set_format_mode_and_quality_effort() to set this rather
than manipulating it directly.
param<int> m_rdo_uastc_ldr_4x4_dict_sizeRDO dictionary size. Defaults to
BASISU_RDO_UASTC_DICT_SIZE_DEFAULT, range
[BASISU_RDO_UASTC_DICT_SIZE_MIN,
BASISU_RDO_UASTC_DICT_SIZE_MAX].
m_rdo_uastc_ldr_4x4_max_smooth_block_error_scale,
m_rdo_uastc_ldr_4x4_smooth_block_max_std_dev,
m_rdo_uastc_ldr_4x4_max_allowed_rms_increase_ratio,
m_rdo_uastc_ldr_4x4_skip_block_rms_threshAdvanced UASTC LDR 4x4 RDO tuning parameters
(param<float>). They control how aggressively RDO
optimizes smooth blocks and how much quality degradation is allowed.
They default to their respective UASTC_RDO_DEFAULT_*
constants.
Smooth areas of a texture are less resilient to distortion than
detailed/noisy areas because of the texture masking effect — the human
visual system readily perceives artifacts in smooth gradients but tends
to mask them in complex regions. The smooth block parameters
(m_rdo_uastc_ldr_4x4_max_smooth_block_error_scale and
m_rdo_uastc_ldr_4x4_smooth_block_max_std_dev) exist to
protect these perceptually sensitive areas from excessive RDO
degradation.
bool_param<true> m_rdo_uastc_ldr_4x4_favor_simpler_modes_in_rdo_modeIf true (the default), the RDO post-processor favors
simpler UASTC modes.
bool_param<true> m_rdo_uastc_ldr_4x4_multithreadingEnables multithreading for the UASTC LDR 4x4 RDO post-processor.
Defaults to true.
uastc_hdr_4x4_codec_options m_uastc_hdr_4x4_optionsUASTC HDR 4x4 codec options structure. Initialized via its
init() method on clear().
If m_perceptual is true, you can customize
the channel weights directly by setting
m_uastc_hdr_4x4_options.m_r_err_scale and
m_uastc_hdr_4x4_options.m_g_err_scale to the desired RG
weights (B is always 1.0).
struct uastc_hdr_4x4_codec_optionsIt's recommended to use set_format_mode_and_effort() or
set_format_mode_and_quality_effort() to configure the UASTC
HDR 4x4 codec. However, if you need lower-level control, you can
manipulate this struct directly.
struct uastc_hdr_4x4_codec_options : astc_hdr_codec_base_options
{
uastc_hdr_4x4_codec_options();
void init();
static const int cMinLevel = 0;
static const int cMaxLevel = 4;
static const int cDefaultLevel = 1;
void set_quality_level(int level); // sets internal codec parameters for the given level [0,4]
};set_quality_level() configures the codec's internal
parameters for a given quality level from cMinLevel
(0) to cMaxLevel (4). Higher
levels produce better quality but are slower. The default level is
cDefaultLevel (1).
Note that calling set_format_mode_and_quality_effort()
will set this quality level for you via the unified effort mapping. If
you call set_quality_level() directly afterward, it will
override the unified effort level that was set previously.
astc_6x6_hdr::astc_hdr_6x6_global_config m_astc_hdr_6x6_optionsASTC HDR 6x6 and UASTC HDR 6x6i codec options structure. Cleared via
its clear() method.
It's recommended to use set_format_mode_and_effort() or
set_format_mode_and_quality_effort() to configure this
codec. However, directly setting m_lambda may be necessary
for advanced use, because it's quite difficult to map an integer [1,100]
quality level to a usable RDO lambda across the wide range of HDR
content this codec handles.
Important:
m_astc_hdr_6x6_options.m_rec2020_bt2100_color_gamut is also
used to set the KTX2 DFD's color primaries field for
all codecs, not just ASTC HDR 6x6 / UASTC HDR 6x6i. Set
this to true if your input uses the REC 2020/BT.2100 gamut.
By default (false), REC 709 is assumed. This is a known
misplacement — in a future release, this option will be moved into the
main basis_compressor_params structure.
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.
struct astc_hdr_6x6_global_configThe "user comp level" is the codec's effort level, ranging from 0 to
ASTC_HDR_6X6_MAX_USER_COMP_LEVEL (12). The
default is ASTC_HDR_6X6_DEF_USER_COMP_LEVEL
(2). This is translated internally into
m_master_comp_level and
m_highest_comp_level.
// Constants
const uint32_t ASTC_HDR_6X6_DEF_USER_COMP_LEVEL = 2;
const uint32_t ASTC_HDR_6X6_MAX_USER_COMP_LEVEL = 12;
struct astc_hdr_6x6_global_config
{
// --- Input colorspace ---
// If true, input is treated as REC 2020/BT.2100 gamut (wider than REC 709).
// By default (false), input is assumed to be REC 709 linear light in absolute nits.
bool m_rec2020_bt2100_color_gamut = false;
// --- Compression levels ---
// These are set automatically by set_user_level(). Levels 0-3 are normal, 4 is exhaustive.
uint32_t m_master_comp_level = 0;
uint32_t m_highest_comp_level = 1;
// --- RDO lambda ---
// Controls rate-distortion optimization. 0.0 = no RDO.
// Directly setting this may be necessary for advanced use cases.
float m_lambda = 0.0f;
// --- Encoding options ---
bool m_extra_patterns_flag = false; // works in comp levels [1,4]
bool m_brute_force_partition_matching = false;
bool m_force_one_strip = false;
bool m_disable_delta_endpoint_usage = false; // may give slight increase in RDO efficiency, also faster
// --- JND (Just Noticeable Difference) optimization ---
// Defaults to false for HDR inputs. For SDR upconverted images, can default to enabled.
bool m_jnd_optimization = false;
float m_jnd_delta_itp_thresh = 0.75f;
// --- Gaussian fallback filters ---
bool m_gaussian1_fallback = true; // if disabled, m_gaussian2_fallback should be disabled too
float m_gaussian1_strength = 1.45f;
bool m_gaussian2_fallback = true;
float m_gaussian2_strength = 1.83f;
// --- Dark pixel adjustment ---
// Scale up Delta ITP errors for very dark pixels, assuming they may be brightly exposed.
bool m_delta_itp_dark_adjustment = true;
// --- Compatibility ---
// Write v1.6 compatible UASTC HDR 6x6i files for KTX-Software compatibility.
// The transcoder supports both variants.
bool m_write_basisu_1_6_compatible_files = true;
void clear();
// Max level is ASTC_HDR_6X6_MAX_USER_COMP_LEVEL (12).
void set_user_level(int level);
};Key members:
m_lambda controls the RDO strength. A value of
0.0 disables RDO entirely. Higher values produce smaller
files at the cost of quality. Because Delta ITP colorspace error metrics
are used internally, finding a good lambda value depends heavily on the
input content's luminance range, which is why the unified quality
mapping can be difficult to apply universally to HDR content.
m_rec2020_bt2100_color_gamut controls the assumed input
color gamut for the ASTC HDR 6x6 encoder's Delta E ITP error metric. By
default (false), the encoder assumes REC 709 linear light
RGB in absolute luminance (nits). If true, the wider REC
2020/BT.2100 gamut is assumed. For SDR/LDR→HDR upconverted content, the
sRGB input should be converted to linear light and scaled by 80–100 nits
(typical SDR monitor luminance). Upconversion to normalized [0,1]
luminances (i.e. non-absolute) is not supported because ITP errors will
not be predicted correctly.
m_jnd_optimization enables Just Noticeable Difference
optimization, which allows the encoder to use cheaper encodings when the
resulting error is modeled to be invisible or nearly invisible
(m_jnd_delta_itp_thresh controls the threshold). This
defaults to false. In practice, JND mode works well for
upconverted SDR/LDR content but can be fragile with native HDR
content.
set_user_level() configures the internal compression
levels for a given user effort level [0, 12]. Calling
set_format_mode_and_effort() or
set_format_mode_and_quality_effort() will call this for you
via the unified effort mapping.
bool_param<false> m_hdr_favor_astcIf true, ASTC HDR quality is favored more than BC6H
quality by the UASTC HDR 4x4 dual-target encoder. Otherwise it's a rough
balance. Defaults to false.
param<int> m_xuastc_ldr_effort_levelXUASTC LDR effort level. Defaults to
astc_ldr::EFFORT_LEVEL_DEF, range
[astc_ldr::EFFORT_LEVEL_MIN,
astc_ldr::EFFORT_LEVEL_MAX]. It's recommended to use
set_format_mode_and_quality_effort() to set this rather
than manipulating it directly.
bool_param<false> m_xuastc_ldr_use_dctEnables Weight Grid DCT for XUASTC LDR. The DCT quality is controlled
by m_quality_level [1,100]. Defaults to
false.
bool_param<false> m_xuastc_ldr_use_lossy_supercompressionAllows the compressor to introduce a bounded amount of distortion if
doing so would produce smaller ASTC or XUASTC files. Defaults to
false.
bool_param<false> m_xuastc_ldr_force_disable_subsetsDisables 2-3 subset usage in all effort levels. Results in faster
encoding, faster transcoding to BC7, but lower quality. Defaults to
false.
bool_param<false> m_xuastc_ldr_force_disable_rgb_dual_planeDisables RGB dual plane usage (dual plane on alpha blocks is still
allowed). Results in faster transcoding to BC7 but lower quality.
Defaults to false.
param<int> m_xuastc_ldr_syntaxControls the XUASTC LDR syntax mode, which trades decompression speed
against compression ratio. Defaults to
basist::astc_ldr_t::xuastc_ldr_syntax::cFullZStd (fastest
transcoding but lower ratio).
uint32_t m_xuastc_ldr_channel_weights[4]Per-channel error weights for XUASTC LDR. Defaults to
{1,1,1,1}.
bool_param<false> m_xuastc_ldr_blurringExperimental blurring option. Not recommended, very slow. Defaults to
false.
These param<float> variables control the XUASTC
lossy supercompression (also known as windowed or bounded RDO) quality
thresholds:
param<float> m_ls_min_psnr; // default 35.0
param<float> m_ls_min_alpha_psnr; // default 38.0
param<float> m_ls_thresh_psnr; // default 1.5
param<float> m_ls_thresh_alpha_psnr; // default 0.75
param<float> m_ls_thresh_edge_psnr; // default 1.0
param<float> m_ls_thresh_edge_alpha_psnr; // default 0.5
These parameters control how LDR/SDR input images are converted to HDR when compressing to an HDR output format.
Important: LDR/SDR→HDR upconversion is currently
only supported when reading source images from files
(m_read_source_images = true). It is not applied when
providing images directly in memory via m_source_images. If
you need to provide LDR images in memory and compress to an HDR format,
you must perform the upconversion yourself and place the results in
m_source_images_hdr.
bool_param<true> m_ldr_hdr_upconversion_srgb_to_linearIf true (the default), LDR images (such as PNG) will be
converted from sRGB to linear light via the sRGB→linear transfer
function. If false, LDR images are assumed to already be in
linear light (i.e. they don't use the sRGB transfer function). After
this step, m_ldr_hdr_upconversion_nit_multiplier and
m_ldr_hdr_upconversion_black_bias are applied, and the
result is then processed as HDR.
param<float> m_ldr_hdr_upconversion_nit_multiplierLuminance multiplier used when loading SDR/LDR images and compressing
to an HDR output format. Defaults to 0.0, which means use
the default of 100.0 nits (LDR_TO_HDR_NITS).
This value is an override for the default.
UASTC HDR 4x4: The default multiplier of 1.0 was
previously used in this codec's original release. Note this encoder
isn't dependent on absolute nits, unlike the ASTC HDR 6x6 encoder.
ASTC HDR 6x6 / UASTC HDR 6x6i: These encoders expect inputs in absolute nits, so the LDR upconversion luminance multiplier default is 100 nits. (Most SDR monitors are/were 80–100 nits.)
param<float> m_ldr_hdr_upconversion_black_biasOptional sRGB-space bias applied during LDR→HDR upconversion. Should
be between [0, ~0.49]. Only applied to black (0.0) color components.
Defaults to 0.0 (no bias).
m_read_source_images
(bool_param<false>, default: false)If true, input image files (in any of the supported
image file or .DDS format) will be read using filenames in the
m_source_filenames and
m_source_alpha_filenames arrays.
For .DDS source files: the library uses a forked version of TinyDDS (with some fixes)
to read .DDS images. Plain 2D textures are supported, with or without
mipmaps, but cubemaps and texture arrays are not currently supported.
The supported .DDS pixel formats are: R8G8B8A8_UNORM,
R8G8B8A8_SRGB, B8G8R8A8_UNORM,
B8G8R8A8_SRGB (LDR), R16G16B16A16_SFLOAT (half
float HDR), and R32G32B32A32_SFLOAT (float HDR). DDS
loading has been tested against the format AMD Compressonator
supports. Using mipmapped .DDS files allows the developer to control
exactly what each mipmap level contains, bypassing the automatic mipmap
generator. Note: if any input filename is .DDS, all input filenames must
be .DDS, and either all must be LDR .DDS or all must be HDR .DDS.
For .EXR source files: the TinyEXR library is used to read .EXR images. This small library does not support all .EXR compression methods. For unsupported images, you can use a tool like ImageMagick to convert them to uncompressed .EXR.
Otherwise, the inputs are assumed to be directly in the
m_source_images, m_source_images_hdr,
m_source_mipmap_images, and
m_source_mipmap_images_hdr arrays.
basisu::vector<std::string> m_source_filenames
and
basisu::vector<std::string> m_source_alpha_filenamesThe input filenames to process. m_read_source_images
must be true to read images from files.
basisu::vector<image> m_source_images
and basisu::vector<imagef> m_source_images_hdrThe source images to process. Note the compressor only accepts all-LDR or all-HDR input images (i.e. you can't mix LDR and HDR inputs).
Source images do not need to be a multiple of the codec's block size. Before compression, the compressor will automatically enlarge each image to block boundaries by duplicating edge pixels (rows and/or columns), which avoids introducing extra colors into border blocks.
basisu::vector< basisu::vector<image> > m_source_mipmap_images
and
basisu::vector< basisu::vector<imagef> > m_source_mipmap_images_hdrThe optional source mipmaps to process. These member variables allow the developer to bypass the automatic mipmap generator.
Stores mipmaps starting from level 1 (level 0 is still in
m_source_images). If m_source_mipmap_images
(or m_source_mipmap_images_hdr for HDR inputs) isn't empty,
automatic mipmap generation is skipped. Its size must
equal m_source_images.size() (or
m_source_images_hdr.size()) or the compressor returns an
error. The compressor applies the user-provided swizzling (in
m_swizzle) to these images.
The number of source images the compressor expects depends on
m_tex_type:
cBASISTexType2D: N images = N slices (typically N=1 for
a single texture). cBASISTexType2DArray: N images = N array
layers. cBASISTexTypeCubemapArray: N must be a multiple of
6 (6 faces per cubemap). For cubemap arrays, faces are grouped in sets
of 6: [cube0 faces 0..5][cube1 faces 0..5].... The expected
face order is +X, -X, +Y, -Y, +Z, -Z. KTX2 cubemap faces
must be square. cBASISTexTypeVideoFrames: N images = N
video frames.
Dimension constraints differ between .basis and .KTX2:
For .basis files in 2D mode (cBASISTexType2D), the
format supports non-uniform collections of texture slices — each input
image can have a different resolution. In array mode
(cBASISTexType2DArray) and texture video mode
(cBASISTexTypeVideoFrames), each slice must be the same
resolution.
For .KTX2 files, the KTX2 standard is more constrained: all base (mip 0) images must have the same dimensions, and each slice must have the same number of mipmap levels.
For .basis files in array, texture video, cubemap, and cubemap array modes, each slice must also have the same resolution and the same number of mipmap levels. In plain 2D mode, .basis is more flexible — each slice can have a different resolution and a different number of mipmap levels.
These constraints are validated before compression.
All source images must be the same type (all LDR or all HDR — you cannot mix them).
When providing custom mipmaps via m_source_mipmap_images
(or m_source_mipmap_images_hdr):
| What you provide | Where it goes |
|---|---|
| Mip level 0 (base) | m_source_images[i] or
m_source_images_hdr[i] |
| Mip levels 1..N | m_source_mipmap_images[i][0..N-1] or
m_source_mipmap_images_hdr[i][0..N-1] |
The outer vector size must equal the number of source images
(slices/faces/frames). Each slice must provide a contiguous mipmap chain
starting from level 1 — you cannot skip levels in the middle. However,
the chain can stop at any dimension you want (i.e. you don't have to go
all the way down to 1x1). If custom mipmaps are present, automatic
mipmap generation (m_mip_gen) is skipped entirely. The same
dimension and mipmap count constraints described in Source Image Count Rules above
apply.
The expected dimensions for each mipmap level follow the standard GPU convention (OpenGL, WebGL, D3D, Vulkan, Metal):
mip_width = max(1, base_width >> mip_index)
mip_height = max(1, base_height >> mip_index)
Where mip_index is 0 for the base level (in
m_source_images), 1 for the first mip (in
m_source_mipmap_images[i][0]), and so on.
See the UASTC HDR 6x6i Texture Array with Custom Mipmaps example for a working demonstration.
m_resample_width,
m_resample_height, and m_resample_factorThese settings control how the input images are resampled prior to compression. By default there is no resampling.
param<int> m_resample_width;
param<int> m_resample_height;
param<float> m_resample_factor;
If m_resample_width and m_resample_height
are both > 0, the input images will be resampled to the specified
dimensions in texels. If m_resample_factor is not 0.0, the
input images will be resampled by the specified scaling factor using a
box filter.
In both cases, for LDR/SDR inputs, the m_perceptual
member variable will control whether or not sRGB to linear conversion
will be applied before filtering, and linear to sRGB conversion after
filtering.
Mipmap generation is controlled by the m_mip_gen
bool_param<false> member variable.
The following parameters control the automatic mipmap generator:
// mipmap generation parameters
bool_param<false> m_mip_gen;
param<float> m_mip_scale; // scales the filter kernel: <1.0 sharpens, >1.0 blurs. Slightly sharpening (e.g. ~0.9) can be useful for textures.
std::string m_mip_filter;
bool_param<false> m_mip_srgb; // if true, LDR images are converted sRGB→linear before filtering, then back to sRGB. Recommended to use set_srgb_options() instead.
bool_param<true> m_mip_premultiplied; // not currently supported, but you can filter the mipmaps yourself and pass them in as .DDS or into member variables
bool_param<false> m_mip_renormalize; // if true, each mip texel is renormalized to approximately unit length (for tangent space normal maps)
bool_param<true> m_mip_wrapping; // if true, assumes wrap UV addressing; if false, assumes clamp
bool_param<true> m_mip_fast; // if true, generates each mip from the previous level (faster); if false, always from the top level (more accurate)
param<int> m_mip_smallest_dimension;
If m_mip_gen is true the automatic mipmap
generator is enabled, and the other "mip" related settings control its
behavior. It defaults to false.
m_mip_scale defaults to 1.0.
m_mip_filter defaults to "kaiser".
m_mip_smallest_dimension defaults to 1 texel.
Available m_mip_filter names: "box",
"tent", "bell", "b-spline",
"mitchell", "blackman",
"lanczos3", "lanczos4",
"lanczos6", "lanczos12",
"kaiser", "gaussian",
"catmullrom", "quadratic_interp",
"quadratic_approx", "quadratic_mix".
Note for HDR mode: the HDR resample filter applied is currently
always "box" (independent of the selected filter in
m_mip_filter). This is done to avoid introducing negative
pixel values, caused by negative filter kernel weights. We will be
improving this in a future release to use range compression filtering
(or log-domain filtering).
The automatic mipmap generator computes mipmap level sizes as follows:
w = base_width
h = base_height
total_levels = 1
while max(w, h) > m_mip_smallest_dimension:
w = max(w >> 1, 1) // integer (flooring) division by 2
h = max(h >> 1, 1) // integer (flooring) division by 2
total_levels++
Each dimension is halved per level (with a minimum of 1), and
generation stops once the largest dimension reaches
m_mip_smallest_dimension.
std::string m_out_filenameThe output filename. m_write_output_basis_or_ktx2_files
must be set to true to have the compressor write output
files to disk.
m_write_output_basis_or_ktx2_files
(bool_param<false>, default: false)The output filename is controlled by m_out_filename.
If true an output file will be written to disk.
bool_param<false> m_create_ktx2_fileIf true, the compressor will also generate a KTX2 file
in addition to the .basis file. Internally, the compressor always
creates a .basis file first, then converts it losslessly to KTX2.
Defaults to false.
basist::ktx2_supercompression m_ktx2_uastc_supercompressionSets the type of KTX2 supercompression to apply for those codecs which support it: UASTC LDR 4x4, UASTC HDR 4x4, ASTC HDR 6x6, and ASTC LDR 4x4-12x12.
Set to basist::KTX2_SS_ZSTANDARD or
basist::KTX2_SS_NONE (the default).
basist::ktx2_transcoder::key_value_vec m_ktx2_key_valuesThis member variable allows the developer to insert custom key-value entries into the output KTX2 file.
param<int> m_ktx2_zstd_supercompression_levelSets the KTX2 Zstd supercompression level. The default Zstd level is 6. (See the Zstd documentation for more information.)
bool_param<true> m_ktx2_and_basis_srgb_transfer_functionControls the transfer function value written into the DFD of the
generated .KTX2 file (and also used for .basis files). Defaults to
true (sRGB transfer function). Set to false
for linear transfer function.
For ASTC LDR and XUASTC LDR, this setting also controls which ASTC decode profile (sRGB vs. linear) is used when unpacking ASTC block data to texels during compression. For maximum quality, it's important to match this setting against how the ASTC texture will be decoded by the GPU.
See set_srgb_options()
for the recommended way to set this along with related parameters.
m_status_output
(bool_param<true>, default: true)If true, codec status output will be printed to
stdout.
m_debug
(bool_param<false>, default: false)If true, low-level codec debug information will be
printed to stdout. You must also call
basisu::enable_debug_printf(true) to enable debug output at
the library level. See Debug Output for
details.
m_debug_images
(bool_param<false>, default: false)If true, low-level codec specific debug images will be
written to disk, typically as .PNG or .EXR files. (This slows
compression.)
m_validate_etc1s
(bool_param<false>, default: false)Low-level ETC1S data validation during encoding. This is slower and primarily useful during development.
m_compute_stats
(bool_param<false>, default: false) and
m_print_stats (bool_param<true>,
default: true)These member variables control codec statistic computation and
display. m_print_stats only has an effect if
m_compute_stats is true. Enabling
m_compute_stats slows compression.
m_validate_output_data
(bool_param<false>, default: false)If true, the compressor will try transcoding the
generated output after compression to a few formats, to verify the
output is valid.
param<uint32_t> m_transcode_flags
(default: 0)The flags to use while transcoding if
m_validate_output_data is true.
m_multithreading
(bool_param<true>, default: true)If true, the ETC1S codec will use multiple threads. The
other codecs always distribute their work into the job pool as tasks
regardless of this flag — they will utilize threading if the job pool
has more than one thread. The job pool always has at least one thread
(the calling thread).
The recommended way to control threading is to initialize the job
pool to the desired number of threads and set
m_multithreading accordingly. To fully disable
multithreading, create the job pool with 1 thread (the calling thread
only) and set m_multithreading to false.
m_y_flip
(bool_param<false>, default: false)If true each source image will be flipped on the Y axis,
which is useful for API's such as WebGL/OpenGL.
m_check_for_alpha
(bool_param<true>, default: true) and
m_force_alpha (bool_param<false>,
default: false)These parameters control how the compressor decides if the input image(s) have alpha channels or not. For ETC1S, if the input is determined (or forced) to have alpha, the output will contain alpha slices.
If m_check_for_alpha is true, the alpha
channels of each source image are checked for any values < 255, and
if so the input is assumed to have alpha.
If m_force_alpha is true, it's assumed the
input always has alpha. It defaults to false.
uint8_t m_swizzle[4]This array remaps input channels before compression. Each element is
a source channel index (0=R, 1=G, 2=B, 3=A). The default
{0,1,2,3} is identity (no swizzle). For example, setting
{0,0,0,1} copies R to RGB and G to alpha, which is useful
for compressing two-channel data (such as a normal map's XY stored in
RG) into a basis/KTX2 file with alpha slices.
m_renormalize
(bool_param<false>, default: false)Treats the input LDR image as a tangent space normal map. If
true the input texels of all input images will be
renormalized to approximately unit length. See the
image::renormalize_normal_map() method for details on
exactly how this is done.
uint32_t m_userdata0,
uint32_t m_userdata1, and
uint32_t m_us_per_frameThese fields go directly into the .basis file header.
m_userdata0 and m_userdata1 default to
0. m_us_per_frame (microseconds per frame, for
texture video) defaults to 0.
job_pool *m_pJob_poolPointer to the job pool used for multithreaded work distribution.
MUST not be nullptr — see the initialization example at the
top of this section.
class basis_compressorThis class compresses one or more source images (specified via
filenames or directly as 32-bpp RGBA or float images in memory) to a
.basis or .KTX2 file. It's located in encoder/basisu_comp.h.
The compressor is thread safe — multiple
basis_compressor instances can run concurrently. However,
each compressor instance must be given its own individual (unique)
job_pool object.
Here are the primary methods used for compression:
bool init(const basis_compressor_params ¶ms)Initializes the compressor with the specified parameter structure.
Returns true on success, or false on
failure.
Note it should be possible to call init() multiple times
with different inputs, but this scenario isn't well tested yet. Ideally,
create one basis_compressor object, compress, then delete
it.
error_code process()Valid to call after a successful call to init().
Compresses the input to .basis and optionally .KTX2.
Returns cECSuccess, one of these error codes:
enum error_code
{
cECSuccess = 0,
cECFailedInitializing,
cECFailedReadingSourceImages,
cECFailedValidating,
cECFailedEncodeUASTC,
cECFailedFrontEnd,
cECFailedFrontendExtract,
cECFailedBackend,
cECFailedCreateBasisFile,
cECFailedWritingOutput,
cECFailedUASTCRDOPostProcess,
cECFailedCreateKTX2File,
cECFailedInvalidParameters
};
const uint8_vec &get_output_basis_file()Returns a reference to a uint8_t dynamic array
containing the output .basis file data, which is always valid if
process() succeeds.
const uint8_vec& get_output_ktx2_file()Returns a reference to a uint8_t dynamic array
containing the output .KTX2 file data, which is valid if
process() succeeds and KTX2 output file generation was
enabled by setting the m_create_ktx2_file parameter to
true.
This example compresses an LDR image to an ETC1S .KTX2 file using the C++ API directly.
#include "../encoder/basisu_comp.h"
static bool encode_etc1s()
{
// basisu_encoder_init() MUST have been called before this point.
basisu_encoder_init();
const uint32_t W = 256, H = 256;
image img(W, H);
for (uint32_t y = 0; y < H; y++)
for (uint32_t x = 0; x < W; x++)
img(x, y).set(((x ^ y) & 1) ? 255 : 0);
basis_compressor_params params;
// Set the format to ETC1S using the recommended unified method.
// Quality [1,255], unified effort [0,10].
params.set_format_mode_and_quality_effort(basist::basis_tex_format::cETC1S, 75, 3);
// Use perceptual colorspace error metrics.
params.set_srgb_options(true);
// Provide the LDR source image.
params.m_source_images.push_back(img);
// Enable debug/status output and statistics.
params.m_debug = true;
params.m_status_output = true;
params.m_compute_stats = true;
// Write a .KTX2 file to disk.
params.m_create_ktx2_file = true;
params.m_write_output_basis_or_ktx2_files = true;
params.m_out_filename = "test_etc1s.ktx2";
// Create a job pool. A job pool MUST always be created, even if threading is disabled.
// num_total_threads is the TOTAL thread count: 1 = calling thread only, 7 = calling thread + 6 extra.
const uint32_t NUM_THREADS = 7;
job_pool jp(NUM_THREADS);
params.m_pJob_pool = &jp;
params.m_multithreading = true; // only affects ETC1S; other codecs use the job pool directly
// Initialize and run the compressor.
basis_compressor comp;
if (!comp.init(params))
return false;
basisu::basis_compressor::error_code ec = comp.process();
if (ec != basisu::basis_compressor::cECSuccess)
return false;
return true;
}This example compresses an LDR image to a UASTC LDR 4x4 .KTX2 file using the C++ API directly.
#include "../encoder/basisu_comp.h"
static bool encode_uastc_ldr_4x4()
{
// basisu_encoder_init() MUST have been called before this point.
basisu_encoder_init();
const uint32_t W = 256, H = 256;
image img(W, H);
for (uint32_t y = 0; y < H; y++)
for (uint32_t x = 0; x < W; x++)
img(x, y).set(((x ^ y) & 1) ? 255 : 0);
basis_compressor_params params;
// Set the format to UASTC LDR 4x4 using the recommended unified method.
// Unified quality [1,100], unified effort [0,10].
params.set_format_mode_and_quality_effort(basist::basis_tex_format::cUASTC_LDR_4x4, 75, 3);
// Input is sRGB.
params.set_srgb_options(true);
// Provide the LDR source image.
params.m_source_images.push_back(img);
// Enable debug/status output and statistics.
params.m_debug = true;
params.m_status_output = true;
params.m_compute_stats = true;
// Write a .KTX2 file to disk.
params.m_create_ktx2_file = true;
params.m_write_output_basis_or_ktx2_files = true;
params.m_out_filename = "test_uastc_ldr_4x4.ktx2";
// Create a job pool. A job pool MUST always be created, even if threading is disabled.
// num_total_threads is the TOTAL thread count: 1 = calling thread only, 7 = calling thread + 6 extra.
const uint32_t NUM_THREADS = 7;
job_pool jp(NUM_THREADS);
params.m_pJob_pool = &jp;
params.m_multithreading = true; // only affects ETC1S; other codecs use the job pool directly
// Initialize and run the compressor.
basis_compressor comp;
if (!comp.init(params))
return false;
basisu::basis_compressor::error_code ec = comp.process();
if (ec != basisu::basis_compressor::cECSuccess)
return false;
return true;
}This example compresses an HDR image to a UASTC HDR 4x4 .KTX2 file using the C++ API directly.
#include "../encoder/basisu_comp.h"
static bool encode_uastc_hdr_4x4()
{
// basisu_encoder_init() MUST have been called before this point.
basisu_encoder_init();
const uint32_t W = 256, H = 256;
imagef img(W, H);
for (uint32_t y = 0; y < H; y++)
for (uint32_t x = 0; x < W; x++)
img(x, y).set(((x ^ y) & 1) ? basist::ASTC_HDR_MAX_VAL : 1000.0f);
basis_compressor_params params;
// Set the format to UASTC HDR 4x4 using the recommended unified method.
// Unified quality [1,100], unified effort [0,10].
params.set_format_mode_and_quality_effort(basist::basis_tex_format::cUASTC_HDR_4x4, 100, 8);
// This sets the low-level UASTC HDR 4x4 codec quality level directly
// (overriding set_format_mode_and_quality_effort()'s unified effort level set previously).
//params.m_uastc_hdr_4x4_options.set_quality_level(3);
// Use perceptual channel weights (2,3,1) for RGB error metrics instead of uniform (1,1,1).
params.set_srgb_options(true);
// Provide the HDR source image.
params.m_source_images_hdr.push_back(img);
// Enable debug/status output and statistics.
params.m_debug = true;
params.m_status_output = true;
params.m_compute_stats = true;
// Write a .KTX2 file to disk.
params.m_create_ktx2_file = true;
params.m_write_output_basis_or_ktx2_files = true;
params.m_out_filename = "test_uastc_hdr_4x4.ktx2";
// Create a job pool. A job pool MUST always be created, even if threading is disabled.
// num_total_threads is the TOTAL thread count: 1 = calling thread only, 7 = calling thread + 6 extra.
const uint32_t NUM_THREADS = 7;
job_pool jp(NUM_THREADS);
params.m_pJob_pool = &jp;
params.m_multithreading = true; // only affects ETC1S; other codecs use the job pool directly
// Initialize and run the compressor.
basis_compressor comp;
if (!comp.init(params))
return false;
basisu::basis_compressor::error_code ec = comp.process();
if (ec != basisu::basis_compressor::cECSuccess)
return false;
return true;
}This example compresses an HDR image to an ASTC HDR 6x6 .KTX2 file using the C++ API directly.
#include "../encoder/basisu_comp.h"
static bool encode_astc_hdr_6x6()
{
// basisu_encoder_init() MUST have been called before this point.
basisu_encoder_init();
const uint32_t W = 256, H = 256;
imagef img(W, H);
for (uint32_t y = 0; y < H; y++)
for (uint32_t x = 0; x < W; x++)
img(x, y).set(((x ^ y) & 1) ? basist::ASTC_HDR_MAX_VAL : 1000.0f);
basis_compressor_params params;
// Set the format to ASTC HDR 6x6 using the recommended unified method.
// Unified quality [1,100], unified effort [0,10].
params.set_format_mode_and_quality_effort(basist::basis_tex_format::cASTC_HDR_6x6, 100, 8);
// Input is sRGB.
params.set_srgb_options(true);
// Provide the HDR source image.
params.m_source_images_hdr.push_back(img);
// Enable debug/status output and statistics.
params.m_debug = true;
params.m_status_output = true;
params.m_compute_stats = true;
// Write a .KTX2 file to disk.
params.m_create_ktx2_file = true;
params.m_write_output_basis_or_ktx2_files = true;
params.m_out_filename = "test_astc_hdr_6x6.ktx2";
// Create a job pool. A job pool MUST always be created, even if threading is disabled.
// num_total_threads is the TOTAL thread count: 1 = calling thread only, 7 = calling thread + 6 extra.
const uint32_t NUM_THREADS = 7;
job_pool jp(NUM_THREADS);
params.m_pJob_pool = &jp;
params.m_multithreading = true; // only affects ETC1S; other codecs use the job pool directly
// Initialize and run the compressor.
basis_compressor comp;
if (!comp.init(params))
return false;
basisu::basis_compressor::error_code ec = comp.process();
if (ec != basisu::basis_compressor::cECSuccess)
return false;
return true;
}This example compresses an HDR image to a UASTC HDR 6x6 intermediate .KTX2 file using the C++ API directly.
#include "../encoder/basisu_comp.h"
static bool encode_uastc_hdr_6x6i()
{
// basisu_encoder_init() MUST have been called before this point.
basisu_encoder_init();
const uint32_t W = 256, H = 256;
imagef img(W, H);
for (uint32_t y = 0; y < H; y++)
for (uint32_t x = 0; x < W; x++)
img(x, y).set(((x ^ y) & 1) ? basist::ASTC_HDR_MAX_VAL : 1000.0f);
basis_compressor_params params;
// Set the format to UASTC HDR 6x6i using the recommended unified method.
// Unified quality [1,100], unified effort [0,10].
params.set_format_mode_and_quality_effort(basist::basis_tex_format::cUASTC_HDR_6x6_INTERMEDIATE, 75, 8);
// Input is sRGB.
params.set_srgb_options(true);
// Provide the HDR source image.
params.m_source_images_hdr.push_back(img);
// Enable debug/status output and statistics.
params.m_debug = true;
params.m_status_output = true;
params.m_compute_stats = true;
// Write a .KTX2 file to disk.
params.m_create_ktx2_file = true;
params.m_write_output_basis_or_ktx2_files = true;
params.m_out_filename = "test_uastc_hdr_6x6i.ktx2";
// Create a job pool. A job pool MUST always be created, even if threading is disabled.
// num_total_threads is the TOTAL thread count: 1 = calling thread only, 7 = calling thread + 6 extra.
const uint32_t NUM_THREADS = 7;
job_pool jp(NUM_THREADS);
params.m_pJob_pool = &jp;
params.m_multithreading = true; // only affects ETC1S; other codecs use the job pool directly
// Initialize and run the compressor.
basis_compressor comp;
if (!comp.init(params))
return false;
basisu::basis_compressor::error_code ec = comp.process();
if (ec != basisu::basis_compressor::cECSuccess)
return false;
return true;
}This example compresses an LDR image to an ASTC LDR 6x6 .KTX2 file
(with Zstd supercompression and automatic mipmap generation) using the
C++ API directly. Any of the standard ASTC block sizes from 4x4 to 12x12
can be used by changing the basis_tex_format value.
#include "../encoder/basisu_comp.h"
static bool encode_astc_ldr_6x6()
{
// basisu_encoder_init() MUST have been called before this point.
basisu_encoder_init();
const uint32_t W = 256, H = 256;
image img(W, H);
for (uint32_t y = 0; y < H; y++)
for (uint32_t x = 0; x < W; x++)
img(x, y).set(((x ^ y) & 1) ? 255 : 0);
basis_compressor_params params;
// Set the format to ASTC LDR 6x6 using the recommended unified method.
// Unified quality [1,100], unified effort [0,10].
params.set_format_mode_and_quality_effort(basist::basis_tex_format::cASTC_LDR_6x6, 75, 3);
// Input is sRGB.
params.set_srgb_options(true);
// Provide the LDR source image.
params.m_source_images.push_back(img);
// Enable debug/status output and statistics.
params.m_debug = true;
params.m_status_output = true;
params.m_compute_stats = true;
// Write a .KTX2 file to disk.
params.m_create_ktx2_file = true;
params.m_write_output_basis_or_ktx2_files = true;
params.m_out_filename = "test_astc_ldr_6x6.ktx2";
// Enable Zstd supercompression.
params.m_ktx2_uastc_supercompression = basist::KTX2_SS_ZSTANDARD;
// Enable automatic mipmap generation.
params.m_mip_gen = true;
// Create a job pool. A job pool MUST always be created, even if threading is disabled.
// num_total_threads is the TOTAL thread count: 1 = calling thread only, 7 = calling thread + 6 extra.
const uint32_t NUM_THREADS = 7;
job_pool jp(NUM_THREADS);
params.m_pJob_pool = &jp;
params.m_multithreading = true; // only affects ETC1S; other codecs use the job pool directly
// Initialize and run the compressor.
basis_compressor comp;
if (!comp.init(params))
return false;
basisu::basis_compressor::error_code ec = comp.process();
if (ec != basisu::basis_compressor::cECSuccess)
return false;
return true;
}This example compresses an LDR image to a XUASTC LDR 6x6 .KTX2 file
(with automatic mipmap generation) using the C++ API directly. Any of
the standard ASTC block sizes from 4x4 to 12x12 can be used by changing
the basis_tex_format value.
#include "../encoder/basisu_comp.h"
static bool encode_xuastc_ldr_6x6()
{
// basisu_encoder_init() MUST have been called before this point.
basisu_encoder_init();
const uint32_t W = 256, H = 256;
image img(W, H);
for (uint32_t y = 0; y < H; y++)
for (uint32_t x = 0; x < W; x++)
img(x, y).set(((x ^ y) & 1) ? 255 : 0);
basis_compressor_params params;
// Set the format to XUASTC LDR 6x6 using the recommended unified method.
// Unified quality [1,100], unified effort [0,10].
params.set_format_mode_and_quality_effort(basist::basis_tex_format::cXUASTC_LDR_6x6, 75, 3);
// Input is sRGB.
params.set_srgb_options(true);
// Provide the LDR source image.
params.m_source_images.push_back(img);
// Enable debug/status output and statistics.
params.m_debug = true;
params.m_status_output = true;
params.m_compute_stats = true;
// Write a .KTX2 file to disk.
params.m_create_ktx2_file = true;
params.m_write_output_basis_or_ktx2_files = true;
params.m_out_filename = "test_xuastc_ldr_6x6.ktx2";
// Enable automatic mipmap generation.
params.m_mip_gen = true;
// Create a job pool. A job pool MUST always be created, even if threading is disabled.
// num_total_threads is the TOTAL thread count: 1 = calling thread only, 7 = calling thread + 6 extra.
const uint32_t NUM_THREADS = 7;
job_pool jp(NUM_THREADS);
params.m_pJob_pool = &jp;
params.m_multithreading = true; // only affects ETC1S; other codecs use the job pool directly
// Initialize and run the compressor.
basis_compressor comp;
if (!comp.init(params))
return false;
basisu::basis_compressor::error_code ec = comp.process();
if (ec != basisu::basis_compressor::cECSuccess)
return false;
return true;
}This example compresses a sequence of LDR frames to an ETC1S .basis
texture video file. The resulting file can be viewed using the webgl/video_test
WebGL sample. For more information about the best settings to use for
encoding texture video, see Encoding ETC1S
and XUASTC LDR Texture Video.
.KTX2 texture video texture files can also be viewed using our ktx2_encode_test WebGL sample.
#include "../encoder/basisu_comp.h"
// View the resulting texture video .basis file using the webgl/video_test WebGL sample:
// https://github.com/BinomialLLC/basis_universal/tree/master/webgl/video_test
static bool encode_etc1s_texture_video()
{
// basisu_encoder_init() MUST have been called before this point.
basisu_encoder_init();
const uint32_t NUM_FRAMES = 50;
const uint32_t W = 384, H = 256;
basis_compressor_params params;
// Set the format to ETC1S using the recommended unified method.
// Quality [1,255], unified effort [0,10].
params.set_format_mode_and_quality_effort(basist::basis_tex_format::cETC1S, 100, 3);
// Input is sRGB.
params.set_srgb_options(true);
// Create the frames to compress.
for (uint32_t frame_index = 0; frame_index < NUM_FRAMES; frame_index++)
{
image img(W, H);
img.debug_text(frame_index, 20, 1, 1, g_white_color, &g_black_color, false, fmt_string("Frame {}", frame_index).c_str());
params.m_source_images.push_back(img);
}
// Enable debug/status output and statistics.
params.m_debug = true;
params.m_status_output = true;
params.m_compute_stats = true;
// Set the texture type to video frames, which causes the compressor to treat the
// images as a texture video sequence (using skip blocks).
params.m_tex_type = basist::basis_texture_type::cBASISTexTypeVideoFrames;
// Write a .basis file to disk.
// (.KTX2 supports texture video too, but our current texture video WebGL sample only supports .basis.)
params.m_write_output_basis_or_ktx2_files = true;
params.m_out_filename = "test_etc1s_texture_video.basis";
// Create a job pool. A job pool MUST always be created, even if threading is disabled.
// num_total_threads is the TOTAL thread count: 1 = calling thread only, 7 = calling thread + 6 extra.
const uint32_t NUM_THREADS = 7;
job_pool jp(NUM_THREADS);
params.m_pJob_pool = &jp;
params.m_multithreading = true; // only affects ETC1S; other codecs use the job pool directly
// Initialize and run the compressor.
basis_compressor comp;
if (!comp.init(params))
return false;
basisu::basis_compressor::error_code ec = comp.process();
if (ec != basisu::basis_compressor::cECSuccess)
return false;
return true;
}This example compresses a sequence of LDR frames to a XUASTC LDR 8x8
.basis texture video file. The resulting file can be viewed using the webgl/video_test
WebGL sample. For more information about the best settings to use for
encoding texture video, see Encoding ETC1S
and XUASTC LDR Texture Video.
.KTX2 texture video texture files can also be viewed using our ktx2_encode_test WebGL sample.
#include "../encoder/basisu_comp.h"
// View the resulting texture video .basis file using the webgl/video_test WebGL sample:
// https://github.com/BinomialLLC/basis_universal/tree/master/webgl/video_test
static bool encode_xuastc_ldr_texture_video()
{
// basisu_encoder_init() MUST have been called before this point.
basisu_encoder_init();
const uint32_t NUM_FRAMES = 50;
const uint32_t W = 384, H = 256;
basis_compressor_params params;
// Set the format to XUASTC LDR 8x8 using the recommended unified method.
// Unified quality [1,100], unified effort [0,10].
params.set_format_mode_and_quality_effort(basist::basis_tex_format::cXUASTC_LDR_8x8, 75, 3);
// Input is sRGB.
params.set_srgb_options(true);
// Create the frames to compress.
for (uint32_t frame_index = 0; frame_index < NUM_FRAMES; frame_index++)
{
image img(W, H);
img.debug_text(frame_index, 20, 1, 1, g_white_color, &g_black_color, false, fmt_string("Frame {}", frame_index).c_str());
params.m_source_images.push_back(img);
}
// Enable debug/status output and statistics.
params.m_debug = true;
params.m_status_output = true;
params.m_compute_stats = true;
// Set the texture type to video frames, which causes the compressor to treat the
// images as a texture video sequence.
params.m_tex_type = basist::basis_texture_type::cBASISTexTypeVideoFrames;
// Write a .basis file to disk.
// (.KTX2 supports texture video too, but our current texture video WebGL sample only supports .basis.)
params.m_write_output_basis_or_ktx2_files = true;
params.m_out_filename = "test_xuastc_ldr_texture_video.basis";
// Create a job pool. A job pool MUST always be created, even if threading is disabled.
// num_total_threads is the TOTAL thread count: 1 = calling thread only, 7 = calling thread + 6 extra.
const uint32_t NUM_THREADS = 7;
job_pool jp(NUM_THREADS);
params.m_pJob_pool = &jp;
params.m_multithreading = true; // only affects ETC1S; other codecs use the job pool directly
// Initialize and run the compressor.
basis_compressor comp;
if (!comp.init(params))
return false;
basisu::basis_compressor::error_code ec = comp.process();
if (ec != basisu::basis_compressor::cECSuccess)
return false;
return true;
}This example creates a 2D texture array with custom mipmap levels,
performing manual LDR→HDR upconversion in memory, and outputs a UASTC
HDR 6x6i .KTX2 file. It demonstrates how to use
m_source_mipmap_images_hdr to provide your own mipmap chain
and how to use convert_ldr_to_hdr_image() for manual
upconversion.
.KTX2 texture array files can also be viewed using our ktx2_encode_test WebGL sample.
#include "../encoder/basisu_comp.h"
static bool encode_uastc_hdr_6x6i_array_custom_mipmap()
{
// basisu_encoder_init() MUST have been called before this point.
basisu_encoder_init();
const uint32_t ARRAY_SIZE = 2;
const uint32_t W = 384, H = 256;
basis_compressor_params params;
// Set the format to UASTC HDR 6x6i using the recommended unified method.
// Unified quality [1,100], unified effort [0,10].
params.set_format_mode_and_quality_effort(basist::basis_tex_format::cUASTC_HDR_6x6_INTERMEDIATE, 75, 3);
// Input is linear.
params.set_srgb_options(false);
// Create the array slices, each with a full custom mipmap chain.
for (uint32_t array_index = 0; array_index < ARRAY_SIZE; array_index++)
{
int cur_w = W, cur_h = H;
int mip_index = 0;
params.m_source_images_hdr.enlarge(1);
params.m_source_mipmap_images_hdr.enlarge(1);
do
{
image img(cur_w, cur_h);
img.debug_text(0, 10, 1, 1, g_white_color, &g_black_color, false,
fmt_string("{} {} {}x{}", array_index, mip_index, cur_w, cur_h).c_str());
// Manually upconvert LDR to HDR (sRGB→linear, 100 nits, no black bias).
imagef hdr_img;
convert_ldr_to_hdr_image(hdr_img, img, true, 100.0f, 0.0f);
// The first mip level (0) goes in m_source_images_hdr,
// and the remaining mip levels go in m_source_mipmap_images_hdr.
if (!mip_index)
params.m_source_images_hdr[array_index] = hdr_img;
else
params.m_source_mipmap_images_hdr[array_index].push_back(hdr_img);
++mip_index;
cur_w = maximum(1, cur_w / 2);
cur_h = maximum(1, cur_h / 2);
} while ((cur_w > 1) || (cur_h > 1));
}
// Enable debug/status output and statistics.
params.m_debug = true;
params.m_status_output = true;
params.m_compute_stats = true;
// Set the texture type to 2D array.
params.m_tex_type = basist::basis_texture_type::cBASISTexType2DArray;
// Write a .KTX2 file to disk.
params.m_create_ktx2_file = true;
params.m_write_output_basis_or_ktx2_files = true;
params.m_out_filename = "test_uastc_hdr_6x6i_array_custom_mips.ktx2";
// Create a job pool. A job pool MUST always be created, even if threading is disabled.
// num_total_threads is the TOTAL thread count: 1 = calling thread only, 7 = calling thread + 6 extra.
const uint32_t NUM_THREADS = 7;
job_pool jp(NUM_THREADS);
params.m_pJob_pool = &jp;
params.m_multithreading = true; // only affects ETC1S; other codecs use the job pool directly
// Initialize and run the compressor.
basis_compressor comp;
if (!comp.init(params))
return false;
basisu::basis_compressor::error_code ec = comp.process();
if (ec != basisu::basis_compressor::cECSuccess)
return false;
return true;
}This example creates a KTX2 ETC1S cubemap texture file with automatic mipmap generation. In KTX2, cubemap faces must be square. For cubemap arrays, provide 6×N faces.
#include "../encoder/basisu_comp.h"
static bool encode_etc1s_cubemap()
{
// basisu_encoder_init() MUST have been called before this point.
basisu_encoder_init();
// In KTX2, cubemap faces must be square.
const uint32_t W = 256, H = 256;
basis_compressor_params params;
// Set the format to ETC1S using the recommended unified method.
// Quality [1,255], unified effort [0,10].
params.set_format_mode_and_quality_effort(basist::basis_tex_format::cETC1S, 75, 3);
// Input is sRGB.
params.set_srgb_options(true);
// Standard cubemap face order: +X, -X, +Y, -Y, +Z, -Z.
static const char* s_pFace_names[6] = { "+X", "-X", "+Y", "-Y", "+Z", "-Z" };
// Create the 6 faces to compress (for cubemap arrays, provide 6*N faces).
for (uint32_t face_index = 0; face_index < 6; face_index++)
{
image img(W, H);
img.debug_text(0, 10, 1, 1, g_white_color, &g_black_color, false,
fmt_string("Face {} {}", face_index, s_pFace_names[face_index]).c_str());
params.m_source_images.push_back(img);
}
// Enable debug/status output and statistics.
params.m_debug = true;
params.m_status_output = true;
params.m_compute_stats = true;
// Set the texture type to cubemap/cubemap array.
params.m_tex_type = basist::basis_texture_type::cBASISTexTypeCubemapArray;
// Enable automatic mipmap generation.
params.m_mip_gen = true;
// Write a .KTX2 file to disk.
params.m_create_ktx2_file = true;
params.m_write_output_basis_or_ktx2_files = true;
params.m_out_filename = "test_etc1s_cubemap.ktx2";
// Create a job pool. A job pool MUST always be created, even if threading is disabled.
// num_total_threads is the TOTAL thread count: 1 = calling thread only, 7 = calling thread + 6 extra.
const uint32_t NUM_THREADS = 7;
job_pool jp(NUM_THREADS);
params.m_pJob_pool = &jp;
params.m_multithreading = true; // only affects ETC1S; other codecs use the job pool directly
// Initialize and run the compressor.
basis_compressor comp;
if (!comp.init(params))
return false;
basisu::basis_compressor::error_code ec = comp.process();
if (ec != basisu::basis_compressor::cECSuccess)
return false;
return true;
}