A Compose Multiplatform library for generating color palettes from images, including the dominant color. You can use this library in combination with MaterialKolor to generate dynamic Material themes based on images.
Supports loading images from several sources, see sources.
Note: This is a port of
the androidx.palette
library.
Platforms
This library is written for Compose Multiplatform, and can be used on the following platforms:
- Android
- iOS / MacOS
- JVM (Desktop)
Inspiration
I created this library because I wanted to use the
androidx.palette
library in a
Compose Multiplatform app. But that library is not multiplatform, so I decided to port it.
Dynamic Material Themes
Want to create a dynamic Material theme based on the dominant color in an image?
Check out my other Compose Multiplatform library MaterialKolor!
Setup
You can add this library to your project using Gradle. There are several optional extension libraries, see sources.
Version Catalog
In libs.versions.toml
:
[versions]
kmpalette = "1.0.0"
[libraries]
kmpalette-core = { module = "com.kmpalette:kmpalette-core", version.ref = "kmpalette" }
# Optional source libraries
kmpalette-extensions-base64 = { module = "com.kmpalette:extensions-base64", version.ref = "kmpalette" }
kmpalette-extensions-bytearray = { module = "com.kmpalette:extensions-bytearray", version.ref = "kmpalette" }
kmpalette-extensions-libres = { module = "com.kmpalette:extensions-libres", version.ref = "kmpalette" }
kmpalette-extensions-network = { module = "com.kmpalette:extensions-network", version.ref = "kmpalette" }
kmpalette-extensions-resources = { module = "com.kmpalette:extensions-resources", version.ref = "kmpalette" }
To add to a multiplatform project, add the dependency to the common source-set:
kotlin {
sourceSets {
commonMain {
dependencies {
// Core library
implementation(libs.kmpalette.core)
// Optional extensions based on your image source
implementation(libs.kmpalette.extensions.base64)
implementation(libs.kmpalette.extensions.bytearray)
implementation(libs.kmpalette.extensions.libres)
implementation(libs.kmpalette.extensions.network)
implementation(libs.kmpalette.extensions.resources)
}
}
}
}
Usage
In order to use this library you first must have a ImageBitmap
object. You can get this from using
one of the sources or by using a library that creates one for you.
Since this library is a port of
the androidx.palette
library,
the usage is very similar. However this library provides some helpful extension functions and
composables.
Look in kmpalette-core
for the main library, including extensions for the Palette
and Swatch
objects.
Included are two helpful @Composeable
-ready State objects:
DominantColorState
– A state object that holds a generated dominantColor
object.PaletteState
– A state object that holds a generatedPalette
object.
They can be used like so:
Dominant Color
You can generate a dominant color from an ImageBitmap
using the rememberDominantColorState
composeable. This will also provide a onColor
for you to use as a text color.
@Composable
fun SomeComposable(bitmap: ImageBitmap) {
val dominantColorState = rememberDominantColorState()
LaunchedEffect(bitmap) {
dominantColorState.updateFrom(bitmap)
}
Box(
modifier = Modifier
.width(200.dp)
.height(100.dp)
.background(dominantColorState.color)
) {
Text("Some Text", color = dominantColorState.onColor)
}
}
Since the generation of the dominant color is an asynchronous operation that can fail, you can track
the results of the operation using the DominantColorState.result
object.
For more examples of getting a dominant color see the demo app
Generate a color Palette
If you want a whole color palette instead of just a dominate color, you can use
the rememberPaletteState
composeable. This will provide a Palette
object which contains a few
different color Swatch
s, each have their own color and onColor.
fun SomeComposable(bitmap: ImageBitmap) {
val paletteState = rememberPaletteState()
LaunchedEffect(bitmap) {
paletteState.generate(bitmap)
}
Box(
modifier = Modifier
.width(200.dp)
.height(100.dp)
.background(paletteState.vibrantSwatch?.color ?: Color.White)
) {
Text(
"Some Text",
color = paletteState.vibrantSwatch?.onColor ?: Color.Black,
)
}
}
Since the generation of the dominant color is an asynchronous operation that can fail, you can track
the results of the operation using the DominantColorState.result
object.
For more examples of generating a Palette see the demo app
Sources
In order to generate a color palette, you must first have an ImageBitmap
object. This library
provides some extensions artifacts for some popular sources.
Artifact | Library | Loader | Input Class | Demo |
---|---|---|---|---|
extensions-base64 |
N/A | Base64Loader |
String |
Base64DemoScreen |
extensions-bytearray |
N/A | ByteArrayLoader |
ByteArray |
N/A |
extensions-libres |
libres | LibresLoader |
Image |
LibresPaletteScreen |
extensions-network |
ktor | NetworkLoader |
Url |
NetworkDemoScreen |
extensions-resources |
Compose Multiplatform Resources | ResourceLoader |
Resource |
ResourcesPaletteScreen |
Each of these extensions provides a ImageBitmapLoader
object that can be used to generate
an ImageBitmap
from the input class. For example, the NetworkLoader
can be used to generate
an ImageBitmap
from a Url
:
@Composable
fun SomeComposable(url: Url) {
val dominantColorState = rememberDominantColorState(loader = NetworkLoader())
LaunchedEffect(url) {
dominantColorState.updateFrom(url)
}
Box(
modifier = Modifier
.width(200.dp)
.height(100.dp)
.background(dominantColorState.color)
) {
Text("Some Text", color = dominantColorState.onColor)
}
}
Demo
A demo app is available in the demo
directory. It is a Compose Multiplatform app that runs on
Android, iOS and Desktop.
See the README for more information.
Feature Requests
If you have a feature request, please open an issue. If you would like to implement a feature request refer to the Contributing section.
Contributing
Contributions are always welcome!. If you’d like to contribute, please feel free to create a PR or open an issue.
License
The module androidx-palette
is licensed under the Apache License, Version 2.0. See
their LICENSE and their
repository here for more
information.
Changes from original source
- Convert Java code to Kotlin
- Convert library to Kotlin Multiplatform
For the remaining code see LICENSE for more information.