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

41
demandé sur Nidonocu 2008-09-19 02:27:34

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.

28
répondu clahey 2008-09-18 22:41:30

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 );
45
répondu Keith 2010-04-22 14:27:32

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;
}
20
répondu KPexEA 2008-09-18 22:37:00

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.

14
répondu Travis Illig 2008-09-18 23:17:01

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.

10
répondu Nils Pipenbrinck 2008-09-18 22:29:56

j'ai utilisé le ControlPaint.Sombre() et .La lumière() dans le Système.Windows.Forme.

9
répondu GregUzelac 2008-10-18 01:26:57

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.

4
répondu DarenW 2012-02-02 14:57:08

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

3
répondu sachaa 2008-09-18 22:37:40

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.

0
répondu Dima 2008-09-18 22:30:45

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

0
répondu alastairs 2008-09-18 22:37:19

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.

0
répondu 2008-09-18 22:48:49

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

0
répondu DarenW 2008-09-18 22:53:50

Ce site web notes que vous pouvez utiliser le ControlPaint classe au sein de la BCL C# Système.Windows.Les formes de l'espace de noms.

0
répondu TK. 2008-12-02 15:29:09