Как получить градиент цвета радуги в C#?

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

Я вижу в основном два способа сделать это:

  1. Создайте таблицу поиска, содержащую несколько важных эталонных цветов, и интерполируйте их. Мне вообще не нравится эта идея.

  2. Примените более или менее причудливую математику. Наверное, меньше, но я не совсем понимаю, как это работает. Есть идеи?

(О, и хотя я провел небольшое 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);

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