Selecting Colors with the Palette API

Good visual design is essential for a successful app, and color schemes are a primary component of design. The palette library is a support library that extracts prominent colors from images to help you create visually engaging apps.

You can use the palette library to design layout themes and apply custom colors to visual elements in your app. For example, you can use a palette to create a color-coordinated title card for a song based on its album cover or to adjust an app’s toolbar color when its background image changes. The Palette object gives you access to the colors in a Bitmap image while also providing six main color profiles from the bitmap to help inform your design choices.

Set up the library

To use the palette library, install or update the Android Support Library to version 24.0.0 or higher and follow the instructions for Adding Support Libraries to add the palette library to your app development project.

Make sure that the version specified in your dependency identifier matches your app’s compileSdkVersion, set in the build.gradle file:

Groovy

android {
    compileSdkVersion 33
    ...
}

dependencies {
    ...
    implementation 'com.android.support:palette-v7:28.0.0'
}

Kotlin

android {
    compileSdkVersion(33)
    ...
}

dependencies {
    ...
    implementation("com.android.support:palette-v7:28.0.0")
}

Note: If you are using the Android Plugin for Gradle 3.0.0 or higher , use the "implementation" keyword. If you are using another version of the Android Plugin for Gradle, use the "compile" keyword.

For more information about adding the palette dependency, read about the palette feature in the support library documentation.

Create a palette

A Palette object gives you access to the primary colors in an image, as well as the corresponding colors for overlaid text. Use palettes to design your app’s style and to dynamically change your app’s color scheme based on a given source image.

To create a palette, first instantiate a Palette.Builder from a Bitmap. You can then use the Palette.Builder to customize the palette before generating it. This section will describe palette generation and customization from a bitmap image.

Generate a Palette instance

Generate a Palette instance using Palette’s from(Bitmap bitmap) method to first create a Palette.Builder from a Bitmap. The builder can then generate the palette either synchronously or asynchronously.

Use synchronous palette generation if you want to create the palette on the same thread as the method being called. If you generate the palette asynchronously on a different thread, use the onGenerated() method to access the palette immediately after it has been created.

The following code snippet provides example methods for both types of palette generation:

Kotlin

// Generate palette synchronously and return it
fun createPaletteSync(bitmap: Bitmap): Palette = Palette.from(bitmap).generate()

// Generate palette asynchronously and use it on a different
// thread using onGenerated()
fun createPaletteAsync(bitmap: Bitmap) {
    Palette.from(bitmap).generate { palette ->
        // Use generated instance
    }
}

Java

// Generate palette synchronously and return it
public Palette createPaletteSync(Bitmap bitmap) {
  Palette p = Palette.from(bitmap).generate();
  return p;
}

// Generate palette asynchronously and use it on a different
// thread using onGenerated()
public void createPaletteAsync(Bitmap bitmap) {
  Palette.from(bitmap).generate(new PaletteAsyncListener() {
    public void onGenerated(Palette p) {
      // Use generated instance
    }
  });
}

If you need to continuously generate palettes for a sorted list of images or objects, consider caching the Palette instances to prevent slow UI performance. You also should not create the palettes on your main thread.

Customize your palette

The Palette.Builder allows you to customize your palette by choosing how many colors are in the resulting palette, what area of your image the builder uses to generate the palette, and what colors are allowed in the palette. For example, you can filter out the color black or ensure that the builder only uses the top half of an image to generate your palette.

Fine-tune your palette’s size and colors with the following methods from the Palette.Builder class:

addFilter()
This method adds a filter that indicates what colors are allowed in the resulting palette. Pass in your own Palette.Filter and modify its isAllowed() method to determine which colors are filtered from the palette.
maximumColorCount()
This method sets the maximum number of colors in your palette. The default value is 16, and the optimal value depends on the source image. For landscapes, optimal values range from 8-16 while pictures with faces usually have values that fall between 24-32. The Palette.Builder takes longer to generate palettes with more colors.
setRegion()
This method indicates what area of the bitmap the builder uses when creating the palette. You can only use this method when generating the palette from a bitmap, and it does not affect the original image.
addTarget()
This method allows you to perform your own color matching by adding a Target color profile to the builder. If the default Targets are not sufficient, advanced developers can create their own Targets using a Target.Builder.

Extract color profiles

