Сортировка по цвету

У меня длинный список (1000+) шестицветных цветов, разбитых в общих цветовых категориях (красный, оранжевый, синий и т. Д.). Когда я показываю список цветов в каждой категории, мне нужно показать их в порядке тени. т.е. сначала светло-красный и темно-красный.

Каким будет алгоритм для этого? (googling провалил меня)

Преобразуйте цвета из RGB в HSV или HSL, а затем отсортируйте их по значению или легкости. Легкость может работать лучше, так как она будет захватывать «выцветшие» цвета лучше, например, розовый -> красный -> темно-красный.

RGB для преобразования цветового пространства HSV .

Я знаю, что этот вопрос старый, но я не нашел довольно эффективного решения этой проблемы, поэтому я немного расследую и хочу поделиться тем, что я сделал для гипотетических будущих гуглеров.

Во-первых, конвертировать в HSL – отличная идея. Но сортировка только по оттенку или свету не решила полностью проблему, когда ваш цвет не «классифицирован».

Учитывая массив, который выглядит так:

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

Сначала мы преобразуем все цвета Hex в 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)); } 

Затем сортируйте цвета

Мы сравниваем:

  • Их оттенок, если они находятся в одном и том же «интервале» ( это помогает понять, почему я выбираю 30 ° ). Поэтому мы сравниваем оттенок только в том случае, если оба находятся в [0-30], [30-60], [60-90], …
  • Если не в тот же интервал, сортируйте по их Светлости, затем по насыщению, если обе обладают одинаковой легкостью.

Так:

 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 найдено на http://www.brandonheyer.com

hexToRgb найдено в stackoverflow

Если вы преобразуете цвета в пространство HSV, вы можете отсортировать их по оттенку, а затем по значению.

Тон будет определять цвет «категория» – то есть красный, синий, зеленый и т. Д.

Значение и насыщенность будут влиять на «легкость» конечного цвета. Однако вам может потребоваться некоторое экспериментирование, чтобы получить идеальный вид.