web-dev-qa-db-fra.com

Algorithme: Comment passer du rouge au vert en passant par le jaune en utilisant des valeurs RVB?

Je souhaite afficher une couleur basée sur une valeur comprise entre 0 et 100. À une extrémité (100), il s’agit du rouge pur, à l’autre extrémité (0), du vert pur. Au milieu (50), je veux que ce soit jaune.

Et je veux que les couleurs s'estompent progressivement, de telle sorte qu'à 75 ans, la couleur soit moitié rouge et moitié jaune, etc.

Comment programmer les valeurs RVB pour refléter cet affaiblissement? Merci.

46
user776676

Les valeurs RVB pour les couleurs:

  • Rouge 255, 0, 0
  • Jaune 255, 255, 0
  • Vert 0, 255, 0

Entre le rouge et le jaune, espacez également vos ajouts au canal vert jusqu'à atteindre 255. Entre le jaune et le vert, espacez également vos soustractions du canal rouge.

36
jterrace

J'ai eu le même besoin et je viens de résoudre avec ceci:

myColor = new Color(2.0f * x, 2.0f * (1 - x), 0);

Explication: Au lieu de la plage [0-255], concentrons-nous sur la plage [0.0-1.0] pour les composants couleur:

  • Vert = 0.0, 1.0, 0.0
  • Jaune = 1,0, 1,0, 0,0
  • Rouge = 1,0, 0,0, 0,0

Si vous vous contentez de redimensionner le composant vert de 0,0 (sur une extrémité) à 1,0 (de l'autre) et de faire la même chose avec le composant rouge (mais en reculant), vous obtiendrez une distribution de couleurs laide et non uniforme.

Pour que cela paraisse bien, nous pourrions écrire beaucoup de code, ou nous pourrions être plus intelligents.

Si vous regardez attentivement les composants individuels, vous pouvez voir que nous pouvons diviser la plage en deux parties égales: dans la première, nous augmentons la composante rouge de 0,0 à 1,0, en laissant le vert à 1,0 et le bleu à 0,0; dans le second cas, nous diminuons la composante verte en laissant les 2 autres tels quels. Nous pouvons tirer parti du fait que toute valeur supérieure à 1.0 sera lue comme 1.0, en maximisant nos valeurs pour simplifier le code. En supposant que votre valeur x passe de 0,00 (0%) à 1,00 (100%), vous pouvez la multiplier par 2 pour la laisser dépasser la limite de 1,0 définie pour les composants de couleur. Maintenant, vos composants vont de 0,0 à 2,0 (le rouge) et de 2,0 à 0,0 (le rouge). Laissez-les être coupés à des plages de [0.0-1.0] et voilà.

Si votre x se déplace dans une autre plage (comme [0-100]), vous devez choisir un facteur approprié au lieu de 2

65
Giorgio Aresu

Voici une très simple interpolation linéaire des composantes de la couleur. Cela pourrait servir vos besoins.

public Color GetBlendedColor(int percentage)
{
    if (percentage < 50)
        return Interpolate(Color.Red, Color.Yellow, percentage / 50.0);
    return Interpolate(Color.Yellow, Color.Lime, (percentage - 50) / 50.0);
}

private Color Interpolate(Color color1, Color color2, double fraction)
{
    double r = Interpolate(color1.R, color2.R, fraction);
    double g = Interpolate(color1.G, color2.G, fraction);
    double b = Interpolate(color1.B, color2.B, fraction);
    return Color.FromArgb((int)Math.Round(r), (int)Math.Round(g), (int)Math.Round(b));
}

private double Interpolate(double d1, double d2, double fraction)
{
    return d1 + (d2 - d1) * fraction;
}
17
Rick Sladkey

Je ne connais pas C #, cette réponse est donc une approche suggérée. Soit x le int compris entre 0 et 100. Quelque chose comme ça devrait marcher:

red   = (x > 50 ? 1-2*(x-50)/100.0 : 1.0);
green = (x > 50 ? 1.0 : 2*x/100.0);
blue  = 0.0

L'idée est de commencer au rouge: (1.0,0.0,0.0). Puis augmentez le vert pour obtenir le jaune: (1.0,1.0,0.0). Ensuite, diminuez le rouge pour devenir vert: (0.0,1.0,0.0).

Edit: Voici le code en C #

static Color GetColorFromRedYellowGreenGradient(double percentage)
{
    var red = (percentage > 50 ? 1 - 2 * (percentage - 50) / 100.0 : 1.0) * 255;
    var green = (percentage > 50 ? 1.0 : 2 * percentage / 100.0) * 255;
    var blue = 0.0;
    Color result = Color.FromArgb((int)red, (int)green, (int)blue);
    return result;
}
10
PengOne

Après avoir expérimenté pendant un moment avec des couleurs plus réalistes, voici ma formule:

public Color GetColorOf(double value, double minValue, double maxValue)
{
    if (value == 0 || minValue == maxValue) return Color.White;

    var g = (int)(240 * value / maxValue);
    var r = (int)(240 * value / minValue);

    return (value > 0
        ? Color.FromArgb(240 - g, 255 - (int)(g * ((255 - 155) / 240.0)), 240 - g)
        : Color.FromArgb(255 - (int)(r * ((255 - 230) / 240.0)), 240 - r, 240 - r));
}
  • Vous n'obtenez aucun arrière-plan (c'est-à-dire Color.White) pour 0 (ou NULL), ou lorsque min = max.
  • Pour toutes les valeurs positives, vous obtenez une couleur verte uniformément répartie entre RVB (240, 255, 240) et RVB (0, 155, 0).
  • Pour toutes les valeurs négatives, vous obtenez une couleur rouge uniformément répartie entre RVB (255, 240, 240) et RVB (230, 0, 0).

 heat map

