Farben zwischen Rot und Grün für einen Leistungsmesser erzeugen?

136

Ich schreibe ein Java-Spiel und möchte einen Leistungsmesser implementieren, um festzustellen, wie schwer es ist, etwas zu schießen.

Ich muss eine Funktion schreiben, die ein int zwischen 0 und 100 annimmt. Basierend auf der Höhe dieser Zahl wird eine Farbe zwischen Grün (0 auf der Leistungsskala) und Rot (100 auf der Leistungsskala) zurückgegeben.

Ähnlich wie bei der Lautstärkeregelung:
Lautstärkeregelung

Welche Operation muss ich für die Rot-, Grün- und Blau-Komponenten einer Farbe ausführen, um die Farben zwischen Grün und Rot zu erzeugen?

Ich könnte also sagen, getColor(80)und es wird eine orange Farbe zurückgeben (seine Werte in R, G, B) oder getColor(10)die einen grün / gelben RGB-Wert zurückgibt.

Ich weiß, dass ich die Komponenten der R-, G- und B-Werte für eine neue Farbe erhöhen muss, aber ich weiß nicht genau, was nach oben oder unten geht, wenn sich die Farben von Grün-Rot ändern.


Fortschritt:

Am Ende habe ich den HSV / HSB-Farbraum verwendet, weil mir der Farbverlauf besser gefallen hat (keine dunklen Brauntöne in der Mitte).

Die Funktion, die ich benutzte, war:

public Color getColor(double power)
{
    double H = power * 0.4; // Hue (note 0.4 = Green, see huge chart below)
    double S = 0.9; // Saturation
    double B = 0.9; // Brightness

    return Color.getHSBColor((float)H, (float)S, (float)B);
}

Wobei "Leistung" eine Zahl zwischen 0,0 und 1,0 ist. 0.0 gibt ein helles Rot zurück, 1.0 gibt ein helles Grün zurück.

Java Hue Chart:
Java-Farbtondiagramm

mmcdole
quelle
Ich habe zuvor die gleiche (extrem ähnliche) Frage hier gestellt: http://stackoverflow.com/questions/168838/color-scaling-function
Tomas Pajonk
2
Sollten Sie die Leistung nicht umkehren? Angenommen, Rot ist der höchste Treffer, und Sie arbeiten zwischen 0,1 und 0,4. Je höher die Leistung,
desto
Verwenden Sie OpenGL? Es gibt Möglichkeiten, die Punkte eines Dreiecks auf verschiedene Farben einzustellen und dann zwischen ihnen zu mischen / zu verlaufen. Sie erhalten wahrscheinlich eine bessere Leistung, wenn Sie die Grafikkarte bitten, die Arbeit für Sie zu erledigen. Auch der Code könnte einfacher / anpassungsfähiger sein (sagen wir, wenn Sie möchten, dass ein Aliens-Leistungsmesser von grün nach blau wechselt)
DarcyThomas

Antworten:

202

Dies sollte funktionieren - skalieren Sie die roten und grünen Werte einfach linear. Angenommen , Ihr max rot / grün / blau - Wert ist 255, und nist in Reichweite0 .. 100

R = (255 * n) / 100
G = (255 * (100 - n)) / 100 
B = 0

(Geändert für ganzzahlige Mathematik, Spitze des Hutes an Ferrucio)

Eine andere Möglichkeit wäre, ein HSV-Farbmodell zu verwenden und den Farbton von 0 degrees(rot) nach 120 degrees(grün) mit der für Sie geeigneten Sättigung und dem für Sie geeigneten Wert zu wechseln. Dies sollte einen angenehmeren Gradienten ergeben.

Hier ist eine Demonstration jeder Technik - der obere Gradient verwendet RGB, der untere verwendet HSV:

http://i38.tinypic.com/29o0q4k.jpg

