2014/02/14

非.NET4.5でもトースト通知(補足)

トースト通知のテストアプリではトーストの文字色(=ショートカットのタイルの文字色)を背景色に応じて自動選択する形にしましたが、このアルゴリズムが色によっては今一つだったので、変えてみました。

1. アルゴリズム

MSDNの「デスクトップアプリのスタート画面のタイルをカスタマイズする方法」では、トーストの文字色と背景色の輝度の比率を4.5以上にすべしとしています。これは以下のW3Cのアクセシビリティガイドラインに従ったものです。
このガイドラインに色の輝度(relative luminance)とコントラスト比率(contrast ratio)の計算方法が示されているので、これを利用します。

まず色の輝度について、RGBの各色を以下のように数値化します。
private static double CalcColorChannel(byte channel)
{
    var buff = (double)channel / 255d;

    if (buff <= 0.03928)
        return (buff / 12.92);
    else
        return Math.Pow((buff + 0.055) / 1.055, 2.4);
}
これを元に各色に加重を掛けて輝度を計算します。どうせなのでColorの拡張メソッドにしてみました。
public static double GetLuminance(this Color source)
{
    var r = CalcColorChannel(source.R);
    var g = CalcColorChannel(source.G);
    var b = CalcColorChannel(source.B);

    return 0.2126 * r + 0.7152 * g + 0.0722 * b;
}
この輝度の範囲は0(最も暗い場合)~1(最も明るい場合)になります。

次に2つの輝度からコントラスト比率を計算するには以下のようにします。明るい輝度の方が常に分子。
private double GetContrastRatio(double luminance1, double luminance2)
{
    if (luminance1 > luminance2)
        return (luminance1 + 0.05) / (luminance2 + 0.05);
    else
        return (luminance2 + 0.05) / (luminance1 + 0.05);
}
これらを使って、文字色のlight(白)とdark(黒)のそれぞれと背景色(background)とのコントラスト比率を計算し、より高い方を選択するようにします。戻り値は定義済みのForegroundColorType列挙型にしました。
internal ForegroundColorType GetHigherContrastColor(Color background)
{
    var luminanceLight = 1d; // = Colors.White.GetLuminance()
    var luminanceDark = 0d;  // = Colors.Black.GetLuminance()
    var luminanceBackground = background.GetLuminance();

    var ratioLight = GetContrastRatio(luminanceLight, luminanceBackground);
    var ratioDark = GetContrastRatio(luminanceDark, luminanceBackground);

    return (ratioLight >= ratioDark) ? ForegroundColorType.light : ForegroundColorType.dark;
}
2. テスト

前の方法ではとくに青系の色が苦手で、暗い色でもdark(黒)が選択されていました。

これがlight(白)が選択されるようになります。

他の色でも大体問題なさそうだったので、テストアプリを差し替えました。
実行ファイル
ソースコード

3. 輝度

参考までに、既定の16色の輝度を同じアルゴリズムで計算すると以下のようになります。
  •  black : 0 
  •  silver : 0.527 
  •  gray : 0.216 
  •  white : 1 
  •  maroon : 0.046 
  •  red : 0.213 
  •  purple : 0.061 
  •  fuchsia : 0.285 
  •  green : 0.154 
  •  lime : 0.715 
  •  olive : 0.200 
  •  yellow : 0.928 
  •  navy : 0.016 
  •  blue : 0.072 
  •  teal : 0.167 
  •  aqua : 0.787 
感覚的に合うような合わないような……色は難しいです。

0 コメント :