class new in 2019.10
BasisImageConverterBasis Universal image converter plugin.
Creates Basis Universal compressed image files (*.basis
or *.ktx2
) from 2D and 2D array images with optional mip levels. You can use BasisImporter to import images in this format.
This plugin provides BasisKtxImageConverter
.
Usage
This plugin depends on the Trade and Basis Universal libraries and is built if MAGNUM_WITH_BASISIMAGECONVERTER
is enabled when building Magnum Plugins. To use as a dynamic plugin, load "BasisImageConverter"
via Corrade::v1_50_0_2
1.16.4
and v1_15_update2
tags, but could possibly compile against newer versions as well.
Additionally, if you're using Magnum as a CMake subproject, bundle the magnum-plugins, zstd and basis-universal repositories and do the following. Basis uses Zstd for KTX2 images, instead of bundling you can depend on an externally-installed zstd package, in which case omit the first part of the setup below. If Zstd isn't bundled and isn't found externally, Basis will be compiled without Zstd support.
set(ZSTD_BUILD_PROGRAMS OFF CACHE BOOL "" FORCE) # Create a static library so the plugin is self-contained set(ZSTD_BUILD_SHARED OFF CACHE BOOL "" FORCE) set(ZSTD_BUILD_STATIC ON CACHE BOOL "" FORCE) # Basis doesn't use any multithreading in zstd, this prevents a need to link to # pthread on Linux set(ZSTD_MULTITHREAD_SUPPORT OFF CACHE BOOL "" FORCE) # Don't build Zstd tests if enable_testing() was called in parent project set(ZSTD_BUILD_TESTS OFF CACHE BOOL "" FORCE) add_subdirectory(zstd/build/cmake EXCLUDE_FROM_ALL) set(BASIS_UNIVERSAL_DIR ${CMAKE_CURRENT_SOURCE_DIR}/basis-universal) set(MAGNUM_WITH_BASISIMAGECONVERTER ON CACHE BOOL "" FORCE) add_subdirectory(magnum-plugins EXCLUDE_FROM_ALL) # So the dynamically loaded plugin gets built implicitly add_dependencies(your-app MagnumPlugins::BasisImageConverter)
When compiling Basis from source with BASIS_UNIVERSAL_DIR
, Basis will be built with OpenCL support if the OpenCL package is found. To build Basis without a hard dependency on OpenCL, pass -DCMAKE_DISABLE_FIND_PACKAGE_OpenCL=ON
to CMake, or set()
it before the add_subdirectory()
call if using Magnum Plugins as a subproject.
To use as a static plugin or as a dependency of another plugin with CMake, request the BasisImageConverter
component of the MagnumPlugins
package and link to the MagnumPlugins::BasisImageConverter
target:
find_package(MagnumPlugins REQUIRED BasisImageConverter) # ... target_link_libraries(your-app PRIVATE MagnumPlugins::BasisImageConverter)
See Downloading and building plugins, Plugin usage with CMake, Loading and using plugins and File format support for more information.
Behavior and limitations
Accepts 2D, 2D array, cube map and cube map array images, recognizing ImageFlag3D::
HDR floating point formats require at least version 1.50 of Basis.
The alpha channel of RGBA32F will be dropped and transcoded to 1 because Basis UASTC HDR doesn't support alpha channels.
Even though the KTX container format supports 1D, 1D array and 3D images, Basis Universal doesn't. In particular, if a 2D image with ImageFlag2D::
The plugin recognizes ImageConverterFlag::
Multilevel images
Images can be saved with multiple levels by using the list variants of convertToFile() / convertToData(). Largest level is expected to be first, with each following level having width and height divided by two, rounded down. Because only 2D array images are supported, depth has to have the same size in all levels. Incomplete mip chains are supported.
To generate mip levels from a single top-level image instead, you can use the mip_gen
configuration option.
Implicit swizzling
If no user-specified channel mapping is supplied through the swizzle
configuration option, the converter swizzles 1- and 2-channel formats before compression as follows:
- 1-channel formats (PixelFormat::
R8Unorm / PixelFormat:: R8Srgb / PixelFormat:: R32F) are remapped as RRR, producing an opaque gray-scale image - 2-channel formats (PixelFormat::
RG8Unorm / PixelFormat:: RG8Srgb / PixelFormat:: RG32F) are remapped as RRRG, ie. G becomes the alpha channel. This significantly improves compressed image quality because RGB and alpha get separate slices instead of the two channels being compressed into a single slice.
Setting the swizzle
option to any value disables this behavior. To keep the original channel order, set swizzle=rgba
.
Converting to KTX2
To create Khronos Texture 2.0 (*.ktx2
) files, either load the plugin as BasisKtxImageConverter
or call convertToFile() with the .ktx2
extension. In all other cases, a Basis Universal (*.basis
) file is created.
The extension() is "ktx2"
and mimeType() "image/ktx2"
if the plugin is loaded as BasisKtxImageConverter
. In all other cases (and independently of what file extension is used in a call to convertToFile()), extension is "basis"
and mimeType() is an empty string as the Basis Universal file format doesn't have a registered MIME type.
Loading the plugin fails with undefined symbol: pthread_create
On Linux it may happen that loading the plugin will fail with undefined symbol: pthread_create
. The Basis encoder is optionally multithreaded and while linking the dynamic plugin library to pthread
would resolve this particular error, the actual thread creation (if the threads
configuration option is set to something else than 1
) later would cause std::pthread
instead. With CMake it can be done like this:
find_package(Threads REQUIRED) target_link_libraries(your-application PRIVATE Threads::Threads)
Thread safety
While the encoder library should behave in a way that doesn't modify any global state, in versions before 1.16 the library initialization done at plugin load time is populating global safe in a non-thread-safe way. Thus you have to ensure that the plugin isn't loaded from multiple threads at the same time, or loaded while being already used from another thread.
Plugin-specific configuration
Basis compression can be configured to produce better quality or reduce encoding time. Configuration options are equivalent to parameters of the C++ encoder API in basis_compressor
. The basisu
tool options mostly match the encoder API parameters and its help text provides useful descriptions of most of the parameters, their ranges and the impact on quality/speed. The full form of the configuration is shown below:
[configuration] # All following options correspond to parameters of the `basis_compressor` # C++ API and may differ from what the basisu tool exposes. # Options quality_level=128 # Treat images as sRGB color data, rather than linear intensity. Leave blank # to determine from the image format. perceptual= debug=false validate=false debug_images=false compute_stats=false compression_level=2 # More options max_endpoint_clusters=512 max_selector_clusters=512 y_flip=true # The `normal_map` setting is just an alias disabling `perceptual` and # `mip_srgb` and enabling `no_selector_rdo` & `no_endpoint_rdo` check_for_alpha=true force_alpha=false # Remap color channels before compression. Must be empty or 4 characters # long, valid characters are r,g,b,a. This replaced # separate_rg_to_color_alpha, for the same effect use 'rrrg'. swizzle= renormalize=false resample_width= resample_height= resample_factor= # Number of threads Basis should use during compression, 0 sets it to the # value returned by std::thread::hardware_concurrency(), 1 disables # multithreading. This value is clamped to # std::thread::hardware_concurrency() internally by Basis itself. threads=1 disable_hierarchical_endpoint_codebooks=false # Mipmap generation options # Generate mipmaps from the base image. If you pass custom mip levels into # openData, this option will be ignored. Leave blank to determine from the # number of levels passed to convertToData. mip_gen=false # Filter mipmaps assuming sRGB color data, rather than linear intensity. # Leave blank to determine from the image format. mip_srgb= mip_scale=1.0 mip_filter=kaiser mip_renormalize=false mip_wrapping=true mip_fast=true mip_smallest_dimension=1 # Backend endpoint/selector RDO codec options no_selector_rdo=false selector_rdo_threshold=1.25 no_endpoint_rdo=false endpoint_rdo_threshold=1.5 # UASTC options uastc=false pack_uastc_level=2 pack_uastc_flags= rdo_uastc=false rdo_uastc_quality_scalar=1.0 rdo_uastc_dict_size=4096 rdo_uastc_max_smooth_block_error_scale=10.0 rdo_uastc_smooth_block_max_std_dev=18.0 rdo_uastc_max_allowed_rms_increase_ratio=10.0 rdo_uastc_skip_block_rms_threshold=8.0 rdo_uastc_favor_simpler_modes_in_rdo_mode=true # HDR options # Quality level from 0 (fastest) to 4 (highest quality) hdr_quality_level=1 hdr_favor_astc=false # KTX2 options ktx2_uastc_supercompression=true ktx2_zstd_supercompression_level=6 # OpenCL acceleration. Falls back to CPU encoding if OpenCL isn't supported or # fails during encoding. use_opencl=false # Set various fields in the Basis file header userdata0=0 userdata1=0
See Editing plugin-specific configuration for more information and an example showing how to edit the configuration values.
Base classes
- class AbstractImageConverter
- Base for image converter plugins.
Public types
Public static functions
- static void initialize() new in Git master
- Initialize Basis encoder.
- static void finalize() new in Git master
- Finalize Basis encoder.
Constructors, destructors, conversion operators
- BasisImageConverter(Format format = Format{}) deprecated in Git master explicit
- Default constructor.
-
BasisImageConverter(PluginManager::
AbstractManager& manager, const Containers:: StringView& plugin) explicit - Plugin manager constructor.
Enum documentation
Function documentation
Magnum:: Trade:: BasisImageConverter:: BasisImageConverter(Format format = Format{}) explicit
Default constructor.