[英]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.