6
Cristi S.

Méthode d'extension simplifiée;

public static Color Interpolate(this Color source, Color target, double percent)
{
    var r = (byte)(source.R + (target.R - source.R) * percent);
    var g = (byte)(source.G + (target.G - source.G) * percent);
    var b = (byte)(source.B + (target.B - source.B) * percent);

    return Color.FromArgb(255, r, g, b);
}

Usage;

var low = 33.0;
var high = 100.0;
var color = Color.Red.Interpolate(Color.Green, low / high);
6
Vorspire

Vous devez utiliser la représentation des couleurs HSB ou HSV à la place et jouer avec la valeur H ("Hue"). Voir cette autre SO question sur la transformation entre RVB et HSB/HSV: Comment changer la couleur RVB en HSV?

3
Simon Mourier

Jetez un oeil à LinearGradientBrush . Cela devrait être une implémentation complète de ce que vous recherchez.

1
PedroC88

J'ai écrit une extension Swift 4 pour UIColor qui convertit un pourcentage (0-100) en UIColor du rouge au vert. 

Je l'utilise actuellement pour les barres de progression dans une application d'analyse. Voici un exemple:

let myNewColor = UIColor().greenRedProgress(percent: Int))

Voici l'extension:

extension UIColor{

func greenRedProgress(percent: Int) -> UIColor{
    let modVal = CGFloat((Double(percent).truncatingRemainder(dividingBy: 50) / 50) * 255)
    if percent <= 0{
        return UIColor(red: 1.0, green: 0, blue: 0, alpha: 1)
    }else if percent >= 100{
        return UIColor(red: 0, green: 1.0, blue: 0, alpha: 1)
    }else{
        switch percent{
            case 1..<50: return UIColor(red: 1.0, green: (modVal/255), blue: 0, alpha: 1)
            case 51..<100: return UIColor(red: (255 - modVal)/255, green: 1.0, blue: 0, alpha: 1)
            case 50: return UIColor(red: 1.0, green: 1.0, blue: 0, alpha: 1)
            default: return UIColor(red: 0, green: 1.0, blue: 0, alpha: 1)
        }
    }
}}
0
Jordan

