[英]How do I determine darker or lighter color variant of a given color?
给定系统或用户的任何色调的源颜色,我想要一个简单的算法,我可以使用它来计算出所选颜色的更浅或更深的变体。 类似于在 Windows Live Messenger 上用于设置用户界面样式的效果。
语言是带有 .net 3.5 的 C#。
回应评论:颜色格式为(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,根据亮度添加/减去值,然后转换回 System.Drawing.Color 以在您的应用程序中使用。
您可以将您的颜色转换为 HSL 颜色空间,在那里对其进行操作并转换回您选择的颜色空间(很可能是 RGB)
颜色越浅,L 值越高,颜色越深,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 - 它全为零,使数学更容易。
我省略了一些细节,例如将结果转换回字节,这可能是您想要做的。
如果您使用的是 RGB 颜色,我会将这些颜色参数转换为HSL (色调、饱和度、亮度),修改亮度参数,然后再转换回 RGB。 谷歌一下,你会发现很多关于如何进行这些颜色表示转换(RGB 到 HSL,反之亦然)的代码示例。
这是我很快发现的: http : //bytes.com/forum/thread250450.html
本网站指出,您可以在 BCL C# System.Windows.Forms 命名空间中使用 ControlPaint 类。
假设您将颜色设为 RGB,首先将其转换为 HSV(色调、饱和度、值)颜色空间。 然后增加/减少该值以产生更浅/更深的颜色阴影。 然后转换回RGB。
如果您的颜色是 RGB 格式(或者,大概是 CMYK),您可以使用相当粗略的方法来增加颜色的每个分量的值。 例如,在 HTML 中,颜色表示为三个两位的十六进制数字。 #ff0000 会给你一个亮红色,然后可以通过将 G 和 B 组件的值增加相同的数量来淡化,例如#ff5555(给出更浅的红色)。 大概对于色相、饱和度和亮度 (HSL) 颜色,您可以只提高 L 分量,但我不能肯定; 我对这个色彩空间不太熟悉。
不过,正如我所说,这种方法非常粗糙。 根据我对 Live Messenger 的记忆,听起来您正在尝试进行渐变,这在 Windows Presentation Foundation(WPF,.NET 3.0 的一部分)中可以非常轻松地应用。 WPF 支持许多不同类型的渐变画笔,包括线性渐变和径向渐变。
我强烈推荐 Adam Nathan 的书Windows Presentation Foundation Unleashed作为对 WPF 的一个很好的全面介绍。
HTH
在 HSL/HSV 中可以更好地完成颜色的任何变化。
一个很好的测试是在 RGB 空间和 HSL 空间中的两个等效值之间进行插值。 HSL 空间的斜坡看起来是一个自然的过程。 在 RGB 空间中,它通常看起来很不自然。 HSL 映射到我们的视觉色彩空间感知比 RGB 好得多。
转换为 HSV 或其他一些颜色空间的想法似乎不错,并且对于精确的颜色工作可能是必要的,但对于普通目的,在 RGB 中工作的错误可能还不够重要。 此外,处理边界情况可能会很痛苦:RGB 是一个立方体形状的空间,而 HSV 不是。 如果使用字节值,则可以在空间之间进行多对一和一对多映射。 这可能是也可能不是问题,具体取决于应用程序。 青年会
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.