Panama FFM bindings for libavif with bundled, from-source native libraries. One Maven coordinate gives Java 22+ direct access to the complete public libavif 1.4.2 C API, without JNI or a system libavif installation.
| Artifact | Contents | License |
|---|---|---|
io.github.ghosthack:libavif-ffm |
jextract-generated Java stubs and runtime loader | MIT |
io.github.ghosthack:libavif-ffm-natives |
platform shared library with statically linked codecs | BSD licenses; see THIRD-PARTY.md |
Supported classifiers are macos-arm64, windows-x64, and linux-x64.
The native build uses dav1d 1.5.3 for decoding, libaom 3.14.1 for encoding,
and libyuv for accelerated RGB/YUV conversion. libavif's automatic decoder
selection prefers dav1d.
<dependency>
<groupId>io.github.ghosthack</groupId>
<artifactId>libavif-ffm</artifactId>
<version>1.4.2-0.1.0</version>
</dependency>
<dependency>
<groupId>io.github.ghosthack</groupId>
<artifactId>libavif-ffm-natives</artifactId>
<version>1.4.2-0.1.0</version>
<classifier>macos-arm64</classifier> <!-- windows-x64 or linux-x64 -->
<scope>runtime</scope>
</dependency>On the module path, declare requires libavif.ffm; and run with
--enable-native-access=libavif.ffm. On the class path, use
--enable-native-access=ALL-UNNAMED.
import io.github.ghosthack.libavifffm.libavif.LibAvif;
String version = LibAvif.avifVersion().getString(0);
String decoder = LibAvif.avifCodecName(
LibAvif.AVIF_CODEC_CHOICE_AUTO(),
LibAvif.AVIF_CODEC_FLAG_CAN_DECODE()).getString(0); // dav1dThe API intentionally mirrors C: pointers are MemorySegment, structs have
generated layout/accessor classes such as avifImage, avifDecoder, and
avifRGBImage, and callers own native lifetimes. See
core/src/test/java/io/github/ghosthack/libavifffm/LibAvifSmokeTest.java for a
complete RGBA → AVIF → RGBA encode/decode round trip with correct cleanup.
The generated stubs resolve symbols lazily in this order:
-Dlibavifffm.libdir=<dir>orLIBAVIF_FFM_LIBDIR;- the matching natives classifier jar, extracted once under
~/.cache/libavif-ffm/<version>-<platform>/; - libraries already loaded by the host process and the platform's default symbol lookup.
The override is useful for testing a compatible system build or substituting custom codec options.
Each native classifier must be built on its target OS. Start from the tagged libavif source:
mkdir -p build
curl -sfL https://github.com/AOMediaCodec/libavif/archive/refs/tags/v1.4.2.tar.gz | tar xz -C build
build-natives/macos-arm64.sh
jextract/gen-bindings.sh
mvn installgen-bindings.sh uses jextract 22 from ../ffmpeg-ffm by default; set
JEXTRACT=/path/to/jextract to override it. Stub generation is performed once
on macOS because libavif's public C layouts are portable across the supported
64-bit targets.
The Linux script needs CMake, GCC/G++, Git, Meson, Ninja, NASM, Perl, and patchelf. The Windows script documents its MSYS2 MINGW64 prerequisites in its header. Every script rejects unexpected dynamic dependencies and stages licenses plus reproducible build metadata beside the library.
jextract 22's indexed accessor for an array field can address relative to the start of a struct rather than the array field. Prefer a field slice, for example:
MemorySegment planes = avifImage.yuvPlanes(image);
MemorySegment yPlane = planes.getAtIndex(ValueLayout.ADDRESS, 0);instead of the generated indexed convenience overload.