给定系统或用户的任何色调的源颜色,我想要一个简单的算法,我可以用来计算所选颜色的较浅或较暗的变体.与Windows Live Messenger上用于为用户界面设置样式的效果类似.
语言是C#,.net 3.5.
回应评论:颜色格式为(Alpha)RGB.值为字节或浮点数.
标记答案:对于我使用的上下文(一些简单的UI效果),我标记为已接受的答案实际上是此上下文中最简单的.但是,我已经放弃了对更复杂和准确答案的投票.任何进行更高级颜色操作并在将来找到此线程的人都应该检查出来.谢谢你.:)
在XNA中,有一种Color.Lerp
静态方法可以将两者作为两种颜色之间的区别.
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 );
只需将RGB值乘以您想要修改级别的数量即可.如果其中一种颜色已经达到最大值,则无法使其更亮(无论如何使用HSV数学).
这样可以得到完全相同的结果,只需要更少的数学运算,即切换到HSV然后修改V.这样可以提供与切换到HSL然后修改L相同的结果,只要您不想开始失去饱和度.
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] = (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; }
Rich Newman 在他的博客上讨论了关于.NET System.Drawing.Color的HSL颜色,甚至还提供了一个HSLColor类,它可以为您完成所有工作.将System.Drawing.Color转换为HSLColor,根据Luminosity添加/减去值,然后转换回System.Drawing.Color以在您的应用中使用.
您可以将颜色转换为HSL颜色空间,在那里进行操作并转换回您选择的颜色空间(很可能是RGB)
较浅的颜色具有较高的L值,较暗的颜色较低.
这是相关的东西和所有方程式:
http://en.wikipedia.org/wiki/HSL_color_space
另一种方法是简单地用白色或黑色插入颜色.这也会使颜色去饱和,但计算起来会更便宜.
我在System.Windows.Forms中使用了ControlPaint.Dark()和.Light().
我猜您正在使用带字节值(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-全为零,使数学运算更容易。
我省略了一些细节,例如将结果转换回字节,这可能是您想要的。