算法:如何使用RGB值从黄色渐变为黄色?

时间:2011-06-18 06:25:48

标签: c# algorithm rgb

我想根据0到100之间的值显示颜色。在一端(100),它是纯红色,另一端是(0),纯绿色。在中间(50),我希望它是黄色的。

我希望颜色逐渐从一个渐变到另一个,这样在75,颜色是半红半黄等。

如何编程RGB值以反映这种衰落?感谢。

17 个答案:

答案 0 :(得分:67)

我有同样的需要,我刚刚解决了这个问题:

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

说明: 而不是[0-255]范围,让我们关注颜色分量的[0.0-1.0]范围:

  • 绿色= 0.0,1.0,0.0
  • 黄色= 1.0,1.0,0.0
  • 红色= 1.0,0.0,0.0

如果你只是将绿色成分从0.0(在一端)缩放到1.0(在另一端)并使用红色成分(但向后)做同样的事情,你会得到丑陋和不均匀的颜色分布。

为了让它看起来不错,我们可以编写很多代码,或者我们可以更聪明。

如果仔细观察单个组件,可以看到我们可以将范围分成两个相等的部分:在第一个组件中,我们将红色组件从0.0增加到1.0,绿色保持为1.0,蓝色保持为0.0 ;在第二个中,我们减少绿色成分,使另外两个原样保持不变。我们可以利用这样的事实:通过最大化我们的值来简化代码,任何大于1.0的值都将被读为1.0。假设您的x值从0.00(0%)变为1.00(100%),您可以将其乘以2,使其超过颜色分量的1.0限制。现在你的组件从0.0到2.0(红色)和2.0到0.0(红色组件)。让它们被剪裁到[0.0-1.0]范围,然后你去。

如果你的x在另一个范围内移动(如[0-100]),你需要选择一个合适的因子而不是2

答案 1 :(得分:38)

颜色的RGB值:

  • 红色255,0,0
  • 黄色255,255,0
  • 绿色0,255,0

在红色和黄色之间,同样将你对绿色通道的添加空间分开,直到它达到255.在黄色和绿色之间,同样将你的减法与红色通道隔开。

答案 2 :(得分:18)

这是一个非常简单的颜色分量线性插值。它可能满足您的需求。

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

答案 3 :(得分:10)

我不知道C#,所以这个答案只是一个建议的方法。让x表示范围从int0的{​​{1}}。这样的事情应该有效:

100

我们的想法是从红色开始:red = (x > 50 ? 1-2*(x-50)/100.0 : 1.0); green = (x > 50 ? 1.0 : 2*x/100.0); blue = 0.0 。然后增加绿色以获得黄色:(1.0,0.0,0.0)。然后减少红色变为绿色:(1.0,1.0,0.0)

编辑:这是C#中的代码

(0.0,1.0,0.0)

答案 4 :(得分:7)

简化扩展方法;

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

用法;

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

答案 5 :(得分:5)

在我用更逼真的颜色进行了一段时间的实验之后,这是我的公式:

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));
}
  • 0(或NULL)或min = max时没有背景(即Color.White)
  • 对于所有正值,您可以在RGB(240,255,240)和RGB(0,155,0)之间获得均匀分布的绿色。
  • 对于所有负值,RGB(255,240,240)和RGB(230,0,0)之间的红色均匀分布。

heat map

答案 6 :(得分:3)

您需要使用HSB or HSV color representation代替,并使用H(“Hue”)值。请参阅RGB和HSB / HSV之间的另一个转换问题:How to change RGB color to HSV?

答案 7 :(得分:1)

看看LinearGradientBrush。它应该是您正在寻找的完整实现。

答案 8 :(得分:0)

如果您使用的是 Python,那么这可能会有所帮助...


def rgb(p):# <-- percentage as parameter
    #Starting with color red
    d = [255,0,0]
    #formula for finding green value by percentage
    d[1] = int((510*p)/100)
    print(d[1])
    #if green value more than 255
    #set green value 255
    #reduce the red value from remaining green value
    if d[1]>255:
        d[0] -= d[1]-255
        d[1] = 255
        
    return d

print(rgb(0))

答案 9 :(得分:0)