Paul Dixon
quelle
20
Es ist viel, viel besser, dies im HSV-Raum zu tun.
DJClayworth
@ DJClayworth, ja, ich bin mit dem HSV gefahren.
mmcdole
+1; Ich wollte eine neue Frage stellen, wie ich einen Farbalgorithmus verbessern kann, den ich zum Färben eines Balkendiagramms in HTML / PHP habe ... SO schlug diese Frage als ähnlich vor und Ihre Antwort half mir, das Problem zu beheben, ohne die Frage stellen zu müssen! Vielen Dank!
bettelt
Wie würden Sie eine Funktion schreiben, die mit jedem Farbwert funktioniert? Angenommen, berechnen Sie die Farbe zwischen RGB 20,30,190 und RBG 69,190,10?
Kokodoko
1
Dieselbe Technik - um in N Schritten von Wert X zu Wert Y zu wechseln, in jedem Schritt erhöhen Sie X um (YX) / N - obwohl es schöner aussieht, wenn Sie sich im HSV-Raum anstatt in RGB bewegen
Paul Dixon
32

Hier ist der grün-rote Farbtonübergang im HSV-Raum, übersetzt in RGB:

blue = 0.0
if 0<=power<0.5:        #first, green stays at 100%, red raises to 100%
    green = 1.0
    red = 2 * power
if 0.5<=power<=1:       #then red stays at 100%, green decays
    red = 1.0
    green = 1.0 - 2 * (power-0.5)

Die Werte für Rot, Grün und Blau im obigen Beispiel sind Prozentsätze. Sie möchten sie wahrscheinlich mit 255 multiplizieren, um den am häufigsten verwendeten Bereich von 0 bis 255 zu erhalten.

Rafał Dowgird
quelle
12

Kurze Antwort auf Copy'n'Paste ...

Auf Java Std:

int getTrafficlightColor(double value){
    return java.awt.Color.HSBtoRGB((float)value/3f, 1f, 1f);
}

Auf Android:

int getTrafficlightColor(double value){
    return android.graphics.Color.HSVToColor(new float[]{(float)value*120f,1f,1f});
}

Hinweis: Der Wert ist eine Zahl zwischen 0 und 1, die den Rot-Grün-Zustand angibt.

mschmoock
quelle
Um direkt in einen Hex-Farbcode zu konvertieren, möchten Sie vielleichtString.format("#%06X", 0xFFFFFF & getTrafficlightColor(value));
ngeek
10

Wenn Sie eine grün-gelb-rote Darstellung wünschen, wie sie in der akzeptierten Antwort vorgeschlagen wird, sehen Sie sich diese an.

http://jsfiddle.net/0awncw5u/2/

function percentToRGB(percent) {
    if (percent === 100) {
        percent = 99
    }
    var r, g, b;

    if (percent < 50) {
        // green to yellow
        r = Math.floor(255 * (percent / 50));
        g = 255;

    } else {
        // yellow to red
        r = 255;
        g = Math.floor(255 * ((50 - percent % 50) / 50));
    }
    b = 0;

    return "rgb(" + r + "," + g + "," + b + ")";
}


function render(i) {
    var item = "<li style='background-color:" + percentToRGB(i) + "'>" + i + "</li>";
    $("ul").append(item);
}

function repeat(fn, times) {
    for (var i = 0; i < times; i++) fn(i);
}


repeat(render, 100);
li {
    font-size:8px;
    height:10px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.0/jquery.min.js"></script>
<ul></ul>

Blowsie
quelle
Ich erhalte mit diesem Code gleiche Werte für verschiedene Prozentsätze ... irgendwelche Ideen? Zum Beispiel geben die folgenden Prozentsätze alle RGB 1.255,0 zurück: 0,277, 0,222, 0,111 ... die höheren Werte (zum Beispiel 1,0) geben die richtigen RGBs mit hellerem Grün zurück, aber sie hören nach einem Schwellenwert auf, und ich bekomme nur Grüntöne auf meiner Skala.
Patrick
8

Die lineare Interpolation zwischen Grün und Rot sollte fast funktionieren, außer dass in der Mitte eine schlammige braune Farbe entsteht.

Die flexibelste und am besten aussehende Lösung besteht darin, eine Bilddatei mit genau der gewünschten Farbrampe zu haben. Und dann suchen Sie dort nach dem Pixelwert. Dies hat die Flexibilität, dass Sie den Verlauf so einstellen können, dass er genau richtig ist .

Wenn Sie dies dennoch aus Code heraus tun möchten, ist es wahrscheinlich am besten, zwischen grünen und gelben Farben auf der linken Seite und zwischen Gelb und Rot auf der rechten Seite zu interpolieren. Im RGB-Raum ist Grün (R = 0, G = 255, B = 0), Gelb ist (R = 255, G = 255, B = 0), Rot ist (R = 255, G = 0, B = 0) ) - Dies setzt voraus, dass jede Farbkomponente von 0 bis 255 reicht.

