Dynamic Color Retrieval from Images using Jetpack Compose
In recent times, dynamic color adaptation has become a popular trend in mobile app design. Take a look at apps like Spotify, Youtube, or Youtube Music — their background colors adjust dynamically based on the artwork of the song or video being played. This not only adds a touch of visual appeal but also enhances the user experience by creating a cohesive look and feel. This article will explore how to achieve this functionality using Jetpack Compose in Kotlin.
Extracting Dominant Color from an Image
The first step involves obtaining the dominant color from an image. Jetpack Compose offers a powerful tool called Palette
for color analysis. Here's how to utilize it:
private fun getHslOfDrawable(drawable: Drawable): FloatArray? {
val palette = Palette.Builder(
drawable.toBitmap()
.copy(Bitmap.Config.RGBA_F16, true)
)
.clearFilters()
.maximumColorCount(8)
.generate()
val hsl = palette.dominantSwatch?.hsl
return hsl
}
This function converts the Drawable
to a bitmap with ARGB format (Bitmap.Config.RGBA_F16
), generates a palette with a maximum of 8 colors for analysis, and then retrieves the HSL (Hue, Saturation, Lightness) values of the dominant color swatch (if available).
Adjusting the Color for Background Use
Once you have the HSL values, you can manipulate them to create a suitable background color. We’ll adjust the saturation and lightness for better readability of foreground content. Here, Jetpack Compose’s Color.hsl
function comes in handy for creating colors from HSL values. ( this is simply the same calculation that we have used in the SwiftUI-Blog )
var ambientColor by remember { mutableStateOf(Color.White) }
LaunchedEffect(drawable) {
val drawable = drawable ?: return@LaunchedEffect
val hsl = getHslOfDrawable(drawable)
hsl?.let {
ambientColor = Color.hsl(hsl.hue(), 0.9f, 0.06f, 1f)
}
}
If we gather everything together, we end up with something like this
@Composable
fun AmbientColorView(
modifier: Modifier = Modifier
) {
var photoUri by remember { mutableStateOf<Uri?>(null) }
var drawable by remember { mutableStateOf<Drawable?>(null) }
val photoPicker =
rememberLauncherForActivityResult(contract = ActivityResultContracts.PickVisualMedia(),
onResult = { uri -> uri?.let { photoUri = it } })
var ambientColor by remember { mutableStateOf(Color.White) }
LaunchedEffect(drawable) {
// ... (code as shown previously)
}
Surface(
modifier = modifier.fillMaxSize(),
color = ambientColor
) {
Box {
// ... (rest of the UI content)
}
}
}
After putting everything together, the end result looks like this.

Feel free to experiment with different values for saturation and lightness to create the desired background effect. You can also explore advanced color analysis techniques offered by the Palette
class for more fine-grained control. ( source code is below 👇 ).
In Conclusion
This article provided a basic approach to dynamically extract color from images and use it for background adjustments in Jetpack Compose applications. By leveraging Jetpack Compose’s Palette
and color manipulation functions, you can create visually appealing and dynamic user interfaces.