Створіть кольори між червоним та зеленим для вимірювача потужності?


137

Я пишу гру на Java і хочу впровадити лічильник потужності для того, наскільки важко ви збираєтесь щось знімати.

Мені потрібно написати функцію, яка займає int між 0 - 100, і виходячи з того, наскільки високе це число, вона поверне колір між зеленим (0 за шкалою потужності) та червоним (100 за шкалою потужності).

Подібно до того, як працюють регулятори гучності:
регулювання гучності

Які операції мені потрібно зробити на червоному, зеленому та синьому компонентах кольору, щоб генерувати кольори між зеленим та червоним?

Отже, я можу запустити скажу, getColor(80)і він поверне помаранчевий колір (його значення в R, G, B) або getColor(10)який поверне більше зеленого / жовтого значення RGB.

Я знаю, що мені потрібно збільшити компоненти R, G, B значень для нового кольору, але я не знаю конкретно, що йде вгору чи вниз, коли кольори змінюються від зеленого на червоний.


Прогрес:

Я в кінцевому підсумку використовував кольоровий простір HSV / HSB, тому що мені більше сподобався градієнт (у середині немає темних коричневих кольорів).

Я використовував функцію:

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);
}

Де "потужність" - це число від 0,0 до 1,0. 0,0 поверне яскраво-червоний, 1,0 поверне яскраво-зелений.

Діаграма відтінку Java:
Діаграма відтінку Java


Раніше я задавав те саме (надзвичайно схоже) питання тут: http://stackoverflow.com/questions/168838/color-scaling-function
Томаш Пайонк

2
Ви не повинні інвертувати владу? Якщо припустити, що червоний колір найбільше вражає, і ви працюєте між 0,1 і 0,4, чим більша потужність, тим менша Н
Адріан Давел

Ви використовуєте OpenGL? Оскільки існують способи встановлення точок трикутника на різні кольори, а потім їх змішування / градієнт. Ви, мабуть, отримаєте кращі показники роботи, попросивши відеокарту виконати роботу за вас. Також код може бути простішим / адаптованішим (скажімо, якщо ви хочете, щоб лічильник потужності прибульців перейшов від зеленого до синього)
DarcyThomas

Відповіді:


203

Це повинно працювати - просто лінійно масштабуйте червоні та зелені значення. Якщо припустити, що ваше максимальне червоне / зелене / синє значення є 255і nзнаходиться в діапазоні0 .. 100

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

(Змінено з цілої математики, наконечник капелюха до Феррусіо)

Інший спосіб зробити це - використовувати кольорову модель HSV та провести циклічний відтінок від 0 degrees(червоний) до 120 degrees(зелений) з будь-якою насиченістю та значенням, яке вам підходить. Це повинно дати приємніший градієнт.

Ось демонстрація кожної техніки - верхній градієнт використовує RGB, нижній - HSV:

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


20
Це набагато, набагато краще зробити це в космосі HSV.
DJClayworth

@DJClayworth, так, я пішов з ВПГ.
mmcdole

+1; Я збирався задати нове запитання про те, як поліпшити алгоритм кольорів у мене для фарбування смужкової діаграми в HTML / PHP ... Так запропонував це питання як подібне, і ваша відповідь допомогла мені виправити проблему, не задаючи питання! Дякую!
благає

Як би ви написали функцію, яка працює з будь-яким значенням кольору? Скажіть, обчисліть колір між RGB 20,30,190 та RBG 69,190,10?
Кокодоко

1
та сама техніка - переходити від значення X до значення Y за N кроків, кожен крок ви збільшуєте X на (YX) / N - хоча це буде виглядати приємніше, якщо ви рухаєтеся в просторі HSV, а не RGB
Пол Діксон

32

Ось у верхній частині голови, ось перехід зелено-червоного відтінку в просторі HSV, перекладений на 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)

Червоні, зелені, сині значення у наведеному вище прикладі - це відсотки, ви, ймовірно, хочете помножити їх на 255, щоб отримати найбільш використовуваний діапазон 0-255.


12

Коротка відповідь Copy'n'Paste ...

На Java Std:

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

На Android:

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

Примітка: значення - це число від 0 до 1, що вказує на стан червоно-зеленого кольору.


Для прямого перетворення в шістнадцятковий кольоровий код ви можете скористатисяString.format("#%06X", 0xFFFFFF & getTrafficlightColor(value));
ngeek

10

Якщо ви хочете, щоб зелено-жовто-червоне зображення, як прийнята відповідь, запропонуйте, тоді погляньте на це.

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>


Я отримую рівні значення для різних відсотків за допомогою цього коду ... будь-які ідеї? Наприклад, наступні відсотки повертають RGB 1,255,0: 0,277, 0,222, 0,111 ... більш високі значення (наприклад 1,0) дійсно повертають правильні RGB з яскравішим зеленим, але вони перестають відставати після порогу, і я отримую лише відтінки зеленого в моєму масштабі.
Патрік

8

Лінійна інтерполяція між зеленим і червоним майже повинна працювати, за винятком того, що посередині буде мутно-коричневий колір.

Найбільш гнучко і найкраще виглядає рішення - мати файл зображення десь із точним кольоровим пандусом, який ви хочете. А потім знайдіть значення пікселя там. Це гнучкість, що ви можете налаштувати градієнт, щоб бути правильним .

