Gerar colors entre vermelho e verde para um medidor de energia?

Eu estou escrevendo um jogo Java e quero implementar um medidor de energia para o quão duro você vai filmar alguma coisa.

Eu preciso escrever uma function que leva um int entre 0 – 100, e com base em quão alto esse número é, ele retornará uma cor entre verde (0 na escala de energia) e vermelho (100 na escala de energia).

Semelhante a como os controles de volume funcionam:
controle de volume

Qual operação eu preciso fazer nos componentes Vermelho, Verde e Azul de uma cor para gerar as colors entre Verde e Vermelho?

Então, eu poderia rodar say, getColor(80) e ele retornará uma cor laranja (seus valores em R, G, B) ou getColor(10) que retornará um valor RGB mais Verde / Amarelo.

Eu sei que preciso aumentar os componentes dos valores R, G, B para uma nova cor, mas não sei especificamente o que sobe ou desce quando as colors mudam de verde-vermelho.


Progresso:

Eu acabei usando o espaço de cor HSV / HSB porque eu gostei do gradiant melhor (sem marrom escuro no meio).

A function que usei foi:

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

Onde “power” é um número entre 0.0 e 1.0. 0.0 retornará um vermelho shiny, 1.0 retornará um verde shiny.

Gráfico de Matiz Java:
Gráfico de Matiz Java

Isso deve funcionar – basta dimensionar linearmente os valores vermelho e verde. Assumindo que o valor máximo de vermelho / verde / azul é 255 , e n está no intervalo 0 .. 100

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

(Alterado para matemática inteira, ponta do chapéu para Ferrucio)

Outra maneira de fazer isso seria usar um modelo de colors HSV , e passar o tom de 0 degrees (vermelho) para 120 degrees (verde) com qualquer valor de saturação e adequado para você. Isso deve dar um gradiente mais agradável.

Aqui está uma demonstração de cada técnica – top gradiente usa RGB, bottom usa HSV:

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

No topo da minha cabeça, aqui está a transição de matiz verde-vermelho no espaço do HSV, traduzida para 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) 

Os valores de vermelho, verde e azul no exemplo acima são porcentagens, você provavelmente deseja multiplicá-los por 255 para obter o intervalo de 0 a 255 mais usado.

Resposta curta de Copy’n’Paste …

No Java Std:

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

No Android:

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

note: value é um número entre 0 e 1, indicando a condição de vermelho para verde.

Interpolação linear entre verde e vermelho quase deve funcionar, exceto que no meio haverá cor marrom lamacenta.

A solução mais flexível e mais atraente é ter um arquivo de imagem em algum lugar que tenha a rampa de colors exata desejada. E, em seguida, procure o valor de pixel lá. Isto tem a flexibilidade que você pode ajustar o gradiente para ser apenas para a direita .

Se você ainda quiser fazer isso a partir do código, provavelmente é melhor interpolar entre as colors verde e amarela no lado esquerdo e entre amarelo e vermelho no lado direito. No espaço RGB, verde é (R = 0, G = 255, B = 0), amarelo é (R = 255, G = 255, B = 0), vermelho é (R = 255, G = 0, B = 0 ) – isto assume que cada componente de cor vai de 0 a 255.

Se você quiser uma representação verde-amarelo-vermelho como a resposta aceita sugere, então dê uma olhada nisso.

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 = "
  • " + i + "
  • "; $("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; } 
      

      Eu fiz uma pequena function que lhe dá o valor inteiro rgb para um valor percentual:

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

      Portanto, se seu valor atual for 50 e seu valor max é 100, essa function retornará a cor necessária, portanto, se você aplicar o loop a essa function com um valor percentual, seu valor de cor passará de verde para vermelho. Desculpe pela má explicação

      A resposta aceita nem sequer respondeu à pergunta …

      C ++

      Aqui está um segmento de código C ++ simples do meu mecanismo que interpola de forma linear e eficiente entre três colors arbitrárias:

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

      O interpolation_factor é considerado como estando no intervalo de 0.0 ... 1.0 .
      As colors são consideradas no intervalo de 0.0 ... 1.0 (por exemplo, para OpenGL).

      C #

      Aqui está a mesma function escrita em 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))); } 

      O interpolationFactor é considerado como estando na faixa de 0.0 ... 1.0 .
      As colors são consideradas no intervalo de 0 ... 255 .

      Você precisa interpolar linearmente (LERP) os componentes de cor. Veja como é feito em geral, dado um valor inicial v0 , um valor final v1 e a taxa necessária (um valor normalizado entre 0.0 e 1.0):

       v = v0 + ratio * (v1 - v0) 

      Isto dá v0 quando a relação é 0.0, v1 quando a relação é 1.0, e tudo entre nos outros casos.

      Você pode fazer isso nos componentes RGB ou usando algum outro esquema de colors, como HSV ou HLS. Os dois últimos serão mais visualmente agradáveis, pois trabalham em componentes de matiz e brilho que melhor mapeiam a nossa percepção de colors.

      Eu diria que você quer algo entre um segmento de linha no espaço HSV (que tem um amarelo um pouco shiny demais no centro) e um segmento de linha no espaço RGB (que tem um marrom feio no centro). Eu usaria isso, onde power = 0 vai dar verde, power = 50 vai dar um amarelo levemente opaco, e power = 100 vai dar vermelho.

       blue = 0; green = 255 * sqrt( cos ( power * PI / 200 )); red = 255 * sqrt( sin ( power * PI / 200 )); 
       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); } } 

      Se você precisar desse tipo de gradiente (na verdade invertido) em CSS (min versão 2.1), você também pode usar o HSL.

      Supondo que você esteja em um modelo AngularJs, o valor é um número de 0 a 1 e você deseja estilizar um elemento (fundo ou cor de texto) …

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

      Primeiro valor: graus (0 vermelho, 120 verde) Segundo valor: saturação (50% é neutro) Terceiro valor: leveza (50% neutro)

      Um bom artigo aqui

      Teoria na Wikipedia aqui

      Aqui está uma solução de copiar e colar para a escala Swift e HSV:

      O inicializador UIColor aceita matiz, saturação e brilho em [0, 1], portanto, para determinado valor de [0, 1], temos:

       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) 

      Aqui está a versão Objective-C da solução da 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]; } 

      Onde level seria um valor entre 0.0 e 1.0 .
      Espero que isso ajude alguém!

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

      Porcentagem é, claro, value / max_value . Ou se a sua escala não começar em 0 então (value - min_value) / (max_value - min_value) .

      JavaScript

      Estou usando o Google Visualization com o gráfico de barras e queria que as barras fossem verdes a vermelhas com base em uma porcentagem. Esta acabou por ser a solução mais limpa que encontrei e funciona perfeitamente.

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

      Apenas certifique-se de que sua porcentagem seja 50 para 50% e não 0,50.

      Exemplo auto contido

             

      Eu atualizei a resposta aceita dividindo-a na primeira e segunda metade do intervalo (0,100) e substituindo 100 por um nível máximo, para que o intervalo possa se tornar dynamic. O resultado é exatamente como no modelo HSV, mas ainda usando RGB. A chave é ter o (255,255,0) no meio para representar a cor amarela. Combinei essa ideia na resposta aceita e em outro código do VBA, para obtê-lo no VBA e usá-lo no Excel. Espero que a lógica ajude e possa ser usada em outras linguagens / aplicações.

       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 

      Felicidades, Pavlin

      Isso irá variar de vermelho para amarelo e depois para verde
      valor varia de 0 a 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]; } 

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