RGB到颜色名称映射(近似颜色映射)

时间:2017-10-25 15:30:22

标签: javascript react-native

我正在建造颜色选择器。如果用户选择颜色方块,则会转换为近似颜色名称

例如,如果用户选择C0C0C0BEBEBE的颜色,即使每种颜色都有特定的颜色名称,两种颜色的字符串也会转换为grey

我甚至无法弄清楚我是如何解决这个问题的,谷歌也没有帮助我! :(

这是我的颜色函数的sudo代码

getApproxColor = (colorString) => {
    if(`BBBBBB` <= colorString  <= 'CCCCCC') {
        return 'grey'
    }
    ...
}

我应该在这个函数上写整个颜色名吗?是否有任何十六进制颜色的公式?

2 个答案:

答案 0 :(得分:1)

TL; DR:只需使用此库。这是我所说的混合而是由Kaiido提到的复杂性解决:http://chir.ag/projects/ntc/

保留原来的答案,但不会完全奏效。往上看。

嗯,每种颜色都是六位六位数的组合。

如果将该数字转换为int,请说BEBEBE为12500670.

然后,您可以拥有一个小表,其中包含每个已知名称的密钥/对及其对应的整数值。

然后只是在表中找到最接近的整数。

编辑:

基本上,如果你有你的颜色选择器并且说这个人选择'BEBEBE'你就必须:

  1. 将hexa转换为十进制。有多个教程和在线工具,我不会在这里详细介绍。这不是很难。
  2. 然后你会有一个表,对象,数组,你想要的十进制值及其对应名称。例: http://cloford.com/resources/colours/500col.htm您可以使用具有hexa代码的表并将其转换为十进制。 [{ 名称:'grey',hexa:'bebebe',十进制:'12500670' }, [...] //插入更多颜色 ]
  3. 然后,您可以迭代列表,将用户的十进制输入与您拥有的十进制输入进行比较,并在达到比您的数字更高的数字时停止,您可以存储刚刚找到的数字和前一个数字。
  4. 你发现你刚发现的那个和前一个之间的区别,差异较小的那个是最接近的那个
  5. 利润

答案 1 :(得分:1)

我不确定这是否是最佳方式,但如果我不得不做这样的事情,我想我会先将这些十六进制值转换为hsl。

然后你必须检查饱和度和亮度,以便找到灰色并在你的发现中添加更多的粒度。

这是一个粗略的概念证明,仅使用6种基色并使用stolen code from an older question来执行此操作hex =&gt; hsl转换。

inp.oninput = e => {
  if (!inp.checkValidity()) return;
  var val = inp.value;
  if (val.length !== 3 && val.length !== 6) return;
  var color = hexToName(inp.value);
  if (color) {
    inp.style.backgroundColor = '#' + val;
    log.textContent = color;
  }
}


function hexToName(hex) {
  // first get hsl correspondance
  var hsl = hexToHsl(hex);
  if(!hsl){
    return;
  }
  // get the base color
  var color = getColorName(hsl[0] * 360);
  // check saturation and luminosity
  // needs more granularity, left as an exercise for the reader
  if (hsl[1] < .5) {
    return hsl[2] <= .5 ? hsl[2] === 0? 'black' : 'darkgray' : hsl[2] === 1 ? 'white': 'gray';
  }
  return hsl[2] <= .5 ? color : 'light' + color;
}
function getColorName(hue) {
  // here you will need more work:
  // we use fixed distance for this simple demo
  var names = ['red', 'yellow', 'green', 'cyan', 'blue', 'magenta'];
  var angles = [0, 60, 120, 180, 240, 300];
  var match = angles.filter(a =>
    a - 60 <= hue && a + 60 > hue
  )[0] || 0;
  return names[angles.indexOf(match)];
}
// shamelessly stolen from https://stackoverflow.com/a/3732187/3702797
function hexToHsl(hex) {
  if (hex.length === 3) {
    hex = hex.split('').map(c => c.repeat(2)).join('');
  }
  if (hex.length !== 6) {
    return;
  }
  var r = parseInt(hex[0] + hex[1], 16);
  var g = parseInt(hex[2] + hex[3], 16);
  var b = parseInt(hex[4] + hex[5], 16);

  r /= 255, g /= 255, b /= 255;
  var max = Math.max(r, g, b),
    min = Math.min(r, g, b);
  var h, s, l = (max + min) / 2;

  if (max == min) {
    h = s = 0; // achromatic
  } else {
    var d = max - min;
    s = l > 0.5 ? d / (2 - max - min) : d / (max + min);
    switch (max) {
      case r:
        h = (g - b) / d + (g < b ? 6 : 0);
        break;
      case g:
        h = (b - r) / d + 2;
        break;
      case b:
        h = (r - g) / d + 4;
        break;
    }
    h /= 6;
  }

  return [h, s, l];
}
#<input id="inp" type="text" pattern="[0-9a-fA-F]+">
<pre id="log"><pre>