【问题标题】:Is there a built-in C#/.NET System API for HSV to RGB?是否有用于 HSV 到 RGB 的内置 C#/.NET 系统 API?
【发布时间】:2010-11-23 01:18:00
【问题描述】:

.NET 框架中是否有内置于converting HSV to RGB 的 API?我在 System.Drawing.Color 中没有看到用于此的方法,但平台中没有方法似乎令人惊讶。

【问题讨论】:

    标签: c# .net colors


    【解决方案1】:

    没有执行此操作的内置方法,但计算并不是非常复杂。
    另请注意,Color 的 GetHue()、GetSaturation() 和 GetBrightness() 返回 HSL 值,而不是 HSV。

    以下 C# 代码使用Wikipedia 中描述的算法在 RGB 和 HSV 之间进行转换。
    我已经发布了这个答案here,但我会在这里复制代码以供快速参考。

    色调的范围是 0 - 360,饱和度或值的范围是 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);
    }
    

    【讨论】:

    • 您的 ColorFromHSV 可能有问题,我试图使用您的代码将色调旋转 180 度以获得相反的颜色,但效果不太好。接受的代码给出了不同的颜色,这对我来说似乎是正确的。
    • 不过,我正在使用您的 ColorToHSV 函数。它似乎运作良好。
    • @IsaacBolinger 不适用于负色调,适用于色调 >= 0,但最好在代码中使用
    • @IsaacBolinger 我想要同样的效果,将色调线更改为以下对我来说非常有效:hue = (color.GetHue() + 180) % 360
    【解决方案2】:

    我认为 .NET 框架中没有这样做的方法。
    查看Converting HSV to RGB colour using C#

    这是实现代码,

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

    【讨论】:

    • 感谢您的方法。奇怪的是 Color 有 .GetHue()、.GetSaturation() 和 .GetBrightness(),但没有像 .fromHSB() 这样的逆方法。
    • 确实......这是一个非常奇怪的遗漏,imo。
    • 为什么不返回一个 Color 对象而不是使用 out 来表示三个单独的值?
    • @FizzledOut:可能因为这样,代码可以直接用于SWF ColorWPF ColorGdk# Color等。
    • 如果您以 System.Drawing.Color.FromArgb(255, 0, 0) 开头,使用 .GetHue() 等将其发送到 HSV,然后使用此代码往返返回到 Color,您将获得 rgb 127、0、 0..GetBrightness() 返回 0.5,这段代码解释为表示主色是 255*.5 = 127。至少从我的角度来看,这意味着这段代码不能正常工作。
    【解决方案3】:

    它不是内置的,但有一个名为 ColorMine 的开源 C# 库,它可以很容易地在颜色空间之间进行转换。

    RGB 转 Hsv:

    var rgb = new Rgb {R = 123, G = 11, B = 7};
    var hsv = rgb.To<Hsv>();
    

    HSV转RGB:

    var hsv = new Hsv { H = 360, S = .5, L = .17 }
    var rgb = hsv.to<Rgb>();
    

    【讨论】:

    • ColorMine 存储库似乎已经消失(截至 2018 年 8 月 5 日,github 上有 404 个)。此外,Joe 似乎没有后继存储库。但是,我发现ColorMinePortable 可能已经足够接近了。
    • 只是快速搜索一下,看起来用户可能已经删除了他们的 repo。不过它是由其他人分叉的:github.com/hvalidi/ColorMine
    【解决方案4】:

    为此,您可以使用ColorHelper 库:

    RGB rgb = ColorConverter.HsvToRgb(new HSV(100, 100, 100));
    

    【讨论】:

      猜你喜欢
      • 2010-11-12
      • 2011-03-02
      • 1970-01-01
      • 2012-10-15
      • 1970-01-01
      • 1970-01-01
      • 2011-02-03
      • 2011-11-03
      相关资源
      最近更新 更多