78 votes

Alléger une couleur par programme

La Motivation

Je voudrais trouver un moyen de prendre une couleur arbitraire et de l'alléger un peu de nuances, de sorte que je peux en programmant créer un joli dégradé de la couleur d'un objet à une version plus légère. Le gradient utilisé comme arrière-plan dans une INTERFACE utilisateur.

Possibilité 1

Évidemment, je peux juste divisé les valeurs RVB et augmenter individuellement par un certain montant. Est-ce réellement ce que je veux?

Possibilité 2

Ma deuxième pensée a été pour convertir RVB à HSV/TSL/HSL (Hue, Saturation, Value/Luminosité/Luminosité), augmenter la luminosité un peu, diminuer la saturation un peu, et puis la convertir en RVB. Sera-ce l'effet désiré en général?

64voto

Mark Ransom Points 132545

Comme Wedge dit, vous voulez multiplier pour rendre les choses plus lumineux, mais qui ne fonctionne que jusqu'à ce que l'une des couleurs devient saturé (c'est à dire hits 255 ou plus). À ce point, vous pouvez simplement pince les valeurs à 255, mais vous serez subtilement changer la teinte que vous obtenez plus léger. Pour garder la teinte, vous voulez maintenir le ratio (moyen-bas)/(plus haut-plus bas).

Edit: Quelqu'un a donné ce un upvote aujourd'hui, donc je suppose qu'il est temps de faire un bon sur la promesse que j'ai faite il y a 4 ans et comprennent un exemple.

Voici deux fonctions en Python. La première met en œuvre l'approche naïve qui vient de brides les valeurs RVB 255 si ils vont. La deuxième permet de redistribuer l'excédent des valeurs de garder la teinte intacte.

def clamp_rgb(r, g, b):
    return min(255, int(r)), min(255, int(g)), min(255, int(b))

def redistribute_rgb(r, g, b):
    threshold = 255.999
    m = max(r, g, b)
    if m <= threshold:
        return int(r), int(g), int(b)
    total = r + g + b
    if total >= 3 * threshold:
        return int(threshold), int(threshold), int(threshold)
    x = (3 * threshold - total) / (3 * m - total)
    gray = threshold - x * m
    return int(gray + x * r), int(gray + x * g), int(gray + x * b)

J'ai créé un dégradé de départ avec la valeur RVB (224,128,0) et en le multipliant par 1.0, 1.1, 1.2, etc. jusqu'à 2.0. La moitié supérieure est le résultat de l'utilisation d' clamp_rgb et la moitié inférieure est le résultat avec redistribute_rgb. Je pense qu'il est facile de voir que la redistribution de la déborde donne un bien meilleur résultat, sans quitter l'espace de couleurs RVB.

Lightness gradient with clamping (top) and redistribution (bottom)

39voto

Cd-MaN Points 7911

Je pencherais pour la deuxième option. En général, l'espace RVB n'est pas vraiment bon pour faire de la couleur de manipulation (création d'une transition d'une couleur à une autre, d'éclaircissement / assombrissement de la couleur, etc). Voici deux sites que j'ai trouvé avec une recherche rapide pour convertir/RVB/à partir de LGV:

27voto

Nick Points 7173

En C #:

 public static Color Lighten(Color inColor, double inAmount)
{
  return Color.FromArgb(
    inColor.A,
    (int) Math.Min(255, inColor.R + 255 * inAmount),
    (int) Math.Min(255, inColor.G + 255 * inAmount),
    (int) Math.Min(255, inColor.B + 255 * inAmount) );
}
 

Je l'ai utilisé partout.

11voto

Ilya Ryzhenkov Points 5731

La classe ControlPaint dans l'espace de noms System.Windows.Forms a des méthodes statiques Light and Dark:

 public static Color Dark(Color baseColor, float percOfDarkDark);
 

Ces méthodes utilisent une implémentation privée de HLSColor. J'aimerais que cette structure soit publique et dans System.Drawing.

Vous pouvez également utiliser GetHue, GetSaturation, GetBrightness sur la structure Color pour obtenir les composants HSB. Malheureusement, je n'ai pas trouvé la conversion inverse.

9voto

Adam Rosenfield Points 176408

Convertissez-le en RVB et interpolez-le linéairement entre la couleur d'origine et la couleur cible (souvent le blanc). Donc, si vous voulez 16 nuances entre deux couleurs, vous faites:

 
for(i = 0; i < 16; i++)
{
  colors[i].R = start.R + (i * (end.R - start.R)) / 15;
  colors[i].G = start.G + (i * (end.G - start.G)) / 15;
  colors[i].B = start.B + (i * (end.B - start.B)) / 15;
}
 

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X