NeARAZ
quelle
1
Der Vorschlag, das Spektrum in Rot / Gelb und Gelb / Grün aufzuteilen, liefert die angenehmsten gelben Ergebnisse.
Abb.
4

Ich habe eine kleine Funktion erstellt, die Ihnen den ganzzahligen RGB-Wert für einen Prozentwert gibt:

private int getGreenToRedGradientByValue(int currentValue, int maxValue)
{
    int r = ( (255 * currentValue) / maxValue );
    int g = ( 255 * (maxValue-currentValue) ) / maxValue;
    int b = 0;
    return ((r&0x0ff)<<16)|((g&0x0ff)<<8)|(b&0x0ff);
}

Wenn Ihr aktueller Wert also 50 und Ihr maximaler Wert 100 ist, gibt diese Funktion die Farbe zurück, die Sie benötigen. Wenn Sie diese Funktion also mit einem Prozentwert wiederholen, wechselt Ihr Farbwert von grün nach rot. Entschuldigung für die schlechte Erklärung

Nikolaus
quelle
3

Die akzeptierte Antwort beantwortete die Frage nicht einmal wirklich ...

C ++

Hier ist ein einfaches C ++ - Codesegment aus meiner Engine, das linear und effizient zwischen drei beliebigen Farben interpoliert:

const MATH::FLOAT4 color1(0.0f, 1.0f, 0.0f, 1.0f);  // Green
const MATH::FLOAT4 color2(1.0f, 1.0f, 0.0f, 1.0f);  // Yellow
const MATH::FLOAT4 color3(1.0f, 0.0f, 0.0f, 1.0f);  // Red

MATH::FLOAT4 get_interpolated_color(float interpolation_factor)
{
    const float factor_color1 = std::max(interpolation_factor - 0.5f, 0.0f);
    const float factor_color2 = 0.5f - fabs(0.5f - interpolation_factor);
    const float factor_color3 = std::max(0.5f - interpolation_factor, 0.0f);

    MATH::FLOAT4 color;

    color.x = (color1.x * factor_color1 +
               color2.x * factor_color2 +
               color3.x * factor_color3) * 2.0f;

    color.y = (color1.y * factor_color1 +
               color2.y * factor_color2 +
               color3.y * factor_color3) * 2.0f;

    color.z = (color1.z * factor_color1 +
               color2.z * factor_color2 +
               color3.z * factor_color3) * 2.0f;

    color.w = 1.0f;

    return(color);
}

Es interpolation_factorwird angenommen, dass der im Bereich von liegt 0.0 ... 1.0.
Es wird angenommen, dass die Farben im Bereich von 0.0 ... 1.0(z. B. für OpenGL) liegen.

C #

Hier ist die gleiche Funktion, die in C # geschrieben wurde:

private readonly Color mColor1 = Color.FromArgb(255, 0, 255, 0);
private readonly Color mColor2 = Color.FromArgb(255, 255, 255, 0);
private readonly Color mColor3 = Color.FromArgb(255, 255, 0, 0);

