关于Android配色 自适应颜色的实现
在Android4.4系统中,更加详细地介绍了关于颜色的细节并提供了使用colour的新教程,以使我们的应用更加独一无二。也就是说,作为一个设计师或者开发者,为你的APP做完美的配色已经变成了你的职责。
可以通过改变Android Framework界面元素的默认蓝色来使应用更加独特。 ——来自Android Design
最简单的方式就是给Action Bar加上一层自定义的背景,但是在我现在写的一个APP中我希望可以更灵活一些(做到自适应),自适应颜色的最好例子就是iTunes了,它会从专辑中获取配色方案,作用于弹出的曲目列表。

所以,我准备在Android上实现这个技术。
基本理论知识
在网上搜索一遍后,我发现了很多开源的实现方式,不过是用其他语言写的。最好的版本是一个JavaScript库,叫Color Thief,我从里面学到了很多实现这个技术需要的知识,正好是我需要的。
图像量化
这里要做的第一步就是量化源图像,通俗地说,就是减少图像上使用的颜色种类。如果你喜欢动态的GIF,那么只能用8位的色板,所以每一帧最多可以使用256种颜色。
为此,我们就需要减少颜色使用,只使用一些主要的颜色,那我们就用默认的色板吧,再根据需要弄出一些其他的颜色。稍后将详细介绍。
现在需要选择量化算法了,Color Thief用了一个修改版的MCQ(Median Cut Quantization)算法,另称作MMCQ(Modified Median Cut Quantization),如果想了解更多关于MMCQ的信息,可以来 这里 。其他的比较著名的量化技术还有NeuQuant和OctTree。
我还在《Principles of Digital Image Processing 》这本书上找到了一个JAVA的MCQ实现,托管在GitHub上。
这个MCQ算法有很多很棒的特性,所以我决定就用它了:
- 它很快。它比NeuQuant和OctTree还快,在移动设备上这点尤其重要;
- 它内部使用了统计直方图,每种色块都绑定了一个数值,之后排序的时候更方便。
虽然MCQ算法生成的图像质量不是最好的,但是这里只是需要它生成的调色板,不用展示生成的图像,所以,还不错。
处理结果
以下就是处理后的结果,使用Color Thief的例子里的图像。之前说过MCQ里面带有统计直方图,所以我们可以排列出每种颜色使用的频率,它显示了调色板排序后的列表。当然,这还是可以继续改进。



