web-dev-qa-db-fra.com

Comment 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 élaborer des variantes plus claires ou plus sombres de la couleur sélectionnée. Similaire aux effets utilisés sur Windows Live Messenger pour styliser l'interface utilisateur.

Le langage est C # avec .net 3.5.

Répondant au commentaire: Le format de couleur est (Alpha) RVB. Avec des valeurs en octets ou flottants.

Marquage de la réponse: Pour le contexte de mon utilisation (quelques effets d'interface utilisateur simples), la réponse que je marque comme acceptée est en fait la plus simple pour ce contexte. Cependant, j'ai également abandonné les votes pour les réponses plus complexes et précises. Quiconque effectue des opérations de couleur plus avancées et trouve ce fil à l'avenir devrait certainement les vérifier. Merci beaucoup. :)

41
Nidonocu

Multipliez simplement les valeurs RVB par la quantité dont vous souhaitez modifier le niveau. Si l'une des couleurs est déjà à la valeur maximale, vous ne pouvez pas la rendre plus lumineuse (en utilisant les mathématiques HSV de toute façon.)

Cela donne exactement le même résultat avec beaucoup moins de calculs que de passer à HSV puis de modifier V. Cela donne le même résultat que de passer à HSL puis de modifier L, tant que vous ne voulez pas commencer à perdre la saturation.

28
clahey

Dans XNA, il y a le Color.Lerp méthode statique qui fait cela comme la différence entre deux couleurs.

Lerp est une opération mathématique entre deux flottants qui modifie 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;
}

Ainsi, une simple opération de lerp entre deux couleurs utilisant RVB 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 );
46
Keith

HSV (Hue/Saturation/Value) également appelé HSL (Hue/Saturation/Lightness) est juste une représentation de couleur différente.

L'utilisation de cette représentation facilite le réglage de la luminosité. Convertissez donc de RVB en HSV, éclaircissez le "V", puis reconvertissez en RVB.

Ci-dessous, un code C à 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
KPexEA

Rich Newman traite de la couleur HSL par rapport à .NET System.Drawing.Color sur son blog et même fournit une classe HSLColor qui fait tout le travail pour vous. Convertissez votre System.Drawing.Color en HSLColor, ajoutez/soustrayez des valeurs par rapport à la luminosité et reconvertissez en System.Drawing.Color pour une utilisation dans votre application.

14
Travis Illig

Vous pouvez convertir votre couleur dans l'espace colorimétrique HSL, la manipuler et la reconvertir dans l'espace colorimétrique de votre choix (c'est probablement RVB)

Les couleurs plus claires ont une valeur L plus élevée, plus sombre une valeur inférieure.

Voici les trucs pertinents et toutes les équations:

http://en.wikipedia.org/wiki/HSL_color_space

Une autre méthode consiste à simplement interpoler votre couleur avec du blanc ou du noir. Cela désaturera également un peu la couleur, mais c'est moins cher à calculer.

10
Nils Pipenbrinck

J'ai utilisé ControlPaint.Dark () et .Light () dans System.Windows.Forms.

9
GregUzelac

Je suppose que vous utilisez RVB avec des valeurs d'octets (0 à 255) car c'est très courant partout.

Pour plus lumineux, faites la moyenne des valeurs RVB avec la RVB du blanc. Ou, pour avoir un certain contrôle sur la quantité d'éclaircissement, mélangez-les dans une certaine proportion. Laissez f varier 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 les couleurs plus sombres, utilisez le RVB du noir - qui, étant tous des zéros, facilite les calculs.

Je laisse de côté des détails tels que la conversion du résultat en octets, ce que vous voudriez probablement faire.

5
DarenW

Si vous utilisez des couleurs RVB, je transformerais ces paramètres de couleur en HSL (teinte, saturation, luminosité), modifier le paramètre de luminosité, puis reconvertir en RVB. Google autour et vous trouverez de nombreux exemples de code sur la façon de faire ces transformations de représentation des couleurs (RVB en HSL et vice versa).

Voici ce que j'ai rapidement trouvé: http://bytes.com/forum/thread250450.html

3
sachaa

L'idée de convertir en HSV ou dans un autre espace colorimétrique semble bonne et peut être nécessaire pour un travail de couleur précis, mais à des fins ordinaires, l'erreur de travailler en RVB peut ne pas suffire. En outre, il peut être difficile de traiter les cas limites: RVB est un espace en forme de cube, alors que HSV ne l'est pas. Si vous travaillez avec des valeurs d'octets, vous pouvez avoir des mappages plusieurs à un et un à plusieurs entre les espaces. Cela peut ou non être un problème selon l'application. YMMV

0
DarenW

En supposant que vous obteniez la couleur en RVB, convertissez-la d'abord en espace colorimétrique HSV (teinte, saturation, valeur). Augmentez/diminuez ensuite la valeur pour produire une teinte plus claire/plus foncée de la couleur. Puis reconvertissez en RVB.

0
Dima

Si vos couleurs sont au format RVB (ou, vraisemblablement CMJN), vous pouvez utiliser la méthode assez grossière pour augmenter la valeur de chaque composant de la couleur. Par exemple, en HTML, les couleurs sont représentées par trois nombres hexadécimaux à deux chiffres. # ff0000 vous donnera un rouge vif, qui peut ensuite être atténué en augmentant les valeurs des composants G et B de la même quantité, comme # ff5555 (donne un rouge plus clair). Vraisemblablement pour les couleurs Hue, Saturation et Lightness (HSL), vous pouvez simplement augmenter le composant L, mais je ne peux pas le dire avec certitude; Je connais moins bien cet espace colorimétrique.

Comme je l'ai dit, cependant, cette méthode est assez grossière. D'après mes souvenirs de Live Messenger, il semble que vous essayez de faire des dégradés, qui peuvent être appliqués très facilement dans Windows Presentation Foundation (WPF, partie de .NET 3.0). WPF prend en charge de nombreux types de pinceaux de dégradé, y compris les dégradés linéaires et radiaux.

Je peux fortement recommander le livre d'Adam Nathan Windows Presentation Foundation Unleashed comme une bonne et complète introduction à WPF.

HTH

0
alastairs

This website note que vous pouvez utiliser la classe ControlPaint dans l'espace de noms BCL C # System.Windows.Forms.

0
TK.

Toutes les variations de couleur sont mieux effectuées en HSL/HSV.

Un bon test consiste à interpoler entre deux valeurs équivalentes dans l'espace RVB et l'espace HSL. La rampe dans l'espace HSL ressemble à une progression naturelle. Dans l'espace RVB, cela semble généralement peu naturel. HSL correspond bien mieux à notre perception visuelle de l'espace colorimétrique que RVB.

0
who