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

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

23 голосов
/ 11 августа 2009

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

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

Ответы [ 3 ]

11 голосов
/ 31 июля 2015

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

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

Учитывая массив, который похож на:

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

Сначала мы конвертируем все шестнадцатеричные цвета в 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 найден на www.brandonheyer.com

hexToRgb найдено в stackoverflow

8 голосов
/ 11 августа 2009

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

1 голос
/ 11 августа 2009

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

Оттенок будет определять цвет "категория" - то есть: красный, синий, зеленый и т. Д.

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...