//在WM_DRAWITEM上用红黄绿色渐变填充OwnerDraw控件

int cx = lpDis->rcItem.right - lpDis->rcItem.left;

for (int x = 0; x < cx; x++)
{
    COLORREF cr;

    double d = 255 * 2 * (double)x/(double)cx;

    cr = x <= cx/2 ?    RGB(255,     d,   0) :
                        RGB(255 - d, 255, 0);

    HPEN hPen = CreatePen(PS_SOLID, 1, cr);
    HPEN hOldPen = (HPEN)SelectObject(lpDis->hDC, hPen);
    MoveToEx(lpDis->hDC, x, lpDis->rcItem.top, NULL);
    LineTo(lpDis->hDC, x, lpDis->rcItem.bottom);
    SelectObject(lpDis->hDC, hOldPen);
    DeleteObject(hPen);
}

Illustration

答案 10 :(得分:0)

最近,我打算使用Javascript做同样的事情。我遵循了两个步骤。

  1. 首先在0-1范围内缩放值(scaledValue =(值-最小)/(最大-最小))
  2. 如果该值小于或等于0.5,则增加红色通道的值,如果该值大于0.5,则减小绿色通道的值

这是我用于此目的的代码。

var blue = 0.0, red = 0.0, green = 0.0;

if(scaledValue <= 0.5)
{
    red = (scaledValue * 2) * 255.0;
    green = 255.0;
    blue = 0;
}else
{
    red = 255.0;
    green = 255.0 + 255.0 - ((scaledValue  * 2)* 255);
    blue = 0;
}

A sample code for showing this works in C++

此解决方案的灵感来自@jterrace答案。

答案 11 :(得分:0)

更多相同的东西。只是Delphi Pascal进行了编码和简化+锁定为信号灯颜色(红色/黄色/绿色)。

rectangle1.Fill.Color:=DefineColorSemaphore(newcolor);

function TForm1.DefineColorSemaphore(valperc:integer):TAlphaColor;
var
   vcol: TAlphaColorRec;
begin
  vcol.B := 0;    // blue:  always 0
  vcol.A := 255;  // alpha: 255=no
  if (valperc < 50) then
    begin
       // starts @ RGB=255,0,0 and increases G 0->255
       vcol.R := 255;
       vcol.G := trunc(255*valperc/50);
    end
    else
    begin
       // starts @ RGB=255,255,0 and decreases R 255->0
       vcol.R := 255-trunc(255* (valperc - 50)/50);
       vcol.G := 255;
    end;
  result:= TAlphaColor(vcol);
end;

答案 12 :(得分:0)

此方法(使用c#,但可以轻松转换为其他语言)将获取颜色的百分比和列表,并根据您的百分比返回渐变上的颜色。传递颜色时,它们需要按从0值到100值的顺序排列(因此,您希望按该顺序传递绿色,黄色,红色)。如果您发现想要在中间使用不同或更多的颜色,只需按照希望它们出现的顺序将它们添加到传递的颜色列表中即可。

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

答案 13 :(得分:0)

我为UIColor写了一个 Swift 4 扩展名,它将百分比(0-100)转换为UIColor从红色变为绿色。

我目前正在将其用于分析应用中的进度条。这是一个例子:

DispatcherPriority.ApplicationIdle

这是扩展名:

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

答案 14 :(得分:0)

我将1400 MHz和3500 MHz之间的CPU速度值映射到rgb()值以获得绿色 - &gt;黄色 - &gt;红色具有此功能

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

答案 15 :(得分:0)

我今天需要类似的东西。输入百分比从0.0到1.0,输出红色到绿色。基于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);
}

答案 16 :(得分:0)

你只需要用整数参数

创建一个函数
  • 输入100将返回RGB(100,0,0)
  • 输入50将返回RGB(50,50,0)
  • 输入0将返回RGB(0,100,0)
  • 输入99将返回RGB(99,1,0)
  • 输入98将返回RGB(98,2,0)
  • 输入2将返回RGB(2,98,0)
  • 输入1将返回RGB(1,90,0)

        private Color fader(int v){
           return Color.FromArgb(v, 100-v, 0); 
        }