我可能没有使用正确的颜色术语,但我希望基本上能够缩放类似于附加图片的颜色。我一直在寻找饱和度来做到这一点,因为看起来正确的版本只是左边必须不那么饱和的版本。
我正在尝试这个(我发现了),但它看起来并不正确:
Public Shared Function GetDesaturatedColor(color As Color) As Color
Const kValue As Double = 0.01R
Dim greyLevel = (color.R * 0.299R) + _
(color.G * 0.587R) + _
(color.B * 0.144R)
Dim r = greyLevel * kValue + (color.R) * (1 - kValue)
Dim g = greyLevel * kValue + (color.G) * (1 - kValue)
Dim b = greyLevel * kValue + (color.B) * (1 - kValue)
' ColorUtils.ToByte converts the double value
' to a byte safely
Return color.FromArgb(255, _
ColorUtils.ToByte(r), _
ColorUtils.ToByte(g), _
ColorUtils.ToByte(b))
End Function
有没有人知道某些可以做到这一点的算法?
答案 0 :(得分:10)
对于那些想要避免将所有内容转换为HSL / HSV并返回的人来说,这种方法运行得相当好(如果不正确,取决于人们认为“正确”的去饱和图像是什么):
f = 0.2; // desaturate by 20%
L = 0.3*r + 0.6*g + 0.1*b;
new_r = r + f * (L - r);
new_g = g + f * (L - g);
new_b = b + f * (L - b);
答案 1 :(得分:2)
正如@Brad在帖子的评论中提到的,您的第一步是将RGB中的颜色转换为HSL or HSV。从那里开始,降低饱和度是微不足道的 - 只需将饱和度减去或除以一个值就可以减少饱和度。
之后,将您的HSL / HSV颜色转换回RGB并准备好使用。
How to change RGB color to HSV?有一个很好的示例,说明如何执行此操作,Manipulating colors in .net也是如此。
答案 2 :(得分:2)
通过实验显示,仅降低饱和度不足以获得图片中显示的结果。我在下面的代码中使用了OP问题中的颜色。如果你只是降低饱和度,那就是你得到的:
如果你还减少了新颜色的alpha /不透明度,你可以获得更好的结果:
我假设如果你玩参数,你应该能够得到一个完美的匹配。尝试更改alpha
reducedSaturation2
(当前= 40)和GetSaturation
分隔符(当前= 1.3)
这是我的代码示例:
Public Function HSVToColor(ByVal H As Double, ByVal S As Double, ByVal V As Double) As Color
Dim Hi As Integer = (H / 60) Mod 6
Dim f As Double = H / 60 Mod 1
Dim p As Integer = V * (1 - S) * 255
Dim q As Integer = V * (1 - f * S) * 255
Dim t As Integer = V * (1 - (1 - f) * S) * 255
Select Case Hi
Case 0 : Return Color.FromArgb(V * 255, t, p)
Case 1 : Return Color.FromArgb(q, V * 255, p)
Case 2 : Return Color.FromArgb(p, V * 255, t)
Case 3 : Return Color.FromArgb(p, V * 255, q)
Case 4 : Return Color.FromArgb(t, p, V * 255)
Case 5 : Return Color.FromArgb(V * 255, q, p)
End Select
End Function
Private Sub Button1_Click(sender As System.Object, e As System.EventArgs) Handles Button1.Click
Dim normalSaturation As Color = Color.FromArgb(255, 216, 53, 45)
Me.CreateGraphics.FillRectangle(New SolidBrush(normalSaturation), 100, 0, 100, 100)
Dim reducedSaturation As Color = HSVToColor(normalSaturation.GetHue, normalSaturation.GetSaturation / 1.3, normalSaturation.GetBrightness)
Dim reducedSaturation2 As Color = Color.FromArgb(40, reducedSaturation)
Me.CreateGraphics.FillRectangle(New SolidBrush(reducedSaturation2), 0, 0, 100, 100)
End Sub
答案 3 :(得分:1)
这是我的公式,用于更改C#中给定Color
的饱和度。结果等于应用CSS效果filter: saturate(...)
,因为这是W3C规范使用的公式。
private static Color Saturate(Color c, double saturation) {
// Values from: https://www.w3.org/TR/filter-effects-1/#feColorMatrixElement , type="saturate"
var s = saturation;
Func<double, int> clamp = i => Math.Min(255, Math.Max(0, Convert.ToInt32(i)));
return Color.FromArgb(255,
clamp((0.213 + 0.787 * s) * c.R + (0.715 - 0.715 * s) * c.G + (0.072 - 0.072 * s) * c.B),
clamp((0.213 - 0.213 * s) * c.R + (0.715 + 0.285 * s) * c.G + (0.072 - 0.072 * s) * c.B),
clamp((0.213 - 0.213 * s) * c.R + (0.715 - 0.715 * s) * c.G + (0.072 + 0.928 * s) * c.B));
}