Update README.md
An LDR/HDR portable GPU supercompressed texture transcoding system.
Basis Universal v2.0 is an open source supercompressed LDR/HDR GPU compressed texture interchange system from Binomial LLC that supports two intermediate file formats: the .KTX2 open standard from the Khronos Group, and our own “.basis” file format. These file formats support rapid transcoding to virtually any compressed GPU texture format released over the past ~25 years.
Our overall goal is to simplify the encoding and efficient distribution of portable LDR and HDR GPU texture, image, and short texture video content in a way that is compatible with any GPU or rendering/graphics API.
The system supports seven modes (or codecs):
The C/C++ encoder and transcoder libraries can be compiled to native code or WebAssembly (web or WASI), and all encoder/transcoder features can be accessed from JavaScript via a C++ wrapper library which optionally supports WASM multithreading for fast encoding in the browser. WASM WASI builds, for the command line tool and the encoder/transcoder as a WASI module using a pure C API, are also supported.
Full Python support for encoding/transcoding is now available, supporting native or WASM modules, but is still in the early stages of development.
ETC1S, UASTC LDR 4x4, XUASTC LDR 4x4-12x12 and ASTC LDR 4x4-12x12 files can be transcoded to:
UASTC HDR 4x4, ASTC HDR 6x6, and UASTC HDR 6x6 files can be transcoded to:
ETC1S: A roughly .3-3bpp low to medium quality supercompressed mode based on a subset of ETC1 called “ETC1S”. This mode supports variable quality vs. file size levels (like JPEG), alpha channels, built-in compression, and texture arrays optionally compressed as a video sequence using skip blocks (Conditional Replenishment). This mode can be rapidly transcoded to all of the supported LDR texture formats.
UASTC LDR 4x4: An 8 bits/pixel LDR high quality mode. UASTC LDR is a 19 mode subset of the standard ASTC LDR 4x4 (8bpp) texture format, but with a custom block format containing transcoding hints. Transcoding UASTC LDR to ASTC LDR and BC7 are particularly fast and simple, because UASTC LDR is a common subset of both BC7 and ASTC. The transcoders for the other texture formats are accelerated by several format-specific hint bits present in each UASTC LDR block.
This mode supports an optional Rate-Distortion Optimized (RDO) post-process stage that conditions the encoded UASTC LDR texture data in the .KTX2/.basis file so it can be more effectively LZ compressed. More details here.
Here is the UASTC LDR 4x4 specification document.
Here is the UASTC HDR 4x4 specification document, and here are some compressed example images.
The ASTC HDR decoder, used in the transcoder module, supports the entire ASTC HDR format.
UASTC HDR 6x6 Intermediate (“GPU Photo”): A custom compressed intermediate format that can be rapidly transcoded to ASTC HDR 6x6, BC6H, and various uncompressed HDR formats. The custom compressed file format is described here. The format supports 75 unique ASTC configurations, weight grid upsampling, 1-3 subsets, single or dual planes, CEM's 7 and 11, and all unique ASTC partition patterns.
Standard ASTC LDR-4x4-12x12. Supports all 14 ASTC block sizes. Transcodable to any other supported LDR texture format.
The ASTC LDR decoder, used in the transcoder module, supports the entire standard ASTC LDR format.
Supported ASTC configurations: L/LA/RGB/RGBA CEM‘s, base+scale or RGB/RGBA direct, base+ofs CEM’s, Blue Contraction encoding, 1-3 subsets, all partition patterns, single or dual plane. Here is the XUASTC LDR specification.
Notes:
Both .basis and .KTX2 files support mipmap levels, texture arrays, cubemaps, cubemap arrays, and texture video, in all modes. Additionally, .basis files support non-uniform texture arrays, where each image in the file can have a different resolution or number of mipmap levels.
In ETC1S mode, the compressor is able to exploit color and pattern correlations across all the images in the entire file using global endpoint/selector codebooks, so multiple images with mipmaps can be stored efficiently in a single file. The ETC1S mode also supports skip blocks (Conditional Replenishment) for short video sequences, to prevent sending blocks which haven't changed relative to the previous frame.
The LDR image formats supported for reading are .PNG, .DDS with mipmaps, .TGA, .QOI, and .JPG. The HDR image formats supported for reading are .EXR, .HDR, and .DDS with mipmaps. The library can write .basis, .KTX2, .DDS, .KTX (v1), .ASTC, .OUT, .EXR, and .PNG files.
The system now supports loading basic 2D .DDS files with optional mipmaps, but the .DDS file must be in one of the supported uncompressed formats: 24bpp RGB, 32bpp RGBA/BGRA, half-float RGBA, or float RGBA. Using .DDS files allows the user to control exactly how the mipmaps are generated before compression.
The encoding library and command line tool have no required 3rd party dependencies that are not already in the repo itself. The transcoder is a single .cpp source file (in transcoder/basisu_transcoder.cpp) which has no 3rd party dependencies.
We build and test under:
Under Windows with Visual Studio you can use the included basisu.sln file. Alternatively, you can use cmake to create new VS solution/project files.
To build, first install cmake, then:
mkdir build cd build cmake .. make
To build with SSE 4.1 support on x86/x64 systems (ETC1S encoding is roughly 15-30% faster), add -DBASISU_SSE=TRUE to the cmake command line. Add -DBASISU_OPENCL=TRUE to build with (optional) OpenCL support. Use -DCMAKE_BUILD_TYPE=Debug to build in debug. To build 32-bit executables, add -DBASISU_BUILD_X64=FALSE.
After building, the native command line tool used to create, validate, and transcode/unpack .KTX2/.basis files is bin/basisu.
To build the WASM WASI executables, you will need the WASM WASI SDK installed. The WASI_SDK_PATH environment variable must be set to the correct path where the SDK is installed.
Multithreaded:
mkdir build_wasm_mt cd build_wasm_mt cmake -DCMAKE_TOOLCHAIN_FILE=$WASI_SDK_PATH/share/cmake/wasi-sdk-pthread.cmake -DCMAKE_BUILD_TYPE=Release -DBASISU_WASM_THREADING=ON .. make
Single threaded:
mkdir build_wasm_st cd build_wasm_st cmake -DCMAKE_TOOLCHAIN_FILE=$WASI_SDK_PATH/share/cmake/wasi-sdk.cmake -DCMAKE_BUILD_TYPE=Release -DBASISU_WASM_THREADING=OFF .. make
The WASM WASI executables will be placed in the bin/basisu directory. These platform-independent executables are fully functional, and can be executed using a WASM WASI runtime such as wasmtime.
Precompiled single and multithreaded WASM WASI executables have been checked into the bin directory. A WASM WASI runtime, like wasmtime, is required to run them. The WASM executables have been so far tested under Windows, Ubuntu Linux, and macOS. Examples:
Multithreaded (greatly recommended):
cd bin wasmtime run --dir=. --dir=../test_files --wasm threads=yes --wasi threads=yes ./basisu_mt.wasm -test
Single threaded example:
cd bin wasmtime run --dir=. --dir=../test_files ./basisu_st.wasm -test
Also see the runw.sh and runwt.sh helper scripts.
The command line tool includes some automated LDR/HDR encoding/transcoding tests:
cd ../bin basisu -test basisu -test_hdr_4x4 basisu -test_hdr_6x6 basisu -test_hdr_6x6i basisu -test_xuastc_ldr
To test the codec in OpenCL mode (must have OpenCL libs/headers/drivers installed and have compiled OpenCL support in by running cmake with -DBASISU_OPENCL=TRUE):
basisu -test -opencl
basisu -xuastc_ldr_6x6 -quality 75 -effort 4 x.png
An alias for -xuastc_ldr_6x6 is -ldr_6x6i (where ‘i’=“intermediate”).
The options -xuastc_arith, -xuastc_zstd (the default), and -xuastc_hybrid control the XUASTC LDR profile used. The arithmetic profile trades off transcoding throughput for 5-18% better compression vs. the Zstd profile, and the hybrid profile is a balance between the two.
All 14 standard ASTC block sizes are supported, from 4x4-12x12.
basisu -astc_ldr_6x6 -effort 4 x.png
An alias for -astc_ldr_6x6 is -ldr_6x6.
All 14 standard ASTC block sizes are supported, from 4x4-12x12. Internally the XUASTC LDR encoder is used, but standard ASTC block data is output, instead of supercompressed XUASTC LDR.
basisu -quality 100 x.png
-quality 50, or the older -q 128):basisu -linear x.png
basisu -uastc x.png
basisu x.exr
basisu -hdr_6x6 x.exr basisu -hdr_6x6 -lambda 500 x.exr basisu -hdr_6x6_level 5 -lambda 500 x.exr
basisu -hdr_6x6i x.exr basisu -hdr_6x6i -lambda 500 x.exr basisu -hdr_6x6i_level 5 -lambda 500 x.exr
Note the unified -quality and -effort options work in HDR, too. These examples use the older non-unified options, which allow more direct/precise control.
Be aware that the .EXR reader we‘re using is TinyEXR's, which doesn’t support all possible .EXR compression modes. Tools like ImageMagick can be used to create .EXR files that TinyEXR can read.
Alternatively, LDR images (such as .PNG) can be compressed to an HDR format by specifying -hdr, -hdr_6x6, or -hdr_6x6i. By default LDR images, when compressed to an HDR format, are first upconverted to HDR by converting them from sRGB to linear light and scaled to 100 nits (candelas per square meter). The sRGB conversion step can be disabled by specifying -hdr_ldr_no_srgb_to_linear, and the normalized RGB linear light to nit multiplier can be changed by specifying -hdr_ldr_upconversion_nit_multiplier X.
Note: If you‘re compressing LDR/SDR image files to an HDR format, the codec’s default behavior is to convert the 8-bit image data to linear light (by undoing the sRGB transfer function). It then multiplies the linear light RGB values by the LDR->HDR upconversion multiplier, which is in nits (candela per sq. meter). In previous versions of the codec, this multiplier was effectively 1 nit, but it now defaults to 100 nits in all modes. (The typical luminance of LDR monitors is 80-100 nits.) To change this, use the “-hdr_ldr_upconversion_nit_multiplier X” command line option. (This is done because the HDR 6x6 codecs function internally in the ICtCp HDR colorspace. LDR/SDR images must be upconverted to linear light HDR images scaled to a proper max. luminance based on how the image data will be displayed on actual SDR/HDR monitors.)
All codecs now support simple unified “quality” and “effort” settings. -effort X [0,10] controls how much of the search space (and how slowly) compression proceeds, and quality X [1,100] controls the quality vs. bitrate tradeoff. Internally these settings will be mapped to each codec's specific configuration settings. Almost all the older settings still work, however. Previously, -q X, where X ranged from [1,255], controlled the ETC1S quality setting. This option is still available, but -quality is preferred now.
-debug causes the encoder to print internal and developer-oriented verbose debug information.
-stats to see various quality (PSNR) statistics.
-linear: ETC1S defaults to sRGB colorspace metrics, UASTC LDR currently always uses linear metrics, and UASTC HDR defaults to weighted RGB metrics (with 2,3,1 weights). If the input is a normal map, or some other type of non-sRGB (non-photographic) texture content, be sure to use -linear to avoid extra unnecessary artifacts. (Angular normal map metrics for UASTC LDR/HDR are definitely doable and on our TODO list.)
Specifying -opencl enables OpenCL mode, which currently only accelerates ETC1S encoding.
The compressor is multithreaded by default, which can be disabled using the -no_multithreading command line option. The transcoder is currently single threaded, although it is thread safe (i.e. it supports decompressing multiple texture slices in parallel).
basisu -uastc -uastc_rdo_l 1.0 -mipmap x.png
-uastc_rdo_l X controls the RDO (Rate-Distortion Optimization) quality setting. The lower this value, the higher the quality, but the larger the compressed file size. Good values to try are between .2-3.0. The default is 1.0.
basisu -mipmap -quality 75 x.png
There are several mipmap options to change the filter kernel, the filter colorspace for the RGB channels (linear vs. sRGB), the smallest mipmap dimension, etc. The tool also supports generating cubemap files, 2D/cubemap texture arrays, etc. To bypass the automatic mipmap generator, you can create LDR or HDR uncompressed .DDS texture files and feed them to the compressor.
basisu -comp_level 2 x.png
On some rare images (ones with blue sky gradients come to mind), you may need to increase the ETC1S -comp_level setting, which ranges from 1 to 6. This controls the amount of overall effort the encoder uses to optimize the ETC1S codebooks and the compressed data stream. Higher comp_level's are significantly slower.
basisu x.png -comp_level 2 -max_endpoints 16128 -max_selectors 16128
basisu -tonemap x.exr
basisu -compare a.png b.png
basisu -compare_hdr a.exr b.exr
See the help text for a complete listing of the tool's command line options. The command line tool is just a thin wrapper on top of the encoder library.
You can either use the command line tool or call the transcoder directly from JavaScript or C/C++ code to decompress .KTX2/.basis files to GPU texture data or uncompressed image data. To unpack a .KTX2 or .basis file to multiple .png/.exr/.ktx/.dds files:
basisu x.ktx2
Use the -no_ktx and -etc1_only/-format_only options to unpack to less files.
-info and -validate will just display file information and not output any files.
The written mipmapped, cubemap, or texture array .KTX/.DDS files will be in a wide variety of compressed GPU texture formats (PVRTC1 4bpp, ETC1-2, BC1-5, BC7, etc.), and to our knowledge there is unfortunately (as of 2024) still no single .KTX or .DDS viewer tool that correctly and reliably supports every GPU texture format that we support. BC1-5 and BC7 files are viewable using AMD‘s Compressonator, ETC1/2 using Mali’s Texture Compression Tool, and PVRTC1 using Imagination Tech's PVRTexTool. RenderDoc has a useful texture file viewer for many formats. The macOS Finder supports previewing .EXR and .KTX files in various GPU formats. The Windows 11 Explorer can preview .DDS files. The online OpenHDR Viewer is useful for viewing .EXR/.HDR image files.
All key encoder and all transcoder functionality is now available from Python, but this is still in the early stages of development. See the README files in the python directory for how to build the native SO‘s/PYD’s. The Python support module supports both native and WASM modules, which is used as a fallback if native libraries can't be loaded. Python support has been tested under Ubuntu Linux and Windows 11 so far.
Example:
cd python python3 -m tests.test_backend_loading ========== BACKEND LOADING TEST ========== Testing native backend... [Encoder] Using native backend [OK] Native backend loaded Hello from basisu_wasm_api.cpp version 200 Native get_version() ? 200 Native alloc() returned ptr = 190977024 Native free() OK [OK] Native basic operations working. Testing WASM backend... [WASM Encoder] Loaded: /mnt/c/dev/xuastc4/python/basisu_py/wasm/basisu_module_st.wasm [Encoder] Using WASM backend [OK] WASM backend loaded Hello from basisu_wasm_api.cpp version 200 WASM get_version() ? 200 WASM alloc() returned ptr = 26920160 WASM free() OK [OK] WASM basic operations working. ========== DONE ==========
The ‘WebGL’ directory contains several simple WebGL demos that use the transcoder and compressor compiled to WASM with emscripten. These demos are online here. See more details in the readme file here.
Both the transcoder and encoder may be compiled using emscripten to WebAssembly and used on the web. A set of JavaScript wrappers to the codec, written in C++ with emscripten extensions, is located in webgl/transcoding/basis_wrappers.cpp. The JavaScript wrapper supports nearly all features and modes, including texture video. See the README.md and CMakeLists.txt files in webgl/transcoder and webgl/encoder.
To build the WASM transcoder, after installing emscripten:
cd webgl/transcoder/build emcmake cmake .. make
To build the WASM encoder:
cd webgl/encoder/build emcmake cmake .. make
There are two simple encoding/transcoding web demos, located in webgl/ktx2_encode_test and webgl/texture_test, that show how to use the encoder‘s and transcoder’s JavaScript wrapper APIs.
Some simple examples showing how to directly call the C++ encoder and transcoder library APIs are in example/examples.cpp.
See the wiki here.
You can download and install Basis Universal using the vcpkg dependency manager:
git clone https://github.com/Microsoft/vcpkg.git cd vcpkg ./bootstrap-vcpkg.sh ./vcpkg integrate install vcpkg install basisu
The Basis Universal port in vcpkg is kept up to date by Microsoft team members and community contributors. If the version is out of date, please create an issue or pull request on the vcpkg repository. (9/10/2024: UASTC HDR support is not available here yet.)
The transcoder and core encoder libraries are Apache 2.0. The transcoder utilizes no 3rd party libraries or dependencies. See LICENSE.
The encoder library is Apache 2.0, but it utilizes some open source 3rd party modules (in ‘encoder/3rdparty’ and in the ‘Zstd’ directory) to load .QOI, .DDS, .EXR images, to handle Zstd compression, and to unpack ASTC texture blocks. See the LICENSES and .reuse folders.
The repository has been updated to be compliant with the REUSE license checking tool (https://reuse.software/). See the .reuse subdirectory.
Online .EXR HDR Image File Viewer
Windows HDR + WCG Image Viewer - A true HDR image viewer for Windows. Also see the github repo.
Mali Texture Compression Tool - Now deprecated
For more useful links, papers, and tools/libraries, see the end of the UASTC HDR texture specification.
E-mail: info @ binomial dot info, or contact us on Twitter
Here's the Sponsors wiki page.