到交换机RGB和HSB颜色值之间的算法 [英] Algorithm to Switch Between RGB and HSB Color Values

查看:517
本文介绍了到交换机RGB和HSB颜色值之间的算法的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我读了文章算法到交换机之间的RGB和HSB颜色值

 键入RGBColor
     红色为字节
     绿色为字节
     蓝色为字节
结束类型键入HSB颜色
     色相双
     饱和度双
     亮度双
结束类型功能RGBToHSB(RGB作为RGBColor)作为HSB颜色
     暗淡minRGB,maxRGB,台达为双
     昏暗的H,S,B为双
     H = 0
     minRGB =最小值(最小(rgb.Red,rgb.Green),rgb.Blue)
     maxRGB = MAX(最大(rgb.Red,rgb.Green),rgb.Blue)
     三角洲=(maxRGB - minRGB)
     B = maxRGB
     如果(maxRGB&所述;&0)。然后
          S = 255 *三角洲/ maxRGB
     其他
          S = 0
     万一
     如果(S&所述;&0)。然后
          如果rgb.Red = maxRGB然后
               H =(CDbl(rgb.Green) - CDbl(rgb.Blue))/三角洲
          其他
               如果rgb.Green = maxRGB然后
                    H = 2 +(CDbl(rgb.Blue) - CDbl(rgb.Red))/三角洲
               其他
                    如果rgb.Blue = maxRGB然后
                         H = 4 +(CDbl(rgb.Red) - CDbl(rgb.Green))/三角洲
                    万一
               万一
          万一
     其他
          H = -1
     万一
     H = H * 60
     如果H< 0则H = H + 360
     RGBToHSB.Hue = H
     RGBToHSB.Saturation = S *二百五十五分之一百
     RGBToHSB.Brightness = B *二百五十五分之一百
结束功能功能HSBToRGB(HSB作为HSB颜色)由于RGBColor
     暗淡maxRGB,台达为双
     昏暗的H,S,B为双
     H = hsb.Hue / 60
     S = hsb.Saturation *一百分之二百五十五
     B = hsb.Brightness *一百分之二百五十五
     maxRGB = B
     如果s = 0则
          HSBToRGB.Red = 0
          HSBToRGB.Green = 0
          HSBToRGB.Blue = 0
     其他
          三角洲= S * maxRGB / 255
          如果H> 3然后
               HSBToRGB.Blue = CByte(圆形(maxRGB))
               如果H> 4然后
                    HSBToRGB.Green = CByte(圆形(maxRGB - 三角洲))
                    HSBToRGB.Red = CByte(圆形((H - 4)*三角洲))+ HSBToRGB.Green
               其他
                    HSBToRGB.Red = CByte(圆形(maxRGB - 三角洲))
                    HSBToRGB.Green = CByte(HSBToRGB.Red - 圆((H - 4)*三角洲))
               万一
          其他
               如果H> 1然后
                    HSBToRGB.Green = CByte(圆形(maxRGB))
                    如果H> 2然后
                         HSBToRGB.Red = CByte(圆形(maxRGB - 三角洲))
                         HSBToRGB.Blue = CByte(圆形((H - 2)*三角洲))+ HSBToRGB.Red
                    其他
                         HSBToRGB.Blue = CByte(圆形(maxRGB - 三角洲))
                         HSBToRGB.Red = CByte(HSBToRGB.Blue - 圆((H - 2)*三角洲))
                    万一
               其他
                    如果H>然后-1
                         HSBToRGB.Red = CByte(圆形(maxRGB))
                         如果H> 0,则
                              HSBToRGB.Blue = CByte(圆形(maxRGB - 三角洲))
                              HSBToRGB.Green = CByte(圆形(H *三角洲))+ HSBToRGB.Blue
                         其他
                              HSBToRGB.Green = CByte(圆形(maxRGB - 三角洲))
                              HSBToRGB.Blue = CByte(HSBToRGB.Green - 圆(H *三角洲))
                         万一
                    万一
               万一
          万一
     万一
结束功能

然后是人谁张贴,有一个错误,但没有详细说明多少


  

但我认为这需要管理时,h是超过5个,例如对于颜色R:130 G:65乙:111


 如果H> 5然后
    HSBToRGB.Red = CByte(圆形(maxRGB))
