将hex / hsl值映射到颜色范围

时间:2019-07-17 09:07:00

标签: php hex rgb hsl

给出十六进制/ rgb / hsl值,我该如何将该值放入自定义范围内,例如红色,蓝色等11种基本颜色

我能做的最好的就是肉眼观察hsl的色相范围,但是饱和度和亮度会改变感知的颜色。

我正在寻找一种算法,以使所述值适合颜色范围。

1 个答案:

答案 0 :(得分:1)

如果您只说11种基本颜色(例如红色,橙色,黄色,绿色,青色,蓝色,紫色,洋红色,黑色,白色,灰色),我想您已经在那儿了。色调匹配是您自己需要匹配颜色的全部条件,只要它们在S和L的合理范围内即可。

在我看来,任何大于95ish的L都足够接近白色,而任何小于5ish的L都足够接近黑色。

然后,如果您的S小于10,则取决于L,您可以选择黑色,灰色和白色,甚至可以使用相同的规则。黑色<= 5,白色> = 95,否则为灰色。

然后要匹配色相,使用我的示例颜色列表,您不能真正使用统一的范围,因为光谱红色端的颜色之间的差异远小于青色端的颜色之间的差异。您既可以手动定义它们,也可以使用逻辑函数获得不错的结果。


TL:DR;数学的东西,可能是矫kill过正。

  

我只是盯着色调,因为为此制定公式是不必要且复杂的。

话虽如此,这是我尝试的一种与常用颜色匹配的逻辑功能。

formula

您可以将k值调整为所需的任何值。我认为1.1给出了合理的价差(尽管我只尝试了几个值)。 8为您提供了您希望从该函数中获得的值的数量。因此,由于我们要尝试匹配8种不同的颜色(除了黑色,白色和灰色),因此我使用了8种。

3将域向右移动3个单位。我用了3,因为它是我们要用于此功能的域的一半(中点两侧各3个单位)。

为澄清起见,这是最终功能:

final

对于x,此公式已调整为最小值为0,最大值为6,并且将从青色开始。因此,如果0 <= f(x) < 1是绿色;如果1 <= f(x) < 2是青色,等等。

由于它始于青色,因此您必须调整色相输入值,以使0等于您认为青色而不是绿色的最边缘。让我们以150为例。这意味着青色的宽度为60度,这是我从中获得1.1 K值的地方,因为它排列得很好。

因此,我们的x值将为x = ((hue + (360 - 150)) % 360) / 60.0x = (hue + 210) % 360) / 60.0

然后我们可以将其插入f(x)并获得0到8之间的数字,我们可以使用该数字来获得可疑的颜色。如果我们对颜色进行排列,则可以将值取底并将其用作索引,因为0-6的域将为我们提供大约0.36-7.7的范围,因此它永远不会超过8或低于0。

[cyan, blue, purple, magenta, red, orange, yellow, green]

这太过分了吗?可能。

更有趣吗?肯定是


最后,代码

function hsl($h, $s, $l){
    $options = array("cyan", "blue", "purple", "magenta", "red", "orange", "yellow", "green");
    if($l >= 95)
        return "white";
    else if($l <= 5)
        return "black";
    else if($s <= 10)
        return "gray";

    //Convert hue to x value
    $x = (($h + 210) % 360) / 60.0;
    $match = matchHue($x);
    return $options[$match];
}

function matchHue($x){
    return intval(floor(8 / (1 + pow(M_E, (-1.1 * ($x - 3))))));
}

这一切都取决于您的用例和您尝试使用的颜色,所以是ymmv,但是如果您想要一个公式而不是一个硬编码的列表,则这样的逻辑函数可能是您最好的选择,以反映感知到的颜色从色调。


更加矫over过正。因为为什么呢?

如果您想要S和L的更多选项,例如具有额外的阴影,则可以使用相同样式的逻辑函数,甚至可以使用线性函数。

亮度将遵循完全相同的功能。中灰色是饼图的最大部分,因此您应将x = 0设置为中灰色的下限。

饱和度更多是对数函数。前25%左右具有几种可识别的阴影,而高75%的阴影要少得多。

log

其中N是要识别的阴影数量。该函数的范围是0-100,范围是0-N。您可以根据自己的喜好调整k来更改步长,但是即使将k保留为1也可以得到足够的结果。