gpt4 book ai didi

c# - 在 RGB 和 HSB 颜色值之间切换的算法

转载 作者:太空狗 更新时间:2023-10-29 22:14:59 25 4
gpt4 key购买 nike

我读了文章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

然后有人发帖说有错误但是没有详细说明

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

我需要添加那段代码吗?我认为它应该进入 HSB 到 RGB(在我的 C# 转换中)

...
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)
{
...

另外,是不是应该像上面那样,或者

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

最佳答案

使用 .NET 的 Color 对象中内置的方法是行不通的,因为正如一些答案所指出的那样,它们不支持反向操作(将 HSB 颜色转换为 RGB)。此外,Color.GetBrightness实际上返回亮度,而不是亮度/值。由于 HSB/HSV 和 HSL 颜色空间之间的相似性 (Wikipedia),因此存在很多混淆。我看到很多颜色选择器最终使用了错误的算法和/或模型。

在我看来,在给定 RGB 颜色的情况下,原始代码在计算色调值时似乎遗漏了一些可能的情况。我有点难以理解您正在考虑添加到代码中的内容,但我首先想到的(并且您似乎没有建议更正)是当饱和度 = 0 时,您设置色调为-1。当您稍后将色相乘以 60 时,最终得到 -60,然后将其与 360 ( If h < 0 Then h = h + 360 ) 相加,结果为 300,这是不正确的。

我使用以下代码(在 VB.NET 中)在 RGB 和 HSB(我称之为 HSV)之间进行转换。结果已经过非常广泛的测试,结果几乎与 Photoshop 的颜色选择器给出的结果相同(除了它对颜色配置文件所做的补偿)。发布的代码和我的代码之间的主要区别(除了计算色调的重要部分)是我更喜欢将 RGB 值标准化为 0 到 1 之间来进行计算,而不是使用 0 到 255 之间的原始值。这也消除了您发布的原始代码中的一些低效和多次转换。

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

您没有发布用于将 HSB(我称之为 HSV)颜色转换为 RGB 的代码,但这是我使用的代码,再次使用介于 0 和 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

编辑:此代码看起来与 Richard J. Ross III 在 C 中提供的代码非常相似。我在网上搜索了尽可能多的不同算法,重写了很多代码,借鉴了每个算法的精华,并进行了广泛的测试以验证结果的准确性。我忘了记下我从谁那里借来的代码,因为这只是一个私有(private)图书馆。也许 VB 版本会帮助那些不想从 C 进行转换的人。:-)

关于c# - 在 RGB 和 HSB 颜色值之间切换的算法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4123998/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com