到交换机RGB和HSB颜色值之间的算法 [英] Algorithm to Switch Between RGB and HSB Color Values
问题描述
我读了文章算法到交换机之间的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)。此外,
Color.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屋!