如何确定给定颜色的深色或浅色变体?
给定系统或用户的任何色调的源颜色,我想要一个简单的algorithm,我可以使用它来找出所选颜色的较亮或较暗的变体。 类似于Windows Live Messenger上使用的用于界面风格的效果。
语言是C#与.net 3.5。
回应评论:彩色格式是(Alpha)RGB。 用值作为字节或浮点数。
标记答案:对于我使用的上下文(几个简单的UI效果),我被标记为接受的答案实际上是最简单的这个上下文。 不过,我已经放弃了对更复杂和准确的答案投票。 任何人做更高级的颜色操作,并在未来find这个线程,一定要检查出来。 感谢所以。 🙂
简单地把RGB值乘以你想要修改的值。 如果其中一种颜色已经达到最大值,那么你就无法使它变得更亮(反正使用HSVmath)。
这就给出了与切换到HSV然后修改V完全相同的结果,并且math上less了很多。这个结果与切换到HSL然后修改L一样,只要你不想开始失去饱和度。
在XNA中有Color.Lerp
静态方法 ,这是两种颜色之间的区别。
Lerp
是两个花车之间的math运算,它们通过它们之间的差异的比率来改变第一个花车的值。
这里有一个扩展方法来做到这一点:
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 );
HSV(色调/饱和度/值)也被称为HSL(色调/饱和度/亮度)仅仅是一种不同的颜色表示。
使用此表示法可以更轻松地调整亮度。 因此,从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] = (gb)/delta; } else if (g==max) { ph[0] = 2.0 + (br)/delta; } else if (b==max) { ph[0] = 4.0 + (rg)/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; }
Rich Newman在他的博客中讨论了HSL颜色与.NET System.Drawing.Color的关系,甚至提供了一个HSLColor类来完成所有工作。 将您的System.Drawing.Color转换为HSLColor,根据亮度添加/减去值,然后转换回System.Drawing.Color,以便在您的应用程序中使用。
你可以将你的颜色转换成HSL色彩空间,在那里处理它并转换回你select的色彩空间(很可能是RGB)
较轻的颜色具有较高的L值,较深的颜色较低。
这里是相关的东西和所有的方程:
http://en.wikipedia.org/wiki/HSL_color_space
另一种方法是简单地插入白色或黑色的颜色。 这也会使颜色饱和一点,但计算起来更便宜。
我在System.Windows.Forms中使用了ControlPaint.Dark()和.Light()。
我猜你正在使用RGB字节值(0到255),因为这是非常普遍的。
为了更明亮,将RGB值与白色的RGB平均。 或者,有一些控制多less增亮,混合在一定比例。 假设f
从0.0变化到1.0,则:
Rnew = (1-f)*R + f*255 Gnew = (1-f)*G + f*255 Bnew = (1-f)*B + f*255
对于较黑的,使用黑色的RGB – 全部为零,使math变得更容易。
我遗漏了诸如将结果转换回字节的细节,这可能是你想要做的。
如果您使用的是RGB颜色,我会将这个颜色参数转换为HSL (色调,饱和度,亮度),修改亮度参数,然后转换回RGB。 谷歌周围,你会发现很多代码样本如何做这些颜色表示转换(RGB到HSL和反之亦然)。
这是我很快find的: http : //bytes.com/forum/thread250450.html
假设你得到RGB的颜色,首先将其转换为HSV(色调,饱和度,值)色彩空间。 然后增大/减小该值以产生颜色的较浅/较深的阴影。 然后转换回RGB。
如果你的颜色是RGB格式(或者可能是CMYK),你可以使用相当粗糙的方法来增加颜色的每个分量的值。 例如,在HTML中,颜色表示为三个两位hex数字。 #ff0000会给你一个明亮的红色,然后可以通过增加相同数量的G和B组件的值来淡化,例如#ff5555(给出一个更淡的红色)。 推测色调,饱和度和亮度(HSL)的颜色,你可以提高L分量,但我不能肯定地说, 我不太了解这个色彩空间。
但正如我所说,这种方法是相当粗糙的。 从我对Live Messenger的回忆中,听起来像是在尝试做渐变,这可以在Windows Presentation Foundation(WPF,.NET 3.0的一部分)中非常容易地应用。 WPF支持许多不同types的渐变画笔,包括线性和径向渐变。
我强烈推荐Adam Nathan的书“ Windows Presentation Foundation Unleashed”,作为对WPF的一个很好的深入介绍。
HTH
在HSL / HSV中,颜色的任何变化都会更好。
一个好的testing是在RGB空间和HSL空间的两个等价值之间进行插值。 HSL空间的坡道看起来像一个自然的进展。 在RGB空间中,它通常看起来很不自然。 HSL比RGB更好地映射到我们的视觉色彩空间感知。
转换到HSV或其他色彩空间的想法看起来不错,而且对于精确的色彩工作可能是必要的,但是对于普通的目的来说,在RGB中工作的误差可能不够重要。 另外,处理边界情况可能会很痛苦:RGB是立方体空间,而HSV不是。 如果使用字节值,则可以在空格之间进行多对一和一对多的映射。 这可能会或可能不会成为一个问题取决于应用程序。 因人而异
本网站指出,您可以在BCL C#System.Windows.Forms命名空间中使用ControlPaint类。