WPFで影の色が思い通りにならない問題と対策

.NET Core, .NET Framework, C#, scRGB, WPF, ガンマ補正

もくじ

問題となる現象

WPFでは,DropShadowEffectのColorプロパティに指定した色がそのまま影の色に反映される訳ではなく,暗めの色に変換されてから表示される。

次の例は,このサイトのテーマカラーである #169632 の色を,WPF上で四角形(Border)とそのDropShadowEffectの両方に設定したもののキャプチャ画像だ。

同じ色を設定したにも関わらず,四角形と影とで実際の色が異なる。

四角形には正確に色が反映されているが,影は暗めに調整されてしまっている。

いつも暗めに調整されるかというとそうでもなく,白(#FFFFFF)に設定すると実際の影の色も真っ白になるからますます訳が分からない。

これでは色の微調整が正確に行えない。

原因

DropShadowEffectのColorプロパティに設定された色は内部で勝手にscRGB色空間に変換されている。

具体的にどのような変換かというと,R,G,Bそれぞれに対してガンマ補正がかけられている。

下の図の,「CRT gamma 2.2」と書かれている,下にカーブした曲線になるように値が変換されているのだ。

これによりほとんどの色は暗めに変換されるが,真っ白の場合は真っ白のまま,真っ黒の場合は真っ黒のままという不思議な挙動となっていた。

対策

ガンマ補正がかけられるのなら,それを見越した色に設定すればよい。

例えば,先ほどの例で四角形に対して #169632 を設定した場合は,影に対して #53CA7A を設定すると同じ色として表示される。

こんな風に。

これで,影の色を思い通りに設定できるようになる。

・・・でも,どうやって?

WPFでは難しい計算を考える必要はない。

Color構造体のFromScRgbメソッドを使って次のようにすれば影に設定すべき色が得られる。

// 四角形に設定する色
Color rectColor = Color.FromRgb(22, 150, 50);
// 影に設定する色
Color shadowColor = Color.FromScRgb(1.0f, rectColor.R/255.0f, rectColor.G/255.0f, rectColor.B/255.0f);

コードビハインドやViewModelクラス内にこの処理を記述すると問題がある場合は,この処理を行うコンバーターを作成し,XAML内で利用すればよい。

コンバーターの作り方についてはこちらで説明している。