Is there an API built into the .NET framework for converting HSV to RGB? I didn't see a method in System.Drawing.Color for this, but it seems surprising that there wouldn't be one in the platform.
6 Answers
There isn't a built-in method for doing this, but the calculations aren't terribly complex.
Also note that Color's GetHue(), GetSaturation() and GetBrightness() return HSL values, not HSV.
The following C# code converts between RGB and HSV using the algorithms described on Wikipedia.
I already posted this answer here, but I'll copy the code here for quick reference.
The ranges are 0 - 360 for hue, and 0 - 1 for saturation or value.
public static void ColorToHSV(Color color, out double hue, out double saturation, out double value)
{
int max = Math.Max(color.R, Math.Max(color.G, color.B));
int min = Math.Min(color.R, Math.Min(color.G, color.B));
hue = color.GetHue();
saturation = (max == 0) ? 0 : 1d - (1d * min / max);
value = max / 255d;
}
public static Color ColorFromHSV(double hue, double saturation, double value)
{
int hi = Convert.ToInt32(Math.Floor(hue / 60)) % 6;
double f = hue / 60 - Math.Floor(hue / 60);
value = value * 255;
int v = Convert.ToInt32(value);
int p = Convert.ToInt32(value * (1 - saturation));
int q = Convert.ToInt32(value * (1 - f * saturation));
int t = Convert.ToInt32(value * (1 - (1 - f) * saturation));
if (hi == 0)
return Color.FromArgb(255, v, t, p);
else if (hi == 1)
return Color.FromArgb(255, q, v, p);
else if (hi == 2)
return Color.FromArgb(255, p, v, t);
else if (hi == 3)
return Color.FromArgb(255, p, q, v);
else if (hi == 4)
return Color.FromArgb(255, t, p, v);
else
return Color.FromArgb(255, v, p, q);
}
-
Your ColorFromHSV might have something wrong with it, I was trying to rotate the hue 180 degrees using your code for an opposite color and it's not working too well. The accepted code gives a different color which seems correct to me. – Isaac Bolinger Jan 21 '16 at 20:30
-
I'm using your ColorToHSV function, however. It seems to work well. – Isaac Bolinger Jan 21 '16 at 20:31
-
@IsaacBolinger does not work well with negative hue, workd well for hue >= 0, but better to use hue between <0, 360) in your code. – xmedeko Oct 19 '17 at 08:26
-
@IsaacBolinger I wanted the same and changing the hue line to the following worked perfectly for me: `hue = (color.GetHue() + 180) % 360` – Bloopy Oct 09 '21 at 06:45
I don't think there's a method doing this in the .NET framework.
Check out Converting HSV to RGB colour using C#
This is the implementation code,
void HsvToRgb(double h, double S, double V, out int r, out int g, out int b)
{
double H = h;
while (H < 0) { H += 360; };
while (H >= 360) { H -= 360; };
double R, G, B;
if (V <= 0)
{ R = G = B = 0; }
else if (S <= 0)
{
R = G = B = V;
}
else
{
double hf = H / 60.0;
int i = (int)Math.Floor(hf);
double f = hf - i;
double pv = V * (1 - S);
double qv = V * (1 - S * f);
double tv = V * (1 - S * (1 - f));
switch (i)
{
// Red is the dominant color
case 0:
R = V;
G = tv;
B = pv;
break;
// Green is the dominant color
case 1:
R = qv;
G = V;
B = pv;
break;
case 2:
R = pv;
G = V;
B = tv;
break;
// Blue is the dominant color
case 3:
R = pv;
G = qv;
B = V;
break;
case 4:
R = tv;
G = pv;
B = V;
break;
// Red is the dominant color
case 5:
R = V;
G = pv;
B = qv;
break;
// Just in case we overshoot on our math by a little, we put these here. Since its a switch it won't slow us down at all to put these here.
case 6:
R = V;
G = tv;
B = pv;
break;
case -1:
R = V;
G = pv;
B = qv;
break;
// The color is not defined, we should throw an error.
default:
//LFATAL("i Value error in Pixel conversion, Value is %d", i);
R = G = B = V; // Just pretend its black/white
break;
}
}
r = Clamp((int)(R * 255.0));
g = Clamp((int)(G * 255.0));
b = Clamp((int)(B * 255.0));
}
/// <summary>
/// Clamp a value to 0-255
/// </summary>
int Clamp(int i)
{
if (i < 0) return 0;
if (i > 255) return 255;
return i;
}

- 6,066
- 4
- 27
- 48