如果H> 6然后
    HSBToRGB.Blue = CByte(圆形(maxRGB - 三角洲))
    HSBToRGB.Green = CByte(圆形((H - 6)*三角洲))HSBToRGB.Blue
其他
    HSBToRGB.Green = CByte(圆形(maxRGB - 三角洲))
    HSBToRGB.Blue = CByte(HSBToRGB.Green-圆((H - 6)*汇))
万一

我需要在那块code的补充?我presume应该进入到HSB RGB(在我的C#转换)

  ...
如果(S!= 0){
    三角洲= S * maxRGB / 255;
    如果(h取代; 5)
        rgb.Red = Convert.ToByte(Math.Round(maxRGB));
    如果(h取代; 6)
    {
        rgb.Green = Convert.ToByte(Math.Round(maxRGB - 三角));
        rgb.Blue = Convert.ToByte(rgb.Green - Math.Round((H - 6)*三角洲));
    }
    如果(h取代; 3)
    {
        ...

也,它应该是像上面,或者

 如果(H> 6){}
否则如果(H→3){}


解决方案

使用内置到.NET的Color对象方法是一种非首发,因为几个问题的答案指出,他们不支持反向(转换一个HSB色彩RGB)。此外, Col​​or.GetBrightness 实际返回的亮度的,而不是亮度/值。有过因为它们的相似(维基百科)的HSB / HSV和HSL色彩空间之间的差异的很多混乱。我看到很多的最终使用了错误的算法和/或模型拾色器中。

原来的code在我看来就像它忽略,当它计算色调值的一些可能的情况下,给出的RGB颜色。这是一个有点困难,我按照你考虑到code的补充,但跳出我的第一件事情(而且你似乎没有建议修正)是当饱和度= 0 ,设置色相为-1。当你以后乘以60的色调,你结束了-60,那么您添加到360(如果h℃,则H = H + 360 ),产生的300的结果,这是不正确的。

我用下面的code(在VB.NET),以RGB和HSB(我称之为HSV)之间进行转换。结果已经很广泛的测试,其结果几乎是一致通过Photoshop的颜色选择器(除了它的颜色配置文件补偿)给出的。张贴code和矿(除了其计算的色调的重要部分)之间的主要区别是,我preFER标准化的RGB值是0和1之间做计算,而不是与工作介于0和255之间的原始值这消除了一些在原来的code,你张贴的效率低下和多次转换,以及

 公共功能RGBtoHSV(BYVALř整数,BYVAL G系列因此整数,BYVAL b以整数)由于HSV
     '#通过缩放它们规格化的RGB值是0和1之间
     暗红为十进制= R / 255D
     昏暗的绿色为十进制= G / 255D
     蓝幽幽的十进制= B / 255D     昏暗minValue(最小值)为十进制= Math.Min(红,Math.Min(绿,蓝))
     昏暗包括maxValue为十进制= Math.Max​​(红,Math.Max​​(绿,蓝))
     昏暗的增量为十进制=包括maxValue - minValue(最小值)     昏暗事项h作为小数
     昏暗的译文]十进制
     昏暗的V作为小数等于MAXVALUE     '#计算色相(以度圆的,0和360之间)
     选择案例包括maxValue
        案例红色
           如果绿色> =蓝色然后
               如果,δ= 0。然后
                  H = 0
               其他
                  H = 60 *(绿 - 蓝)/△
               万一
           elseif的绿色<然后蓝
               H = 60 *(绿 - 蓝)/△+ 360
           万一
        案例绿色
           H = 60 *(蓝 - 红)/△+ 120
        蓝色行动
           H = 60 *(红 - 绿)/△+ 240
     结束选择     '#计算饱和度(0和1之间)
     如果包括maxValue = 0则
        S = 0
     其他
        S = 1D - (minValue(最小值)/包括maxValue)
     万一     ''#尺度饱和度和值的百分比0到100之间
     S * = 100
     V * = 100  ''#返回颜色在新的色彩空间
  返回新HSV(CINT(Math.Round(H,MidpointRounding.AwayFromZero)),_
                 CINT(Math.Round(S,MidpointRounding.AwayFromZero)),_
                 CINT(Math.Round(V,MidpointRounding.AwayFromZero)))
结束功能

您没有贴code用来从HSB(我称之为HSV)转换颜色为RGB,但这里是我用的,再次是0和1之间的中间值的工作:

 公共功能HSVtoRGB(BYVAL H作为整数,BYVAL参考译文]整数,BYVAL V作为整数)由于RGB
     ''#尺度饱和度和值部件为0和1之间
     昏暗的色调为十进制= H
     坐在昏暗十进制= S / 100D
     昏暗VAL为十进制= V / 100D     昏暗 - [R为十进制
     昏暗摹为十进制
     昏暗b以十进制     如果坐在= 0。然后
       ''#如果饱和为0,则所有的颜色是相同的。
       ''#(这是灰色一番风味。)
        R = VAL
        G = VAL
        B = VAL
     其他
        '#计算6份彩色轮的适当扇区
        昏暗sectorPos为十进制=色相/ 60D
        昏暗sectorNumber作为整数= CINT(Math.Floor(sectorPos))        ''#得到该部门的小数部分
        ''#(也就是多少度到你的部门)
        昏暗fractionalSector为十进制= sectorPos - sectorNumber        ''#计算值的颜色的三个轴
        昏暗数p作为小数= VAL *(1 - 坐)
        昏暗的q为十进制= VAL *(1 - (星期六* fractionalSector))
        昏暗T作为小数= VAL *(1 - (星期六*(1 - fractionalSector)))        ''#指定分数的颜色为红色,绿色和蓝色
        '根据扇区的角度在'#部件
        选择案例sectorNumber
           案0,6
              R = VAL
              摹= T
              b = P
           情况1
               - [R = Q
              G = VAL
              b = P
           案例2
               - [R = P
              G = VAL
              B =Ť
           案例3
               - [R = P
              摹= Q
              B = VAL
           案例4
              R =Ť
              摹= P
              B = VAL
           案例5
              R = VAL
              摹= P
              b = Q
        结束选择
     万一     ''#量表红色,绿色和蓝色值是0到255之间
     R * = 255
     G * = 255
     的b * = 255     ''#返回颜色在新的色彩空间
     返回新的RGB(CINT(Math.Round(R,MidpointRounding.AwayFromZero)),_
                    CINT(Math.Round(G,MidpointRounding.AwayFromZero)),_
                    CINT(Math.Round(B,MidpointRounding.AwayFromZero)))
结束功能

编辑::此code看起来非常相似,由理查德·罗斯III使用C提供的。我追杀尽可能多的不同的算法,因为我可以在网上找到,改写了很多code的借用他们每个人的最好的,并进行了广泛的测试,以验证结果的准确性。我忘了注意我借谁code的,因为这是只是一个私人图书馆。也许VB版将帮助别人谁不希​​望做从C转换: - )

I read the article Algorithm to Switch Between RGB and HSB Color Values

Type RGBColor
     Red As Byte
     Green As Byte
     Blue As Byte
End Type

Type HSBColor
     Hue As Double
     Saturation As Double
     Brightness As Double
End Type

Function RGBToHSB(rgb As RGBColor) As HSBColor
     Dim minRGB, maxRGB, Delta As Double
     Dim h, s, b As Double
     h = 0
     minRGB = Min(Min(rgb.Red, rgb.Green), rgb.Blue)
     maxRGB = Max(Max(rgb.Red, rgb.Green), rgb.Blue)
     Delta = (maxRGB - minRGB)
     b = maxRGB
     If (maxRGB <> 0) Then
          s = 255 * Delta / maxRGB
     Else
          s = 0
     End If
     If (s <> 0) Then
          If rgb.Red = maxRGB Then
               h = (CDbl(rgb.Green) - CDbl(rgb.Blue)) / Delta
          Else
               If rgb.Green = maxRGB Then
                    h = 2 + (CDbl(rgb.Blue) - CDbl(rgb.Red)) / Delta
               Else
                    If rgb.Blue = maxRGB Then
                         h = 4 + (CDbl(rgb.Red) - CDbl(rgb.Green)) / Delta
                    End If
               End If
          End If
     Else
          h = -1
     End If
     h = h * 60
     If h < 0 Then h = h + 360
     RGBToHSB.Hue = h
     RGBToHSB.Saturation = s * 100 / 255
     RGBToHSB.Brightness = b * 100 / 255
End Function

Function HSBToRGB(hsb As HSBColor) As RGBColor
     Dim maxRGB, Delta As Double
     Dim h, s, b As Double
     h = hsb.Hue / 60
     s = hsb.Saturation * 255 / 100
     b = hsb.Brightness * 255 / 100
     maxRGB = b
     If s = 0 Then
          HSBToRGB.Red = 0
          HSBToRGB.Green = 0
          HSBToRGB.Blue = 0
     Else
          Delta = s * maxRGB / 255
          If h > 3 Then
               HSBToRGB.Blue = CByte(Round(maxRGB))
               If h > 4 Then
                    HSBToRGB.Green = CByte(Round(maxRGB - Delta))
                    HSBToRGB.Red = CByte(Round((h - 4) * Delta)) + HSBToRGB.Green
               Else
                    HSBToRGB.Red = CByte(Round(maxRGB - Delta))
                    HSBToRGB.Green = CByte(HSBToRGB.Red - Round((h - 4) * Delta))
               End If
          Else
               If h > 1 Then
                    HSBToRGB.Green = CByte(Round(maxRGB))
                    If h > 2 Then
                         HSBToRGB.Red = CByte(Round(maxRGB - Delta))
                         HSBToRGB.Blue = CByte(Round((h - 2) * Delta)) + HSBToRGB.Red
                    Else
                         HSBToRGB.Blue = CByte(Round(maxRGB - Delta))
                         HSBToRGB.Red = CByte(HSBToRGB.Blue - Round((h - 2) * Delta))
                    End If
               Else
                    If h > -1 Then
                         HSBToRGB.Red = CByte(Round(maxRGB))
                         If h > 0 Then
                              HSBToRGB.Blue = CByte(Round(maxRGB - Delta))
                              HSBToRGB.Green = CByte(Round(h * Delta)) + HSBToRGB.Blue
                         Else
                              HSBToRGB.Green = CByte(Round(maxRGB - Delta))
                              HSBToRGB.Blue = CByte(HSBToRGB.Green - Round(h * Delta))
                         End If
                    End If
               End If
          End If
     End If
End Function

Then there was someone who posted that there was a mistake but didn't elaborate much

But I think it need to manage when h is more than 5, for example for the color R:130 G:65 B:111

If h > 5 Then
    HSBToRGB.Red = CByte(Round(maxRGB))
If h > 6 Then
    HSBToRGB.Blue= CByte(Round(maxRGB - Delta))
    HSBToRGB.Green= CByte(Round((h - 6) * Delta)) HSBToRGB.Blue
Else
    HSBToRGB.Green= CByte(Round(maxRGB - Delta))
    HSBToRGB.Blue = CByte(HSBToRGB.Green- Round((h - 6) * Delta))
End If

Do I need to add in that piece of code? And I presume it should go into HSB to RGB (in my C# conversion)

...
if (s != 0) {
    delta = s * maxRGB / 255;
    if (h > 5)
        rgb.Red = Convert.ToByte(Math.Round(maxRGB));
    if (h > 6)
    {
        rgb.Green = Convert.ToByte(Math.Round(maxRGB - delta));
        rgb.Blue = Convert.ToByte(rgb.Green - Math.Round((h - 6) * delta));
    }
    if (h > 3)
    {
        ...

also, should it be like above, or

if (h > 6) { } 
else if (h > 3)  { }

解决方案

Using the methods built into .NET's Color object is a non-starter because, as several of the answers point out, they don't support the reverse (converting an HSB color to RGB). Additionally, Color.GetBrightness actually returns lightness, rather than brightness/value. There is a lot of confusion over the differences between the HSB/HSV and HSL color spaces because of their similarities (Wikipedia). I see lots of color pickers that end up using the wrong algorithm and/or model.

The original code looks to me like it misses a few possible scenarios when it calculates the value for hue, given an RGB color. It's a little difficult for me to follow the additions that you're contemplating to the code, but the first thing that jumps out at me (and that you don't appear to suggest correcting) is that when the saturation = 0, you set hue to -1. When you later multiply the hue by 60, you end up with -60, then you add that to 360 (If h < 0 Then h = h + 360), producing a result of 300, which is not correct.

I use the following code (in VB.NET) to convert between RGB and HSB (which I call HSV). The results have been tested very extensively, and the results are virtually identical to those given by Photoshop's color picker (aside from the compensation it does for color profiles). The major difference between the posted code and mine (aside from the important portion that calculates the hue) is that I prefer normalizing the RGB values to be between 0 and 1 to do the calculations, rather than working with the original values between 0 and 255. This eliminates some of the inefficiencies and multiple conversions in the original code that you posted, as well.

Public Function RGBtoHSV(ByVal R As Integer, ByVal G As Integer, ByVal B As Integer) As HSV
     ''# Normalize the RGB values by scaling them to be between 0 and 1
     Dim red As Decimal = R / 255D
     Dim green As Decimal = G / 255D
     Dim blue As Decimal = B / 255D

     Dim minValue As Decimal = Math.Min(red, Math.Min(green, blue))
     Dim maxValue As Decimal = Math.Max(red, Math.Max(green, blue))
     Dim delta As Decimal = maxValue - minValue

     Dim h As Decimal
     Dim s As Decimal
     Dim v As Decimal = maxValue

     ''# Calculate the hue (in degrees of a circle, between 0 and 360)
     Select Case maxValue
        Case red
           If green >= blue Then
               If delta = 0 Then
                  h = 0
               Else
                  h = 60 * (green - blue) / delta
               End If
           ElseIf green < blue Then
               h = 60 * (green - blue) / delta + 360
           End If
        Case green
           h = 60 * (blue - red) / delta + 120
        Case blue
           h = 60 * (red - green) / delta + 240
     End Select

     ''# Calculate the saturation (between 0 and 1)
     If maxValue = 0 Then
        s = 0
     Else
        s = 1D - (minValue / maxValue)
     End If

     ''# Scale the saturation and value to a percentage between 0 and 100
     s *= 100
     v *= 100

  ''# Return a color in the new color space
  Return New HSV(CInt(Math.Round(h, MidpointRounding.AwayFromZero)), _
                 CInt(Math.Round(s, MidpointRounding.AwayFromZero)), _
                 CInt(Math.Round(v, MidpointRounding.AwayFromZero)))
End Function

You didn't post the code you use to convert from an HSB (which I call HSV) color to RGB, but here's what I use, again working with interim values that are between 0 and 1:

Public Function HSVtoRGB(ByVal H As Integer, ByVal S As Integer, ByVal V As Integer) As RGB
     ''# Scale the Saturation and Value components to be between 0 and 1
     Dim hue As Decimal = H
     Dim sat As Decimal = S / 100D
     Dim val As Decimal = V / 100D

     Dim r As Decimal
     Dim g As Decimal
     Dim b As Decimal

     If sat = 0 Then
       ''# If the saturation is 0, then all colors are the same.
       ''# (This is some flavor of gray.)
        r = val
        g = val
        b = val
     Else
        ''# Calculate the appropriate sector of a 6-part color wheel
        Dim sectorPos As Decimal = hue / 60D
        Dim sectorNumber As Integer = CInt(Math.Floor(sectorPos))

        ''# Get the fractional part of the sector
        ''# (that is, how many degrees into the sector you are)
        Dim fractionalSector As Decimal = sectorPos - sectorNumber

        ''# Calculate values for the three axes of the color
        Dim p As Decimal = val * (1 - sat)
        Dim q As Decimal = val * (1 - (sat * fractionalSector))
        Dim t As Decimal = val * (1 - (sat * (1 - fractionalSector)))

        ''# Assign the fractional colors to red, green, and blue
        ''# components based on the sector the angle is in
        Select Case sectorNumber
           Case 0, 6
              r = val
              g = t
              b = p
           Case 1
              r = q
              g = val
              b = p
           Case 2
              r = p
              g = val
              b = t
           Case 3
              r = p
              g = q
              b = val
           Case 4
              r = t
              g = p
              b = val
           Case 5
              r = val
              g = p
              b = q
        End Select
     End If

     ''# Scale the red, green, and blue values to be between 0 and 255
     r *= 255
     g *= 255
     b *= 255

     ''# Return a color in the new color space
     Return New RGB(CInt(Math.Round(r, MidpointRounding.AwayFromZero)), _
                    CInt(Math.Round(g, MidpointRounding.AwayFromZero)), _
                    CInt(Math.Round(b, MidpointRounding.AwayFromZero)))
End Function

EDIT: This code looks very similar to that provided in C by Richard J. Ross III. I hunted down as many different algorithms as I could find online, rewrote a lot of code borrowing the best from each of them, and did extensive testing to verify the accuracy of the results. I neglected to note who I borrowed code from, as this was just for a private library. Maybe the VB version will help someone who doesn't want to do a conversion from C. :-)

这篇关于到交换机RGB和HSB颜色值之间的算法的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