这些结果和Color Thief生成的图像有点不一样:
- 我的版本选择蓝色作为主要的颜色;
- Color Thief挑选了蓝色,银色和绿色作为主要颜色;
- Color Thief没有选到那些灰色的阴影。所以还需要改进。
接着上文讲的,可以调用MedianCutQuantizer对象的getQuantizedColors()这个方法可以获取调色板。我们可以以颜色使用的数量和比重来对这个集合进行降序显示。很不幸的是结果表明大多数图像用的颜色是黑色和白色(或相近的颜色),这颜色根本不能让我们的应用显得更独特,所以我们要考虑到底选择什么颜色了。
对于我自己的应用来说,我准备使用以下的调色方案:
- 第一位的主色是一种鲜艳的颜色;
- 第二位主色是区别一于第一位主色的另一种亮色;
- 第三位主色是和第一位和第二位主色对比强烈的颜色;
- 一种主要的字体颜色,和整体主色对比明显,可读性强;
- 第二种主要字体颜色就是白色或者黑色,取决于整体主色的亮度,可读性强。
这篇文章主要讲的也就是怎么选择这些颜色。
主色
根据以上我的需求,我决定使用以下因素的平均值:
- 鲜艳度;
- 热度(受欢迎程度)。
鲜艳度
这个其实也很简单,首先要把RGB颜色模型转化成HSV颜色模型,使用Android内置的[Color.RGBToHSV()] (https://developer.android.com/reference/android/graphics/Color.html#RGBToHSV(int, int, int, float[]))方法可以做到。如果不明白HSV颜色模型可以看 这里。
简单地说,这个圆柱形就代表了RGB颜色模型,通过三个坐标来表示颜色:Hue,Saturation和Value(明度)。

HSV颜色模型,来自 Wikipedia
我使用一个简单的方式去计算鲜艳度,通过饱和度(saturation )和色度(value)。在人眼看来这两个值越高,鲜艳度就越高。
- public float[] getHsv() {
- float[] hsv = new float[3];
- Color.RGBToHSV(r, g, b, hsv);
- return hsv;
- }
- public float calculateColorfulness() {
- float[] hsv = getHsv();
- return hsv[1] * hsv[2];
- }
计算的结果会在0.0到1.0的范围内。
热度
还记得之前说过每个颜色都有一个绑定的值吗?这里可以使用这个值来决定一种颜色在调色板中的受欢迎程度。记住值得范围是在0.0到1.0之间。
也就是说我们得到了如下的简单的调色板:
| Color | Count |
----------------------
| White | 200 |
| Purple | 175 |
| Black | 150 |
| Red | 125 |
| Orange | 100 |
| Blue | 50 |
----------------------
| Total | 800 |
我们可以通过图像中的这个比例来计算出颜色占有的比例,上图中有800像素,以紫色为例,它的颜色比例为:175 / 800 = ~0.22。可是这个值很小,只能接近1而已。
反之我们可以选择调色板中最受欢迎的颜色作为基准来计算这个比例。还是用上一个例子,白色是最受欢迎的颜色,所以紫色的比例就是:175 / 200 = 0.87。相对于颜色的受欢迎程度来说,这个更具代表性。
最终值
这里要使用这些值来结合成一个最终的值,这样简单合成没有问题,但是之前说了黑白色是最受欢迎的颜色,考虑到这个,这里我们做一个权重,来决定一些属性的重要程度,这种情况下我们提高了鲜艳度:
- static float weightedAverage(float... values) {
- assert values.length % 2 == 0;
- float sum = 0;
- float sumWeight = 0;
- for (int i = 0; i = SECONDARY_MIN_DIFF_HUE_PRIMARY) {
- return candidate;
- }
- }
- // If we get here, just return the second weighted color
- return mWeightedPalette[1];
第三位主色
这种颜色和上面第二位主色很相似,但是这次就不找Hue值了,我们直接对比前两种颜色就可以了。
- // Contrast values are in the range 0-255.
- private static final int TERTIARY_MIN_CONTRAST_PRIMARY = 20;
- private static final int TERTIARY_MIN_CONTRAST_SECONDARY = 90;
- ...
- // Find the first color which has sufficient contrast from both the primary & secondary
- for (ColorNode color : mWeightedPalette) {
- if (ColorUtils.calculateContrast(color, primary)
- >= TERTIARY_MIN_CONTRAST_PRIMARY
- && ColorUtils.calculateContrast(color, secondary)
- >= TERTIARY_MIN_CONTRAST_SECONDARY) {
- return color.getRgb();
- }
- }
- // We couldn't find a colour. In that case use the primary colour, modifying it's
- // brightness by 45%
- return ColorUtils.changeBrightness(secondary.getRgb(), 0.45f);
来看一下,calculateContrast()这个方法哪来的?这个我也想了很久,其实它来自这篇文章color contrast。
最后我再把RGB颜色模型转换成了YIQ颜色模型,仅仅携带了Y(亮度)值,之后你可以对比下两种颜色的亮度值,看看在明度上有什么不一样,再用临界值来试试。
- /**
- * @return difference in luma. Possible values are 0 (no difference) to
- * 255 (max difference).
- */
- private static final int calculateContrast(int rgbColor1, int rgbColor2) {
- return Math.abs(calculateYiqLuma(rgbColor1) - calculateYiqLuma(rgbColor2));
- }
- /**
- * @return luma value. Values are in the range 0-255.
- */
- public static final int calculateYiqLuma(int color) {
- return (299 * Color.red(color) + 587 * Color.green(color) + 114 * Color.green(color)) / 1000;
- }
代码
我说过要发代码的,看这里:
https://gist.github.com/chrisbanes/ba8e7b9ec0e40f6949c6
这代码也许跑不起来,所以需要修改一下然后包含到你的APP中,这是仅仅是为了让你知道怎么把它集成到APP中,所有重要的东西都在这里了,你只需要考虑怎么集成进你的APP就行了。加油吧。
原文链接: banes 翻译: 伯乐在线 - chris
译文链接: http://blog.jobbole.com/64715/
关于Android配色 自适应颜色的实现的更多相关文章
- Android TextView背景颜色与背景图片设置
Android TextView 背景颜色与背景图片设置,android textview 控件,android textview 背景, android textview 图片,android te ...
- Android实现自适应正方形GridView
Android实现自适应正方形GridView
- 如何改变Android标准键的颜色?
本文选自StackOverflow(简称:SOF)精选问答汇总系列文章之一,本系列文章将为读者分享国外最优质的精彩问与答,供读者学习和了解国外最新技术,本文为大家讲解如何改变Android标准键的颜色 ...
- 003android初级篇之【转】Android开发中颜色的定义方法
正好用到颜色的定义,但脑子里没有记住具体,转载一篇加强印象 1.使用Color类的常量,如: int color = Color.BLUE; // 创建一个蓝色 是使用Android提供的颜色 int ...
- Android(java)学习笔记106:Android设置文本颜色的4种方法
1. Android设置文本颜色的4种方法: (1)利用系统自带的颜色类: tv.setTextColor(android.graphics.Color.RED); (2)数字颜色表示: tv.set ...
- 4种必须知道的Android屏幕自适应解决方案
文章来源:http://blog.csdn.net/shimiso/article/details/19166167 demo下载:http://www.eoeandroid.com/forum.ph ...
- Android中的颜色设置
1.在android中经常看到设置的颜色为八位的十六进制的颜色值,例如 public static final class color { public static final int lightb ...
- Android控件颜色设置为透明
开发Widget时,经常想把Widget的背景设置成透明的,显得比较有品位.如果想让控件的颜色是透明的,可以定义以下的颜色: <color name="black"># ...
- Android 图片的颜色处理
仿造美图秀秀移动鼠标调整seekbar,调整图片的颜色 项目布局如下: <LinearLayout xmlns:android="http://schemas.android.com/ ...
随机推荐
- 【C#、csharp】HTTPGET,POST请求
HTTP定义了与服务器交互的不同方法,基本方法有GET,POST,PUT,DELETE,分别对于查,该,增,删.一般情况下我们只用到GET和POST,其他两种都也可以用GET和POST来实现,很多浏览 ...
- VS2013配置opencv3.0.0 (win8.1)
今天下载了最新版本的opencv3.0.0,之前一直是opencv2.4.8 点击.exe文件,我将解压后的文件夹放在D:\盘,取名opencv30,D:\opencv30 添加环境变量:D:\ope ...
- SuperSocket源码解析之启动过程
一 简介 这里主要说明从配置系统引导启动SuperScoekt作为应用程序,且以控制台程序方式启动 二 启动过程 2.1 配置解析 从读取配置文件开始,直接拿到一个SocketServiceConfi ...
- RPC通信框架——RCF介绍(替换COM)
阅读目录 RPC通信框架 为什么选择RCF 简单的性能测试 参考资料 总结 现有的软件中用了大量的COM接口,导致无法跨平台,当然由于与Windows结合的太紧密,还有很多无法跨平台的地方.那么为了实 ...
- Creating Spatial Indexes(mysql 创建空间索引 The used table type doesn't support SPATIAL indexes)
For MyISAM tables, MySQL can create spatial indexes using syntax similar to that for creating regula ...
- Xcode4.6 自制iOS可用的 Framework
First of all:新建一个空白project. File->New->Project 然后新建两个文件 File->New->File 如图 然后选择targets ...
- 用WebCollector制作一个爬取《知乎》并进行问题精准抽取的爬虫(JAVA)
简单介绍: WebCollector是一个无须配置.便于二次开发的JAVA爬虫框架(内核),它提供精简的的API.仅仅需少量代码就可以实现一个功能强大的爬虫. 怎样将WebCollector导入项目请 ...
- 把VS2010的智能代码提示和注解从英文变成中文
最近安装了个高级点的VS2010,起初还没留意.今天无意发现提示信息只能提示英文.....头大oooo. 我以为是个别现象,于是GG了下,发现有很多盆友都有这种. 记录下来了,以后省事儿: 访问MS的 ...
- iOS- 如何集成支付宝
链接地址:http://www.cnblogs.com/qingche/p/3556365.html 现在不少app内都集成了支付宝功能 使用支付宝进行一个完整的支付功能,大致有以下步骤: 1&g ...
- RS100项目进展更新
1. 添加手机界面访问网页,毕竟PDA的屏幕大小和PC机大小不一致,完成了一自适应网页,便于在手机上观看实时画面: 2. 此项目为一个远程视频监控+远程开关项目,远程PC机或者手机能操作到监控端的开关 ...