J'ai mappé les valeurs de vitesse du processeur entre 1400 MHz et 3500 MHz en rgb () pour obtenir du vert -> jaune -> rouge avec cette fonction

function green_yellow_red(core_MHz, core_id){
  var core_color = ~~core_MHz.map(1400, 3500, 0, 510)

  if(core_color < 255){
    $('#cpu_core_'+core_id).css('background', 'rgb('+core_color+',255 , 0)')
  }else{
    core_color-=255
    $('#cpu_core_'+core_id).css('background', 'rgb(255 ,'+ (255-core_color) +', 0)')
  }
}
0
Barrard

J'avais besoin de quelque chose de similaire aujourd'hui. Le pourcentage d'entrée était de 0,0 à 1,0 et le rouge au vert. Implémentation basée sur la réponse de jterrace:

Color percentToColor(float percent)
{
    if (percent<0 || percent>1) { return Color.Black; }

    int r, g;
    if (percent<0.5)
    {
        r=255;
        g = (int)(255*percent/0.5);  //closer to 0.5, closer to yellow (255,255,0)
    }
    else
    {
        g=255;
        r = 255 - (int)(255*(percent-0.5)/0.5); //closer to 1.0, closer to green (0,255,0)
    }
    return Color.FromArgb(r, g, 0);
}
0
icy

Cette méthode (en c #, mais peut être facilement traduite dans d'autres langues) prend un pourcentage et une liste de couleurs et renvoie la couleur sur le dégradé en fonction de votre pourcentage. Lorsque vous passez dans les couleurs, elles doivent être dans l'ordre de 0 à 100 (vous voudrez donc passer Vert, Jaune, Rouge - dans cet ordre). Si vous pensez que vous voulez des couleurs différentes ou plus au milieu, ajoutez-les simplement à la liste des couleurs que vous transmettez dans l'ordre dans lequel vous souhaitez qu'elles apparaissent.

public Color ColorBasedOnPercent(decimal percent, params Color[] colors)
    {
        if (colors.Length == 0)
        {
            //I am using Transparent as my default color if nothing was passed
            return Color.Transparent;
        }
        if (percent > 1)
        {
            percent = percent / 100;
        }

        //find the two colors within your list of colors that the percent should fall between
        var colorRangeIndex = (colors.Length - 1) * percent;
        var minColorIndex = (int)Math.Truncate(colorRangeIndex);
        var maxColorIndex = minColorIndex + 1;
        var minColor = colors[minColorIndex];

        if (maxColorIndex < colors.Length)
        {
            var maxColor = colors[maxColorIndex];

            //get the differences between all the color values for the two colors you are fading between
            var aScale = maxColor.A - minColor.A;
            var redScale = maxColor.R - minColor.R;
            var greenScale = maxColor.G - minColor.G;
            var blueScale = maxColor.B - minColor.B;

            //the decimal distance of how "far" this color should be from the minColor in the range
            var gradientPct = colorRangeIndex - minColorIndex;

            //for each piece of the color (ARGB), add a percentage(gradientPct) of the distance between the two colors
            int getRGB(int originalRGB, int scale) => (int)Math.Round(originalRGB + (scale * gradientPct));

            return Color.FromArgb(getRGB(minColor.A, aScale), getRGB(minColor.R, redScale), getRGB(minColor.G, greenScale), getRGB(minColor.B, blueScale));
        }
        return minColor;
    }
0
Chaya Sulman

il vous suffit de créer une fonction avec un paramètre entier

  • l'entrée 100 retournera RVB (100, 0, 0)
  • l'entrée 50 retournera RVB (50, 50, 0)
  • l'entrée 0 retournera RVB (0, 100, 0)
  • l'entrée 99 retournera RVB (99, 1, 0)
  • l'entrée 98 renvoie le format RVB (98, 2, 0)
  • l'entrée 2 retournera RVB (2, 98, 0)
  • l'entrée 1 retournera RVB (1, 99, 0)

     Fondu de couleur privé (int v) {
     retourne Color.FromArgb (v, 100-v, 0); 
     } 
    
0
Tun Zarni Kyaw