Search

Extracting Colors to a Palette with Android Lollipop

Brian Gardner

4 min read

Jan 8, 2015

Extracting Colors to a Palette with Android Lollipop

Editor’s Note:n This post has been updated since its initial release. The generate(Bitmap) and
generate(Bitmap, PaletteAsyncListener) methods have been deprecated in favor
of a builder static method on the Palette class. The code listings in this
post now use the new Palette functionality.

With the relase of Android Lollipop, several new support libraries have been
created. One of the new libraries is for the Palette class. This new class makes
it easy to extract prominent colors from bitmap images, which is useful if you
want to style other view components to match colors from your image, such as a
background for the image or a text color with suitable contrast. One way I like to use this is to color the ripple drawable behind the
image. It is a subtle effect, but I think it is a nice improvement over the
standard gray. Before you can use it in your projects you need to add the
following compile line to your Gradle dependencies block in your build.gradle
file.

dependencies {
  compile 'com.android.support:palette-v7:23.1.1'
}

In order to generate the Palette object, there is a static from(Bitmap) method
on the Palette class.
This method returns a Palette.Builder object that you can use to tweak the
generated Palette. Be sure that the Bitmap you supply to the from()
method is neither null nor recycled, or it will throw an
IllegalArgumentException.

Once you have the builder, you can use one of the generate methods to create the
Palette object. One option is to use the no-argument generate() method like
so.

Bitmap myBitmap = BitmapFactory.decodeResource(getResources(), R.drawable.nyancat);
if (myBitmap != null && !myBitmap.isRecycled()) {
    Palette palette = Palette.from(myBitmap).generate();
}

This version of the generate method executes synchronously and it should not be
called on your main thread. This method would typically be used when loading
bitmaps on a background thread.

However, sometimes it may not be possible to do this work on the same thread
that you load your images on, so the Palette.Builder has another generate
method that is configured to do the work asynchronously. This method takes in a
Palette.PaletteAsyncListener as a parameter. The listener has an
onGenerated(Palette)
method that will be triggered when the Bitmap processing is finished.

Palette.PaletteAsyncListener paletteListener = new Palette.PaletteAsyncListener() {
  public void onGenerated(Palette palette) {
    // access palette colors here
  }
}

Bitmap myBitmap = BitmapFactory.decodeResource(getResources(), R.drawable.nyancat);
if (myBitmap != null && !myBitmap.isRecycled()) {
    Palette.from(myBitmap).generate(paletteListener);
}

The Palette object will try to find 16 colors from the image by default, but
there are six color profiles you will use most often:

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

Here is an example of the main color profiles the Palette generates:

Main Palette Colors

Once you have the Palette object, there are built-in getter methods for the six
default color profiles. There is a chance that the Palette won’t be able to find
a color for a particular profile, so you do need to pass in a default color. The
value returned by these methods is an RGB packed integer.

Palette palette = Palette.generate(myBitmap);
int default = 0x000000;
int vibrant = palette.getVibrantColor(default);
int vibrantLight = palette.getLightVibrantColor(default);
int vibrantDark = palette.getDarkVibrantColor(default);
int muted = palette.getMutedColor(default);
int mutedLight = palette.getLightMutedColor(default);
int mutedDark = palette.getDarkMutedColor(default);

Palette Swatches

These generated colors come from an object called a Swatch.
A Swatch object contains some useful data about a color found in the image. You
can get the color in either a RGB packed int or the HSL values. It also includes
the number of pixels of that color in the image (the population). Finally, the Swatch provides
title and body text colors. These colors are guaranteed to have sufficient
contrast with the Swatch color so you won’t have issues with legibility.

Palette palette  = Palette.from(myBitmap).generate();
Palette.Swatch swatch = palette.getVibrantSwatch();
// Gets the RGB packed int -> same as palette.getVibrantColor(defaultColor);
int rgbColor = swatch.getRgb();
// Gets the HSL values
// Hue between 0 and 360
// Saturation between 0 and 1
// Lightness between 0 and 1
float[] hslValues = swatch.getHsl();
// Gets the number of pixels represented by this swatch
int pixelCount = swatch.getPopulation();
// Gets an appropriate title text color
int titleTextColor = swatch.getTitleTextColor();
// Gets an appropriate body text color
int bodyTextColor = swatch.getBodyTextColor();

For each of the six color profiles, there is another method for getting
its Swatch object.
Unlike the get color methods, there is no default parameter for the Swatch
methods. If the Palette object was not able to find a color that matches a
particular color profile the get Swatch method will just return null.

Palette palette = Palette.from(myBitmap).generate;
Palette.Swatch vibrantSwatch = palette.getVibrantSwatch();
Palette.Swatch vibrantLightSwatch = palette.getLightVibrantSwatch();
Palette.Swatch vibrantDarkSwatch = palette.getDarkVibrantSwatch();
Palette.Swatch mutedSwatch = palette.getMutedSwatch();
Palette.Swatch mutedLightSwatch = palette.getLightMutedSwatch();
Palette.Swatch mutedDarkSwatch = palette.getDarkMutedSwatch();

While the system has convenience methods to get the Swatches for the six default
color profiles, the other generated swatches need to be retrieved manually.
There is a getSwatches() method defined on the Palette that will return a List
of all the swatches created. So if you just want to use the Swatch represented
by the most pixels, you could just grab it from that list.

Here is an example of the Swatches the Palette generates with their respective
populations:

Test Palette Colors

In retrospect, the Palette object is a cool way to pull out colors from
Bitmap
images. The fact that it comes with built-in generator methods that run
asynchronously make it very quick to use, and I can see the Palette being used
in a lot of places. To really understand how the Palette works, I recommend
digging through the source files. It is neat to see how it collects the
different colors in the image, then how it narrows those colors down to the max
color number. I had a lot of fun experimenting with the Palette, and I look
forward to using it on future projects.

Juan Pablo Claude

Reviewer Big Nerd Ranch

During his tenure at BNR, Juan Pablo has taught bootcamps on macOS development, iOS development, Python, and Django. He has also participated in consulting projects in those areas. Juan Pablo is currently a Director of Technology focusing mainly on managing engineers and his interests include Machine Learning and Data Science.

Speak with a Nerd

Schedule a call today! Our team of Nerds are ready to help

Let's Talk

Related Posts

We are ready to discuss your needs.

Not applicable? Click here to schedule a call.

Stay in Touch WITH Big Nerd Ranch News