private Color GetInterpolatedColor(double interpolationFactor)
{
    double interpolationFactor1 = Math.Max(interpolationFactor - 0.5, 0.0);
    double interpolationFactor2 = 0.5 - Math.Abs(0.5 - interpolationFactor);
    double interpolationFactor3 = Math.Max(0.5 - interpolationFactor, 0.0);

    return (Color.FromArgb(255,
                (byte)((mColor1.R * interpolationFactor1 +
                        mColor2.R * interpolationFactor2 +
                        mColor3.R * interpolationFactor3) * 2.0),

                (byte)((mColor1.G * interpolationFactor1 +
                        mColor2.G * interpolationFactor2 +
                        mColor3.G * interpolationFactor3) * 2.0),

                (byte)((mColor1.B * interpolationFactor1 +
                        mColor2.B * interpolationFactor2 +
                        mColor3.B * interpolationFactor3) * 2.0)));
}

Es interpolationFactorwird angenommen, dass der im Bereich von liegt 0.0 ... 1.0.
Es wird angenommen, dass die Farben im Bereich von liegen 0 ... 255.

Tara
quelle
1
Der C # -Code hat für mich hervorragend funktioniert (Upvote hinzugefügt), aber es gibt einen Rechtschreibfehler darin interpolationFactorColor2 sollte interpolationFactor2 sein
DJIDave
Der Vollständigkeit halber habe ich auf diese Weise die Funktion verwendet, um RGB an MVC zurückzugeben. Razr view double n = actualValue / maxValue; // Dies ergibt das Verhältnis 0-1 var color = GetInterpolatedColor (n); return string.Concat ("#", colour.R.ToString ("X"), colour.G.ToString ("X"), colour.B.ToString ("X"));
DJIDave
@ DJIDave: Wow, was für ein offensichtlicher und dummer Fehler. Ich habe es behoben. Vielen Dank!
Tara
2

Sie müssen die Farbkomponenten linear interpolieren (LERP). So wird es im Allgemeinen bei einem Startwert v0 , einem Endwert v1 und dem erforderlichen Verhältnis (einem normalisierten Float zwischen 0,0 und 1,0) gemacht:

v = v0 + ratio * (v1 - v0)

Dies ergibt v0, wenn das Verhältnis 0,0 ist, v1, wenn das Verhältnis 1,0 ist, und alles dazwischen in den anderen Fällen.

Sie können dies entweder für die RGB-Komponenten oder mit einem anderen Farbschema wie HSV oder HLS tun. Die beiden letzteren werden optisch ansprechender sein, da sie an Farbton- und Helligkeitskomponenten arbeiten, die besser auf unsere Farbwahrnehmung abgestimmt sind.

efotinis
quelle
2

Ich würde sagen, Sie möchten etwas zwischen einem Liniensegment im HSV-Raum (das in der Mitte ein etwas zu helles Gelb aufweist) und einem Liniensegment im RGB-Raum (das in der Mitte ein hässliches Braun aufweist). Ich würde dies verwenden, wo power = 0Grün power = 50ergibt, ein leicht mattes Gelb power = 100ergibt und Rot ergibt.

blue = 0;
green = 255 * sqrt( cos ( power * PI / 200 ));
red = 255 * sqrt( sin ( power * PI / 200 )); 
Dawood ibn Kareem
quelle
1
import java.awt.Color;

public class ColorUtils {

    public static Color interpolate(Color start, Color end, float p) {
        float[] startHSB = Color.RGBtoHSB(start.getRed(), start.getGreen(), start.getBlue(), null);
        float[] endHSB = Color.RGBtoHSB(end.getRed(), end.getGreen(), end.getBlue(), null);

        float brightness = (startHSB[2] + endHSB[2]) / 2;
        float saturation = (startHSB[1] + endHSB[1]) / 2;

        float hueMax = 0;
        float hueMin = 0;
        if (startHSB[0] > endHSB[0]) {
            hueMax = startHSB[0];
            hueMin = endHSB[0];
        } else {
            hueMin = startHSB[0];
            hueMax = endHSB[0];
        }

        float hue = ((hueMax - hueMin) * p) + hueMin;

        return Color.getHSBColor(hue, saturation, brightness);
    }
}
mawi
quelle
1

Wenn Sie diese Art von Farbverlauf (tatsächlich umgekehrt) in CSS (min. Version 2.1) benötigen, können Sie auch HSL verwenden.

