システムまたはユーザーによる色相のソースカラーを前提として、選択したカラーの明るいまたは暗いバリエーションを計算するために使用できる簡単なアルゴリズムが欲しいのですが。ユーザーインターフェイスのスタイルを設定するためにWindows Live Messengerで使用される効果に似ています。
言語は.net 3.5のC#です。
コメントへの対応:カラー形式は(Alpha)RGBです。バイトまたはフロートとしての値。
マーキングの回答:私の使用のコンテキスト(いくつかの単純なUI効果)の場合、私が承認済みとしてマークしている回答は、実際にはこのコンテキストで最も単純です。しかし、私はもっと複雑で正確な答えにも投票をあきらめました。より高度なカラー操作を行い、将来このスレッドを見つける人は、間違いなくそれらをチェックしてください。どうもありがとう。 :)
RGB値に、レベルを変更する量を掛けるだけです。いずれかの色が既に最大値になっている場合、それを明るくすることはできません(とにかくHSV演算を使用します)。
これにより、HSVに切り替えてからVを変更する場合と比べて、計算がはるかに少ないまったく同じ結果が得られます。これにより、飽和を失い始めない限り、HSLに切り替えてLを変更した場合と同じ結果が得られます。
XNAにはColor.Lerp
静的メソッド これは、2つの色の違いとしてこれを行います。
Lerp
は、2つの浮動小数点数の間の数学的演算であり、最初の値をそれらの差の比率で変更します。
float
に対してそれを行う拡張メソッドは次のとおりです。
public static float Lerp( this float start, float end, float amount)
{
float difference = end - start;
float adjusted = difference * amount;
return start + adjusted;
}
したがって、RGBを使用した2色間の単純な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] = (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;
}
リッチニューマン HSLカラーについて議論する 彼のブログの.NET System.Drawing.Colorについて 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()を使用しました。
RGBをバイト値(0〜255)で使用していると思いますが、それはどこでも非常に一般的であるためです。
明るくするには、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に変換します。 Googleの周りには、これらの色表現変換(RGBからHSLへ、またはその逆)を行う方法に関するコードサンプルが多数あります。
これは私がすぐに見つけたものです: http://bytes.com/forum/thread250450.html
HSVまたは他の色空間に変換するという考えは適切であるように思われ、正確な色の作業には必要かもしれませんが、通常の目的では、RGBでの作業のエラーは問題になるほど十分ではない場合があります。また、境界の場合に対処するのは面倒です。RGBは立方体の空間ですが、HSVはそうではありません。バイト値を使用する場合、スペース間に多対1および1対多のマッピングを設定できます。これは、アプリケーションに応じて問題になる場合と問題にならない場合があります。 YMMV
色をRGBとして取得する場合、最初にHSV(色相、彩度、明度)色空間に変換します。次に、値を増減して、色の色合いを明るく/暗くします。次に、RGBに変換し直します。
色がRGB形式(おそらくCMYK)である場合、色の各コンポーネントの値を増加させるかなり粗い方法を使用できます。たとえば、HTMLの色は3つの2桁の16進数として表されます。 #ff0000を使用すると明るい赤が得られます。GとBのコンポーネントの値を#ff5555などの同じ量だけ増やすと、色を薄くすることができます(明るい赤になります)。おそらく色相、彩度、明度(HSL)の色については、Lコンポーネントを上げるだけで十分ですが、はっきりとは言えません。私はこの色空間に慣れていません。
しかし、私が言うように、この方法はかなり粗雑です。私のLive Messengerの思い出から、グラデーションを実行しようとしているように思えます。グラデーションは、Windows Presentation Foundation(WPF、.NET 3.0の一部)で非常に簡単に適用できます。 WPFは、線形グラデーションや放射状グラデーションなど、さまざまな種類のグラデーションブラシをサポートしています。
アダムネイサンの本 Windows Presentation Foundation Unleashed をWPFの入門書として強くお勧めします。
HTH
この website は、BCL C#System.Windows.Forms名前空間内でControlPaintクラスを使用できることを示しています。
色の変化はHSL/HSVで行う方が適切です。
良いテストは、RGB空間とHSL空間の2つの同等の値の間を補間することです。 HSL空間の傾斜は自然な進行のように見えます。 RGB空間では、通常、かなり不自然に見えます。 HSLは、RGBよりもはるかに優れた視覚的な色空間知覚にマッピングされます。