Создать n-цветную палитру радуги

Я пытаюсь сгенерировать радугу с 15 различными цветами ( код запуска здесь):

size(360,100);
colorMode(HSB, 360, 100, 100); // Hue in degrees in [0, 360],
                               // saturation/brightness in [0, 100]
                               // like in Photoshop
noStroke();

for (int i = 0; i < 15; i++)   
{
    fill(i*24, 100, 100);      // 24*15 = 360
    rect(i*24, 0, 25, 100);
}

но он не дает богатой 15-цветовой палитры, вместо этого отсутствуют некоторые цвета (например, ярко-желтый).

Есть ли хорошо известный алгоритм для создания яркой цветовой палитры радуги?

1 ответ

Решение

Чтобы понять, что происходит, попробуйте создать программу, которая показывает строку для каждого значения 0-360:

size(360,100);
colorMode(HSB, 360, 100, 100);                                         
noStroke();
for (int i = 0; i < 360; i++)   
{
    fill(i, 100, 100);
    rect(i, 0, 1, 100);
}

Вы увидите это:

градиент цвета

Обратите внимание, что "ярко-желтая" полоса гораздо более узкая, чем, например, зеленая или синяя полоса. Вот почему простая выборка каждого значения X не генерирует желтый цвет.

Желтый цвет вокруг значения 60, так что вы можете изменить свой прирост так, чтобы он приземлялся на 60. Рисование 12 прямоугольников шириной 30 позволяет вам приземлиться на желтый:

size(360,100);
colorMode(HSB, 360, 100, 100);                                         
noStroke();
for (int i = 0; i < 360; i++)   
{
    fill(i*30, 100, 100);
    rect(i*30, 0, 30, 100);
}

градиент цвета с желтым

Или вы можете заранее найти нужные значения и поместить их в массив, вместо того, чтобы использовать равномерное распределение:

int[] hueValues = {0, 15, 30, 60, 90, 120, 150, 180, 210, 225, 240, 270, 300, 330, 360};

size(360,100);
colorMode(HSB, 360, 100, 100);                                         
noStroke();
for (int index = 0; index < hueValues.length; index++)   
{
    float rectWidth = width/hueValues.length;
    fill(hueValues[index], 100, 100);
    rect(index*rectWidth, 0, rectWidth, height);
}

градиент цвета массива

Я создал функцию, которая генерирует N цветов (радуга) и выводит список строк (значения Hex). Это на C#, но логику можно преобразовать. Чтобы понять, что происходит, я построил график зависимости красного, синего и зеленого значений от n. При этом вы увидите, что каждый из трех графиков представляет собой кусочные функции с точками интереса при n=0, n=1/4, n=1/2 и n=3/4.

    List<string> GenerateRainbowPalette(int numColors)
    {
        var toRet = new List<SKColor>();
        var n = (float)numColors;
        for(var i = 0; i< numColors; i++)
        {
            int red = 255;
            int green = 0;
            int blue = 0;
            //red: (first quarter)
            if (i <= n / 4)
            {
                red = 255;
                green = (int)(255 / (n / 4) * i);
                blue = 0;
            }
            else if (i <= n / 2)  //2nd quarter
            {
                red = (int)((-255)/(n/4)*i + 255 * 2);
                green = 255;
                blue = 0;
            }
            else if (i <= (.75)*n)
            { // 3rd quarter
                red = 0;
                green = 255;
                blue = (int)(255 / (n / 4) * i + (-255 * 2));
            }
            else if(i > (.75)*n)
            {
                red = 0;
                green = (int)(-255 * i / (n / 4) + (255 * 4));
                blue = 255;
            }

            //generate hex string:
            var redHex = red.ToString("X2");
            var greenHex = green.ToString("X2");
            var blueHex = blue.ToString("X2");

            var color = $"#{redHex}{greenHex}{blueHex}";
        
         
            toRet.Add(color);
        }
        return toRet;
    }


   
Другие вопросы по тегам