- 13,536
- 8
- 56
- 77
-
8Thanks for that method. Weird that Color has .GetHue(), .GetSaturation() and .GetBrightness(), but no inverse method like .fromHSB(). – MusiGenesis Aug 26 '09 at 15:23
-
1
-
2Why not return a Color object instead of using *out* for three separate values? – Jun 14 '14 at 13:52
-
-
2@FizzledOut: Maybe because like this, the code can directly be used for [SWF `Color`](https://msdn.microsoft.com/en-us/library/system.drawing.color%28v=vs.85%29.aspx), [WPF `Color`](https://msdn.microsoft.com/en-us/library/system.windows.media.color%28v=vs.110%29.aspx), [Gdk# `Color`](http://docs.go-mono.com/?link=T%3aGdk.Color), and others. – O. R. Mapper Feb 28 '15 at 17:53
-
2If you start with for example, `System.Drawing.Color.FromArgb(255, 0, 0)`, use `.GetHue()` etc to emit that to HSV, then use this code to roundtrip back to a `Color`, you get rgb 127, 0, 0. `.GetBrightness()` returns 0.5, and this code interprets that to mean the dominant color is 255*.5 = 127. At least from my perspective that means this code does not work properly. – Chris Moschini Jul 20 '15 at 04:28
-
I'm using a combination of the above code, and ColorToHSV given below. Works great. – Isaac Bolinger Jan 21 '16 at 20:33
-
1Wouldn't be ``H = (H % 360 + 360) % 360;`` be way more efficient than those two while loops? – Stefan Mar 05 '20 at 16:29
It's not built in, but there's there's an open-source C# library called ColorMine which makes converting between color spaces pretty easy.
Rgb to Hsv:
var rgb = new Rgb {R = 123, G = 11, B = 7};
var hsv = rgb.To<Hsv>();
Hsv to Rgb:
var hsv = new Hsv { H = 360, S = .5, L = .17 }
var rgb = hsv.to<Rgb>();
-
1The ColorMine repository seems to have disappeared (404 on github as of 05 Aug 2018). Also, there doesn't seem to be a successor repository owned by Joe. However, I found [ColorMinePortable](https://github.com/muak/ColorMinePortable) which may be close enough. – Manfred Aug 04 '18 at 22:20
-
Just doing a quick search, it looks like the user might have deleted their repo. It was forked by others though: https://github.com/hvalidi/ColorMine – flndr Apr 05 '19 at 22:01
For this you can use ColorHelper library:
RGB rgb = ColorConverter.HsvToRgb(new HSV(100, 100, 100));

- 2,782
- 3
- 14
- 32
There is no built-in method (I couldn't find it), but here is code that might help you out. (above solutions didn't work for me)
/// <summary>
/// Converts HSV color values to RGB
/// </summary>
/// <param name="h">0 - 360</param>
/// <param name="s">0 - 100</param>
/// <param name="v">0 - 100</param>
/// <param name="r">0 - 255</param>
/// <param name="g">0 - 255</param>
/// <param name="b">0 - 255</param>
private void HSVToRGB(int h, int s, int v, out int r, out int g, out int b)
{
var rgb = new int[3];
var baseColor = (h + 60) % 360 / 120;
var shift = (h + 60) % 360 - (120 * baseColor + 60 );
var secondaryColor = (baseColor + (shift >= 0 ? 1 : -1) + 3) % 3;
//Setting Hue
rgb[baseColor] = 255;
rgb[secondaryColor] = (int) ((Mathf.Abs(shift) / 60.0f) * 255.0f);
//Setting Saturation
for (var i = 0; i < 3; i++)
rgb[i] += (int) ((255 - rgb[i]) * ((100 - s) / 100.0f));
//Setting Value
for (var i = 0; i < 3; i++)
rgb[i] -= (int) (rgb[i] * (100-v) / 100.0f);
r = rgb[0];
g = rgb[1];
b = rgb[2];
}

- 11
- 1
I've searched the internet for better way to do this, but I can't find it.
This is a C# method to convert HSV to RGB, the method arguments are in range of 0-1, the output is in range of 0-255
private Color hsv2rgb (float h, float s, float v)
{
Func<float, int> f = delegate (float n)
{
float k = (n + h * 6) % 6;
return (int)((v - (v * s * (Math.Max(0, Math.Min(Math.Min(k, 4 - k), 1))))) * 255);
};
return Color.FromArgb(f(5), f(3), f(1));
}

- 17,736
- 16
- 35
- 75

- 27
- 5