Reputation: 32650
I'd like to have an enumeration of Colors based on the rainbow colors (red... yellow... green... blue...).
I see basically two ways to do that:
Create a lookup table containing some important reference colors and interpolate between these. I don't like this idea at all.
Apply some more or less fancy math. Probably less, but I don't quite see how it works. Any ideas?
(Oh, and while I did some SO research, I found no good results. If this question was already posted, please just point me to the location and I'll delete this.)
Edit: I'd prefer to have this independent of the used technology to display the gradient. For instance, something like GetRainbowColor (float f) with f ranging from 0 (red) to 1 (violet) would work great.
Upvotes: 20
Views: 42576
Reputation: 8148
I see so many code samples which use doubles. But R,G,B are bytes, so it makes no sense to use doubles.
By the way: there are only 1536 possible colors when you sweep through all possible rainbow colors with 0...255 for each color.
Each of the 3 colors sweeps up and down = 6 sweeps. The maximum colors you get with this algorithm are 6 * 256 = 1536 colors.
Any formulas that you find here which produce more colors than 1536 will contain repeating colors!
The following algorithm works only with integers.
/// <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;
}
Upvotes: 2
Reputation: 1
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
}
}
if wheelpos == 5, it return (15, 240, 0)
6 = (18, 237, 0)
Upvotes: 0
Reputation: 1
Just use the Rainbow.dll
. This is probably not the best library, but for a smooth Rainbow effect on, I think, every WinForm Control you want, this is it.
Link: https://marschalldev.com/2018/08/02/csharp-rainbow-effect-net-dll/
How to use:
Yourcontrol.background = Color.FromArgb(Class1.A, Class1.R, Class1.G);
Upvotes: -2
Reputation: 87
http://colorfulconsole.com/ Allows pretty much what you're looking for, also can be installed as a NuGet package. It's not exactly a rainbow gradient. But it can write gradients to the console, also this confuses the IDE between the
Colorful.Console
and
System.Console
So make sure to define the right Console.
Upvotes: 0
Reputation: 4310
Here's one I like to use (the output is an HTML RGB color):
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");
}
Upvotes: 3
Reputation: 14085
I like to use this:
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);
}
}
Upvotes: 9
Reputation: 46173
In winforms(or anything using GDI+) you could use System.Drawing.Drawing2D.LinearGradientBrush to do the interpolation for you.
WPF's System.Windows.Media.GradientBrush could work as well. It's abstract so you might end up with WPF's LinearGradientBrush. It's in a different namespace than the other.
EDIT: since the question was edited to indicate that you want to be tech independent I don't think this answer applies. I'm going to leave it here for now in case someone is looking for Gradients in C#, but if someone finds that objectionable I'll remove the answer.
I did a quick check to see if you could at least get at some of the functionality in a more independent way (such as getting an array of Point or something). Doesn't appear to be the case.
Upvotes: 2
Reputation: 347256
This is easier than you think.
First you need an hsv or hsl to rgb conversion function. Here is C# code to do that conversion.
Then you simply iterate over all of the possible values of the hue h
while keeping the saturation
s and luminosity l
constant.
If you want 100 colors of the rainbow spaced out equally:
for(double i = 0; i < 1; i+=0.01)
{
ColorRGB c = HSL2RGB(i, 0.5, 0.5);
//do something with the color
}
You could also easily create your desired function GetRainbowColor
this way by adding all of these colors to a List<ColorRGB>
and returning the appropriate indexed color.
Upvotes: 34