特定の色の濃いカラーバリエーションまたは明るいカラーバリエーションを決定するにはどうすればよいですか?
質問
システムまたはユーザーによって任意の色相のソース カラーが与えられた場合、選択した色の明るいまたは暗いバリエーションを計算するために使用できるシンプルなアルゴリズムが必要です。Windows Live Messenger でユーザー インターフェイスのスタイルを設定するために使用される効果に似ています。
言語は.net 3.5のC#です。
コメントへの返信: カラーフォーマットは(Alpha)RGBです。バイトまたは浮動小数点数としての値。
答えを採点する: 私の使用のコンテキスト (いくつかの単純な UI 効果) では、私が受け入れ済みとしてマークしている答えが、実際にはこのコンテキストでは最も単純です。ただし、より複雑で正確な回答への投票も放棄しました。より高度なカラー操作を行う人で、今後このスレッドを見つける人は、必ずチェックしてください。ありがとうSO。:)
解決
RGB 値にレベルを変更したい量を掛けるだけです。色の 1 つがすでに最大値にある場合、それをさらに明るくすることはできません (とにかく 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 値が高く、暗いほど L 値が低くなります。
関連するものとすべての方程式は次のとおりです。
http://en.wikipedia.org/wiki/HSL_color_space
もう 1 つの方法は、単純に白または黒で色を補間することです。これにより色の彩度も少し下がりますが、計算コストが安くなります。
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 を使用します。これはすべて 0 なので、計算が簡単になります。
結果をバイトに変換し直すなどの詳細は省略しますが、これはおそらく実行したいと思われます。
RGB カラーを使用している場合、このカラーパラメータを次のように変換します。 HSL (色相、彩度、明度)、明度パラメータを変更してから、RGB に変換し直します。Google で検索すると、これらの色表現変換 (RGB から HSL、またはその逆) を行う方法に関するコード サンプルがたくさん見つかります。
すぐに見つけたのは次のとおりです。http://bytes.com/forum/thread250450.html
カラーを RGB として取得すると仮定して、まずそれを HSV (色相、彩度、明度) 色空間に変換します。次に、値を増減して、色の明るい/暗い色合いを生成します。次に、RGB に変換し直します。
カラーが RGB フォーマット (または、おそらく CMYK) である場合は、カラーの各コンポーネントの値を増やすというかなり大雑把な方法を使用できます。たとえば、HTML では、色は 3 つの 2 桁の 16 進数として表されます。#ff0000 は明るい赤を与えます。#ff5555 (明るい赤を与えます) のように、G コンポーネントと B コンポーネントの値を同じ量だけ増やすことで色を薄くすることができます。おそらく、色相、彩度、明度 (HSL) 色の場合は、L コンポーネントを上げるだけで済みますが、確実なことは言えません。私はこの色空間についてあまり詳しくありません。
ただし、何度も言いますが、この方法は非常に大雑把です。Live Messenger に関する私の記憶によると、グラデーションを実行しようとしているように思えますが、これは Windows Presentation Foundation (WPF、.NET 3.0 の一部) で非常に簡単に適用できます。WPF は、線形グラデーションや放射状グラデーションなど、さまざまな種類のグラデーション ブラシをサポートしています。
アダム・ネイサンの本を強くお勧めします Windows プレゼンテーション ファウンデーションが解き放たれる WPF の優れた完全な入門書として役立ちます。
HTH
色のバリエーションはすべて HSL/HSV で行う方がよいでしょう。
良いテストは、RGB 空間と HSL 空間の 2 つの同等の値の間を補間することです。HSL 空間のランプは自然な経過のように見えます。RGB 空間では、通常、非常に不自然に見えます。HSL は、RGB よりもはるかに優れた視覚的な色空間認識にマッピングされます。
HSV または他の色空間に変換するというアイデアは良いように思えますし、正確な色の作業には必要かもしれませんが、通常の目的では、RGB での作業の誤差は問題になるほど十分ではないかもしれません。また、境界ケースに対処するのは面倒な場合があります。RGB は立方体状の空間ですが、HSV は立方体ではありません。バイト値を扱う場合は、スペース間に多対 1 および 1 対多のマッピングを行うことができます。これはアプリケーションによっては問題になる場合もあれば、問題にならない場合もあります。YMMV
これ Webサイト BCL C# System.Windows.Forms 名前空間内で ControlPaint クラスを使用できることに注意してください。