Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Sorting by Color

Tags:

I have a long list (1000+) of hex colors broken up in general color categories (Red, Orange, Blue, etc). When I show the list of colors in each category I need to show them in order of shade. i.e. light red first and dark red last.

What would the algorithm be to do this? (googling has failed me)

like image 715
user154442 Avatar asked Aug 11 '09 15:08

user154442


People also ask

How do you sort things by color?

When organizing by color, look to the rainbow. Walker recommends this method as you sort: "Start with white, cream, pink, red, orange, yellow, green, blue, indigo, violet, brown, gray, and black," she says. Gold and silver can be tricky, so she suggests moving them around to see what looks best to you.

Why is sorting by color important?

Sorting objects, matching shapes, colours and then pictures helps build visual perception and thinking skills. Children can generally sort into colours before they can identify the name of the colours. Learning to categorise and classify helps memory skills.

What is color sort?

Colour sorters are used for the food processing industry, such as coffee, nuts, and oil crops. The goal is the separation of items that are discoloured, toxic (such as ergot), not as ripe as required, or still with hull after dehulling such as sunflower seeds..

Is sorting by color math?

Start with learning to sort by color, and then move on to other sorting, such as sorting by beginning sounds, sorting by quantity, sorting by patterns and sorting by attribute. Sorting is such an important early math skill. As adults, we sort all the time!


1 Answers

I know this question is old, but I didn't found a pretty solution to this problem, so I investigate a little bit and want to share what I did for hypothetical future googlers.

First, convert to HSL is a great idea. But sort only by hue or light didn't solve completely the issue when your color are not "classified".

Given an array which look like:

$colors = [             [ 'color' => '#FDD4CD'],             [ 'color' => '#AE3B3B'],             [ 'color' => '#DB62A0'],             ...           ] 

First we convert all Hex colors to HSL

foreach ($colors as &$color) {        $color['hsl'] = hexToHsl($color['color']); }   /**  * Convert a hexadecimal color in RGB  * @param string $hex  * @return array  */ function hexToHsl($hex){     list($r, $g, $b) = sscanf($hex, "#%02x%02x%02x");     return rgbToHsl($r, $g, $b); }  /**  * Convert a RGB color in its HSL value  * @param int $r red  * @param int $g green  * @param int $b blue  * @return array  */ function rgbToHsl($r, $g, $b) {     $r /= 255;     $g /= 255;     $b /= 255;      $max = max($r, $g, $b);     $min = min($r, $g, $b);      $h = 0;     $l = ($max + $min) / 2;     $d = $max - $min;      if ($d == 0) {         $h = $s = 0; // achromatic     } else {         $s = $d / (1 - abs(2 * $l - 1));          switch ($max) {             case $r:                 $h = 60 * fmod((($g - $b) / $d), 6);                 if ($b > $g) {                     $h += 360;                 }                 break;              case $g:                 $h = 60 * (($b - $r) / $d + 2);                 break;              case $b:                 $h = 60 * (($r - $g) / $d + 4);                 break;         }     }     return array('h' => round($h, 2), 's' => round($s, 2), 'l' => round($l, 2)); } 

Then sort colors

We compare:

  • Their hue if they are in the same 'interval' (This help to understand why I choose 30°). So we compare the hue only if both are in [0-30], [30-60], [60-90],...
  • If not in the same interval, sort by their Lightness, then by saturation if both share the same Lightness.

So:

usort($colors, function ($a, $b) {     //Compare the hue when they are in the same "range"     if(!huesAreinSameInterval($a['hsl']['h'],$b['hsl']['h'])){        if ($a['hsl']['h'] < $b['hsl']['h'])            return -1;        if ($a['hsl']['h'] > $b['hsl']['h'])            return 1;     }     if ($a['hsl']['l'] < $b['hsl']['l'])         return 1;     if ($a['hsl']['l'] > $b['hsl']['l'])         return -1;     if ($a['hsl']['s'] < $b['hsl']['s'])          return -1;     if ($a['hsl']['s'] > $b['hsl']['s'])           return 1;     return 0;  });  /**  * Check if two hues are in the same given interval  * @param float $hue1  * @param float $hue2  * @param int $interval  * @return bool  */ function huesAreinSameInterval($hue1, $hue2, $interval = 30){     return (round(($hue1 / $interval), 0, PHP_ROUND_HALF_DOWN) === round(($hue2 / $interval), 0, PHP_ROUND_HALF_DOWN)); } 

rgbToHsl found on www.brandonheyer.com

hexToRgb found on stackoverflow

like image 186
Getz Avatar answered Oct 06 '22 08:10

Getz