考虑到系统或用户的任何色调的源颜色,我想要一个简单的算法,我可以用它来计算所选颜色的较浅或较暗的变体。与Windows Live Messenger上用于为用户界面设置样式的效果类似。
语言是C#,带有.net 3.5。
回应评论:颜色格式为(Alpha)RGB。值为字节或浮点数。
标记答案:对于我使用的上下文(一些简单的UI效果),我标记为已接受的答案实际上对于此上下文来说是最简单的。但是,我已经放弃了对更复杂和准确答案的投票。任何进行更高级颜色操作并在将来找到此线程的人都应该检查出来。谢谢你。 :)
答案 0 :(得分:46)
在XNA there is the Color.Lerp
static method中,这是两种颜色之间的区别。
Lerp
是两个浮点数之间的数学运算,它通过它们之间的差值比率改变第一个值的值。
以下是对float
public static float Lerp( this float start, float end, float amount)
{
float difference = end - start;
float adjusted = difference * amount;
return start + adjusted;
}
那么使用RGB在两种颜色之间进行简单的lerp操作将是:
public static Color Lerp(this Color colour, Color to, float amount)
{
// start colours as lerp-able floats
float sr = colour.R, sg = colour.G, sb = colour.B;
// end colours as lerp-able floats
float er = to.R, eg = to.G, eb = to.B;
// lerp the colours to get the difference
byte r = (byte) sr.Lerp(er, amount),
g = (byte) sg.Lerp(eg, amount),
b = (byte) sb.Lerp(eb, amount);
// return the new colour
return Color.FromArgb(r, g, b);
}
应用此示例的例子如下:
// make red 50% lighter:
Color.Red.Lerp( Color.White, 0.5f );
// make red 75% darker:
Color.Red.Lerp( Color.Black, 0.75f );
// make white 10% bluer:
Color.White.Lerp( Color.Blue, 0.1f );
答案 1 :(得分:28)
只需将RGB值乘以您想要修改级别的数量。如果其中一种颜色已经达到最大值,则无法使其更亮(无论如何使用HSV数学。)
这给出了完全相同的结果,并且在切换到HSV然后修改V时数学少得多。这给出了与切换到HSL然后修改L相同的结果,只要您不想开始失去饱和。
答案 2 :(得分:20)
使用此表示可以更轻松地调整亮度。因此,从RGB转换为HSV,使'V'变亮,然后转换回RGB。
下面是一些要转换的C代码
void RGBToHSV(unsigned char cr, unsigned char cg, unsigned char cb,double *ph,double *ps,double *pv)
{
double r,g,b;
double max, min, delta;
/* convert RGB to [0,1] */
r = (double)cr/255.0f;
g = (double)cg/255.0f;
b = (double)cb/255.0f;
max = MAXx(r,(MAXx(g,b)));
min = MINx(r,(MINx(g,b)));
pv[0] = max;
/* Calculate saturation */
if (max != 0.0)
ps[0] = (max-min)/max;
else
ps[0] = 0.0;
if (ps[0] == 0.0)
{
ph[0] = 0.0f; //UNDEFINED;
return;
}
/* chromatic case: Saturation is not 0, so determine hue */
delta = max-min;
if (r==max)
{
ph[0] = (g-b)/delta;
}
else if (g==max)
{
ph[0] = 2.0 + (b-r)/delta;
}
else if (b==max)
{
ph[0] = 4.0 + (r-g)/delta;
}
ph[0] = ph[0] * 60.0;
if (ph[0] < 0.0)
ph[0] += 360.0;
}
void HSVToRGB(double h,double s,double v,unsigned char *pr,unsigned char *pg,unsigned char *pb)
{
int i;
double f, p, q, t;
double r,g,b;
if( s == 0 )
{
// achromatic (grey)
r = g = b = v;
}
else
{
h /= 60; // sector 0 to 5
i = (int)floor( h );
f = h - i; // factorial part of h
p = v * ( 1 - s );
q = v * ( 1 - s * f );
t = v * ( 1 - s * ( 1 - f ) );
switch( i )
{
case 0:
r = v;
g = t;
b = p;
break;
case 1:
r = q;
g = v;
b = p;
break;
case 2:
r = p;
g = v;
b = t;
break;
case 3:
r = p;
g = q;
b = v;
break;
case 4:
r = t;
g = p;
b = v;
break;
default: // case 5:
r = v;
g = p;
b = q;
break;
}
}
r*=255;
g*=255;
b*=255;
pr[0]=(unsigned char)r;
pg[0]=(unsigned char)g;
pb[0]=(unsigned char)b;
}
答案 3 :(得分:14)
Rich Newman discusses HSL color关于.NET System.Drawing.Color在他的博客上,甚至是provides an HSLColor class,它为你完成所有工作。将System.Drawing.Color转换为HSLColor,根据Luminosity添加/减去值,然后转换回System.Drawing.Color以在您的应用中使用。
答案 4 :(得分:10)
您可以将颜色转换为HSL颜色空间,在那里进行操作并转换回您选择的颜色空间(很可能是RGB)
较浅的颜色具有较高的L值,较暗的颜色较低。
以下是相关内容和所有方程式:
http://en.wikipedia.org/wiki/HSL_color_space
另一种方法是简单地用白色或黑色插入颜色。这也会使颜色去饱和,但计算起来会更便宜。
答案 5 :(得分:9)
我在System.Windows.Forms中使用了ControlPaint.Dark()和.Light()。
答案 6 :(得分:4)
我猜你正在使用带有字节值(0到255)的RGB,因为这在任何地方都很常见。
为了更亮,使用RGB白色平均RGB值。或者,要控制多少亮度,将它们按一定比例混合。让f
从0.0变为1.0,然后:
Rnew = (1-f)*R + f*255
Gnew = (1-f)*G + f*255
Bnew = (1-f)*B + f*255
对于较暗的,使用黑色RGB - 全部为零,使数学更容易。
我遗漏了一些细节,例如将结果转换回字节,这可能是你想要的。
答案 7 :(得分:3)
如果您使用RGB颜色,我会将此颜色参数转换为HSL(色调,饱和度,亮度),修改亮度参数,然后转换回RGB。谷歌周围,你会发现很多代码样本如何进行这些颜色表示转换(RGB到HSL和反之亦然)。
这是我很快发现的: http://bytes.com/forum/thread250450.html
答案 8 :(得分:0)
假设您将颜色变为RGB,首先将其转换为HSV(色调,饱和度,值)颜色空间。然后增加/减少该值以产生更浅/更深的颜色阴影。然后转换回RGB。
答案 9 :(得分:0)
如果您的颜色是RGB格式(或者,可能是CMYK),您可以使用相当粗略的方法来增加颜色的每个组成部分的值。例如,HTML颜色表示为三个两位十六进制数。 #ff0000会给你一个鲜红色,然后可以通过增加相同数量的G和B组件的值来淡化,例如#ff5555(给出较浅的红色)。据推测,对于Hue,饱和度和亮度(HSL)颜色,你可以提高L分量,但我不能肯定地说;我不熟悉这个色彩空间。
正如我所说,这种方法非常粗糙。从我对Live Messenger的回忆中,听起来你正在尝试做渐变,这可以在Windows Presentation Foundation(WPF,.NET 3.0的一部分)中非常容易地应用。 WPF支持许多不同类型的渐变画笔,包括线性和径向渐变。
我强烈推荐Adam Nathan的书Windows Presentation Foundation Unleashed作为对WPF的一个好的和全面的介绍。
HTH
答案 10 :(得分:0)
在HSL / HSV中,颜色的任何变化都会更好。
一个好的测试是在RGB空间和HSL空间中的两个等效值之间进行插值。 HSL空间的斜坡看起来像是一个自然的进展。在RGB空间中,它通常看起来非常不自然。 HSL比RGB更好地映射到我们的视觉色彩空间感知。
答案 11 :(得分:0)
转换为HSV或其他颜色空间的想法似乎很好,可能是精确色彩工作所必需的,但对于普通用途,RGB工作的错误可能不够重要。此外,处理边界情况可能会很痛苦:RGB是一个立方体形状的空间,而HSV则不是。如果使用字节值,则可以在空格之间进行多对一和一对多映射。根据应用,这可能是也可能不是问题。 YMMV
答案 12 :(得分:0)
此website指出您可以在BCL C#System.Windows.Forms命名空间中使用ControlPaint类。