将RGB转换为HSB颜色

我正在尝试将HSB颜色转换为RGB。 我这样做的方式是

System.Windows.Media.Color winColor = value; System.Drawing.Color drawColor = System.Drawing.Color.FromArgb(winColor.R, winColor.G, winColor.B); Hue = (byte)(drawColor.GetHue()*255); Saturation = (byte)(drawColor.GetSaturation()*255); Luminosity = (byte)(drawColor.GetBrightness()*255); 

我发现当我有FF0000 ,它将转换为H = 0, S = 255, L = 127 ,转换为RGB FF0E0E 。 我觉得Luminosity应该是120? 或者我是否让整个HSB错了? 当我在Photoshop中查看颜色选择器时,Hue为0-360度,饱和度,亮度为0-100%。 我的HSB值介于0到255之间,我做错了吗?

也许你已经看过这篇维基百科文章 ,但要说清楚。

HSL和HSB(又名HSV)之间存在差异。

因此,您不能从颜色类中获取(B)正确性,并将其用作(L)不透明度。

要从Color类返回提供的值GetHue()GetSaturation()GetBrightness()为正常颜色,您应该给这个扩展方法一个机会。

 ///  /// Creates a Color from alpha, hue, saturation and brightness. ///  /// The alpha channel value. /// The hue value. /// The saturation value. /// The brightness value. /// A Color with the given values. public static Color FromAhsb(int alpha, float hue, float saturation, float brightness) { if (0 > alpha || 255 < alpha) { throw new ArgumentOutOfRangeException( "alpha", alpha, "Value must be within a range of 0 - 255."); } if (0f > hue || 360f < hue) { throw new ArgumentOutOfRangeException( "hue", hue, "Value must be within a range of 0 - 360."); } if (0f > saturation || 1f < saturation) { throw new ArgumentOutOfRangeException( "saturation", saturation, "Value must be within a range of 0 - 1."); } if (0f > brightness || 1f < brightness) { throw new ArgumentOutOfRangeException( "brightness", brightness, "Value must be within a range of 0 - 1."); } if (0 == saturation) { return Color.FromArgb( alpha, Convert.ToInt32(brightness * 255), Convert.ToInt32(brightness * 255), Convert.ToInt32(brightness * 255)); } float fMax, fMid, fMin; int iSextant, iMax, iMid, iMin; if (0.5 < brightness) { fMax = brightness - (brightness * saturation) + saturation; fMin = brightness + (brightness * saturation) - saturation; } else { fMax = brightness + (brightness * saturation); fMin = brightness - (brightness * saturation); } iSextant = (int)Math.Floor(hue / 60f); if (300f <= hue) { hue -= 360f; } hue /= 60f; hue -= 2f * (float)Math.Floor(((iSextant + 1f) % 6f) / 2f); if (0 == iSextant % 2) { fMid = (hue * (fMax - fMin)) + fMin; } else { fMid = fMin - (hue * (fMax - fMin)); } iMax = Convert.ToInt32(fMax * 255); iMid = Convert.ToInt32(fMid * 255); iMin = Convert.ToInt32(fMin * 255); switch (iSextant) { case 1: return Color.FromArgb(alpha, iMid, iMax, iMin); case 2: return Color.FromArgb(alpha, iMin, iMax, iMid); case 3: return Color.FromArgb(alpha, iMin, iMid, iMax); case 4: return Color.FromArgb(alpha, iMid, iMin, iMax); case 5: return Color.FromArgb(alpha, iMax, iMin, iMid); default: return Color.FromArgb(alpha, iMax, iMid, iMin); } } 

更新

所以只是为了清楚。 我上面的代码和上面提到的Color类中的三个方法都使用HSB(aka HSV)颜色模型,但Photoshop使用HSL颜色模型。

你在评论中写道,参数Hue = 0Saturation = 1Brightness = 1会在Photoshop中为你提供红色和白色以上的代码。 当您仔细研究这些模式的差异时,这绝对有意义:

HSL气缸

HSL气缸

  • 在两种模型中,色调的作用相同,使用红色作为起点和终点(零点和360度)。
    • 只要看一下你就会得到一种红色的色调。
  • 饱和度定义了颜色的不透明程度或白色部分的多少。
    • 因此,通过将其设置为一个,您说您想要一个完全shiny的红色。
  • 照明现在定义了颜色中黑色和白色部分的多少。 通过将其设置为零,您将获得黑色,一个意味着白色,0.5意味着完美的权重。
    • 因此,通过将其设置为1,您可以说它希望它尽可能明亮,从而产生白色。

HSB气缸

HSB气缸

  • 在两种模型中,色调的作用相同,使用红色作为起点和终点(零点和360度)。
    • 只要看一下你就会得到一种红色的色调。
  • 饱和度定义了颜色的不透明程度或白色部分的多少。
    • 因此,通过将其设置为一个,您说您想要一个完全shiny的红色。
  • 亮度(或值)现在定义颜色中的黑色部分(不是白色部分)的多少。
    • 因此,通过将其设置为一个,您可以说它需要全彩色,从而产生完全shiny的红色。

如您所见,Photoshop和.Net框架(包括我的扩展function)正在使用不同的着色模型。 因此,您应该检查是否找到了其他着色模型的实现,转换或其他能够为您提供所需结果的实现。

这工作…从Java源代码修改。 另一个答案仍然是HSL,这实际上是HSB到RGB(实际上它是HSB / HSV到System.Windows.Media.Color作为我的返回类型)

  public static Color HSBtoRGB(float hue, float saturation, float brightness) { int r = 0, g = 0, b = 0; if (saturation == 0) { r = g = b = (int)(brightness * 255.0f + 0.5f); } else { float h = (hue - (float)Math.Floor(hue)) * 6.0f; float f = h - (float)Math.Floor(h); float p = brightness * (1.0f - saturation); float q = brightness * (1.0f - saturation * f); float t = brightness * (1.0f - (saturation * (1.0f - f))); switch ((int)h) { case 0: r = (int)(brightness * 255.0f + 0.5f); g = (int)(t * 255.0f + 0.5f); b = (int)(p * 255.0f + 0.5f); break; case 1: r = (int)(q * 255.0f + 0.5f); g = (int)(brightness * 255.0f + 0.5f); b = (int)(p * 255.0f + 0.5f); break; case 2: r = (int)(p * 255.0f + 0.5f); g = (int)(brightness * 255.0f + 0.5f); b = (int)(t * 255.0f + 0.5f); break; case 3: r = (int)(p * 255.0f + 0.5f); g = (int)(q * 255.0f + 0.5f); b = (int)(brightness * 255.0f + 0.5f); break; case 4: r = (int)(t * 255.0f + 0.5f); g = (int)(p * 255.0f + 0.5f); b = (int)(brightness * 255.0f + 0.5f); break; case 5: r = (int)(brightness * 255.0f + 0.5f); g = (int)(p * 255.0f + 0.5f); b = (int)(q * 255.0f + 0.5f); break; } } return Color.FromArgb(Convert.ToByte(255), Convert.ToByte(r), Convert.ToByte(g), Convert.ToByte(b)); }