C# 什么';褪色的正确数学是什么?

C# 什么';褪色的正确数学是什么?,c#,c++,.net,colors,C#,C++,.net,Colors,我正在尝试褪色一种颜色,比如说在一段时间内从黄色变为白色。我已经设置好了计时器,并且我正在应用新的颜色,但是淡出不是平滑的(例如,它在变成白色之前会淡出一些奇怪的颜色,其中一些颜色比“淡出链”(我们称之为“淡出链”)上的前一个颜色要暗)。我相信这是因为数学是错误的,但我似乎找不到一个好的数学例子来修改我正在做的事情 我甚至从这个问题中提取了彩色天花板代码的基本知识: 现在我使用一种颜色,并调用扩展方法Increase: dataGridViewResults.Rows[0].DefaultCel

我正在尝试褪色一种颜色,比如说在一段时间内从
黄色
变为
白色
。我已经设置好了计时器,并且我正在应用新的颜色,但是淡出不是平滑的(例如,它在变成
白色之前会淡出一些奇怪的颜色,其中一些颜色比“淡出链”(我们称之为“淡出链”)上的前一个颜色要暗)。我相信这是因为数学是错误的,但我似乎找不到一个好的数学例子来修改我正在做的事情

我甚至从这个问题中提取了
彩色天花板
代码的基本知识:

现在我使用一种颜色,并调用扩展方法
Increase

dataGridViewResults.Rows[0].DefaultCellStyle.BackColor.Increase(50);

public static Color Increase(this Color color, byte offset)
{
    return Color.FromArgb(
        color.A.ColorCeiling(offset),
        color.R.ColorCeiling(offset),
        color.G.ColorCeiling(offset),
        color.B.ColorCeiling(offset));
}
正如您所看到的,然后通过偏移量修改每种颜色,并考虑天花板,以防止抛出异常。扩展方法,
color天花板
如下所示:

public static int ColorCeiling(this byte val, byte modifier, byte ceiling = 255)
{
    return (val + modifier > ceiling) ? ceiling : val + modifier;
}

现在,我确信
colorselimp
是个问题,但老实说,我就是找不到数学。老实说,我觉得增加ARGB几乎肯定是错误的方法,似乎你会说我希望你轻50%,但就代码而言,我不知道这意味着什么

不要在红、绿、蓝的空间里计算。相反,将您的颜色视为包含三个组成部分:

  • 色调(是红色、橙色、黄色、绿色、蓝色、紫色等)
  • 饱和度(颜色有多浓?)
  • 值(颜色中有多少黑色?)
有从RGB到HSV的转换算法;查一查。这是一个很好的起点:


现在,当您从一种颜色淡入另一种颜色时,请沿HSV轴而不是RGB轴采取步骤

渐变就是你要找的。你必须把它们分开,然后像这样重新组合

int rMax = Color.Yellow.R;
int rMin = Color.White.R;
int bMax = Color.Yellow.B;
int bMin = Color.White.B;
int gMax = Color.Yellow.G;
int gMin = Color.White.G;

var colorList = new List<Color>();
for(int i=0; i<size; i++)
{
    var rAverage = rMin + (int)((rMax - rMin) * i / size);
    var bAverage = bMin + (int)((bMax - bMin) * i / size);
    var gAverage = gMin + (int)((gMax - gMin) * i / size);

    colorList.Add(Color.FromArgb(rAverage, gAverage, bAverage));
}
int rMax=Color.Yellow.R;
int rMin=Color.White.R;
int bMax=Color.Yellow.B;
int bMin=颜色.White.B;
int gMax=Color.Yellow.G;
int gMin=Color.White.G;
var colorList=新列表();

