title: Why this color conversion maps to gray so often?
body: <p>I want to convert the RGB Color to an indexed color, here is my code, it works. But although some colors are converted to blue or red, but others that look like blue or red got converted to gray. How to fix this? You can check my snippet, click the color from big table and see the results down there.</p>
  
  <p><div class="snippet" data-lang="js" data-hide="false">
  <div class="snippet-code">
  <pre class="snippet-code-js lang-js prettyprint-override"><code>var palette = [0, 0xff0000, 0xff00, 0xffff00, 0xff, 0xff00ff, 0xffff, 0x808080]
  
  function rgb(c) {
      return [c &amp; 0xff, (c &gt;&gt; 8) &amp; 0xff, (c &gt;&gt; 16) &amp; 0xff]
    }
    // http://alienryderflex.com/hsp.html
  
  function rgb2lum(r, g, b) {
    return Math.sqrt(Pr * r * r + Pg * g * g + Pb * b * b)
  }
  var Pr = .2126,
    Pg = .7152,
    Pb = .0722;
  var rd = 255,
    gd = 255,
    bd = 255,
    maxDist = Math.sqrt(Pr * rd * rd + Pg * gd * gd + Pb * bd * bd);
  
  function colorDist(a, b) {
    a = rgb(a), b = rgb(b)
    var rd = b[0] - a[0],
      gd = b[1] - a[1],
      bd = b[2] - a[2]
    return Math.sqrt(Pr * rd * rd + Pg * gd * gd + Pb * bd * bd) / maxDist
  }
  
  function randomColor() {
    var r = Math.floor(Math.random() * 256)
    var g = Math.floor(Math.random() * 256)
    var b = Math.floor(Math.random() * 256)
    var c = (r + (g &lt;&lt; 8) + (b &lt;&lt; 16))
    return c
  }
  
  function hex(c) {
    c = c.toString(16)
    while (c.length &lt; 6) c = '0' + c
    return '#' + c
  }
  
  function f(a) {
    var id = -1,
      val = 2
    for (var i = 0; i &lt; palette.length; i++) {
      var c = palette[i],
        d = colorDist(a, c)
      if (d &lt; val) id = i, val = d
    }
    out.innerHTML += ('&lt;span style="border:1px solid black"&gt;&lt;span style=background:' + hex(a) + '&gt;&amp;nbsp&amp;nbsp&amp;nbsp&amp;nbsp&amp;nbsp&amp;nbsp&lt;/span&gt;&lt;span style=background:' + hex(palette[id]) + '&gt;&amp;nbsp&amp;nbsp&amp;nbsp&amp;nbsp&amp;nbsp&amp;nbsp&lt;/span&gt;&lt;/span&gt;, ')
  }
  var W = 60,
    H = 10
  var s = '&lt;table border=0 cellspacing=0 style=cursor:pointer&gt;'
  for (var y = 0; y &lt; H; y++) {
    s += '&lt;tr&gt;'
    for (var x = 0; x &lt; W; x++) {
      var c = randomColor()
      s += '&lt;td style="background:' + hex(c) + '" onclick=f(' + c + ')&gt;&amp;nbsp;&amp;nbsp;&lt;/td&gt;'
    }
    s += '&lt;/tr&gt;'
  }
  s += '&lt;/table&gt;'
  s += 'palette:&lt;table border=1&gt;&lt;tr&gt;'
  for (var x = 0; x &lt; palette.length; x++) {
    s += '&lt;td style="background:' + hex(palette[x]) + '" onclick=f(' + palette[x] + ')&gt;&amp;nbsp;&amp;nbsp;&lt;/td&gt;'
  }
  s += '&lt;/tr&gt;&lt;/table&gt;'
  out.innerHTML = s</code></pre>
  <pre class="snippet-code-html lang-html prettyprint-override"><code>&lt;span id=out&gt;&lt;/span&gt;</code></pre>
  </div>
  </div>
  </p>