我正在聊天,用户可以在其中选择自己喜欢的文本颜色。相同的聊天将显示在网站的多个位置。在某些地方,背景会很暗,而在其他地方,背景会很亮。因此,在某些聊天框中,大多数选定的颜色可能难以辨认。
所以我正在寻找一种算法,给定一种在一种类型的背景(浅色或深色)上效果很好的颜色,产生另一种在相反类型的背景上看起来不错并且与第一种颜色尽可能相似的颜色(所以用户得到的印象是他在任何地方都使用相同的颜色)。
我知道这可能不可能做到完美,但欢迎任何尝试。
好的,在这里和那里阅读了几件事之后。到目前为止,这是我能够找到的。
首先,我想强调几点,并确保阅读我的答案的任何人都能够理解我在这里所说的内容。
什么是色彩空间?
可以通过颜料的原色创建一系列颜色,然后这些颜色定义特定的颜色空间。颜色空间,也称为颜色模型(或颜色系统),是一种抽象的数学模型,它简单地将颜色范围描述为数字元组,通常为 3 或 4 个值或颜色分量(例如:RGB)。基本上,色彩空间是对坐标系和子空间的一种阐述。系统中的每种颜色都由一个点表示。
我们大多数开发人员使用以下颜色空间之一(HEX、RGB、RGBA),有些甚至会使用(CMYK、HSV和HSL等),它可以通过主颜色的组合为您提供您想要的任何颜色(红色,绿色,蓝色,阿尔法)。
如果我们想知道一种颜色是否接近另一种颜色,我们会用眼睛观察它,但由于我们想让计算机以编程方式为我们做这件事,所以我们以数学方式看待它。
假设颜色A在HEX颜色空间#FF0000中是红色,颜色B在HEX颜色空间中也是绿色#00FF00并且根据我们对RGB的理解,前两个值是红色的表示,后两个值是绿色的表示,最后两个值是蓝色的表示颜色,因为我们知道每一个这些值都是其值 (0-9) 的数字表示,所以 (A, B, C, D, F) = (10, 11, 12, 13, 14)。然后我们可以在 3D 维度中绘制颜色,并使用欧几里得等定律计算它们之间的距离。
EX:A = (R1 = FF, G1 = 00, B1 = 00)
B = (R2 = 00, G2 = FF, B2 = 00)
我们这里有两个点,现在我们可以使用欧几里得定律
Distance = sqrt(( R2 - R1)^2 + (G2 - G1)^2 + (B2 - B1)^2)
到目前为止一切顺利,对吧?
不。
随着我们使用 HEX、RGBA、CMYK 或任何其他颜色空间,除了颜色空间中两种颜色之间的距离(有时可能是完全不同的颜色)之外,我们将一无所知,但它们之间的距离很小,因为它们不要考虑我们的眼睛如何看待颜色。
但是还有其他色彩空间(科学的)考虑到我们的眼睛看到颜色的方式以及我们的大脑如何解释它们。其中之一是Lab。
颜色转换
一般来说,一个绝对颜色空间中的颜色可以转换为另一个绝对颜色空间,然后再转换回来;但是,某些色彩空间可能有色域限制,并且转换超出该色域的颜色不会产生正确的结果。也可能存在舍入误差,特别是如果使用每个组件(8 位颜色)只有 256 个不同值的流行范围。
什么是色域?
在色彩再现中,包括计算机图形和摄影,色域或色域是颜色的某个完整子集。最常见的用法是指可以在给定环境中准确表示的颜色子集,例如在给定颜色空间内或由某个输出设备。
现在我们了解了我们将要实现的基本功能,让我们在知道以下等式的情况下开始编码。
十六进制转 RGB
我们有 HEX 作为十六进制值的颜色表示,我们只需要获取它们的十进制值,现在我们在 RGB 颜色空间中有我们的颜色。
A = RGB(255, 0, 0) 红色
B = RGB(0, 255, 0) 绿色
RGB 转 XYZ
我们必须遵循以下数学定律
color = current color / 255
if color > 0.04045
color = ( ( color + 0.055 ) / 1.055 ) ^ 2.4
else
color = color / 12.92
color = color * 100
X = colorRed * 0.4124 + colorGreen * 0.3576 + colorBlue * 0.1805
Y = colorRed * 0.2126 + colorGreen * 0.7152 + colorBlue * 0.0722
Z = colorRed * 0.0193 + colorGreen * 0.1192 + colorBlue * 0.9505
那就是它
例如:- A = RGB(255, 0, 0) 红色
colorRed = 255/255
colorGreen = 0/255
colorBlue = 0/255
if (colorRed > 0.04045){
colorRed = ( ( colorRed + 0.055 ) / 1.055 ) ^ 2.4
}else{
colorRed = colorRed / 12.92
}
if (colorGreen > 0.04045){
colorGreen = ( ( colorGreen + 0.055 ) / 1.055 ) ^ 2.4
}else{<br/>
colorGreen = colorGreen / 12.92
}
if (colorBlue > 0.04045){
colorBlue = ( ( colorBlue + 0.055 ) / 1.055 ) ^ 2.4
}else{
colorBlue = colorBlue / 12.92
}
colorRed = colorRed * 100
colorGreen = colorGreen * 100
colorBlue = colorBlue * 100
X = (colorRed * 0.4124) + (colorGreen * 0.3576) + (colorBlue * 0.1805)
Y = (colorRed * 0.2126) + (colorGreen * 0.7152) + (colorBlue * 0.0722)
Z = (colorRed * 0.0193) + (colorGreen * 0.1192 ) + (colorBlue * 0.9505)
A XYZ(X, Y, Z)
XYZ 到实验室
// Reference-X、Reference-Y 和 Reference-Z 指的是特定的光源和观察者。
X = X / 参考-X
Y = Y / 参考-Y
Z = Z / 参考-Z
if ( X > 0.008856 ) {
X = X ^ ( 1/3 )
}else{
X = ( 7.787 * X ) + ( 16 / 116 )
}
if ( Y > 0.008856 ) {
Y = Y ^ ( 1/3 )
}else{
Y = ( 7.787 * Y ) + ( 16 / 116 )
}
if ( Z > 0.008856 ) {
Z = Z ^ ( 1/3 )
}else{
Z = ( 7.787 * Z ) + ( 16 / 116 )
}
CIE-L* = (116 * Y) - 16
CIE-a* = 500 * (X - Y)
CIE-b* = 200 * (Y - Z)
参考
//2o 观察者 (CIE 1931)
// X2, Y2, Z2
CIE2_A = {109.850f, 100f, 35.585f} //白炽灯
CIE2_C = {98.074f, 100f, 118.232f}
CIE2_D50 = {96.422f, 100f, 82.521f }
CIE2_D55 = {95.682f, 100f, 92.149f}
CIE2_D65 = {95.047f, 100f, 108.883f} //日光
CIE2_D75 = {94.972f, 100f, 122.638f}
CIE2_F2 = {99.187f, 100f, 7.6f荧光
CIE2_F7 = {95.044f, 100f, 108.755f}
CIE2_F11 = {100.966f, 100f, 64.370f}
//10o 观察者 (CIE 1964)
// X2, Y2, Z2
CIE10_A = {111.144f, 100f, 35.200f} //白炽灯
CIE10_C = {97.285f, 100f, 116.145f}
CIE10_D50 = {96.720f, 100f, 81.427f }
CIE10_D55 = {95.799f, 100f, 90.926f}
CIE10_D65 = {94.811f, 100f, 107.304f} //日光
CIE10_D75 = {94.416f, 100f, 120.641f}
CIE10_F2 = {103.280f, 10} //0, 680f, 1.荧光
CIE10_F7 = {95.792f, 100f, 107.687f}
CIE10_F11 = {103.866f, 100f, 65.627f}
Lap 颜色空间中两种颜色之间的距离
像我们之前所做的那样将颜色视为 3d 维度,现在我们有了两种颜色相对于人眼的精确距离。
包括
更多地研究一种我们应该使用的技术来改变颜色,但具有相同的颜色,但对人眼来说感觉就像另一种颜色,通过它我们可以看到背景和使用相同颜色绘制在它上面的东西颜色。
--
更新 #1 (10/09/2018)
有一些数学方程可以计算关于人类感知的色差,称为 CIE。这些年来,它们已经有过几次迭代。(CIE 1976、CIE 1994、CIE 2000)。
1976 年
它是 3D 空间中两种颜色之间的距离,几乎是欧几里得距离公式。
1994 年
1994年,对原有的Delta E公式进行了改进。新公式将考虑每个亮度、色度和色调值的某些加权因子。
CIE 2000
CIE 组织决定通过引入 dE00 来解决亮度不准确的问题。它是目前可用的最复杂但最准确的 CIE 色差算法。
由于 CIE 2000 是最准确的,我们将直接使用它。
附言
你不需要自己实现它。我在 github Is This Color Similar Repository上用 Javascript 创建了一个版本。
运行代码后,我们将得到一个值,该值仅表示两种颜色相对于人类感知的差异,其值从 0 到 100。请查看下表以获得更多说明。
╔═══════════════╦════════════════════════════════════════╗
║ Delta E Value ║ Perception ║
╠═══════════════╬════════════════════════════════════════╣
║ <= 1.0 ║ Not perceptible by human eyes. ║
║ 1 - 2 ║ Perceptible through close observation. ║
║ 2 - 10 ║ Perceptible at a glance. ║
║ 11 - 49 ║ Colors are more similar than opposite. ║
║ 100 ║ Colors are exact opposite. ║
╚═══════════════╩════════════════════════════════════════╝
现在我们知道颜色 A 是否更接近颜色 B 或有点远。
这是第一点。现在我们知道了。我们应该怎么做才能处理这样的事情。我们可以在颜色值上玩 3 个东西。
Lab色彩空间在以下意义上是独一无二的。
亮度值 L* 表示 L* = 0 时最暗的黑色,以及 L* = 100 时最亮的白色。
a* 和 b* 用于绿色-红色和蓝色-黄色分量。
颜色通道 a* 和 b* 表示 a* = 0 和 b* = 0 处的真实中性灰度值。
a* 轴代表绿色-红色分量,绿色为负方向,红色为正方向。
b* 轴代表蓝黄色分量,蓝色为负方向,黄色为正方向。
由于我们想要相同的颜色,但此时您需要的颜色会更暗或更亮。
我们将采用该颜色的 Lab 值并更改 L 值。因为它负责颜色的明暗。通过在现有 L 值的一小部分 (0.05) 上添加(更多亮度)或从现有 L 值中减去(更多暗度)(0.05)。
在代码中提供了一个完整的工作示例,您可以查看以下 URL Is This Color Similar Online 示例。
希望这对您有所帮助。
查看http://en.wikipedia.org/wiki/HSL_and_HSV
只要你保持色调和饱和度不变,它就会看起来是相同的颜色,你可以使用亮度来与背景形成对比
例如,要使颜色更深,请将 RGB 分量乘以 0.5 或 0.75。
缩放 RGB 值,每个都按相同的因子,具有使颜色更暗或更亮而不改变色调的效果。