// Copyright © 2022 Rangeproof Pty Ltd. All rights reserved. import UIKit.UIColor public extension UIColor { private func clamp(_ value: CGFloat, _ minValue: CGFloat, _ maxValue: CGFloat) -> CGFloat { return max(minValue, min(maxValue, value)) } private func clamp01(_ value: CGFloat) -> CGFloat { return clamp(value, 0, 1) } private func lerp(_ left: CGFloat, _ right: CGFloat, _ alpha: CGFloat) -> CGFloat { return ((left * (1 - alpha)) + (right * alpha)) } func toImage() -> UIImage { let bounds: CGRect = CGRect(x: 0, y: 0, width: 1, height: 1) let renderer: UIGraphicsImageRenderer = UIGraphicsImageRenderer(bounds: bounds) return renderer.image { rendererContext in rendererContext.cgContext.setFillColor(self.cgColor) rendererContext.cgContext.fill(bounds) } } func blend(with otherColor: UIColor, alpha: CGFloat) -> UIColor { var r0: CGFloat = 0 var g0: CGFloat = 0 var b0: CGFloat = 0 var a0: CGFloat = 0 self.getRed(&r0, green: &g0, blue: &b0, alpha: &a0) var r1: CGFloat = 0 var g1: CGFloat = 0 var b1: CGFloat = 0 var a1: CGFloat = 0 self.getRed(&r1, green: &g1, blue: &b1, alpha: &a1) let finalAlpha: CGFloat = clamp01(alpha) return UIColor( red: lerp(r0, r1, finalAlpha), green: lerp(g0, g1, finalAlpha), blue: lerp(b0, b1, finalAlpha), alpha: lerp(a0, a1, finalAlpha) ) } func brighten(by percentage: CGFloat) -> UIColor { guard percentage != 0 else { return self } var hue: CGFloat = 0 var saturation: CGFloat = 0 var brightness: CGFloat = 0 var alpha: CGFloat = 0 // Note: Looks like as of iOS 10 devices use the kCGColorSpaceExtendedGray color // space for grayscale colors which seems to be compatible with the RGB color space // meaning we don't need to check 'getWhite:alpha:' if the below method fails, for // more info see: https://developer.apple.com/documentation/uikit/uicolor#overview guard self.getHue(&hue, saturation: &saturation, brightness: &brightness, alpha: &alpha) else { return self } return UIColor( hue: hue, saturation: saturation, brightness: (brightness + percentage), alpha: alpha ) } }