如何将 RGB 颜色转换为 HSV?

发布于 2024-07-09 19:00:15 字数 60 浏览 4 评论 0原文

如何使用 C# 将 RGB 颜色转换为 HSV?
我一直在寻找一种无需使用任何外部库的快速方法。

How can I convert a RGB Color to HSV using C#?
I've searched for a fast method without using any external library.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(7

长途伴 2024-07-16 19:00:15

请注意,Color.GetSaturation()Color.GetBrightness() 返回 HSL 值,而不是 HSV。
下面的代码演示了其中的区别。

Color original = Color.FromArgb(50, 120, 200);
// original = {Name=ff3278c8, ARGB=(255, 50, 120, 200)}

double hue;
double saturation;
double value;
ColorToHSV(original, out hue, out saturation, out value);
// hue        = 212.0
// saturation = 0.75
// value      = 0.78431372549019607

Color copy = ColorFromHSV(hue, saturation, value);
// copy = {Name=ff3278c8, ARGB=(255, 50, 120, 200)}

// Compare that to the HSL values that the .NET framework provides: 
original.GetHue();        // 212.0
original.GetSaturation(); // 0.6
original.GetBrightness(); // 0.490196079

以下 C# 代码就是您想要的。 它使用 Wikipedia 上描述的算法在 RGB 和 HSV 之间进行转换。 hue 的范围为 0 - 360,saturationvalue 的范围为 0 - 1。

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);
}

Note that Color.GetSaturation() and Color.GetBrightness() return HSL values, not HSV.
The following code demonstrates the difference.

Color original = Color.FromArgb(50, 120, 200);
// original = {Name=ff3278c8, ARGB=(255, 50, 120, 200)}

double hue;
double saturation;
double value;
ColorToHSV(original, out hue, out saturation, out value);
// hue        = 212.0
// saturation = 0.75
// value      = 0.78431372549019607

Color copy = ColorFromHSV(hue, saturation, value);
// copy = {Name=ff3278c8, ARGB=(255, 50, 120, 200)}

// Compare that to the HSL values that the .NET framework provides: 
original.GetHue();        // 212.0
original.GetSaturation(); // 0.6
original.GetBrightness(); // 0.490196079

The following C# code is what you want. It converts between RGB and HSV using the algorithms described on Wikipedia. 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);
}
青朷 2024-07-16 19:00:15

您是否考虑过简单地使用 System.Drawing 命名空间? 例如:

System.Drawing.Color color = System.Drawing.Color.FromArgb(red, green, blue);
float hue = color.GetHue();
float saturation = color.GetSaturation();
float lightness = color.GetBrightness();

