Solución:
Para aquellos que quieren evitar convertir todo a HSL / HSV y viceversa, esto funciona razonablemente bien (si no correctamente, dependiendo de lo que uno crea que es la imagen desaturada “correcta”):
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);
Esto es convertir r, g, b a escala de grises utilizando la suposición común de que el verde, el rojo y el azul corresponden a la luminancia de una imagen en proporciones decrecientes, respectivamente. Entonces L es una imagen en escala de grises y luego f simplemente se interpola linealmente entre la imagen RGB de entrada y esa imagen en escala de grises.
Como @Brad mencionó en los comentarios de su publicación, su primer paso es convertir los colores de RGB a HSL o HSV. A partir de ahí, reducir la saturación es trivial: simplemente reste o divida la saturación por un valor para reducirla.
Después de eso, convierta su color HSL / HSV nuevamente a RGB y estará listo para usar.
¿Cómo cambiar el color RGB a HSV? tiene un buen ejemplo de cómo hacer esto, al igual que Manipulación de colores en .net.
Parece por experimento que simplemente reducir la saturación no es suficiente para obtener el resultado que se muestra en la imagen. Usé los colores de la pregunta de OP en el código que se muestra a continuación. Si solo reduce la saturación, esto es lo que obtiene:
Si también reduce el alfa / opacidad del nuevo color, puede lograr un mejor resultado:
Supongo que si juegas con parámetros, deberías poder obtener una combinación perfecta. Intenta cambiar alpha
por reducedSaturation2
(actualmente = 40) y GetSaturation
divisor (actualmente = 1,3)
Aquí está mi ejemplo de código:
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