Angenommen, Sie befinden sich in einer AngularJs-Vorlage und der Wert ist eine Zahl von 0 bis 1, und Sie möchten ein Element (Hintergrund- oder Textfarbe) formatieren ...

hsl({{ value * 120}}, 50%, 35%)

Erster Wert: Grad (0 rot, 120 grün) Zweiter Wert: Sättigung (50% ist neutral) Dritter Wert: Helligkeit (50% neutral)

Ein schöner Artikel hier

Theorie auf Wikipedia hier

lucabelluccini
quelle
1

Hier ist eine Copy-and-Paste-Lösung für die Swift- und HSV-Skala:

Der UIColor-Initialisierer akzeptiert Farbton, Sättigung und Helligkeit in [0, 1]. Für den angegebenen Wert aus [0, 1] haben wir also:

let hue:        CGFloat = value / 3
let saturation: CGFloat = 1 // Or choose any
let brightness: CGFloat = 1 // Or choose any
let alpha:      CGFloat = 1 // Or choose any

let color = UIColor(hue: hue, saturation: saturation, brightness: brightness, alpha: alpha)
Stanislav Pankevich
quelle
1

Hier ist die Objective-CVersion von Simucals Lösung:

- (UIColor*) colorForCurrentLevel:(float)level
{
    double hue = level * 0.4; // Hue (note 0.4 = Green)
    double saturation = 0.9; // Saturation
    double brightness = 0.9; // Brightness

    return [UIColor colorWithHue:hue saturation:saturation brightness:brightness alpha:1.0];
}

Wobei Niveau ein Wert zwischen 0.0und wäre 1.0.
Hoffe das hilft jemandem!

S1LENT WARRIOR
quelle
1

In Python 2.7:

import colorsys

def get_rgb_from_hue_spectrum(percent, start_hue, end_hue):
    # spectrum is red (0.0), orange, yellow, green, blue, indigo, violet (0.9)
    hue = percent * (end_hue - start_hue) + start_hue
    lightness = 0.5
    saturation = 1
    r, g, b = colorsys.hls_to_rgb(hue, lightness, saturation)
    return r * 255, g * 255, b * 255

# from green to red:
get_rgb_from_hue_spectrum(percent, 0.3, 0.0)

# or red to green:
get_rgb_from_hue_spectrum(percent, 0.0, 0.3)

Prozent ist natürlich value / max_value. Oder wenn Ihre Skala dann nicht bei 0 beginnt (value - min_value) / (max_value - min_value).

Christopher Galpin
quelle
1

JavaScript

Ich verwende Google Visualization mit Balkendiagramm und wollte, dass die Balken basierend auf einem Prozentsatz grün bis rot sind. Dies stellte sich als die sauberste Lösung heraus, die ich gefunden habe und die perfekt funktioniert.

function getGreenToRed(percent){
    r = percent<50 ? 255 : Math.floor(255-(percent*2-100)*255/100);
    g = percent>50 ? 255 : Math.floor((percent*2)*255/100);
    return 'rgb('+r+','+g+',0)';
}

Stellen Sie einfach sicher, dass Ihr Prozentsatz 50 für 50% und nicht 0,50 beträgt .

Patrick
quelle
1

Ich habe die akzeptierte Antwort aktualisiert, indem ich sie in die erste und zweite Hälfte des Bereichs (0,100) aufgeteilt und 100 durch eine maximale Stufe ersetzt habe, damit der Bereich dynamisch wird. Das Ergebnis ist genau wie beim HSV-Modell, verwendet jedoch weiterhin RGB. Der Schlüssel ist, die (255,255,0) in der Mitte zu haben, um die gelbe Farbe darzustellen. Ich habe diese Idee in der akzeptierten Antwort und einem anderen VBA-Code kombiniert, also erreiche ich sie in VBA und verwende sie in Excel. Ich hoffe, die Logik hilft und kann in anderen Sprachen / Anwendungen verwendet werden.