for(inti=0;iPercentage意味着乘法,而不是加法。在我的示例中,我通过定义两种颜色并混合RGB维度来实现这类操作

从我的色彩课:

this.getBlendedColor = function(color, percent) {
    // limit percent between 0 and 1.
    // this percent is the amount of 'color' rgb components to use
    var p = percent > 0 ? percent : 0;
    p = p < 1 ? p : 1;

    // amount of 'this' rgb components to use
    var tp = 1 - p;

    // blend the colors
    var r = Math.round(tp * this.r + p * color.r);
    var g = Math.round(tp * this.g + p * color.g);
    var b = Math.round(tp * this.b + p * color.b);

    // return new color object
    return new Color(r, g, b);
} // getBlendedColor ()
如果您使用的是alpha通道,则可以显式地包含它,而不会造成任何问题——在您的示例中,两种颜色可能都是100%不透明度


使用简单RGB颜色混合数学的渐变示例:

这里是一些我用来在RGB颜色空间中从一种颜色渐变到另一种颜色的代码。出于我的目的,它工作得很好。您可能需要调整它以分步返回颜色。目前,对于每个
I
,您将有一个
curClr
,即
I/discreteUnits
baseClr
fadeTo
之间的百分比

int discreteUnits = 10;
Color fadeTo = Color.Green;
Color baseClr = Color.Red;
float correctionFactor = 0.0f;
float corFactorStep = 1.0f / discreteUnits;

for(int i = 0; i < discreteUnits; i++)
{
    correctionFactor += corFactorStep;
    float red = (fadeTo.R - baseClr.R) * correctionFactor + baseClr.R;
    float green = (fadeTo.G - baseClr.G) * correctionFactor + baseClr.G;
    float blue = (fadeTo.B - baseClr.B) * correctionFactor + baseClr.B;
    Color curClr = Color.FromArgb(baseClr.A, (int)red, (int)green, (int)blue);
}
int discreteUnits=10;
Color fadeTo=颜色。绿色;
Color baseClr=Color.Red;
浮动校正系数=0.0f;
浮动系数步骤=1.0f/不一致;
for(int i=0;i

感谢这个网站为我提供了一个起点:

在这个过程中,颜色的ARGB值是多少?顺便说一下,你的
color天花
方法可以简化为:
return Math.Min(val+修饰符,天花)
,但它看起来运行得很好。@TimS.,关于值,因为我从
黄色开始(255255,0),唯一真正随时间变化的值是
B
。因此它将随时间增加
50
。感谢
返回的提示,这样更好。类似的问题:@MichaelPerrenoud你检查过实际值,看它们是否与你说的相符吗?你所说的数字是我所期望的,但是您描述的颜色与此不匹配。作为一般解决方案,我同意您的意见,但对于从黄色(FF FF 00)到白色(FF FF FF FF)的简单淡入,这是否真的会有任何不同,更不用说引起他所看到的大问题了?我喜欢这个答案。(+1)它提供了一个在概念上更符合所需颜色偏移的选项——不过,应该注意的是,RGB HSV转换是“有损的”这是一个不好的建议。在色调空间中插值会产生比所需颜色更多的颜色。例如,插值红色->青色将产生红色->黄色->绿色->青色。更不用说需要小心,并循环插值色调(我的意思是,插值10到350需要与零相交)。使用CIELAB是一个更好的插值颜色空间。或者甚至在线性RGB空间中使用简单的线性插值也更好。如果你要复制答案,至少
int discreteUnits = 10;
Color fadeTo = Color.Green;
Color baseClr = Color.Red;
float correctionFactor = 0.0f;
float corFactorStep = 1.0f / discreteUnits;

for(int i = 0; i < discreteUnits; i++)
{
    correctionFactor += corFactorStep;
    float red = (fadeTo.R - baseClr.R) * correctionFactor + baseClr.R;
    float green = (fadeTo.G - baseClr.G) * correctionFactor + baseClr.G;
    float blue = (fadeTo.B - baseClr.B) * correctionFactor + baseClr.B;
    Color curClr = Color.FromArgb(baseClr.A, (int)red, (int)green, (int)blue);
}