Якщо ви все ще хочете зробити це з коду, то, мабуть, найкраще інтерполювати між зеленим та жовтим кольорами в лівій частині, а між жовтим та червоним у правій частині. У просторі RGB зелений (R = 0, G = 255, B = 0), жовтий (R = 255, G = 255, B = 0), червоний (R = 255, G = 0, B = 0 ) - припускаючи, що кожен кольоровий компонент переходить від 0 до 255.


1
Тут пропонується розділити спектр на червоний / жовтий та жовтий / зелений, що дає найприємніші жовті результати.
фіг

4

Я зробив невелику функцію, яка дає вам ціле значення rgb для відсоткового значення:

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);
}

Отже, якщо ваш currentValue дорівнює 50, а ваш maxValue - 100, ця функція поверне потрібний вам колір, тож якщо ви закріпіть цю функцію із відсотковим значенням, ваше значення кольору перейде від зеленого до червоного. Вибачте за неправильне пояснення


3

Прийнята відповідь навіть не дуже відповіла на питання ...

C ++

Ось простий сегмент коду C ++ від мого двигуна, який лінійно та ефективно інтерполює між трьома довільними кольорами:

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);
}

interpolation_factorПередбачається в діапазоні 0.0 ... 1.0.
Кольори передбачаються в діапазоні 0.0 ... 1.0(наприклад, для OpenGL).

C #

Ось та сама функція, написана на C #:

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)));
}

interpolationFactorПередбачається в діапазоні 0.0 ... 1.0.
Кольори припускаються в діапазоні 0 ... 255.


1
Код C # спрацював для мене блискуче (додано оновлення), але в ньому є орфографічна помилка interpolationFactorColor2 має бути інтерполяцієюFactor2
DJIDave

Також для повноти це те, як я використав функцію для повернення RGB в MVC razr view подвійний n = фактичнийValue / maxValue; // Це дає відношення 0-1 var color = GetInterpolatedColor (n); повернути рядок.Concat ("#", colour.R.ToString ("X"), colour.G.ToString ("X"), color.B.ToString ("X"));
DJIDave

@DJIDave: Вау, яка очевидна і дурна помилка. Я це виправив. Дякую!
Тара

2

Вам потрібно лінійно інтерполювати (LERP) кольорові компоненти. Ось як це робиться загалом, враховуючи початкове значення v0 , кінцеве значення v1 та необхідне відношення (нормалізований поплавок між 0,0 та 1,0):

v = v0 + ratio * (v1 - v0)

Це дає v0, коли коефіцієнт дорівнює 0,0, v1, коли відношення 1,0, і все між іншими в інших випадках.

Це можна зробити або на компонентах RGB, або за допомогою іншої кольорової гами, наприклад, HSV або HLS. Останні два будуть візуально приємнішими, оскільки вони працюють на комп’ютерах відтінку та яскравості, які краще відображають наше кольорове сприйняття.


2

Я б сказав, що вам потрібно щось середнє між сегментом лінії в просторі HSV (який має трохи занадто яскравий жовтий в центрі) і сегментом лінії в просторі RGB (у центрі якого є потворне коричневе). Я б використав це, де power = 0дасть зелений колір, power = 50дасть трохи тьмяний жовтий колір, і power = 100дасть червоний.

blue = 0;
green = 255 * sqrt( cos ( power * PI / 200 ));
red = 255 * sqrt( sin ( power * PI / 200 )); 

2

Ось рішення копіювання та вставки для масштабу Swift та HSV:

Ініціалізатор UIColor приймає відтінок, насиченість та яскравість у [0, 1], тому для заданого значення від [0, 1] ми маємо:

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)

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);
    }
}

1

Якщо вам потрібен такий тип градієнта (фактично зворотний) у CSS (хв. Версія 2.1), ви також можете використовувати HSL.

Припустимо, ви знаходитесь у шаблоні AngularJs і значення - це число від 0 до 1, і ви хочете стилізувати елемент (колір тла або тексту) ...

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

Перше значення: градуси (0 червоних, 120 зелених) Друге значення: насиченість (50% є нейтральним) Третє значення: легкість (50% нейтральність)

Приємна стаття тут

Теорія у Вікіпедії тут


1

Ось Objective-Cверсія рішення Simucal:

- (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];
}

Де рівень буде значенням між 0.0та 1.0.
Сподіваюся, це допоможе комусь!


1

У 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)

Відсоток - це звичайно value / max_value. Або якщо ваша шкала не починається з 0, тоді (value - min_value) / (max_value - min_value).


1

JavaScript

Я використовую візуалізацію Google з діаграмою та хотів, щоб бари були зеленими та червоними на основі відсотка. Це виявилося найчистішим рішенням, яке я знайшов і працює чудово.

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)';
}

Просто переконайтесь, що ваш відсоток становить 50 на 50%, а не 0,50.


1

Я оновив прийняту відповідь, розділивши її на першу та другу половину (0,100) діапазону і замінивши 100 на максимальний рівень, щоб діапазон став динамічним. Результат точно такий, як у моделі HSV, але все ще використовується RGB. Головне, щоб посередині (255,255,0) було зображено жовтий колір. Я поєднав цю ідею у прийнятій відповіді та іншому коді VBA, тому досягайте її у VBA та використовуйте в Excel. Я сподіваюся, що логіка допомагає і може використовуватися в інших мовах / програмах.

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

Ура, Павлін


1

В.Б.

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

Хоча це може спрацювати, було б корисно, якщо ви
дасте

0

Самостійний приклад

<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>

0

Це змінюватиметься від червоного до жовтого, а потім до зеленого
значення коливатиметься від 0 до 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];
}
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.