我想根据彩虹颜色枚举颜色(红...黄...绿...蓝...)。
我基本上看到两种方法可以做到这一点:
创建一个包含一些重要参考颜色的查找表并在它们之间进行插值。我一点也不喜欢这个主意。
应用一些或多或少的奇特数学。可能更少,但我不太明白它是如何工作的。有什么想法吗?
(哦,虽然我做了一些研究,但我没有找到好的结果。如果这个问题已经发布,请指出我的位置,我会删除它。)
编辑:我更希望使其独立于所使用的技术来显示渐变。例如,像 GetRainbowColor (float f) 这样的函数,其中 f 的范围从 0(红色)到 1(紫色),效果会很好。
这比你想象的要容易。
首先你需要一个 hsv 或 hsl 到 rgb 转换函数。 这是执行该转换的 C# 代码。
然后,您只需迭代色调
h
的所有可能值,同时保持 saturation
s 和亮度 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");
}
在 winforms(或任何使用 GDI+ 的东西)中,您可以使用 System.Drawing.Drawing2D.LinearGradientBrush 来为您进行插值。
WPF 的 System.Windows.Media.GradientBrush 也可以工作。它很抽象,因此您最终可能会使用 WPF 的 LinearGradientBrush。它位于与另一个不同的命名空间中。
编辑:由于问题经过编辑以表明您想要技术独立,所以我认为这个答案不适用。我暂时将其留在这里,以防有人在 C# 中寻找渐变,但如果有人发现令人反感,我将删除答案。
我做了一个快速检查,看看您是否至少可以以更独立的方式获取某些功能(例如获取 Point 数组或其他内容)。看来情况并非如此。
从这里开始:http://www.midnightkite.com/color.html
你可以解释这个:http://www.physicals.sfasu.edu/astro/color/spectra.html它是FORTRAN,但它的作用非常明显。
此外,您可以在这里阅读更多内容:http://en.wikipedia.org/wiki/CIE_1931_color_space
这是 Python 版本:http://www.johnny-lin.com/py_code/wavelen2rgb.py
顺便说一句,C# 的第一个 google 搜索是这样的:http://miguelmoreno.net/sandbox/wavelengthtoRGB/default.aspx
http://colorfulconsole.com/ 几乎可以满足您所需的功能,也可以作为 NuGet 包安装。 它不完全是彩虹渐变。 但它可以将渐变写入控制台,这也使 IDE 之间感到困惑
Colorful.Console
和
System.Console
因此请确保定义正确的控制台。
uint32_t Wheel(byte WheelPos) { // 0 - 255 return unit32_t
if(WheelPos < 85) {
return strip.Color(WheelPos * 3, 255 - WheelPos * 3, 0); //red + green
} else if(WheelPos < 170) {
WheelPos -= 85;
return strip.Color(255 - WheelPos * 3, 0, WheelPos * 3); //blue + red
} else {
WheelPos -= 170;
return strip.Color(0, WheelPos * 3, 255 - WheelPos * 3); //green + blue
}
}
如果wheelpos == 5,则返回(15, 240, 0)
6 = (18, 237, 0)
我看到很多使用双精度的代码示例。如果我们有 R、G、B 的字节值,那么我认为使用双精度数是没有意义的。
顺便说一句,当您扫描所有可能的彩虹颜色(每种颜色为 0...255)时,只有 1535 种可能的颜色。
使用此算法获得的最大颜色为 6 * 256 - 1。
以下算法仅适用于整数并创建所有可能的颜色。
/// <summary>
/// A full rainbow sweep requires V = 0 ... 256 * 6 - 1 = 1535
/// A rainbow sweep from blue to red requires V = 0 ... 256 * 4 - 1 = 1023
/// Any formulas for a rainbow which produce more colors than this will have repeating colors!
/// </summary>
private static Color GetRainbowColor(int V)
{
int R,G,B;
int E = V % 256;
switch (V / 256)
{
case 0: // Blue
R = 0;
G = E;
B = 255;
break;
case 1: // Cyan
R = 0;
G = 255;
B = 255 - E;
break;
case 2: // Green
R = E;
G = 255;
B = 0;
break;
case 3: // Yellow
R = 255;
G = 255 - E;
B = 0;
break;
case 4: // Red
R = 255;
G = 0;
B = E;
break;
case 5: // Magenta
R = 255 - E;
G = 0;
B = 255;
break;
default:
Debug.Assert(false);
return Color.Empty;
}
return Color.FromArgb(255, R, G, B);
}
只需使用
Rainbow.dll
。这可能不是最好的库,但为了在您想要的每个 WinForm 控件上实现平滑的彩虹效果,这就是它。
链接:https://marschalldev.com/2018/08/02/csharp-rainbow-effect-net-dll/
使用方法:
Yourcontrol.background = Color.FromArgb(Class1.A, Class1.R, Class1.G);