Standalone Java decoder/transcoder port for Basis Universal, and Gradle plugin for build-time texture conversion.
Note
The original code was ported primarily by GPT-5.5, with minimal human intervention limited to testing and patching.
decoder: pure Java runtime API and implementation. This is the artifact to embed in applications and engine integrations.parity-tests: end-to-end parity harness. It builds the officialbasisutool from the trackedbasis_universalsubmodule inbuild/, encodes test PNGs, unpacks them with the official tool, decodes the same payload with Java, and compares RGBA pixels plus packed RGB565/BGR565/RGBA4444 output derived from the official unpack.basis-gradle-plugin: Gradle plugin for build-time texture conversion. It scans resources, writes generated.basisfiles underbuild/generated, and wires them into the runtime classpath without modifying developer source resources.basis_universal: Git submodule pinned to the official Basis Universal reference repository.
./gradlew :decoder:test
./gradlew :parity-tests:test
./gradlew parityTest
./gradlew checkTip
Running parityTest requires a native C++ toolchain with CMake.
The decoder library and the basis-gradle-plugin are published with the
org.ngengine.basis Maven group. Local development defaults to
1.0.0-SNAPSHOT; release automation supplies the version from the GitHub
release tag.
GitHub Actions publishes 1.0.0-SNAPSHOT to the Central Portal snapshot
repository after every successful commit on master. A Maven Central release
is published when a GitHub Release is published, using a tag such as v1.0.0.
The Central Portal namespace org.ngengine.basis must be verified and have
snapshot publishing enabled before the workflows can deploy. Configure these
repository secrets:
GPG_PRIVATE_KEYGPG_PASSPHRASESONATYPE_USERNAMESONATYPE_PASSWORD
For local snapshot publication, run:
./gradlew publishSnapshots -PprojectVersion=1.0.0-SNAPSHOTThe runtime decoder is platform and rendering-engine agnostic. Callers must
choose a BasisTranscodeTarget explicitly; the decoder never inspects
GPU capabilities, identifies a runtime platform, or selects a fallback format.
Platform-specific target ordering belongs in the consuming engine or
application.
.basisETC1S to RGBA8, RGB565/BGR565/RGBA4444, ETC1/ETC2, ETC2 EAC R11/RG11, BC1/BC3/BC4/BC5/BC7.basisUASTC LDR 4x4 to RGBA8, RGB565/BGR565/RGBA4444, ETC1/ETC2, ETC2 EAC R11/RG11, BC1/BC3/BC4/BC5/BC7, and ASTC 4x4- KTX2 ETC1S to RGBA8, RGB565/BGR565/RGBA4444, ETC1/ETC2, ETC2 EAC R11/RG11, BC1/BC3/BC4/BC5/BC7
- KTX2 UASTC LDR 4x4 to RGBA8, RGB565/BGR565/RGBA4444, ETC1/ETC2, ETC2 EAC R11/RG11, BC1/BC3/BC4/BC5/BC7, and ASTC 4x4, including selected array images
- KTX2 XUASTC LDR to RGBA8, RGB565/BGR565/RGBA4444,
ETC1/ETC2, ETC2 EAC R11/RG11, BC1/BC3/BC4/BC5, matching ASTC LDR block
sizes covered by the native-gold fixture suite, default BC7 for validated
4x4, 5x4, 5x5, 6x5, 6x6, 8x5, and 8x6 streams, including the dedicated
4x4, 6x6, and 8x6 fast paths, plus the same validated block sizes on the
cDecodeFlagXUASTCLDRDisableFastBC7Transcodinggeneric path, BC7 no-deblock parity for 8x8, 10x5, 10x6, 10x8, 10x10, 12x10, and 12x12 streams whencDecodeFlagsNoDeblockFilteringis requested, and reference parity for BC7 high-quality and whole-image deblocked transcoding paths covered by the parity fixture suite .basisUASTC HDR 4x4, ASTC HDR 6x6, and UASTC HDR 6x6 intermediate to matching ASTC HDR GPU payloads (ASTC_HDR_4X4/ASTC_HDR_6X6) and CPU HDR payloads (RGB_HALF/RGBA_HALF/RGB_9E5), plus HDR toBC6H, with parity against the official Basis Universal transcoder for default and high-quality 6x6 BC6H paths- KTX2 UASTC HDR 4x4, ASTC HDR 6x6, and UASTC HDR 6x6 intermediate
(
KTX2_SS_UASTC_HDR_6x6I, plus legacy v1.6/v2.0BASISLZ-marked 6x6I containers) to matching ASTC HDR GPU payloads and CPU HDR payloads (RGB_HALF/RGBA_HALF/RGB_9E5), plus HDR toBC6H, including the standard KTX2 Zstandard-compressed level payloads emitted bybasisu, with parity against the official Basis Universal transcoder for default and high-quality 6x6 BC6H paths - plain uncompressed KTX2 RGBA payload pass-through, plus Java materialization of KTX2 NONE, Zstandard, and Deflate/Zlib level payloads for direct Java-supported formats
- KTX2 Basis Universal supercompression schemes used by supported texture
payloads:
BASISLZ,XUASTC_LDR, andUASTC_HDR_6x6I
| Format family | Basis Universal targets | Java status | Reason |
|---|---|---|---|
| PVRTC1 | cTFPVRTC1_4_RGB, cTFPVRTC1_4_RGBA |
Not implemented | Legacy PowerVR/mobile path; not a target for the standalone runtime. |
| PVRTC2 | cTFPVRTC2_4_RGB, cTFPVRTC2_4_RGBA |
Not implemented | Narrow hardware support and low integration value for the planned loader. |
| ATC | cTFATC_RGB, cTFATC_RGBA |
Not implemented | Obsolete vendor-specific mobile format. |
| FXT1 | cTFFXT1_RGB |
Not implemented | Obsolete desktop/vendor-specific format. |
The repository includes a plugin for converting textures at build time using the native basisu tool (for macOS, Linux, and Windows on aarch64 and x86_64).
Apply the org.ngengine.basis.texture-encoder plugin to your Java project. By default, the plugin scans src/main/resources for common image formats and generates corresponding .basis files in the build directory.
The plugin can be configured in your build.gradle file as follows:
basisTextures {
imageExtensions.addAll('png', 'jpg', 'jpeg')
resourceDirectories.add('src/main/resources')
excludeOriginalsWhenEncoded = false
}