Создать 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;
}