颜色表示和位操作
今天在看一个Android开源代码的时候看到中间有这么一句:
mTextView.setBackgroundColor(alpha << 24 | (0xbbffbb));
mTextView.setTextColor(alpha << 24 | (0x000000));
其中mTextView是TextView类的对象,而alpha是一个0到255之间的int值。
虽然知道是设置颜色,但是这种写法还是引起了我的好奇心。
怎么又是位移操作又是与运算的。
搜索一下,找到一份资料:http://m.oschina.net/blog/104123
整理转述得此文。
首先科普一下颜色的表示:
首先,颜色各个分量一般是以每8位为一个单位。
8位,8bit,即一个字节,10进制数的取值范围是0~255,一般用16进制表示,0x开头,取值范围是0x00到0xFF(不区分大小写)。
颜色一般有24位和32位两种表示方法。
24位颜色:每8位表示RGB中的一个分量。RGB颜色分量的值越大的时候最终颜色越偏向于这个颜色。
32位颜色:除了每8位表示RGB中的一个分量,还有一个8位用于表示透明度,表示为ARGB形式。
A即alpha值,alpha值为0时颜色为透明,alpha值为最大值时颜色为完全不透明,即可完全覆盖处于它下面的其他颜色,无其他颜色可以透过它而显示出来。
那么位移操作是怎么回事呢?
如图:
表示颜色分量的数要想转化成一个整个的颜色,就必须和其他的分量组合,每个分量放在自己应当处于的位置,就应该进行位移操作。
当然我开始的时候还小迷惑了一下这个资料中给出的例子:http://m.oschina.net/blog/104123,
如果颜色值都是34,23,88等两位十进制数,而它所说的转换居然也就是把数字直接放过去了,那0到255的数字,255咋办?三位数呢?
后来想了一下,作者的图是对的,但是文字配的有点问题。
图中的颜色值34,23和88都是十六进制表示的,所以移位操作的时候可以直接移动位置表示。
移位后就是整体移动相应的位数,一个字母代表四位。
R移动16位,G移动8位,B不需要移动。
如果有A值,则A需要向左移动24位。
需要注意的是,不管是用什么进制表示,十进制还是十六进制还是二进制,位移操作都是二进制范畴的。
为什么说原作者有点小错误呢?
十进制的34,用十六进制表示是0x22。
如果是十进制R34,G23,B88。移位操作后,得到的颜色数值应该是0x221758。
反向的转换:从颜色中提取分量
反向的转换则是右移。
知道一个颜色整体值,想提取某一个颜色分量,方法就是向右移动相应的位数,然后做一个与运算,与0xFF做与运算可以提取最低的两位。
这一步参考资料说得很明白:
直接把例子搬过来:
现在我们知道了rgb的16进制值,那反过来呢?如果我们知道了一个颜色值,如何反向求解rgb值呢?
var color:uint = 0x342388; var r:uint = color >> 16;//右移16位,把2388移出,取0x34 var g:uint = color >> 8 & 0xff;//右移8位,把88移出,得0x3423,与0xff按位与操作,得0x23 var b:uint = color & 0xff;//得到0x88
我们再来看看32位的:
var color:uint = 0xff342388; var a:uint = color >>> 24 //注意这里是>>>,无符号右移位操作,右移24位,把342388移出,得到0xff var r:uint = color >> 16 & 0xff;//右移16位,把2388移出,取0x34 var g:uint = color >> 8 & 0xff;//右移8位,把88移出,得0x3423,与0xff按位与操作,得0x23 var b:uint = color & 0xff;//得到0x88
参考资料:
位操作也疯狂:http://m.oschina.net/blog/104123
PS,推荐在线颜色选择器:http://coolshell.cn/articles/3314.html
PPS:FireFox上也有插件(ColorZilla),可以直接从网页上提取颜色,获取其颜色值。