Как случайным образом генерировать только полностью насыщенные цвета? - PullRequest
4 голосов
/ 12 декабря 2011

Я обычно использую следующий код для генерации случайных цветов:

Random rand = new Random();

Color random = Color.FromArgb((int)(rand.NextDouble() * 255), 
                              (int)(rand.NextDouble() * 255), 
                              (int)(rand.NextDouble() * 255));

Но большинство из них выглядят как вариации серого.Как я могу ограничить вывод только полностью насыщенными цветами?

Спасибо.

Ответы [ 3 ]

4 голосов
/ 12 декабря 2011

Theory

Полная насыщенность (используемая HSL и аналогичными цветовыми схемами) фактически означает, что у вас есть одно значение RGB при полном, одно при 0 и одно при любом другом значении.

Причина этого заключается в том, что насыщенность основана на разнице между самым высоким и самым низким цветовыми компонентами и является самой высокой, когда они находятся в крайних значениях. Фактические определения являются более сложными (и включают в себя яркость), но достаточно сказать, что компонент 0 и другой из 1 дадут максимальное насыщение.

Алгоритм 1

Это приводит к относительно простому способу сделать это.

  1. Генерация случайного числа от 0 до 1.
  2. Назначьте это число случайным образом для элементов R, G и B.
  3. Произвольно присвоить ноль одному из оставшихся элементов.
  4. установить конечный элемент равным 1.

Это даст вам максимальную насыщенность цвета относительно просто.

Для реализации, вероятно, проще всего сгенерировать случайное число от 1 до 6 для 6 возможных вариантов выбора, для какого компонента вы назначаете 0, 1 и случайный элемент, а затем используете какой-то переключатель.

Это самый простой алгоритм, но не обязательно самая простая реализация из-за выбора / ветвления.

Алгоритм 2

Второй метод, предложенный Джимом Мишелем, основан на похожей теории, но реализован немного по-другому.

  1. Генерация случайных значений для каждого из компонентов R, G и B
  2. Найдите максимальный компонент.
  3. Найдите минимальный компонент.
  4. Установите максимальный компонент равным 1.
  5. Установите минимальный компонент на 0.

Это имеет тот же эффект установки одного значения в 1, одного в 0 и одного в случайное значение. У него есть то преимущество, что вам не нужно использовать грязный оператор switch, но вместо этого вы можете получить несколько грязных циклов. Также в зависимости от точности ваших компонентов (например, если вы идете прямо с байтами), тогда, если ваше среднее значение на самом деле равно вашему верху или низу (или все три одинаковы), то это может также сброситься в зависимости от того, как вы кодируете ваш алгоритм. Это в основном будет иметь эффект искажения случайности, но вряд ли это будет заметно заметно.

Реализация кода для метода два также любезно предоставлена ​​Jim

    int[] rgb = new int[3];
    rgb[0] = rnd.Next(256);  // red
    rgb[1] = rnd.Next(256);  // green
    rgb[2] = rnd.Next(256);  // blue

    // Console.WriteLine("{0},{1},{2}", rgb[0], rgb[1], rgb[2]);

    // find max and min indexes.
    int max, min;

    if (rgb[0] > rgb[1])
    {
        max = (rgb[0] > rgb[2]) ? 0 : 2
        min = (rgb[1] < rgb[2]) ? 1 : 2;
    }
    else
    {
        max = (rgb[1] > rgb[2]) ? 1 : 2;
        int notmax = 1 + max % 2;
        min = (rgb[0] < rgb[notmax]) ? 0 : notmax;
    }
    rgb[max] = 255;
    rgb[min] = 0;

    // Console.WriteLine("{0},{1},{2}", rgb[0], rgb[1], rgb[2]);
2 голосов
/ 12 декабря 2011

Полагаю, вы хотите сгенерировать свои цвета в значениях HSL, установив насыщенность, установленную на ее максимальное значение, и только случайным образом настроить оттенок и яркость. Вы можете найти класс для цвета HSL здесь .

0 голосов
/ 07 августа 2013

Для справки, вот небольшая адаптация к предложению Джиму Мишелю (ниже приведен код Java, адаптация к .net тривиальна):

private static Random r = new Random();

public static final String randomColor() {
    int[] arr = new int[3];
    arr[0] = 0x80;
    arr[1] = 0xFF;
    arr[2] = r.nextInt(0x10) * 8 + 0x80;
    // Fisher–Yates shuffle
    for (int i1 = arr.length - 1; i1 >= 0; i1--) {
        int i2 = r.nextInt(i1 + 1);
        int tmp = arr[i2];
        arr[i2] = arr[i1];
        arr[i1] = tmp;
    }
    return String.format("%02x%02x%02x", arr[0], arr[1], arr[2]);
}

Мы устанавливаем 3 значения случайным образом:

  • от одного до 0x80
  • другой к 0xFF
  • оставшемуся случайному значению от 0X80 до 0xFF.

Случайное значение генерируется с шагом 0x10, чтобы получить уменьшенный набор различных цветов (а именно 6 x 8 = 48), вы можете написать arr[2] = r.nextInt(0x80) + 0x80; для большего выбора.

Я также установил минимальное значение 0x80, чтобы получить менее насыщенный цвет, который, на мой взгляд, выглядит немного лучше (это вопрос плохого вкуса ...). Вы можете уменьшить этот минимум, чтобы увеличить насыщенность.

...