
Pure AV1/AVIF decoding: still images and sequences, grid composition, alpha/depth/gain map handling, CICP/ICC/Exif metadata passthrough, multiple bit-depths, and full AV1 toolset.
English | 简体中文
A pure-Kotlin AV1 / AVIF decoder for Kotlin Multiplatform.
dimg) with cell composition and edge trimming.ispe) and depth.nclx CICP conversion (BT.601/709/2020, FCC, SMPTE 240M, YCgCo, identity), ICC profile,
Exif and XMP metadata passthrough.irot, imir, clap.| Target | Minimum |
|---|---|
| JVM | Java 8 |
| Android | API 21 (Android 5.0) |
Add the dependency to your build.gradle.kts:
implementation("io.github.zf1234d:kavif-kmp:<version>")import org.glavo.avif.AvifImage
val image = AvifImage.read(bytes)
val frame = image.firstFrame()
val width = frame.width()
val height = frame.height()
// 8-bit packed, non-premultiplied ARGB in 0xAARRGGBB.
val argb: IntArray = frame.intPixels()
// 16-bit packed, non-premultiplied ARGB in 0xAAAA_RRRR_GGGG_BBBB.
val argb16: LongArray = frame.longPixels()intPixels() and longPixels() are interchangeable. An 8-bit frame expands each channel to
16-bit on longPixels(); a 16-bit frame reduces each channel to 8-bit with rounding on
intPixels().
val frames = AvifImage.read(bytes).frames() // every frame, in presentation orderval info = image.info()
val alphaPresent = info.alphaPresent()
val colorInfo = info.colorInfo() // CICP primaries / transfer / matrix, or null
val iccProfile = info.iccProfile()
val exif = info.exif()
val xmp = info.xmp()Provides Bitmap helpers. Decoding is CPU-bound; call it off the main thread.
import io.github.zf1234d.avif.decodeBitmap
import io.github.zf1234d.avif.decodeBitmaps
import io.github.zf1234d.avif.toBitmap
val bitmap: Bitmap = decodeBitmap(bytes) // first frame as a Bitmap
val bitmaps: List<Bitmap> = decodeBitmaps(bytes) // every frame as a Bitmap
val frameBitmap: Bitmap = frame.toBitmap() // any AvifFrame as a BitmapBitmap is always 8-bit ARGB_8888; HDR (10/12-bit) content is rounded down. Use longPixels()
if your pipeline needs full precision before tone mapping.
Requirements: JDK 17 or newer, and an Android SDK for the Android target.
# compile all targets and run all tests
./gradlew build
# JVM test suite only
./gradlew jvmTest
# Android AAR, JVM JAR, metadata
./gradlew assemble
# install to ~/.m2 for local testing
./gradlew publishToMavenLocalLicensed under the Apache License 2.0. See LICENSE for details.
Some source files are derived from javif and remain under the
Mozilla Public License 2.0, with the original copyright preserved in the file headers. See
LICENSE-MPL for the license text.
This project (source code and documentation alike) was produced with AI assistance and reviewed and iteratively debugged by a human. AI-generated content may contain errors, omissions, outdated or misleading information; read the code and verify its behavior yourself before use.
javif by Glavo.
Referenced the decoding behavior of libavif.
English | 简体中文
A pure-Kotlin AV1 / AVIF decoder for Kotlin Multiplatform.
dimg) with cell composition and edge trimming.ispe) and depth.nclx CICP conversion (BT.601/709/2020, FCC, SMPTE 240M, YCgCo, identity), ICC profile,
Exif and XMP metadata passthrough.irot, imir, clap.| Target | Minimum |
|---|---|
| JVM | Java 8 |
| Android | API 21 (Android 5.0) |
Add the dependency to your build.gradle.kts:
implementation("io.github.zf1234d:kavif-kmp:<version>")import org.glavo.avif.AvifImage
val image = AvifImage.read(bytes)
val frame = image.firstFrame()
val width = frame.width()
val height = frame.height()
// 8-bit packed, non-premultiplied ARGB in 0xAARRGGBB.
val argb: IntArray = frame.intPixels()
// 16-bit packed, non-premultiplied ARGB in 0xAAAA_RRRR_GGGG_BBBB.
val argb16: LongArray = frame.longPixels()intPixels() and longPixels() are interchangeable. An 8-bit frame expands each channel to
16-bit on longPixels(); a 16-bit frame reduces each channel to 8-bit with rounding on
intPixels().
val frames = AvifImage.read(bytes).frames() // every frame, in presentation orderval info = image.info()
val alphaPresent = info.alphaPresent()
val colorInfo = info.colorInfo() // CICP primaries / transfer / matrix, or null
val iccProfile = info.iccProfile()
val exif = info.exif()
val xmp = info.xmp()Provides Bitmap helpers. Decoding is CPU-bound; call it off the main thread.
import io.github.zf1234d.avif.decodeBitmap
import io.github.zf1234d.avif.decodeBitmaps
import io.github.zf1234d.avif.toBitmap
val bitmap: Bitmap = decodeBitmap(bytes) // first frame as a Bitmap
val bitmaps: List<Bitmap> = decodeBitmaps(bytes) // every frame as a Bitmap
val frameBitmap: Bitmap = frame.toBitmap() // any AvifFrame as a BitmapBitmap is always 8-bit ARGB_8888; HDR (10/12-bit) content is rounded down. Use longPixels()
if your pipeline needs full precision before tone mapping.
Requirements: JDK 17 or newer, and an Android SDK for the Android target.
# compile all targets and run all tests
./gradlew build
# JVM test suite only
./gradlew jvmTest
# Android AAR, JVM JAR, metadata
./gradlew assemble
# install to ~/.m2 for local testing
./gradlew publishToMavenLocalLicensed under the Apache License 2.0. See LICENSE for details.
Some source files are derived from javif and remain under the
Mozilla Public License 2.0, with the original copyright preserved in the file headers. See
LICENSE-MPL for the license text.
This project (source code and documentation alike) was produced with AI assistance and reviewed and iteratively debugged by a human. AI-generated content may contain errors, omissions, outdated or misleading information; read the code and verify its behavior yourself before use.
javif by Glavo.
Referenced the decoding behavior of libavif.