酢ろぐ!

カレーが嫌いなスマートフォンアプリプログラマのブログ。

Swiftで 背景色に応じた見やすい文字色を求める

ユーザーがタグ色を選択できるプロダクトの場合、ユーザーが決めた色の上にテキストを配置しなければいけない。たとえば、下図の GitHub のタグのような場合である。

背景色に応じて、視認しやすいテキストカラーが利用されていることがわかる。

  • enhancement の背景色は #b5f0f2 で、テキスト色は黒色
  • task の背景色は #2b76db で、テキスト色は白色

当初は YCbCr や HSV の輝度を使って判断しようと考えていたが、調査を進めたところ、背景色に応じた見やすい文字色を求めるには WCAG 2.0 を利用するのが良いことがわかった。

背景色に応じて見やすい文字色を求める

元ネタの C# 版を Swift版に書き換えた。

import UIKit

struct ColorUtils {

    static func relativeLuminance(_ color: CGColor) -> CGFloat {
        let sRGBColorSpace = CGColorSpace(name: CGColorSpace.extendedSRGB)!
        let sRGB = color.converted(
            to: sRGBColorSpace,
            intent: .defaultIntent,
            options: nil)!
            .components!
        let adjusted = sRGB.map { (c) -> CGFloat in
            if c <= 0.03928 {
                return c / 12.92
            } else {
                return pow((c + 0.055)/1.055, 2.4)
            }
        }
        return 0.2126 * adjusted[0] +
            0.7152 * adjusted[1] +
            0.0722 * adjusted[2]
    }

    static func foregroundTextColor(_ background: UIColor) -> UIColor {
        // 背景色の相対輝度
        let background = relativeLuminance(background.cgColor)

        // 黒文字と白文字の判定に使う相対輝度境界値
        let border: CGFloat = 0.17912878474779

        // 背景色の相対輝度が境界値以上なら黒文字、未満なら白文字
        return background >= border ? UIColor.black : UIColor.white
    }
}

参考記事