Based on the standards of material design, the palette library extracts commonly used color profiles from an image. Each profile is defined by a Target, and colors extracted from the bitmap image are scored against each profile based on saturation, luminance, and population (number of pixels in the bitmap represented by the color). For each profile, the color with the best score defines that color profile for the given image.

By default, a Palette object contains 16 primary colors from a given image. When generating your palette, you can customize its number of colors using the Palette.Builder. Extracting more colors provides more potential matches for each color profile but also causes Palette.Builder to take longer when generating the palette.

The palette library attempts to extract the following six color profiles:

  • Light Vibrant
  • Vibrant
  • Dark Vibrant
  • Light Muted
  • Muted
  • Dark Muted

Each of Palette’s get<Profile>Color() methods returns the color in the palette associated with that particular profile, where <Profile> is replaced by the name of one of the six color profiles. For example, the method to get the Dark Vibrant color profile is getDarkVibrantColor(). Since not all images will contain all color profiles, you must also provide a default color to return.

Figure 1 displays a photo and its corresponding color profiles from the get<Profile>Color() methods.

Figure 1. An example image and its extracted color profiles given the default maximum color count (16) for the palette.

Use swatches to create color schemes

The Palette class also generates Palette.Swatch objects for each color profile. Palette.Swatch objects contain the associated color for that profile, as well as the color’s population in pixels.

Swatches have additional methods for accessing more information about the color profile, such as HSL values and pixel population. You can use swatches to help create more comprehensive color schemes and app themes using the getBodyTextColor() and getTitleTextColor() methods. These methods return colors appropriate for use over the swatch’s color.

Each of Palette’s get<Profile>Swatch() methods returns the swatch associated with that particular profile, where <Profile> is replaced by the name of one of the six color profiles. Although the palette’s get<Profile>Swatch() methods do not require default value parameters, they return null if that particular profile does not exist in the image. Therefore, you should check that a swatch is not null before using it. For example, the following code gets the title text color from a palette if the Vibrant swatch is not null:

Kotlin

val vibrant = myPalette.vibrantSwatch
// In Kotlin, check for null before accessing properties on the vibrant swatch.
val titleColor = vibrant?.titleTextColor

Java

Palette.Swatch vibrant = myPalette.getVibrantSwatch();
if(vibrant != null){
    int titleColor = vibrant.getTitleTextColor();
    // ...
}

To access all colors in a palette, the getSwatches() method returns a list of all swatches generated from an image, including the standard six color profiles.

The following snippet of code uses the methods from the above code snippets to synchronously generate a palette, get its vibrant swatch, and change the colors of a toolbar to match the bitmap image. Figure 2 displays the resulting image and toolbar.

Kotlin

// Set the background and text colors of a toolbar given a
// bitmap image to match
fun setToolbarColor(bitmap: Bitmap) {
    // Generate the palette and get the vibrant swatch
    val vibrantSwatch = createPaletteSync(bitmap).vibrantSwatch

    // Set the toolbar background and text colors.
    // Fall back to default colors if the vibrant swatch is not available.
    with(findViewById<Toolbar>(R.id.toolbar)) {
        setBackgroundColor(vibrantSwatch?.rgb ?:
                ContextCompat.getColor(context, R.color.default_title_background))
        setTitleTextColor(vibrantSwatch?.titleTextColor ?:
                ContextCompat.getColor(context, R.color.default_title_color))
    }
}

Java

// Set the background and text colors of a toolbar given a
// bitmap image to match
public void setToolbarColor(Bitmap bitmap) {
    // Generate the palette and get the vibrant swatch
    // See the createPaletteSync() method
    // from the code snippet above
    Palette p = createPaletteSync(bitmap);
    Palette.Swatch vibrantSwatch = p.getVibrantSwatch();

    Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);

    // Load default colors
    int backgroundColor = ContextCompat.getColor(getContext(),
        R.color.default_title_background);
    int textColor = ContextCompat.getColor(getContext(),
        R.color.default_title_color);

    // Check that the Vibrant swatch is available
    if(vibrantSwatch != null){
        backgroundColor = vibrantSwatch.getRgb();
        textColor = vibrantSwatch.getTitleTextColor();
    }

    // Set the toolbar background and text colors
    toolbar.setBackgroundColor(backgroundColor);
        toolbar.setTitleTextColor(textColor);
}

Figure 2. An example image with its vibrant-colored toolbar and corresponding title text color.