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.
See Header: basisu_wasm_api.h
This header provides the C-style encoder/compressor API for Basis
Universal. It supports compressing RGBA32 or float RGBA images into
.basis or .ktx2 files using ETC1S, UASTC
LDR/HDR, XUASTC LDR, or ASTC LDR/HDR formats.
All common constants, types, and flags referenced below are defined
in Pure C API - Common
Definitions page (or see basisu_wasm_api_common.h).
These API's are essentially C-style wrappers to the C++ API's basis_compress2()
compression helper functions, defined in
encoder/basisu_comp.h. Also see the remarks before this
function.
Also see KTX2 File Format Support Technical Details, which has low level information about each of the supported codecs and how they are written to KTX2 files.
Note: These API's aren't just for WASM WASI module usage, they are also available for calling the native library via plain C API's.
bu_get_version()uint32_t bu_get_version();Returns the Basis Universal library version number (decimal 200 for library version v2.00).
bu_enable_debug_printf()void bu_enable_debug_printf(uint32_t flag);Enables or disables internal debug printf output
globally. To see any debug output, this function MUST be called, then
use the BU_COMP_FLAGS_DEBUG_OUTPUT flag during
compression.
| Parameter | Type | Description |
|---|---|---|
flag |
uint32_t |
Non-zero to enable, 0 to disable. |
bu_init()void bu_init();Initializes the Basis Universal encoder. Must be called once,
and allowed to finish and fully return, before any other
bu_* functions are called.
Internally this calls basisu_encoder_init(), which is
mutexed.
Use bu_alloc and bu_free to manage heap
allocated buffers that you pass to the API. In WASI modules, the
returned uint64_t's are casted pointers into the module's
internal address space. In WASM mode, all heap buffers you pass to the C
API must be allocated via these API's. In native
(non-WASM) builds, these "offsets" are just pointers casted to
uint64_t values.
bu_alloc()uint64_t bu_alloc(uint64_t size);Allocates a block of memory (alias to the module's
malloc() function).
| Parameter | Type | Description |
|---|---|---|
size |
uint64_t |
Number of bytes to allocate. |
Returns: Module offset (address) of the allocated
block, or 0 on failure.
bu_free()void bu_free(uint64_t ofs);Frees a block of memory previously allocated by
bu_alloc. Alias to the module's free()
function.
| Parameter | Type | Description |
|---|---|---|
ofs |
uint64_t |
Offset returned by a prior bu_alloc call. |
Compression parameters are managed through an opaque handle (a
uint64_t offset). Create a parameter block, configure it
with source images, then pass it to
bu_compress_texture().
bu_new_comp_params()uint64_t bu_new_comp_params();Allocates and returns a new compression parameter block with default settings.
Returns: Offset of the new parameter block, or
0 on failure.
bu_delete_comp_params()wasm_bool_t bu_delete_comp_params(uint64_t params_ofs);Frees a compression parameter block.
| Parameter | Type | Description |
|---|---|---|
params_ofs |
uint64_t |
Offset of the parameter block to free. |
Returns: Non-zero on success, 0 on
failure.
bu_comp_params_clear()wasm_bool_t bu_comp_params_clear(uint64_t params_ofs);Resets a compression parameter block to its default state, allowing it to be reused for a new compression without reallocating.
| Parameter | Type | Description |
|---|---|---|
params_ofs |
uint64_t |
Offset of the parameter block to clear. |
Returns: Non-zero on success, 0 on
failure.
After a successful call to bu_compress_texture(), the
compressed data is stored inside the parameter block. Use these
functions to retrieve it.
bu_comp_params_get_comp_data_ofs()uint64_t bu_comp_params_get_comp_data_ofs(uint64_t params_ofs);Returns the memory offset of the compressed output data.
| Parameter | Type | Description |
|---|---|---|
params_ofs |
uint64_t |
Offset of the parameter block. |
Returns: Offset of the compressed
.basis or .ktx2 file data in memory.
bu_comp_params_get_comp_data_size()uint64_t bu_comp_params_get_comp_data_size(uint64_t params_ofs);Returns the size in bytes of the compressed output data.
| Parameter | Type | Description |
|---|---|---|
params_ofs |
uint64_t |
Offset of the parameter block. |
Returns: Size of the compressed data in bytes.
Source images are set on the parameter block before compression. Each
image is identified by an image_index (starting at
0). The pixel data must already be allocated in linear
memory via bu_alloc. The compressor immediately copies the
image data, so it can be freed after either set function is called.
For the LDR codecs, the
bu_comp_params_set_image_rgba32() API must be used, and for
the HDR codecs bu_comp_params_set_image_float_rgba() must
be used. Mixing LDR and HDR images isn't supported and will cause
compression to fail. The current C API does not support automatic
LDR/SDR->HDR upconversion.
For BU_COMP_FLAGS_TEXTURE_TYPE_2D (the default), one
source image can be provided per mipmap level, largest mipmap level
first. If a single image is provided, mipmaps can be generated
automatically by using the BU_COMP_FLAGS_GEN_MIPS_CLAMP or
BU_COMP_FLAGS_GEN_MIPS_WRAP flags.
For the other texture types
(BU_COMP_FLAGS_TEXTURE_TYPE_2D_ARRAY,
BU_COMP_FLAGS_TEXTURE_TYPE_CUBEMAP_ARRAY, or
BU_COMP_FLAGS_TEXTURE_TYPE_VIDEO_FRAMES), the source images
are cubemap faces, texture array layers, or texture video frames. The
current C API doesn't support also specifying user-specified mipmaps for
these texture types (however the full C++ API does), but it does support
automatic mipmap generation.
bu_comp_params_set_image_rgba32()wasm_bool_t bu_comp_params_set_image_rgba32(
uint64_t params_ofs,
uint32_t image_index,
uint64_t img_data_ofs,
uint32_t width, uint32_t height,
uint32_t pitch_in_bytes);Sets an 8-bit-per-channel RGBA source image (4 bytes per pixel).
| Parameter | Type | Description |
|---|---|---|
params_ofs |
uint64_t |
Offset of the parameter block. |
image_index |
uint32_t |
Zero-based index of the image to set. |
img_data_ofs |
uint64_t |
Offset of the pixel data in memory (allocated via
bu_alloc). |
width |
uint32_t |
Image width in pixels. |
height |
uint32_t |
Image height in pixels. |
pitch_in_bytes |
uint32_t |
Row stride in bytes. Use width * 4 for tightly packed
rows. |
Returns: Non-zero on success, 0 on
failure.
bu_comp_params_set_image_float_rgba()wasm_bool_t bu_comp_params_set_image_float_rgba(
uint64_t params_ofs,
uint32_t image_index,
uint64_t img_data_ofs,
uint32_t width, uint32_t height,
uint32_t pitch_in_bytes);Sets a 32-bit-float-per-channel RGBA source image (16 bytes per pixel). Use this for HDR content. See the Valid HDR Inputs section in the C++ API documentation for information about the valid range of HDR input values.
| Parameter | Type | Description |
|---|---|---|
params_ofs |
uint64_t |
Offset of the parameter block. |
image_index |
uint32_t |
Zero-based index of the image to set. |
img_data_ofs |
uint64_t |
Offset of the pixel data in memory (allocated via
bu_alloc). |
width |
uint32_t |
Image width in pixels. |
height |
uint32_t |
Image height in pixels. |
pitch_in_bytes |
uint32_t |
Row stride in bytes. Use width * 16 for tightly packed
rows. |
Returns: Non-zero on success, 0 on
failure.
bu_compress_texture()wasm_bool_t bu_compress_texture(
uint64_t params_ofs,
uint32_t desired_basis_tex_format,
int quality_level,
int effort_level,
uint64_t flags_and_quality,
float low_level_uastc_rdo_or_dct_quality);Compresses the source image(s) previously set on the parameter block.
The parameter block must contain a full mipmap chain, or a single image.
This function is a wrapper over basis_compress2() in the
C++ library.
| Parameter | Type | Description |
|---|---|---|
params_ofs |
uint64_t |
Offset of the parameter block (with source images already set). |
desired_basis_tex_format |
uint32_t |
Target file format — one of the BTF_* constants (e.g.
BTF_ETC1S, BTF_UASTC_LDR_4X4). |
quality_level |
int |
Unified Quality level [1,100] (see BU_QUALITY_MIN,
BU_QUALITY_MAX). Use -1 to use older non-unified/direct
codec-specific quality level or lambda (low 8-bits of
flags_and_quality, or via
low_level_uastc_rdo_or_dct_quality). |
effort_level |
int |
Unified Encoder effort [0,10] (see BU_EFFORT_MIN,
BU_EFFORT_MAX). See BU_EFFORT_* presets. Use
-1 to use older non-unified/direct codec-specific effort level (low
8-bits of flags_and_quality for some codecs). |
flags_and_quality |
uint64_t |
Bitwise OR of BU_COMP_FLAGS_* constants. Controls
output format, mipmaps, color space, etc. Low 8-bits are either the
older non-unified quality level, or for some codecs the non-unified
effort level. |
low_level_uastc_rdo_or_dct_quality |
float |
Low-level (non-unified) quality or lambda parameter for UASTC RDO
encoding. Typically 0.0 for defaults. Must be 0.0 if using
unified (not -1) quality level. |
Returns: Non-zero on success, 0 on
failure.
After a successful return, retrieve the output file data using
bu_comp_params_get_comp_data_ofs() and
bu_comp_params_get_comp_data_size().
This function is thread-safe, i.e. you can compress multiple textures in parallel on different threads.
See the C API Example.
High level C example:
#define TRUE (1)
#define FALSE (0)
// Initialize library (once at startup)
bu_init();
// Globally enable library debug output
bu_enable_debug_printf(TRUE);
// Create compression parameters handle
uint64_t params = bu_new_comp_params();
// 32bpp RGBA image's width/height (created elsewhere)
int width, height;
const void *source_image_pixels;
// Allocate and set source image (assume you have RGBA data)
uint64_t img_ofs = bu_alloc(width * height * 4);
memcpy((void*)img_ofs, source_image_pixels, width * height * 4);
// Compressor copies data internally
bu_comp_params_set_image_rgba32(params, 0, img_ofs, width, height, width * 4);
// Free allocation
bu_free(img_ofs);
img_ofs = 0;
// Compress to XUASTC LDR 6x6 with quality 75, effort 3
uint32_t flags = BU_COMP_FLAGS_KTX2_OUTPUT | BU_COMP_FLAGS_KTX2_UASTC_ZSTD | BU_COMP_FLAGS_SRGB | BU_COMP_FLAGS_THREADED | BU_COMP_FLAGS_DEBUG_OUTPUT;
if (!bu_compress_texture(params, BTF_XUASTC_LDR_6X6, 75, 3, flags, 0.0f))
{
// Cleanup
bu_delete_comp_params(params);
// Handle error
}
// Retrieve compressed output
uint64_t size = bu_comp_params_get_comp_data_size(params);
if (!size)
{
// Handle error
}
void* data = (void*)bu_comp_params_get_comp_data_ofs(params);
if (!data)
{
// Handle error
}
// ... write file data to file or use as needed ...
// Cleanup
bu_delete_comp_params(params);The developer can use either the unified, codec-independent quality/effort levels (recommended for simplicity), or lower level codec-specific parameters. It's possible to mix unified quality with a non-unified effort setting, or vice versa, but it's not recommended.
quality_level ranges between [1,100], where
1=lowest quality/smallest files, 100=highest quality/largest files.effort_level ranges between [0,10], where
0=fastest (brittle, lowest quality ceiling), 9=highest practical
(quality ceiling goes up), 10=very slow (highest quality ceiling).Codec unified effort/quality level support matrix:
| Codec | Quality Control | Effort Control | Standard ASTC in .KTX2 File | Built-in Compression/RDO+Zstd Support | Rough On-Disk Bitrate Range |
|---|---|---|---|---|---|
| ETC1S | ✅ Unified | ✅ Unified (Only) | No | Built-in: VQ+entropy coding of ETC1S latent, custom format | ~0.5 - ~2.5 bpp |
| UASTC LDR 4×4 | ✅ Unified | ✅ Unified | No | Via RDO lambda+Zstd | ~4 - 8.0 bpp |
| UASTC HDR 4×4 | ❌ Ignored | ✅ Unified | Yes | No (non-RDO+Zstd) | ~6 - 8.0 bpp |
| ASTC HDR 6×6 | ✅ Unified | ✅ Unified | Yes | Via RDO lambda+Zstd | ~2.25 - 3.56 bpp |
| UASTC HDR 6×6i | ✅ Unified | ✅ Unified | No | Built-in: latent compression of ASTC, custom format | ~1.75 - ~3.0 bpp |
| ASTC LDR 4×4-12×12 | ❌ Ignored | ✅ Unified | Yes | No (non-RDO+Zstd, Windowed RDO not yet exposed via C API) | ~0.89 - 8.0 bpp |
| XUASTC LDR 4×4-12×12 | ✅ Unified | ✅ Unified | No | Built-in: latent compression+DCT+entropy coding of ASTC, custom format | ~0.3 - ~5.7 bpp |
These codecs support direct quality control or RDO:
Note Zstd is only available when writing .KTX2 target files, and is
only applied when the BU_COMP_FLAGS_KTX2_UASTC_ZSTD flag
(which enables Zstd supercompression) is specified during compression.
For codecs with their own built-in compression (like ETC1S or XUASTC),
the BU_COMP_FLAGS_KTX2_UASTC_ZSTD flag is harmless and will
be ignored.
These codecs do not support RDO (at least not via the C API), and the quality level will be ignored:
If you specify a quality level less than 100 for a codec which doesn't support quality levels, a warning message will be printed to stdout.
For the ETC1S codec: The effort level can only be controlled via the
C API when using the unified effort_level parameter.
For the HDR codecs, the input image(s) MUST be float RGBA HDR: use
bu_comp_params_set_image_float_rgba() to provide the input
image(s). Automatic SDR/LDR->HDR upconversion isn't supported yet via
the pure C API.
bu_compress_texture(params_ofs,
BTF_ETC1S, // codec selection
75, 2, // quality 75, effort 2
BU_COMP_FLAGS_THREADED | BU_COMP_FLAGS_SRGB | BU_COMP_FLAGS_KTX2_OUTPUT | BU_COMP_FLAGS_KTX2_UASTC_ZSTD, // flags: threaded, sRGB, KTX2
0.0f);
bu_compress_texture(params_ofs,
BTF_UASTC_LDR_4X4, // codec selection
75, 2, // quality 75 (100=no RDO), effort 2
BU_COMP_FLAGS_THREADED | BU_COMP_FLAGS_SRGB | BU_COMP_FLAGS_KTX2_OUTPUT | BU_COMP_FLAGS_KTX2_UASTC_ZSTD, // flags: threaded, sRGB, KTX2
0.0f);
No support for quality levels/RDO.
bu_compress_texture(params_ofs,
BTF_UASTC_HDR_4X4, // codec selection
100, 2, // quality 100 (ignored), effort 2
BU_COMP_FLAGS_THREADED | BU_COMP_FLAGS_KTX2_OUTPUT | BU_COMP_FLAGS_KTX2_UASTC_ZSTD, // flags: threaded, KTX2
0.0f);
Internally the same codec is used for ASTC HDR 6x6 and UASTC HDR 6x6i.
bu_compress_texture(params_ofs,
BTF_ASTC_HDR_6X6, // codec selection
85, 2, // quality 85 (100=no RDO), effort 2
BU_COMP_FLAGS_THREADED | BU_COMP_FLAGS_KTX2_OUTPUT | BU_COMP_FLAGS_KTX2_UASTC_ZSTD, // flags: threaded, KTX2
0.0f);
Internally the same codec is used for ASTC HDR 6x6 and UASTC HDR 6x6i.
bu_compress_texture(params_ofs,
BTF_UASTC_HDR_6X6, // codec selection
95, 2, // quality 95 (100=no RDO), effort 2
BU_COMP_FLAGS_THREADED | BU_COMP_FLAGS_KTX2_OUTPUT | BU_COMP_FLAGS_KTX2_UASTC_ZSTD, // flags: threaded, KTX2
0.0f);
Internally the same codec is used for ASTC LDR 4x4-12x12 and XUASTC LDR 4x4-12x12.
No support for quality levels/RDO via the C API.
bu_compress_texture(params_ofs,
BTF_ASTC_LDR_4X4, // codec selection
100, 3, // quality 100 (ignored), effort 3
BU_COMP_FLAGS_THREADED | BU_COMP_FLAGS_SRGB | BU_COMP_FLAGS_KTX2_OUTPUT | BU_COMP_FLAGS_KTX2_UASTC_ZSTD, // flags: threaded, KTX2, sRGB
0.0f);
Internally the same codec is used for ASTC LDR 4x4-12x12 and XUASTC LDR 4x4-12x12.
bu_compress_texture(params_ofs,
BTF_XUASTC_LDR_4X4, // codec selection
75, 3, // quality 75 (100=no DCT), effort 3
BU_COMP_FLAGS_THREADED | BU_COMP_FLAGS_SRGB | BU_COMP_FLAGS_KTX2_OUTPUT | BU_COMP_FLAGS_KTX2_UASTC_ZSTD, // flags: threaded, KTX2, sRGB
0.0f);
Beware: This older method for controlling codec quality and
effort has way sharper edges, i.e. it's easy to set the wrong parameters
because the quality and effort level are highly codec-specific.
We recommend enabling codec debug output (call
bu_enable_debug_printf() and enable the
BU_COMP_FLAGS_DEBUG_OUTPUTflag) to double check you've set
the parameters as you expect.
This method does enable direct control over RDO lambda for the HDR codecs, which can be quite useful. It's challenging for us to map a unified [1,100] quality range to a useable lambda setting that works well across a diverse range of HDR imagery.
Only the quality level is controllable (via this API using non-unified effort levels), not the effort level.
uint32_t flags = BU_COMP_FLAGS_KTX2_OUTPUT | BU_COMP_FLAGS_KTX2_UASTC_ZSTD | BU_COMP_FLAGS_SRGB | BU_COMP_FLAGS_THREADED;
int old_quality_effort = 200; // select ETC1S quality level 200, valid range [1,255]
bu_compress_texture(comp_params, BTF_ETC1S, -1, -1, flags | old_quality_effort, 0.0f))
uint32_t flags = BU_COMP_FLAGS_KTX2_OUTPUT | BU_COMP_FLAGS_KTX2_UASTC_ZSTD | BU_COMP_FLAGS_SRGB | BU_COMP_FLAGS_THREADED;
int old_quality_effort = 2; // select UASTC LDR 4x4 with default effort level 2 (cPackUASTCLevelDefault), valid range [0,4]
float rdo_lambda = 1.0f; // RDO lambda, 0=no RDO, higher=lower quality, try [0.1-10.0]
bu_compress_texture(comp_params, BTF_UASTC_LDR_4X4, -1, -1, flags | old_quality_effort, rdo_lambda))
No support for quality levels/RDO.
uint32_t flags = BU_COMP_FLAGS_KTX2_OUTPUT | BU_COMP_FLAGS_KTX2_UASTC_ZSTD | BU_COMP_FLAGS_THREADED;
int old_quality_effort = 1; // use UASTC HDR 4x4 default effort level 1, valid range [0,4]
bu_compress_texture(comp_params, BTF_UASTC_HDR_4X4, -1, -1, flags | old_quality_effort, 0.0f);
Internally the same codec is used for ASTC HDR 6x6 and UASTC HDR 6x6i.
uint32_t flags = BU_COMP_FLAGS_KTX2_OUTPUT | BU_COMP_FLAGS_KTX2_UASTC_ZSTD | BU_COMP_FLAGS_THREADED;
int old_quality_effort = 2; // use RDO ASTC HDR 6x6 default effort level 2, valid range [0,12]
float rdo_lambda = 500.0f; // RDO lambda (0.0f=no RDO, higher=more distortion/smaller files, try roughly [100,10000] for HDR content, or higher for upconverted content)
bu_compress_texture(comp_params, BTF_ASTC_HDR_6X6, -1, -1, flags | old_quality_effort, rdo_lambda);
Internally the same codec is used for ASTC HDR 6x6 and UASTC HDR 6x6i.
uint32_t flags = BU_COMP_FLAGS_KTX2_OUTPUT | BU_COMP_FLAGS_KTX2_UASTC_ZSTD | BU_COMP_FLAGS_THREADED;
int old_quality_effort = 2; // use UASTC HDR 6x6i default effort level 2, valid range [0,12]
float rdo_lambda = 500.0f; // RDO lambda (0.0f=no RDO, higher=more distortion/smaller files, try roughly [100,10000] for HDR content, or higher for upconverted content)
bu_compress_texture(comp_params, BTF_UASTC_HDR_6X6, -1, -1, flags | old_quality_effort, rdo_lambda);
Internally the same codec is used for ASTC LDR 4x4-12x12 and XUASTC LDR 4x4-12x12.
No support for quality levels/RDO via the C API.
uint32_t flags = BU_COMP_FLAGS_KTX2_OUTPUT | BU_COMP_FLAGS_KTX2_UASTC_ZSTD | BU_COMP_FLAGS_THREADED | BU_COMP_FLAGS_SRGB;
int old_effort_level = 2; // use ASTC LDR 4x4-12x12 default effort level 2, valid range [0,10]
float dct_quality = 0.0f; // ASTC LDR doesn't support DCT, so set to 0
bu_compress_texture(comp_params, BTF_ASTC_LDR_4X4, -1, -1, flags | old_effort_level, dct_quality);
Internally the same codec is used for ASTC LDR 4x4-12x12 and XUASTC LDR 4x4-12x12.
uint32_t flags = BU_COMP_FLAGS_KTX2_OUTPUT | BU_COMP_FLAGS_KTX2_UASTC_ZSTD | BU_COMP_FLAGS_THREADED | BU_COMP_FLAGS_SRGB;
int old_effort_level = 2; // use ASTC LDR 4x4-12x12 default effort level 2, valid range [0,10]
float dct_quality = 75.0f; // use DCT level 75, valid range [1,100], 0 or 100=disable DCT, <100 also enables Windowed RDO with default (conservative) settings
bu_compress_texture(comp_params, BTF_XUASTC_LDR_4X4, -1, -1, flags | old_effort_level, dct_quality);
basisu_wasm_api_common.h
— Common definitionsbasisu_wasm_transcoder_api.h
— Transcoder API