Как получить градиент цвета радуги в C#?
Я хотел бы иметь перечисление цветов, основанных на цветах радуги (красный... желтый... зеленый... синий...).
Я вижу в основном два способа сделать это:
Создайте таблицу поиска, содержащую несколько важных эталонных цветов, и интерполируйте их. Мне вообще не нравится эта идея.
Примените более или менее причудливую математику. Наверное, меньше, но я не совсем понимаю, как это работает. Есть идеи?
(О, и хотя я провел небольшое SO-исследование, я не нашел хороших результатов. Если этот вопрос уже был опубликован, просто укажите мне местоположение, и я удалю его.)
Редактировать: я бы предпочел иметь это независимо от используемой технологии для отображения градиента. Например, что-то вроде GetRainbowColor (float f) с f в диапазоне от 0 (красный) до 1 (фиолетовый) будет работать отлично.
9 ответов
Это проще, чем вы думаете.
Сначала вам нужна функция преобразования hsv или hsl в rgb. Вот код C# для этого преобразования.
Затем вы просто перебираете все возможные значения оттенка h
сохраняя saturation
с и светимость l
постоянная.
Если вы хотите, чтобы 100 цветов радуги располагались одинаково:
for(double i = 0; i < 1; i+=0.01)
{
ColorRGB c = HSL2RGB(i, 0.5, 0.5);
//do something with the color
}
Вы также можете легко создать желаемую функцию GetRainbowColor
таким образом, добавив все эти цвета в List<ColorRGB>
и возвращая соответствующий индексированный цвет.
Мне нравится использовать это:
public static Color Rainbow(float progress)
{
float div = (Math.Abs(progress % 1) * 6);
int ascending = (int) ((div % 1) * 255);
int descending = 255 - ascending;
switch ((int) div)
{
case 0:
return Color.FromArgb(255, 255, ascending, 0);
case 1:
return Color.FromArgb(255, descending, 255, 0);
case 2:
return Color.FromArgb(255, 0, 255, ascending);
case 3:
return Color.FromArgb(255, 0, descending, 255);
case 4:
return Color.FromArgb(255, ascending, 0, 255);
default: // case 5:
return Color.FromArgb(255, 255, 0, descending);
}
}
Вот то, что мне нравится использовать (вывод - цвет HTML RGB):
public static String Rainbow(Int32 numOfSteps, Int32 step)
{
var r = 0.0;
var g = 0.0;
var b = 0.0;
var h = (Double)step / numOfSteps;
var i = (Int32)(h * 6);
var f = h * 6.0 - i;
var q = 1 - f;
switch (i % 6)
{
case 0:
r = 1;
g = f;
b = 0;
break;
case 1:
r = q;
g = 1;
b = 0;
break;
case 2:
r = 0;
g = 1;
b = f;
break;
case 3:
r = 0;
g = q;
b = 1;
break;
case 4:
r = f;
g = 0;
b = 1;
break;
case 5:
r = 1;
g = 0;
b = q;
break;
}
return "#" + ((Int32)(r * 255)).ToString("X2") + ((Int32)(g * 255)).ToString("X2") + ((Int32)(b * 255)).ToString("X2");
}
Я вижу так много примеров кода, в которых используются двойные значения. Но R,G,B — это байты, поэтому нет смысла использовать двойные значения.
Кстати: возможных цветов всего 1536, если просмотреть все возможные цвета радуги по 0...255 для каждого цвета.
Каждый из трех цветов движется вверх и вниз = 6 движений. Максимальное количество цветов, которое вы получаете с помощью этого алгоритма, составляет 6 * 256 = 1536 цветов.
Любые формулы, которые вы найдете здесь и которые дают больше цветов, чем 1536, будут содержать повторяющиеся цвета!
Следующий алгоритм работает только с целыми числами.
/// <summary>
/// s32_Sweeps = 4 --> Colors from blue to red, not including magenta (1024 colors)
/// s32_Sweeps = 6 --> Complete sweep with all rainbow colors, also magenta (1536 colors)
/// </summary>
private static Color[] CalcRainbow(int s32_Sweeps)
{
Color[] c_Colors = new Color[s32_Sweeps * 256];
int R,G,B,P=0;
for (int L=0; L<s32_Sweeps; L++)
{
for (int E=0; E<256; E++)
{
switch (L)
{
case 0: R = 0; G = E; B = 255; break; // Blue...Cyan
case 1: R = 0; G = 255; B = 255 - E; break; // Cyan...Green
case 2: R = E; G = 255; B = 0; break; // Green...Yellow
case 3: R = 255; G = 255 - E; B = 0; break; // Yellow...Red
case 4: R = 255; G = 0; B = E; break; // Red...Magenta
case 5: R = 255 - E; G = 0; B = 255; break; // Magenta...Blue
default: throw new ArgumentException();
}
c_Colors[P++] = Color.FromArgb(255, R, G, B);
}
}
return c_Colors;
}
В winforms(или что-либо с помощью GDI+) вы можете использовать System.Drawing.Drawing2D.LinearGradientBrush, чтобы выполнить интерполяцию за вас.
System.Windows.Media.GradientBrush из WPF также может работать. Это абстрактно, так что вы можете получить LinearGradientBrush от WPF. Он находится в другом пространстве имен, чем другое.
РЕДАКТИРОВАТЬ: так как вопрос был отредактирован, чтобы указать, что вы хотите быть технологически независимым, я не думаю, что этот ответ применим. Я собираюсь оставить это здесь пока, если кто-то ищет градиенты в C#, но если кто-то посчитает это нежелательным, я удалю ответ.
Я сделал быструю проверку, чтобы увидеть, сможете ли вы хотя бы получить некоторые функциональные возможности более независимым способом (например, получить массив Point или что-то в этом роде). Похоже, не в этом дело.
Начните здесь: http://www.midnightkite.com/color.html
Вы можете интерпретировать это: http://www.physics.sfasu.edu/astro/color/spectra.html это ФОРТРАН, но вполне очевидно, что он делает.
Кроме того, вы можете прочитать более подробно здесь: http://en.wikipedia.org/wiki/CIE_1931_color_space
Вот версия на Python: http://www.johnny-lin.com/py_code/wavelen2rgb.py
Кстати, первый хит Google для C# заключается в следующем: http://miguelmoreno.net/sandbox/wavelengthtoRGB/default.aspx
http://colorfulconsole.com/ Позволяет в значительной степени то, что вы ищете, также может быть установлен в виде пакета NuGet. Это не совсем градиент радуги. Но он может записывать градиенты на консоль, что также приводит к путанице в среде IDE.
Colorful.Console
а также
System.Console
Поэтому не забудьте определить правильную консоль.
uint32_t Wheel(byte WheelPos) {
if(WheelPos < 85) {
return strip.Color(WheelPos * 3, 255 - WheelPos * 3, 0);
} else if(WheelPos < 170) {
WheelPos -= 85;
return strip.Color(255 - WheelPos * 3, 0, WheelPos * 3);
} else {
WheelPos -= 170;
return strip.Color(0, WheelPos * 3, 255 - WheelPos * 3);
}
}
Просто используйте Rainbow.dll
. Это, вероятно, не лучшая библиотека, но я думаю, что для плавного эффекта радуги на каждом элементе управления WinForm, который вы хотите, это он.
Ссылка: https://marschalldev.com/2018/08/02/csharp-rainbow-effect-net-dll/
Как пользоваться:Yourcontrol.background = Color.FromArgb(Class1.A, Class1.R, Class1.G);