使用Palette抽取Bitmap主色调
关于Palette
一些Support库随着Android Lollipop的发布而诞生了,其中就有Palette。这个库可以让你很轻松地从一幅图中抽取特征颜色,这在你希望界面的颜色风格适应指定图片时非常有用,它还会提供与指定颜色相搭配的字体颜色。
Palette顾名思义调色板, Palette的作用是可以从图像中提取图片的颜色。我们可以把提取的颜色融入到App UI中,可以使UI风格更加美观融洽。有些时候Palette显得非常好用,比如我们可以提取到的突出的色值设置为Toolbar,标题,状态栏的颜色等,可以使我们的整个界面色调统一,效果非常好看。
开始使用
导包
你需要在工程下的build.gradle里添加依赖才可以使用Palette,像如下代码所示:
dependencies {
compile 'com.android.support:palette-v7:21.0.0'
}
生成Palette
生成一幅图像的Palette有一下几种方法:
// Synchronous methods.同步方法--------------------------------
// 这些应该在访问底层图像加载线程时使用。
// 方法1:使用默认16种颜色种类的调色板大小。
Palette p = Palette.generate(bitmap);
// 方法2:允许指定调色板的颜色种类的值,这里为24.
Palette p = Palette.generate(bitmap, 24);
// Asynchronous methods.异步方法--------------------------------
// 这是快速的集成路径,在内部使用AsyncTask等,不一定是最好的方式。
// 方法3:
Palette.generateAsync(bitmap, new Palette.PaletteAsyncListener() {
@Override
public void onGenerated(Palette palette) {
// Here's your generated palette 这是你生成的调色板
}
});
// 方法4:
Palette.generateAsync(bitmap, 24, new Palette.PaletteAsyncListener() {
@Override
public void onGenerated(Palette palette) {
// Here's your generated palette
}
});
同步方法。由于他们很可能会比较耗时(在分析大图片或者所需颜色较多时),所以它们不应该在主线程中执行。你应该先在别的线程中使用这两个函数进行解析,解析成功之后再使用。
异步方法。有时候你不会在加载图片的线程(非主线程)中使用解析出的颜色,所以Palette提供了异步方法,他们与之前的函数的区别就是需要传入PaletteAsyncListener,提供在图片解析完成后的回调函数。
PaletteAsyncListener的实现是非常简单的(参考下面这几行代码),它只要重写onGenerated就好了。如此一来你就可以在任何需要的时候使用这两个函数创建Palette。
Palette.PaletteAsyncListener listener = new Palette.PaletteAsyncListener() {
public void onGenerated(Palette palette) {
// 使用Palette对象,获取解析出的颜色
}
}
提取出的颜色
Palette默认会解析出图像的16种特征颜色种类,但是这六种颜色是你最经常用到的:
- vibrant(鲜艳色)
- dark vibrant(鲜艳色中的暗色)
- light vibrant(鲜艳色中的亮色)
- muted(柔和色)
- dark muted(柔和色中的暗色)
- light muted(柔和色中的亮色)
借一张别人的图,给大家一种更直观的感受。
获取提取的颜色
你获取Palette对象之后,可以通过以下这些内置getter函数直接获取这六个颜色。你需要传入默认颜色防止Palette无法解析到指定颜色种类,返回的类型是24位RGB颜色数值。
Palette palette = Palette.generate(myBitmap);
int vibrant = palette.getVibrantColor(0x000000);
int vibrantLight = palette.getLightVibrantColor(0x000000);
int vibrantDark = palette.getDarkVibrantColor(0x000000);
int muted = palette.getMutedColor(0x000000);
int mutedLight = palette.getLightMutedColor(0x000000);
int mutedDark = palette.getDarkMutedColor(0x000000);
//独特的一种
getDominantColor(int defaultColor)
//返回从调色板中占主导地位的样本的颜色,为RGB包装INT。
获取Swatch
你也可以选择先获取Swatch对象,然后再通过Swatch提供的方法获取颜色的相关信息:
Palette.Swatch s = p.getVibrantSwatch(); //获取到充满活力的这种色调
Palette.Swatch s = p.getDarkVibrantSwatch(); //获取充满活力的黑
Palette.Swatch s = p.getLightVibrantSwatch(); //获取充满活力的亮
Palette.Swatch s = p.getMutedSwatch(); //获取柔和的色调
Palette.Swatch s = p.getDarkMutedSwatch(); //获取柔和的黑
Palette.Swatch s = p.getLightMutedSwatch(); //获取柔和的亮
//独特的一种
getDominantSwatch()
//返回从调色板中占主导地位的样本。
注意:getVibrantSwatch()可能会返回一个null值,所以在使用前检查一下是必须的。
if (swatch != null) {}
Palette解析出的颜色都来自于对应的Swatch,在Swatch里面含有很多关于对应颜色的有用信息。你可以从Swatch中获取RGB颜色值、HSL颜色向量、对应颜色在图像中所占的比例、与对应颜色搭配的标题字体颜色和正文字体颜色(这两个颜色和对应颜色的对比值是处理好的,你不必再去操心)。
swatch对象对应的颜色方法:
getPopulation(): 像素的数量
getRgb(): RGB颜色
getHsl(): HSL颜色
getBodyTextColor(): 用于内容正文文本的颜色
getTitleTextColor(): 标题文本的颜色
Palette只为六种主颜色种类Swatch提供了getter,如果你要使用其他颜色种类的Swatch(一共有16种颜色种类),你需要手动获取它。调用getSwatchs()会返回一个列表,里面有所有获取到的Swatch。
List<Palette.Swatch> swatches = palette.getSwatches();
这里是一个Palette获取所有Swatch的例子,里面展示了它们分别在图像中所占的比例:
关于颜色种类的值size
在上面生成Palette的时候,你可能注意到了可以设置Palette的size。size越大,花费的时间越长,而越小,可以选择的色彩也越小。最佳的选择是根据image的用途:
- 头像之类的,size最好在24-32之间;
- 风景大图之类的,size差不多在8-16;
- 默认是16.
Palette实例
Palette经常用于和ViewPager,Fragment搭配使用,当我们的Pager切换时伴随着Fragment的变化,而Fragment里的内容一般是不同的,所以每个Fragment里的一般视觉效果也是不同的,所以我们可以用Palette来去提取Fragment中的主色调,把这个主色调用于整体的UI风格。
这个例子可以参考这篇博客:http://www.jianshu.com/p/9fcf316031ba
Demo的地址:https://github.com/loonggg/MaterialDesignDemo
另外一个例子:
详情参考这篇博客:http://www.itdadao.com/articles/c15a485862p0.html
Demo下载地址:http://download.csdn.net/detail/breeze_wf/9273313
这篇博客也大多借鉴上面两篇博客的内容。
Palette的异步方法使得它非常容易去使用,而且我也看到了它用在很多地方。它真是一个非常棒的工具,能够收集一幅图中所有的颜色,并将它们总结到几个不同种类的颜色中。建议大家阅读源码来更多地学习它!
关于更多Palette的详细用法,可以查看官方API文档。