将RGB字节转换为HSL,然后再转回来?

3

有没有一种算法可以将RGB byte数组转换为HSL float数组,然后再转回去?

我尝试过在这里找到的算法,但似乎存在一些错误。


@Matt 不是重复问题,因为这个问题专门询问HSL,而你的链接提到的是HSV。它们不是同一件事。 - g t
没错,是我的问题。我删掉了注释。 - Matt
2个回答

6

我使用下面的类来实现HSL到RGB和RGB到HSL的转换。你可以通过一个Color构造一个ColorRGB实例,或者直接将其强制转换。它还公开了HSL属性。我在网络上找到了它。对于原始作者的致歉,我无法找到参考资料:

  public class ColorRGB
  {
    public byte R;
    public byte G;
    public byte B;
    public byte A;

    public ColorRGB()
    {
      R = 255;
      G = 255;
      B = 255;
      A = 255;
    }

    public ColorRGB(Color value)
    {
      this.R = value.R;
      this.G = value.G;
      this.B = value.B;
      this.A = value.A;
    }
    public static implicit operator Color(ColorRGB rgb)
    {
      Color c = Color.FromArgb(rgb.A, rgb.R, rgb.G, rgb.B);
      return c;
    }
    public static explicit operator ColorRGB(Color c)
    {
      return new ColorRGB(c);
    }


    // Given H,S,L in range of 0-1
    // Returns a Color (RGB struct) in range of 0-255
    public static ColorRGB FromHSL(double H, double S, double L)
    {
      return FromHSLA(H, S, L, 1.0);
    }

    // Given H,S,L,A in range of 0-1
    // Returns a Color (RGB struct) in range of 0-255
    public static ColorRGB FromHSLA(double H, double S, double L, double A)
    {
      double v;
      double r, g, b;
      if (A > 1.0)
        A = 1.0;

      r = L;   // default to gray
      g = L;
      b = L;
      v = (L <= 0.5) ? (L * (1.0 + S)) : (L + S - L * S);
      if (v > 0)
      {
        double m;
        double sv;
        int sextant;
        double fract, vsf, mid1, mid2;

        m = L + L - v;
        sv = (v - m) / v;
        H *= 6.0;
        sextant = (int)H;
        fract = H - sextant;
        vsf = v * sv * fract;
        mid1 = m + vsf;
        mid2 = v - vsf;
        switch (sextant)
        {
          case 0:
            r = v;
            g = mid1;
            b = m;
            break;
          case 1:
            r = mid2;
            g = v;
            b = m;
            break;
          case 2:
            r = m;
            g = v;
            b = mid1;
            break;
          case 3:
            r = m;
            g = mid2;
            b = v;
            break;
          case 4:
            r = mid1;
            g = m;
            b = v;
            break;
          case 5:
            r = v;
            g = m;
            b = mid2;
            break;
        }
      }
      ColorRGB rgb = new ColorRGB();
      rgb.R = Convert.ToByte(r * 255.0f);
      rgb.G = Convert.ToByte(g * 255.0f);
      rgb.B = Convert.ToByte(b * 255.0f);
      rgb.A = Convert.ToByte(A * 255.0f);
      return rgb;
    }

    // Hue in range from 0.0 to 1.0
    public float H
    {
      get
      {
        // Use System.Drawing.Color.GetHue, but divide by 360.0F 
        // because System.Drawing.Color returns hue in degrees (0 - 360)
        // rather than a number between 0 and 1.
        return ((Color)this).GetHue() / 360.0F;
      }
    }

    // Saturation in range 0.0 - 1.0
    public float S
    {
      get
      {
        return ((Color)this).GetSaturation();
      }
    }

    // Lightness in range 0.0 - 1.0
    public float L
    {
      get
      {
        return ((Color)this).GetBrightness();
      }
    }
  }

1
我想添加原始链接。 :) http://www.geekymonkey.com/Programming/CSharp/RGB2HSL_HSL2RGB.htm - Keven M
谢谢你,我在搜索代码时找不到它。很高兴我们现在可以归功于原作者。这对我来说太聪明了;-) - ColinE
链接已经失效,但是去掉www后仍然可以访问:http://geekymonkey.com/Programming/CSharp/RGB2HSL_HSL2RGB.htm - Henrik Söderlund
这对其他人有效吗?例如,对于H = .95,S = 1.0,V = 1.0,它不会产生有意义的RGB输出。 - Brent Faust

0

您可以使用ColorHelper库来实现此目的。

RGB转HSL:

using ColorHelper;
HSL hsl = ColorHeConverter.RgbToHsl(new RGB(10, 10, 10));

HSL转RGB:
using ColorHelper;
RGB rgb = ColorConverter.HslToRgb(new HSL(0, 0, 0));

链接:


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接