我正在聊天,用户可以在其中选择自己喜欢的文本颜色。同一聊天将显示在网站的多个位置。在某些地方,背景会是黑暗的,在其他地方,背景会是明亮的。结果,在某些聊天框中,大多数选择的颜色可能难以辨认。

因此,我正在寻找一种算法,给定一种可以在一种类型的背景(浅色或深色)上很好地工作的颜色,可以生成另一种颜色,该颜色在相反类型的背景上看起来很好,并且与第一种颜色尽可能相似(因此用户会感觉到他到处都使用相同的颜色)。

我知道这可能无法完美完成,但是欢迎您尝试。

最佳答案

好吧,在读完这里和那里的几件事之后。到目前为止,这是我能够找到的。
首先,我想强调几点,并确保正在阅读我的答案的任何人都能够理解我在这里所说的话。

什么是色彩空间?

颜料的原色可以创建多种颜色,然后这些颜色定义特定的颜色空间。颜色空间,也称为颜色模型(或颜色系统),是一种抽象的数学模型,它简单地将颜色范围描述为数字元组,通常为3或4个值或颜色分量(例如:RGB)。基本上,色彩空间是对坐标系和子空间的详细说明。系统中的每种颜色都由一个点表示。

我们大多数人使用以下颜色空间之一( HEX RGB RGBA ),甚至使用某些颜色空间( CMYK HSV 以及通过主要颜色的组合使用所需的任何颜色(红色绿色蓝色 Alpha )。

如果我们想知道一种颜色是否接近另一种颜色,我们可以用眼睛观察它,但是由于我们希望计算机能够以编程方式为我们完成该任务,因此我们以数学方式对其进行研究。

假设颜色 A 中的红色十六进制颜色空间#FF0000 和颜色 B 绿色中的绿色ojit_r具有前两个值是红色颜色的表示形式,后两个值是绿色颜色的表示形式,最后两个值是蓝色颜色的表示形式,因为我们知道每个这些值是其值(0-9)的数字表示,然后(A,B,C,D,F)=(10、11、12、13、14)。然后,我们可以在3D维度上绘制颜色,并使用欧几里得等定律计算它们之间的距离。

例如:
A =(R1 = FF,G1 = 00,B1 = 00)
B =(R2 = 00,G2 = FF,B2 = 00)
我们在这里有两点,现在我们可以使用欧几里得定律
距离= sqrt((R2-R1)^ 2 +(G2-G1)^ 2 +(B2-B1)^ 2)

到目前为止一切顺利,对吗?
不,

在使用HEX,RGBA,CMYK或任何其他颜色空间后,我们将一无所知,但两种颜色在它们的颜色空间中的距离有时可能是完全不同的颜色,但它们之间的距离很低,因为它们不要考虑我们的眼睛如何看颜色。

但是,还有其他色彩空间(科学色彩空间)考虑了我们的眼睛看颜色的方式以及我们的思维如何解释它们。其中之一是 Lab

颜色转换

通常,可以将一个绝对颜色空间中的一种颜色转换为另一种绝对颜色空间,然后再转换一次。但是,某些颜色空间可能具有色域限制,并且转换超出该色域的颜色将不会产生正确的结果。舍入误差也很可能出现,特别是如果每​​个组件仅使用256个不同值的流行范围(8位颜色)的话。

什么是色域?

在包括计算机图形和摄影在内的色彩再现中,色域或色域是某种特定的颜色子集。最常见的用法是指可以在给定情况下(例如在给定颜色空间内或由某个输出设备准确表示)的颜色子集。

现在,我们了解了将要实现的基本功能,让我们开始了解以下方程式进行编码。

十六进制到RGB

我们使用十六进制作为十六进制值的颜色表示,我们只需要获取其十进制值即可,现在我们将颜色设置为RGB颜色空间。
A = RGB(255,0,0)红色
B = RGB(0,255,0)绿色

RGB至XYZ

我们必须遵循以下数学定律
颜色=当前颜色/ 255
如果颜色> 0.04045
颜色=((颜色+ 0.055)/ 1.055)^ 2.4
其他
颜色=颜色/ 12.92
颜色=颜色* 100
X =颜色红色* 0.4124 +颜色绿色* 0.3576 +颜色蓝色* 0.1805
Y =颜色红色* 0.2126 +颜色绿色* 0.7152 +颜色蓝色* 0.0722
Z =红色* 0.0193 +绿色* 0.1192 +蓝色* 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 =(颜色红色* 0.4124)+(颜色绿色* 0.3576)+(颜色蓝色* 0.1805)
Y =(颜色红色* 0.2126)+(颜色绿色* 0.7152)+(颜色蓝色* 0.0722)
Z =(红色* 0.0193)+(绿色* 0.1192)+(蓝色* 0.9505)

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,67.395f} //荧光灯
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,100f,69.026f} //荧光灯
CIE10_F7 = {95.792f,100f,107.687f}
CIE10_F11 = {103.866f,100f,65.627f}

重叠颜色空间中两种颜色之间的距离

像我们之前所做的那样,将颜色视为3d尺寸,现在相对于人眼,这两种颜色之间具有确切的距离。

要包括

进一步研究一种我们应该用来改变颜色但仍具有相同颜色但对于人眼来说却像另一种颜色的技术,通过它我们可以看到背景和使用相同颜色绘制在其上的事物颜色。

-

更新#1(10/09/2018)

有一些数学公式可以计算关于人类感知的色差,称为CIE。这些年来,已经有一些迭代。 (CIE 1976,CIE 1994,CIE 2000)。

CIE 1976年

它是3D空间中两种颜色之间的距离,几乎等于欧几里得距离公式。

CIE 1994年

1994年,对原始的Delta E公式进行了改进。新公式将考虑每种亮度,色度和色相值的某些加权因子。

CIE 2000

CIE组织决定通过引入dE00来解决亮度不准确的问题。它是目前最复杂但最准确的CIE色差算法。

由于CIE 2000是最准确的,因此我们将直接进行介绍。

压力

您无需自己实施。我已经在github Is This Colour 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或稍远。

这是第一点。现在我们知道了。我们应该怎么做才能处理这样的事情。我们可以在颜色值中处理三件事。

在以下意义上,实验室色彩空间是唯一的。

亮度值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 Colour Similar Online example

希望这对您有帮助。

09-27 17:04