エントリー
ご存知のように、Windows Mobileデバイスでは、配色を変更する可能性があります。 アプリケーションがグラフィック要素を使用しない場合は、SystemColorsクラスが提供する色のセットを使用するだけで、アプリケーションが現在のスキームと一致します。 最も一般的に使用されるものの中で、ActiveCaption、ActiveCaptionText、InactiveCaption、InactiveCaptionText、WindowTextなどに言及するのは理にかなっています。 また、作業の準備ができたブラシを提供するSystemBrushesクラスを忘れないでください-コンストラクターなどを呼び出す必要はありません。
しかし、現在の配色に一致する必要がある一連の画像がある場合はどうすればよいでしょうか? すべての原色の画像セットを作成することは本当に可能ですか?
これは最善の解決策ではありません。ベースイメージに変更がある場合、同じイメージのすべてのバージョンを異なるシェードで再作成する必要があります。
それで、何が残っていますか? 明らかに、「オンザフライ」で基本イメージを何らかの形で変換する必要があります。 カラースキームの最も重要なコンポーネントは、 HKLM \ Software \ Microsoft \ ColorのレジストリのDWORD変数BaseHueに含まれていることが知られています。 値が0〜255の範囲にある場合、グレーのグラデーションがあります。 256〜510が主な虹です:)さまざまなトピックがこの変数に「何でも」を入れることが実験的に確立されています。 0..510の範囲を大幅に超える値。 その結果、正直なBaseHueを取得するには、次の関数を使用します。
private const String BASEHUE_PATH = "HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Color" ;
public static int GetBaseHue()
{
object baseHue = Registry.GetValue(BASEHUE_PATH, "BaseHue" , 0);
int bh = baseHue == null ? 0: ( int )baseHue;
if (bh < 255)
return bh;
else
return (bh & 0xFF) + 255;
}
* This source code was highlighted with Source Code Highlighter .
BaseHueの本当の意味については、 HSLカラースペースをご覧ください。
つまり、BaseHueの値が0〜255の場合、グレーのグラデーションがあるため、彩度は0になります(つまり、グレースケール画像が保証されます)。 256から510の範囲の場合、必要に応じて飽和度はすでに自由裁量です。 私は255に満足しています。 最大カラー画像。 次に説明しますが、ここでは飽和状態です。
問題は、画像がRGBモデルに保存され、BaseHueがRGBとは何の関係もないということです。 その結果、ベース画像を「色付け」するにはRGB-> HSL変換を実行し、次にピクセルの実際の色を取得するには逆HSL-> RGB変換を実行する必要があることがわかりました。
例としてチェックボックス付きのボタンの適用
したがって、チェックボックス付きのグラフィックボタンの例を使用してアクションのシーケンスを分析し、非アクティブなボタンからアクティブなボタンを作成し、現在のカラースキームと調和します。 非アクティブなボタンの事前に準備された画像を取得します。 ボタンには透明なゾーンがあり、マゼンタ色で、隅に見えることがわかります。
図1オリジナル
最初の変換-ボタン全体を指定されたBaseHue(私の場合は391)に移動します。
図2変換後
それは不運です、透明度の原因となる角のピクセルも色が変わりました! 結果の画像を調べて正義を復元しましょう(元の画像をソートして、そこに透明なピクセルを見つけます):
図3復元された「透明」ピクセル
はい、透明度は今では大丈夫ですが、その下のチェックマークとボックスはあまりにもurtいです。 正義を追加します。
図4復元されたチェックボックス領域
この文章は、おそらく前の文章ほど簡単ではありません。 これはどのように行われましたか?
よく見ると、一般的に、チェックボックスのないボタン画像が繰り返されていることは明らかです(角のあるフィレットを除く)。 そして、まったく同じ素材がチェックボックスの下にあります。 結論は何ですか? 「空の」背景と、この背景の上にチェックボックスがある部分とを比較する機会があり、R、G、またはBの不一致が特定の定数を超えている場合(簡単な検索で25を得た)、色付きの画像でピクセルを元のピクセルに置き換えることができます。
しきい値を使用せずに元の「額」をカットしようとする場合の例を次に示します。
図5しきい値を考慮せずに復元されたチェックボックス領域
いくつかのコード
実装の複雑さについて。 Compact Frameworkには、RGB <-> HSLについての言葉はありません。 グーグルですばやく変換すると、変換に関する問題が解決されました-RGB <-> HSL 。 しかし、コンバージョン率の問題はすぐには解決しませんでした。 ご存知のように、マネージコードはグラフィックスを扱う際に高速ではありません。 GetPixelは非常に遅いです。 しかし、このために解決策が見つかりました。 操作可能なピクセル操作のためのUnsafeBitmapに関する優れた投稿が、Windows Mobile MSDNブログに見つかりました。
以下は、UnsafeBitmapを使用して、指定された色相、彩度、明度で画像を十分にすばやくペイントする関数です。
public static Bitmap ApplyHueSaturation( Bitmap input, int hue, int sat, int brightness)
{
if (input == null )
return null ;
ColorHandler.RGB rgb;
ColorHandler.HSV hsv;
UnsafeBitmap ibmp = new UnsafeBitmap(input);
UnsafeBitmap obmp = new UnsafeBitmap( new Bitmap (input.Width, input.Height));
ibmp.LockBitmap();
obmp.LockBitmap();
for ( int y = 0; y < input.Height; y++)
{
for ( int x = 0; x < input.Width; x++)
{
UnsafeBitmap.PixelData c = ibmp.GetPixel(x, y);
rgb.Red = c.red;
rgb.Blue = c.blue;
rgb.Green = c.green;
hsv = ColorHandler.RGBtoHSV(rgb);
hsv.Hue = hue;
hsv.Saturation = sat;
hsv. value += brightness;
if (hsv. value > 255)
hsv. value = 255;
if (hsv. value < 0)
hsv. value = 0;
ColorHandler.RGB r = ColorHandler.HSVtoRGB(hsv);
obmp.SetPixel(x, y, ( byte )r.Red, ( byte )r.Green, ( byte )r.Blue);
}
}
obmp.UnlockBitmap();
ibmp.UnlockBitmap();
return obmp. Bitmap ;
}
* This source code was highlighted with Source Code Highlighter .
実例はここからダウンロードできます 。
PS。:現実の作業速度は想像を超えるものではありませんが、変換は一度だけ行います。その後、大胆にキャッシュします。VGA解像度の背景全体であっても、小さなファイルの利点は常に得られます。
PSS。:はい。パフォーマンスを最適化するために変換する場合、もちろん、透明なピクセルをすぐに無視して、画像の不要な列挙を回避できます。 同様の手順は、説明のみを目的として示されています。
UPD:現在のレイアウトに画像を適合させるだけでは不十分です;また、それらを正しく表示する必要があります。 丸みを帯びたエッジは紫色の角のままになります :) Compact Frameworkでのグラフィックスの操作に関するシリーズの続きをお読みください。