在某个宁静的午夜,你我仰望星空的时候,可曾想到满目绚烂的星空,是怎样一幅景象?
又是一个宁静的下午,当你打开按键精灵准备写点什么的时候,是否曾好奇,FindColor 找色命令所找的颜色,到底是个什么东西?
对于按键精灵来说,颜色是一个【字符串】表示的固定6位的数据。
有时候,多个颜色也会绑在一起使用,比如找多点,或者找色的时候,附带一个偏色值。
对于其他编程语言来说,更多时候颜色会使用一个【Int32】类型的数字来表示,这个数字固定占据4个字节的空间,能够表示的数字范围从-2147483648 到 2147483647。
这两种颜色值有什么区别吗?
比如红色,按键用【"0000FF"】来表示,其他语言则用【255】或【16711680】来表示,当然,也可以表示为【0xFF】或者【0xFF0000】,下面会讲解为什么这些数值表示的都是同一个红色。
小学的时候,我们应该见过这样一张图片,【三原色】它揭示了关于颜色的秘密。
如果你酷爱科学,喜欢科普类节目,又或许听到过一个说法,这个世界上,【我们看到的紫色】是不存在的,是被虚构出来的。
当我们把电脑屏幕用显微镜放大后,真相就浮出水面了:
屏幕上显示的所有颜色,其实都是由【红、绿、蓝】三种颜色所演化出来的,三原色通过不同的亮度混合,最终就形成了我们看到的颜色,大千世界,丰富多彩。
为什么是红绿蓝三色呢?因为我们眼睛里的视锥细胞,只能识别这三种颜色,再通过运算变成我们看到的色彩,所以本质上,显示设备是专门为我们的眼睛服务的。
我们找色的目标,是一个点,而这个点,其实像上图一样,包含了三个小灯珠,分别用来显示红绿蓝三种颜色,也就是说,电脑里的一个点,其实是有三个数据的。
对于按键精灵来说,一个颜色用6位字符串来表示,把他们俩俩拆开,就是3个2位字符串,于是每个2位字符串,就可以代表一个灯珠的亮度了。
对于其他编程语言来说,一个 Int32 数据包含了32个二进制位,把他们拆分成4等分,就是4个8位的数据,每一个8位的数据,就代表了一个灯珠的亮度,还多出来一个8位的数据,就用来表示【透明度】这个概念,术语叫做 Alpha 通道。
上面关于红色的数值【16711680】是怎么来的呢?它和按键精灵的【FF】又有什么关系呢?其实两个数值表示的差不多是一个意思,因为计算机使用二进制存储数据,我们使用十进制阅读数据,而十进制和二进制是不对齐的。
二进制太长了,为了能够对齐阅读二进制,并且让数据看起来足够简短,我们又开始使用十六进制表示数据,也就是 HEX 列展示的 【FF 0000】
一位十六进制可以代表4位二进制,两位十六进制,就能代表8位二进制了,刚好一个字节,而字节的范围是【0-255】,这个数值足矣表示一个灯珠的亮度了。
这就是按键精灵的颜色,和其他软件的颜色,在表达上的区别,我们也可能看到过类似这样的表达方式【RGB(255, 0, 255)】
其实大同小异,都是用3个字节表示红绿蓝分量。
也就是说:
红色 = 【"FF"】 = 【255】 = 【0xFF】 = 【RGB(255, 0, 0)】
可是 255 显然和 16711680 是不相等的,为什么两个数值都可能表示红色呢?其实两个数值不光都能表示红色,甚至还都能表示蓝色。
因为颜色的排列方式不相同,既可以RGB排列,也可以BGR排列,颜色的排列方式不同,决定了红色和蓝色的位置可能互换。
因为历史遗留原因,现在不同的软件用的标准也不够统一,所以很多情况下,我们需要对颜色进行反色处理,按键精灵X代码如下:
- /*
- 取反色函数,支持输入6位十六进制字符串或整数型颜色值
- */
- Function 反色(颜色)
- Dim iType = Type(颜色)
- Dim iColor
- Select Case iType
- Case 2, 3
- // 整数或小数传入
- iColor = CLng(颜色)
- Case 4
- // 字符串传入
- iColor = CLng("&H" & 颜色)
- Case Else
- Return 0
- End Select
- Dim R = iColor bAnd &HFF0000
- Dim G = iColor bAnd &HFF00
- Dim B = iColor bAnd &HFF
- Return (R bShr 16) bOr G bOr (B bShl 16)
- End Function
- TracePrint Hex(反色("FF55AA"))
复制代码大家常说的 RGB 转 BGR 就是上述代码的实现了。
既然我们已经掌握了颜色的秘密,那颜色处理也就易如反掌了,比如,把一张图片的绿色和蓝色部分去除,把上述代码修改一下:
- Function 只留红色(颜色)
- Dim iType = Type(颜色)
- Dim iColor
- Select Case iType
- Case 2, 3
- // 整数或小数传入
- iColor = CLng(颜色)
- Case 4
- // 字符串传入
- iColor = CLng("&H" & 颜色)
- Case Else
- Return 0
- End Select
- Return iColor bAnd &HFF0000
- End Function
- TracePrint Hex(只留红色("C3586A"))
复制代码大漠插件里神奇的二值化是如何实现的呢?
就是判断红色、绿色、蓝色,是否在给定的颜色范围内,在则返回 true,不在范围内则返回 false,再根据 true 和 false 生成一张黑白图像即可。
各位可以尝试一下实现这个功能,当做作业,代码会复杂一些,但是原理其实很简单。