apng
1.0.1indexedHigh-performance APNG parsing and rendering with precomposed frames, Compose-style painters, declarative and imperative playback controls, optional HTTP network loading and disk LRU caching.
High-performance APNG parsing and rendering with precomposed frames, Compose-style painters, declarative and imperative playback controls, optional HTTP network loading and disk LRU caching.
A high-performance APNG (Animated PNG) parsing and rendering library built with Kotlin Multiplatform(KMP). It provides consistent animation rendering across Android, iOS, Desktop (JVM), and Web (JS/Wasm).
| Android | Desktop (JVM) | iOS | macOS | JS | WasmJS |
|---|
Add the dependencies you need to your build.gradle.kts:
// Core: APNG parsing + frame composing + Compose animation rendering (required)
implementation("io.github.lugf027:apng-core:<version>")
// Network: Ktor-based URL loading with disk LRU caching
implementation("io.github.lugf027:apng-network:<version>")
// Resources: Load APNG from KMP Resources (Res)
implementation("io.github.lugf027:apng-resources:<version>")
apng-networktransitively includesapng-network-core(disk cache layer). You only needapng-network-coredirectly if you want caching without the built-in Ktor client.
// From byte array
val composition by rememberApngComposition(
ApngCompositionSpec.Bytes(byteArray, cacheKey = "my_anim")
)
// From URL (requires apng-network)
val composition by rememberApngComposition(
ApngCompositionSpec.Url("https://example.com/animation.apng")
)
// From Compose Resources (requires apng-resources)
val composition by rememberApngComposition(
ApngCompositionSpec.ComposeResource { Res.readBytes("files/animation.apng") }
)
Declarative (recommended):
val progress by animateApngCompositionAsState(
composition,
isPlaying = true,
iterations = Apng.IterateForever,
)
val painter = rememberApngPainter(composition, progress = { progress })
Image(painter = painter, contentDescription = null)
Imperative:
val animatable = rememberApngAnimatable()
LaunchedEffect(composition) {
animatable.animate(composition, iterations = Apng.IterateForever)
}
val painter = rememberApngPainter(composition, progress = { animatable.progress })
Image(painter = painter, contentDescription = null)
Shorthand:
val painter = rememberApngPainter(composition, isPlaying = true)
Image(painter = painter, contentDescription = null)
val progress by animateApngCompositionAsState(
composition,
isPlaying = true,
speed = 1.5f, // Playback speed
iterations = Apng.IterateForever, // Loop forever (or pass an Int)
clipSpec = ApngClipSpec.Frame(2, 8), // Play only frames 2–8
)
apng-core ← standalone
apng-network-core ← apng-core + okio
apng-network ← apng-core + apng-network-core + ktor-client-core
apng-resources ← apng-core + compose.components.resources
# Desktop
./gradlew :example:desktopApp:run
# Android
./gradlew :example:androidApp:installDebug
# Web (JS)
./gradlew :example:webApp:jsBrowserDevelopmentRun
# Web (WasmJS)
./gradlew :example:webApp:wasmJsBrowserDevelopmentRun
# iOS — open in Xcode, then run (Cmd + R)
open example/iosApp/iosApp.xcodeproj
MIT License
Copyright (c) 2026 lugf027
See LICENSE for details.
| ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
| Module | Artifact | Description |
|---|
| apng-core | io.github.lugf027:apng-core | APNG parsing, frame composing, and Compose animation rendering |
| apng-network-core | io.github.lugf027:apng-network-core | Disk LRU cache and network caching strategy |
| apng-network | io.github.lugf027:apng-network | Ktor-based network loading with built-in disk caching |
| apng-resources | io.github.lugf027:apng-resources | KMP Resources integration |
| Class / Function | Purpose |
|---|
ApngComposition | Pre-composed frame data container |
ApngCompositionSpec | Loading specification (Bytes / Url / ComposeResource) |
rememberApngComposition() | Composable that loads and caches a composition |
animateApngCompositionAsState() | Declarative animation driver |
rememberApngAnimatable() | Imperative animation controller |
rememberApngPainter() | Creates a Painter from a composition + progress |
ApngClipSpec | Frame/progress range clipping |
Apng.IterateForever | Constant for infinite looping |
| Feature | Android | Skiko (JVM / iOS / macOS / JS / WasmJS) |
|---|
| Image decoding | BitmapFactory | Image.makeFromEncoded (Skia) |
| Frame composing | Android Canvas + PorterDuff | Skia Canvas + BlendMode |
| Disk cache | ✅ (FileSystem.SYSTEM) | JVM/Native ✅ · Web ❌ |
Surfaced from shared tags and platforms — no rankings paid for.