将 hex/hsl 值映射到颜色范围
Mapping hex/hsl values to a color range
给定一个 hex/rgb/hsl 值,我如何将该值放入自定义范围内,例如 11 种基本颜色,如红色、蓝色等
我能做的最好的事情就是用眼睛匹配 hsl 中的色调范围,但饱和度和亮度会改变感知的颜色。
我正在寻找一种算法来适应颜色范围内的所述值。
如果您只说 11 种基本颜色(例如红色、橙色、黄色、绿色、青色、蓝色、紫色、品红色、黑色、白色、灰色),我会说您已经知道了。只要颜色在合理的 S 和 L 范围内,您只需进行色调匹配即可匹配颜色本身。
在我看来,任何大于 95ish 的 L 都足够接近白色,任何小于 5ish 的 L 都足够接近黑色。
然后如果你的 S 小于 10,你的选项是黑色、灰色和白色,取决于 L,你甚至可以使用相同的规则。黑色 <= 5,白色 >= 95,否则为灰色。
为了匹配色调,使用我的示例颜色列表,您不能真正使用统一的范围,因为光谱红色端的颜色差异比青色端的颜色差异小得多。您可以手动定义它们,也可以使用逻辑函数获得很好的结果。
TL:DR;数学的东西,可能矫枉过正。
I would just eyeball the hue as making a formula for this is unnecessary and complex.
话虽如此,这是我对与常见颜色感知相匹配的逻辑函数的尝试。
您可以根据需要调整 k 值。我认为 1.1 给出了合理的传播(尽管我只尝试了几个值)。 8 为您提供了您希望从该函数中获取的值的数量。因此,由于我们尝试匹配 8 种不同的颜色(除了黑色、白色和灰色),因此我使用了 8 个。
3 将域向右移动 3 个单位。我使用 3 是因为它是我们将用于此函数的域的一半(中点两侧各有 3 个单位)。
澄清一下,这是最终函数:
对于 x,此公式调整为最小值为 0,最大值为 6,并且将从青色开始。所以如果0 <= f(x) < 1
,就是绿色;如果1 <= f(x) < 2
是青色等
因为它从青色开始,你必须调整你的色调输入值,这样 0 就相当于你认为青色而不是绿色的边缘。我们以 150 为例。这意味着青色的宽度为 60 度,这是我从中获得 1.1 K 值的地方,因为它排列得很好。
那么我们的 x 值将是 x = ((hue + (360 - 150)) % 360) / 60.0
或 x = (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))))));
}
这完全取决于您的用例和您尝试使用的颜色,所以是的,但是如果您想要一个公式而不是硬编码列表,那么像这样的逻辑函数可能是您镜像的最佳选择从色调中感知颜色。
更过分了。为什么不呢?
如果您想要 S 和 L 的更多选项,例如具有额外的颜色阴影,您可以使用相同样式的逻辑函数,甚至可以只使用线性函数。
亮度将遵循相同的功能。中灰色将是饼图的最大部分,因此您可以将 x=0 设置为中灰色的下限。
饱和度更像是一个对数函数。前 25% 左右有几个可识别的阴影,而上 75% 的则少得多。像
其中 N 是要识别的阴影数。该函数的定义域是0-100,范围是0-N。您可以根据自己的喜好调整 k 以更改步长的宽度,但即使将 k 保留为 1 也应该可以获得足够的结果。
给定一个 hex/rgb/hsl 值,我如何将该值放入自定义范围内,例如 11 种基本颜色,如红色、蓝色等
我能做的最好的事情就是用眼睛匹配 hsl 中的色调范围,但饱和度和亮度会改变感知的颜色。
我正在寻找一种算法来适应颜色范围内的所述值。
如果您只说 11 种基本颜色(例如红色、橙色、黄色、绿色、青色、蓝色、紫色、品红色、黑色、白色、灰色),我会说您已经知道了。只要颜色在合理的 S 和 L 范围内,您只需进行色调匹配即可匹配颜色本身。
在我看来,任何大于 95ish 的 L 都足够接近白色,任何小于 5ish 的 L 都足够接近黑色。
然后如果你的 S 小于 10,你的选项是黑色、灰色和白色,取决于 L,你甚至可以使用相同的规则。黑色 <= 5,白色 >= 95,否则为灰色。
为了匹配色调,使用我的示例颜色列表,您不能真正使用统一的范围,因为光谱红色端的颜色差异比青色端的颜色差异小得多。您可以手动定义它们,也可以使用逻辑函数获得很好的结果。
TL:DR;数学的东西,可能矫枉过正。
I would just eyeball the hue as making a formula for this is unnecessary and complex.
话虽如此,这是我对与常见颜色感知相匹配的逻辑函数的尝试。
您可以根据需要调整 k 值。我认为 1.1 给出了合理的传播(尽管我只尝试了几个值)。 8 为您提供了您希望从该函数中获取的值的数量。因此,由于我们尝试匹配 8 种不同的颜色(除了黑色、白色和灰色),因此我使用了 8 个。
3 将域向右移动 3 个单位。我使用 3 是因为它是我们将用于此函数的域的一半(中点两侧各有 3 个单位)。
澄清一下,这是最终函数:
对于 x,此公式调整为最小值为 0,最大值为 6,并且将从青色开始。所以如果0 <= f(x) < 1
,就是绿色;如果1 <= f(x) < 2
是青色等
因为它从青色开始,你必须调整你的色调输入值,这样 0 就相当于你认为青色而不是绿色的边缘。我们以 150 为例。这意味着青色的宽度为 60 度,这是我从中获得 1.1 K 值的地方,因为它排列得很好。
那么我们的 x 值将是 x = ((hue + (360 - 150)) % 360) / 60.0
或 x = (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))))));
}
这完全取决于您的用例和您尝试使用的颜色,所以是的,但是如果您想要一个公式而不是硬编码列表,那么像这样的逻辑函数可能是您镜像的最佳选择从色调中感知颜色。
更过分了。为什么不呢?
如果您想要 S 和 L 的更多选项,例如具有额外的颜色阴影,您可以使用相同样式的逻辑函数,甚至可以只使用线性函数。
亮度将遵循相同的功能。中灰色将是饼图的最大部分,因此您可以将 x=0 设置为中灰色的下限。
饱和度更像是一个对数函数。前 25% 左右有几个可识别的阴影,而上 75% 的则少得多。像
其中 N 是要识别的阴影数。该函数的定义域是0-100,范围是0-N。您可以根据自己的喜好调整 k 以更改步长的宽度,但即使将 k 保留为 1 也应该可以获得足够的结果。