Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to compute color contrast ratio between two UIColor instances

Tags:

ios

swift

uicolor

I'm looking for a concise way to compute the color contrast ratio between two UIColor instances in Swift. I've found examples that are close but are overly complicated or outdated.

like image 353
Mobile Dan Avatar asked Feb 20 '17 23:02

Mobile Dan


1 Answers

UIColor extension with contrast ratio and luminance

The following UIColor extension includes a static and instance contrast ratio method. A bonus luminance method is included since it is used by the static contrastRatio(between:and:) method.

import UIKit

extension UIColor {

    static func contrastRatio(between color1: UIColor, and color2: UIColor) -> CGFloat {
        // https://www.w3.org/TR/WCAG20-TECHS/G18.html#G18-tests

        let luminance1 = color1.luminance()
        let luminance2 = color2.luminance()

        let luminanceDarker = min(luminance1, luminance2)
        let luminanceLighter = max(luminance1, luminance2)

        return (luminanceLighter + 0.05) / (luminanceDarker + 0.05)
    }

    func contrastRatio(with color: UIColor) -> CGFloat {
        return UIColor.contrastRatio(between: self, and: color)
    }

    func luminance() -> CGFloat {
        // https://www.w3.org/TR/WCAG20-TECHS/G18.html#G18-tests

        let ciColor = CIColor(color: self)

        func adjust(colorComponent: CGFloat) -> CGFloat {
            return (colorComponent < 0.04045) ? (colorComponent / 12.92) : pow((colorComponent + 0.055) / 1.055, 2.4)
        }

        return 0.2126 * adjust(colorComponent: ciColor.red) + 0.7152 * adjust(colorComponent: ciColor.green) + 0.0722 * adjust(colorComponent: ciColor.blue)
    }
}

Example Use

// static method
let contrastRatio1 = UIColor.contrastRatio(between: UIColor.black, and: UIColor.white)
print(contrastRatio1) // 21.0

// instance method
let contrastRatio2 = UIColor.black.contrastRatio(with: UIColor.white)
print(contrastRatio2) // 21.0

Note

Following these links:

  • https://www.w3.org/TR/css-color-4/#predefined
  • https://github.com/dequelabs/axe-core/issues/1629#issuecomment-509880306

For predefinite colorspace (like in iOS see this https://developer.apple.com/videos/play/wwdc2016/712/) and also in general the correct THRESHOLD value is 0.04045 and not 0.03928 (read more)

like image 116
Mobile Dan Avatar answered Nov 15 '22 19:11

Mobile Dan