Search code examples
c#wpfcolorsrgb

How can I classify some color to color ranges?


If I get a lightgray color(for example R=G=B=200) and a dark one(for example R=46,G=41,B=35), I'd like to classify both of them to the simple gray color group(imagine a table).

So, how can I organize the colors to color groups?


Solution

  • For visual classification of colors, it is often easier to convert the color to HSL or HSV first. To detect grays, you check if the Saturation is below some threshold. To detect any other color, you check the Hue.

    public string Classify(Color c)
    {
        float hue = c.GetHue();
        float sat = c.GetSaturation();
        float lgt = c.GetLightness();
    
        if (lgt < 0.2)  return "Blacks";
        if (lgt > 0.8)  return "Whites";
    
        if (sat < 0.25) return "Grays";
    
        if (hue < 30)   return "Reds";
        if (hue < 90)   return "Yellows";
        if (hue < 150)  return "Greens";
        if (hue < 210)  return "Cyans";
        if (hue < 270)  return "Blues";
        if (hue < 330)  return "Magentas";
        return "Reds";
    }
    

    You could of course use some other divisions.

    I made a simple JavaScript application to test this:

    function classify(r, g, b) {
      let [hue, sat, lgt] = rgbToHsl(r, g, b);
      if (lgt < 0.2) return "Blacks";
      if (lgt > 0.8) return "Whites";
    
      if (sat < 0.25) return "Grays";
    
      if (hue < 30) return "Reds";
      if (hue < 90) return "Yellows";
      if (hue < 150) return "Greens";
      if (hue < 210) return "Cyans";
      if (hue < 270) return "Blues";
      if (hue < 330) return "Magentas";
      return "Reds";
    }
    
    document.addEventListener('DOMContentLoaded', () => main());
    
    function main() {
      let result = document.querySelector('#result > tbody');
      for (let r = 0; r <= 0xFF; r += 0x33) {
        for (let g = 0; g <= 0xFF; g += 0x33) {
          for (let b = 0; b <= 0xFF; b += 0x33) {
            let hex = '#' + ((r * 256 + g) * 256 + b).toString(16).padStart(6, '0').toUpperCase();
            let tr = document.createElement('tr');
            let td1 = document.createElement('td');
            let box = document.createElement('div');
            box.className = 'color-box';
            box.style.backgroundColor = hex;
            td1.appendChild(box);
            td1.appendChild(document.createTextNode(hex));
            tr.appendChild(td1);
            let td2 = document.createElement('td');
            td2.innerText = classify(r, g, b);
            tr.appendChild(td2);
            result.appendChild(tr);
          }
        }
      }
    }
    
    // Based on: https://www.30secondsofcode.org/js/s/rgb-hex-hsl-hsb-color-format-conversion/#rgb-to-hsl
    function rgbToHsl(r, g, b) {
      r /= 255;
      g /= 255;
      b /= 255;
      const l = Math.max(r, g, b);
      const s = l - Math.min(r, g, b);
      const h = s ?
        l === r ?
        (g - b) / s :
        l === g ?
        2 + (b - r) / s :
        4 + (r - g) / s :
        0;
      return [
        60 * h < 0 ? 60 * h + 360 : 60 * h,
        (s ? (l <= 0.5 ? s / (2 * l - s) : s / (2 - (2 * l - s))) : 0),
        (2 * l - s) / 2
      ];
    }
    .color-box {
      display: inline-block;
      width: 2em;
      height: 1em;
      margin-right: 0.5em;
      border: 1px solid black;
    }
    <table id="result">
      <thead>
        <tr>
          <th>Color</th>
          <th>Classification</th>
        </tr>
      </thead>
      <tbody></tbody>
    </table>