romainguy
vibrance
Kotlinโœจ New

Natural color mixing for Kotlin and Compose Multiplatform.

Last updated Jul 3, 2026
61
Stars
1
Forks
2
Issues
0
Stars/day
Attention Score
43
Language breakdown
Kotlin 57.7%
Python 23.2%
Jupyter Notebook 18.9%
Shell 0.1%
โ–ธ Files click to expand
README

Vibrance

Natural color mixing for Kotlin and Compose Multiplatform.

Using this library you can mix (or interpolate) sRGB colors as real-world paints. This process creates a different path between the source and destination colors, replicating subtractive color mixing.

The screenshot below compares gradients generated by this library to gradients produced by Compose out of the box. In each pair, the left or top gradient was generated by Vibrance, and the right or bottom gradient was generated by Compose:

Gradients Comparison

Features

  • Subtractive color mixing: Interpolates sRGB colors by converting them to a latent color space
representing pigment concentrations (Phthalo Blue, Quinacridone Magenta, Hansa Yellow, and Titanium White).
  • Kotlin Multiplatform: Supports Android, JVM, iOS, macOS, JS, and Wasm.
  • Jetpack Compose / Compose Multiplatform Support: Provides easy-to-use Compose APIs, including
modifiers and brushes to add paint-mixed gradients: - Vertical gradients - Horizontal gradients - Directional gradients - Radial gradients - Sweep gradients

Dependencies

[!WARNING]
Vibrance is not published yet. Stay tuned!

Add the following to your build.gradle.kts:

dependencies {
    // For core color mixing logic
    implementation("dev.romainguy:vibrance:0.x.0")

// For Compose APIs implementation("dev.romainguy:vibrance-compose:0.x.0") }

Usage

Core library (vibrance)

The Vibrance class is the main entry point to mix colors. You can mix sRGB colors directly, or for performance-critical scenarios like animations, you can mix colors in the latent space.

import dev.romainguy.vibrance.Vibrance

val vibrance = Vibrance()

// 1. Direct color mixing // Mix blue and yellow by 25% (amount is between 0.0f and 1.0f) val color = vibrance.colorsMix( srcR = 0.0f, srcG = 0.0f, srcB = 1.0f, // Blue dstR = 0.0f, dstG = 1.0f, dstB = 1.0f, // Yellow amount = 0.25f )

// 2. Optimized mixing via latent colors // Upscaling to latent color space is the most expensive operation. // If you are interpolating frequently, pre-compute the latent colors. val latentBlue = vibrance.colorToLatentColor(0.0f, 0.0f, 1.0f) val latentYellow = vibrance.colorToLatentColor(0.0f, 1.0f, 1.0f)

// Interpolate the latent colors, which is much faster val color = vibrance.latentColorsMix(latentBlue, latentYellow, 0.25f)

You can also explicitly supply an array of floats to prevent allocations:

val latentBlue = FloatArray(6)
vibrance.colorToLatentColor(0.0f, 0.0f, 1.0f, latentBlue)

Jetpack Compose (vibrance-compose)

Modifiers

If you are using Jetpack Compose or Compose Multiplatform, you can easily create natural gradients using the provided modifiers:

import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import dev.romainguy.vibrance.compose.horizontalPaintGradient
import dev.romainguy.vibrance.compose.verticalPaintGradient

// Vertical paint gradient from Blue to Yellow Column(Modifier .fillMaxSize() .verticalPigmentsGradient( startColor = Color.Blue, endColor = Color.Yellow ) ) { // ... }

// Horizontal paint gradient from Red to Green Row(Modifier .fillMaxWidth() .horizontalPigmentsGradient( startColor = Color.Red, endColor = Color.Green ) ) { // ... }

Here are all the available gradient modifiers:

  • Modifier.horizontalPigmentsGradient
  • Modifier.verticalPigmentsGradient
  • Modifier.linearPigmentsGradient
  • Modifier.radialPigmentsGradient
  • Modifier.sweepPigmentsGradient
All gradient types except sweep gradients support the following tile modes:
  • TileMode.Clamp: default behavior, hold the start/end colors outside its bounds.
  • TileMode.Repeated: restarts the gradient outside its bounds.
  • TileMode.Mirror: repeats and mirrors the gradient outside its bounds.
  • TileMode.Decal: output fully transparent pixels outside the gradient bounds.

Brushes

Modifiers are a convenient way to add a gradient as a background to a Composable. For more flexibility, Vibrance offers a set of Brush APIs:

  • Brush.horizontalPigmentsGradient
  • Brush.verticalPigmentsGradient
  • Brush.linearPigmentsGradient
  • Brush.radialPigmentsGradient
  • Brush.sweepPigmentsGradient
They operate exactly like the modifiers and can be used anywhere Compose expects a brush. For instance, to set a Vibrance gradient as a background:

Row(Modifier
    .fillMaxWidth()
    .background(Brush.horizontalPigmentsGradient(Color.Red, Color.Green))
) {
    // ...
}

Or to paint text with a gradient:

Text(
    "Mixing colors as pigments generates natural and vibrant looking gradients.",
    style = MaterialTheme.typography.titleLarge.copy(
        brush = Brush.verticalPigmentsGradient(Color.Cyan, Color.Magenta)
    )
)

Colors

The vibrance-compose module adds a series of extensions to the Vibrance class that accept and return androidx.compose.ui.graphics.Color types instead of raw Float values.

License

This library is available under Apache 2.0. See LICENSE.

ยฉ 2026 GitRepoTrend ยท romainguy/vibrance ยท Updated daily from GitHub