Comment puis-je déterminer la variante de couleur plus foncée ou plus claire d'une couleur donnée?
étant donné une couleur source de n'importe quelle teinte par le système ou l'utilisateur, je voudrais un algorithme simple que je peux utiliser pour travailler sur des variantes plus claires ou plus foncées de la couleur sélectionnée. Similaire aux effets utilisés sur Windows Live Messenger pour le style de l'interface utilisateur.
langue est C# avec .net 3.5.
en réponse au commentaire: le format de couleur est (Alpha)RGB. Avec des valeurs comme bytes ou floats.
Marquage réponse: pour le contexte de mon Utilisation (quelques effets D'interface utilisateur simples), la réponse que je note comme acceptée est en fait la plus simple pour ce contexte. Cependant, j'ai donné des votes aux réponses plus complexes et précises aussi. Quiconque faisant des opérations de couleur plus avancées et de trouver ce fil à l'avenir devrait certainement vérifier ceux. Merci. :)
13 réponses
il suffit de multiplier les valeurs RVB par le montant que vous voulez modifier le niveau par. Si une des couleurs est déjà à la valeur max, alors vous ne pouvez pas le rendre plus lumineux (en utilisant HSV math de toute façon.)
cela donne le même résultat exact avec beaucoup moins de maths que passer à HSV et ensuite modifier V. Cela donne le même résultat que passer à HSL et ensuite modifier L, Aussi longtemps que vous ne voulez pas commencer à perdre la saturation.
Dans XNA il y a le Color.Lerp
la méthode statique qui fait aussi la différence entre les deux couleurs.
Lerp
est une opération mathématique entre deux flotteurs qui change la valeur du premier par un rapport de la différence entre eux.
Voici une méthode d'extension pour le faire à un float
:
public static float Lerp( this float start, float end, float amount)
{
float difference = end - start;
float adjusted = difference * amount;
return start + adjusted;
}
donc une simple opération LARP entre deux couleurs en utilisant RGB serait:
public static Color Lerp(this Color colour, Color to, float amount)
{
// start colours as lerp-able floats
float sr = colour.R, sg = colour.G, sb = colour.B;
// end colours as lerp-able floats
float er = to.R, eg = to.G, eb = to.B;
// lerp the colours to get the difference
byte r = (byte) sr.Lerp(er, amount),
g = (byte) sg.Lerp(eg, amount),
b = (byte) sb.Lerp(eb, amount);
// return the new colour
return Color.FromArgb(r, g, b);
}
un exemple d'application serait quelque chose comme:
// make red 50% lighter:
Color.Red.Lerp( Color.White, 0.5f );
// make red 75% darker:
Color.Red.Lerp( Color.Black, 0.75f );
// make white 10% bluer:
Color.White.Lerp( Color.Blue, 0.1f );
HSV ( Teinte / Saturation / valeur ) aussi appelé HSL (Teinte / Saturation / légèreté ) est juste une représentation de couleur différente.
en utilisant cette représentation, il est plus facile de régler la luminosité. Donc convertissez de RGB en HSV, égayez le 'V', puis convertissez de nouveau en RGB.
ci-dessous est un code C pour convertir
void RGBToHSV(unsigned char cr, unsigned char cg, unsigned char cb,double *ph,double *ps,double *pv)
{
double r,g,b;
double max, min, delta;
/* convert RGB to [0,1] */
r = (double)cr/255.0f;
g = (double)cg/255.0f;
b = (double)cb/255.0f;
max = MAXx(r,(MAXx(g,b)));
min = MINx(r,(MINx(g,b)));
pv[0] = max;
/* Calculate saturation */
if (max != 0.0)
ps[0] = (max-min)/max;
else
ps[0] = 0.0;
if (ps[0] == 0.0)
{
ph[0] = 0.0f; //UNDEFINED;
return;
}
/* chromatic case: Saturation is not 0, so determine hue */
delta = max-min;
if (r==max)
{
ph[0] = (g-b)/delta;
}
else if (g==max)
{
ph[0] = 2.0 + (b-r)/delta;
}
else if (b==max)
{
ph[0] = 4.0 + (r-g)/delta;
}
ph[0] = ph[0] * 60.0;
if (ph[0] < 0.0)
ph[0] += 360.0;
}
void HSVToRGB(double h,double s,double v,unsigned char *pr,unsigned char *pg,unsigned char *pb)
{
int i;
double f, p, q, t;
double r,g,b;
if( s == 0 )
{
// achromatic (grey)
r = g = b = v;
}
else
{
h /= 60; // sector 0 to 5
i = (int)floor( h );
f = h - i; // factorial part of h
p = v * ( 1 - s );
q = v * ( 1 - s * f );
t = v * ( 1 - s * ( 1 - f ) );
switch( i )
{
case 0:
r = v;
g = t;
b = p;
break;
case 1:
r = q;
g = v;
b = p;
break;
case 2:
r = p;
g = v;
b = t;
break;
case 3:
r = p;
g = q;
b = v;
break;
case 4:
r = t;
g = p;
b = v;
break;
default: // case 5:
r = v;
g = p;
b = q;
break;
}
}
r*=255;
g*=255;
b*=255;
pr[0]=(unsigned char)r;
pg[0]=(unsigned char)g;
pb[0]=(unsigned char)b;
}
Rich Newman examine la couleur HSL en ce qui concerne le système .NET.Dessin.Color sur son blog et même fournit une classe HSLColor qui fait tout le travail pour vous. Convertissez votre système.Dessin.Couleur à une couleur HSLColor, ajouter / soustraire des valeurs contre la luminosité, et convertir de nouveau en système.Dessin.Couleur à utiliser dans votre application.
vous pouvez convertir votre couleur dans l'espace de couleur HSL, le manipuler et de convertir de nouveau à votre espace de couleur de choix (très probablement qui est RGB)
les couleurs plus claires ont une valeur plus élevée de L, plus sombre un plus bas.
Voici la substance pertinente et toutes les équations:
http://en.wikipedia.org/wiki/HSL_color_space
une autre méthode est d'interpoler simplement votre couleur avec blanc ou noir. Cela va également Désaturer La couleur un peu, mais il est moins cher à calculer.
j'ai utilisé le ControlPaint.Sombre() et .La lumière() dans le Système.Windows.Forme.
je suppose que vous utilisez RGB avec des valeurs de octet (0 à 255) comme c'est très commun partout.
pour brighter, faire la moyenne des valeurs RVB avec le RVB de blanc. Ou, d'avoir un certain contrôle sur la quantité d'éclaircissement, mélanger dans une certaine proportion. Soit f
varie de 0,0 à 1,0, puis:
Rnew = (1-f)*R + f*255
Gnew = (1-f)*G + f*255
Bnew = (1-f)*B + f*255
pour plus sombre, utilisez le RVB de noir - ce qui, étant tous les zéros, rend le calcul plus facile.
j'oublie les détails comme convertir le résultat en octets, ce que vous voudriez probablement faire.
si vous utilisez des couleurs RGB, Je transformerai ce paramètre de couleur en HSL (teinte, saturation, légèreté), je modifierai le paramètre de légèreté et je me transformerai en RGB. Google autour et vous trouverez beaucoup d'échantillons de code sur la façon de faire ces transformations de représentation de couleur (RGB à HSL et viceversa).
c'est Ce que j'ai rapidement trouvé: http://bytes.com/forum/thread250450.html
en supposant que vous obtenez la couleur en RVB, convertissez-la d'abord en HSV (teinte, saturation, valeur) l'espace de couleur. Puis augmenter/diminuer la valeur pour produire une nuance plus claire / plus foncée de la couleur. Puis le reconvertir en RGB.
si vos couleurs sont au format RVB (ou, probablement CMJN), vous pouvez utiliser la méthode assez rudimentaire pour augmenter la valeur de chaque composante de la couleur. Par exemple, les couleurs HTML sont représentées par trois nombres hexadécimaux à deux chiffres. # ff0000 vous donnera un rouge vif, qui peut ensuite être effacé en augmentant les valeurs des composants G et B du même montant, comme #ff5555 (donne un rouge plus clair). Sans doute pour les couleurs teinte, Saturation et légèreté (HSL) , vous pouvez simplement augmenter le L composant, mais je ne peux pas le dire avec certitude; je suis moins familier avec cet espace de couleur.
comme je le dis, cependant, cette méthode est assez rudimentaire. D'après mes souvenirs de Live Messenger, il semble que vous essayez de faire des gradients, qui peuvent être appliqués très facilement dans Windows Presentation Foundation (WPF, partie de .NET 3.0). WPF supporte de nombreux types de pinceaux à gradient, y compris les gradients linéaires et radiaux.
je recommande vivement Adam Le livre de Nathan Windows Presentation Foundation Unleashed comme une bonne et complète introduction à WPF.
HTH
toutes les variations de couleur sont mieux faites en HSL / HSV.
un bon test consiste à interpoler entre deux valeurs équivalentes dans l'espace RGB et L'espace HSL. La rampe dans l'espace HSL ressemble à une progression naturelle. Dans L'espace du RVB, il semble typiquement peu naturel. HSL correspond à notre perception visuelle de l'espace de couleur beaucoup mieux que RGB.
l'idée de convertir en HSV ou un autre espace de couleur semble bonne, et peut être nécessaire pour un travail de couleur précise, mais pour les besoins ordinaires l'erreur de travailler en RVB peut ne pas être suffisante pour compter. En outre, il peut être une douleur à traiter les cas limites: RVB est un espace cubique, tandis que HSV ne l'est pas. Si vous travaillez avec des valeurs d'octets, vous pouvez avoir plusieurs-à-un et un-à-plusieurs mappages entre les espaces. Cela peut être ou ne pas être un problème selon l'application. YMMV