Sub UpdateConditionalFormatting(rng As Range)
    Dim cell As Range
    Dim max As Integer

    max = WorksheetFunction.max(rng)

    For Each cell In rng.Cells

    If cell.Value >= 0 And cell.Value < max / 2 Then
        cell.Interior.Color = RGB(255 * cell.Value / (max / 2), 255, 0)
    ElseIf cell.Value >= max / 2 And cell.Value <= max Then
        cell.Interior.Color = RGB(255, 255 * ((max) - cell.Value) / (max / 2), 0)
    End If

    Next cell
End Sub

Prost, Pavlin

Pavlin Todorov
quelle
1

VB

Public Function GetPercentageColor( _
  ByVal iPercent As Long, Optional _
  ByVal bOpposit As Boolean) As Long
' 0->100% - Green->Yellow->Red
' bOpposit - Red->Yellow->Green

If bOpposit Then iPercent = (100 - iPercent)

Select Case iPercent
Case Is < 1: GetPercentageColor = 65280 ' RGB(0, 255, 0)
Case Is > 99: GetPercentageColor = 255  ' RGB(255, 0, 0)
Case Is < 50: GetPercentageColor = RGB(255 * iPercent / 50, 255, 0)
Case Else: GetPercentageColor = RGB(255, (255 * (100 - iPercent)) / 50, 0)
End Select

End Function
MartiniB
quelle
Dies mag zwar funktionieren, aber es wäre hilfreich, wenn Sie eine Erklärung
abgeben
0

In sich geschlossenes Beispiel

<html>
<head>
<script>
//--------------------------------------------------------------------------
function gradient(left, mid, right)
{
    var obj = {}

    var lt50 = {"r":(mid.r-left.r)/50.0,
                "g":(mid.g-left.g)/50.0,
                "b":(mid.b-left.b)/50.0}
    var gt50 = {"r":(right.r-mid.r)/50.0,
                "g":(right.g-mid.g)/50.0,
                "b":(right.b-mid.b)/50.0}

    obj.getColor = function(percent) {
        if (percent == 50.0) {
            return mid;
        }
        if (percent < 50.0) {
            return "rgb("+Math.floor(left.r+lt50.r*percent+0.5)+","+
                          Math.floor(left.g+lt50.g*percent+0.5)+","+
                          Math.floor(left.b+lt50.b*percent+0.5)+")";
        }
        var p2 = percent-50.0;
        return "rgb("+Math.floor(mid.r+gt50.r*p2+0.5)+","+
                      Math.floor(mid.g+gt50.g*p2+0.5)+","+
                      Math.floor(mid.b+gt50.b*p2+0.5)+")";
    }

    return obj;
}

//--------------------------------------------------------------------------
var g_gradient = gradient( {"r":255, "g":20, "b":20},  // Left is red
                           {"r":255, "g":255, "b":20}, // Middle is yellow
                           {"r":20, "g":255, "b":20} ); // right is green

//--------------------------------------------------------------------------
function updateColor()
{
    var percent = document.getElementById('idtext').value.length;
    var oscore = document.getElementById('idscore');

    if (percent > 100.0) {
        percent = 100.0;
    }
    if (percent < 0.0) {
        percent = 0.0;
    }
    var col = g_gradient.getColor(percent)
    oscore.style['background-color'] = col;
    oscore.innerHTML = percent + '%';
}

</script>
</head>
<body onLoad="updateColor()">
<input size='100' placeholder='type text here' id='idtext' type="text" oninput="updateColor()" />
<br />
<br />
<div id='idscore' style='text-align:center; width:200px; border-style:solid;
     border-color:black; border-width:1px; height:20px;'> </div>
</body>
</html>
Amnon
quelle
0

Dies variiert von Rot zu Gelb und dann zu Grün. Der
Wert variiert von 0 bis 100

-(UIColor*) redToGreenColorWithPosition:(int) value {

    double R, G;
    if (value > 50) {
        R = (255 * (100 - value)/ 50) ;
        G = 255;
    }else {
        R = 255;
        G = (255 * (value*2)) / 100;
    }

    return [UIColor colorWithRed:R/255.0f green:G/255.0f blue:0.0f alpha:1.0f];
}
Simon Fernandes
quelle