请注意,这并不完全是您所要求的(请参阅HSL 和 HSV 之间的差异 并且 Color 类没有从 HSL/HSV 转换回来,但后者是合理的 易于添加

Have you considered simply using System.Drawing namespace? For example:

System.Drawing.Color color = System.Drawing.Color.FromArgb(red, green, blue);
float hue = color.GetHue();
float saturation = color.GetSaturation();
float lightness = color.GetBrightness();

Note that it's not exactly what you've asked for (see differences between HSL and HSV and the Color class does not have a conversion back from HSL/HSV but the latter is reasonably easy to add.

梦萦几度 2024-07-16 19:00:15

EasyRGB 有许多色彩空间转换。 这是 RGB->HSV 的代码转换。

The EasyRGB has many color space conversions. Here is the code for the RGB->HSV conversion.

人海汹涌 2024-07-16 19:00:15

这里有一个 C 实现:

http://www.cs.rit.edu/ ~ncs/color/t_convert.html

转换为 C# 应该非常简单,因为几乎没有调用任何函数 - 只是计算。

通过 Google 找到

There's a C implementation here:

http://www.cs.rit.edu/~ncs/color/t_convert.html

Should be very straightforward to convert to C#, as almost no functions are called - just calculations.

found via Google

向地狱狂奔 2024-07-16 19:00:15

这是从 BlaM 帖子中的 C 代码移植而来的 VB.net 版本,对我来说工作得很好。

这里有一个 C 实现:

http://www.cs.rit.edu/~ncs /color/t_convert.html

转换为 C# 应该非常简单,因为几乎没有调用任何函数 - 只是 > 计算。


Public Sub HSVtoRGB(ByRef r As Double, ByRef g As Double, ByRef b As Double, ByVal h As Double, ByVal s As Double, ByVal v As Double)
    Dim i As Integer
    Dim f, p, q, t As Double

    If (s = 0) Then
        ' achromatic (grey)
        r = v
        g = v
        b = v
        Exit Sub
    End If

    h /= 60 'sector 0 to 5
    i = Math.Floor(h)
    f = h - i 'factorial part of h
    p = v * (1 - s)
    q = v * (1 - s * f)
    t = v * (1 - s * (1 - f))

    Select Case (i)
        Case 0
            r = v
            g = t
            b = p
            Exit Select
        Case 1
            r = q
            g = v
            b = p
            Exit Select
        Case 2
            r = p
            g = v
            b = t
            Exit Select
        Case 3
            r = p
            g = q
            b = v
            Exit Select
        Case 4
            r = t
            g = p
            b = v
            Exit Select
        Case Else   'case 5:
            r = v
            g = p
            b = q
            Exit Select
    End Select
End Sub

This is the VB.net version which works fine for me ported from the C code in BlaM's post.

There's a C implementation here:

http://www.cs.rit.edu/~ncs/color/t_convert.html

Should be very straightforward to convert to C#, as almost no functions are called - just > calculations.


Public Sub HSVtoRGB(ByRef r As Double, ByRef g As Double, ByRef b As Double, ByVal h As Double, ByVal s As Double, ByVal v As Double)
    Dim i As Integer
    Dim f, p, q, t As Double

    If (s = 0) Then
        ' achromatic (grey)
        r = v
        g = v
        b = v
        Exit Sub
    End If

    h /= 60 'sector 0 to 5
    i = Math.Floor(h)
    f = h - i 'factorial part of h
    p = v * (1 - s)
    q = v * (1 - s * f)
    t = v * (1 - s * (1 - f))

    Select Case (i)
        Case 0
            r = v
            g = t
            b = p
            Exit Select
        Case 1
            r = q
            g = v
            b = p
            Exit Select
        Case 2
            r = p
            g = v
            b = t
            Exit Select
        Case 3
            r = p
            g = q
            b = v
            Exit Select
        Case 4
            r = t
            g = p
            b = v
            Exit Select
        Case Else   'case 5:
            r = v
            g = p
            b = q
            Exit Select
    End Select
End Sub
能怎样 2024-07-16 19:00:15

我因为有同样的需求而来到这里。

下面我将分享迄今为止我能找到的最好、最简单的解决方案。
这是 Greg 的修改答案(在这里找到); 但具有更简单且易于理解的代码。

对于那些正在学习的人,我添加了一些参考资料,为了理解,值得检查。


参考资料

  1. “Lukas Stratmann”HSV 模型工具(包括其他模型系统:CMY / CMYK / HSL)
  2. "平面设计中的 HSV 颜色模型”
  3. “确定感知的公式RGB 颜色的亮度”
  4. 从 RGB 获取色调的最快公式
  5. “颜色转换算法”
  6. "将 RGB 颜色模型更改为 HSV 颜色模型的程序"
  7. < a href="https://math.stackexchange.com/questions/556341/rgb-to-hsv-color-conversion-algorithm">"RGB 到 HSV 颜色转换算法"
  8. "RGB 到 HSV 色彩空间转换 (C)"
  9. < a href="https://stackoverflow.com/questions/359612/how-to-convert-rgb-color-to-hsv">"如何将 RGB 颜色转换为 HSV"

代码

    /// <summary> Convert RGB Color to HSV. </summary>
    /// <param name="color"></param>
    /// <returns> A double[] Containing HSV Color Values. </returns>
    public double[] rgbToHSV(Color color)
    {
        double[] output = new double[3];

        double hue, saturation, 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;

        output[0] = hue;
        output[1] = saturation;
        output[2] = value;

        return output;
    }

I've ended up here by having the same need.

Bellow I'm sharing the best and simpler solution I could find so far.
This is a modified answer from Greg's (found here); but with a humbler and understandable code.

For those who are learning I've added a few references that are worth checking for the sake of understanding.


References

  1. "Lukas Stratmann" HSV Model Tool (Incl. Other Model Systems: CMY / CMYK / HSL)
  2. "The HSV Color Model in Graphic Design"
  3. "Formula to Determine Perceived Brightness of RGB Color"
  4. Fastest Formula to Get Hue from RGB
  5. "Color Conversion Algorithms"
  6. "Program to Change RGB color model to HSV color model"
  7. "RGB to HSV Color Conversion Algorithm"
  8. "RGB to HSV Color Space Conversion (C)"
  9. "How to Convert RGB Color to HSV"

Code

    /// <summary> Convert RGB Color to HSV. </summary>
    /// <param name="color"></param>
    /// <returns> A double[] Containing HSV Color Values. </returns>
    public double[] rgbToHSV(Color color)
    {
        double[] output = new double[3];

        double hue, saturation, 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;

        output[0] = hue;
        output[1] = saturation;
        output[2] = value;

        return output;
    }
伴我老 2024-07-16 19:00:15

首先:确保你有一个颜色作为位图,如下所示:

Bitmap bmp = (Bitmap)pictureBox1.Image.Clone();
paintcolor = bmp.GetPixel(e.X, e.Y);

(e来自选择我的颜色的事件处理程序!)

不久前遇到这个问题时我做了什么,我首先得到了rgba(红色,绿色,蓝色和 alpha)值。
接下来我创建了 3 个浮动:浮动色调、浮动饱和度、浮动亮度。 然后您只需执行

hue = yourcolor.Gethue;
saturation = yourcolor.GetSaturation;
brightness = yourcolor.GetBrightness;

以下操作: 整个过程如下所示:

Bitmap bmp = (Bitmap)pictureBox1.Image.Clone();
            paintcolor = bmp.GetPixel(e.X, e.Y);
            float hue;
            float saturation;
            float brightness;
            hue = paintcolor.GetHue();
            saturation = paintcolor.GetSaturation();
            brightness = paintcolor.GetBrightness();

如果您现在想在标签中显示它们,只需执行以下操作:

yourlabelname.Text = hue.ToString;
yourlabelname.Text = saturation.ToString;
yourlabelname.Text = brightness.ToString;

好了,您现在已将 RGB 值转换为 HSV 值:)

希望这会有所帮助

FIRST: make sure you have a color as a bitmap, like this:

Bitmap bmp = (Bitmap)pictureBox1.Image.Clone();
paintcolor = bmp.GetPixel(e.X, e.Y);

(e is from the event handler wich picked my color!)

What I did when I had this problem a whilke ago, I first got the rgba (red, green, blue and alpha) values.
Next I created 3 floats: float hue, float saturation, float brightness. Then you simply do:

hue = yourcolor.Gethue;
saturation = yourcolor.GetSaturation;
brightness = yourcolor.GetBrightness;

The whole lot looks like this:

Bitmap bmp = (Bitmap)pictureBox1.Image.Clone();
            paintcolor = bmp.GetPixel(e.X, e.Y);
            float hue;
            float saturation;
            float brightness;
            hue = paintcolor.GetHue();
            saturation = paintcolor.GetSaturation();
            brightness = paintcolor.GetBrightness();

If you now want to display them in a label, just do:

yourlabelname.Text = hue.ToString;
yourlabelname.Text = saturation.ToString;
yourlabelname.Text = brightness.ToString;

Here you go, you now have RGB Values into HSV values :)

Hope this helps

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文