Skip to content

Instantly share code, notes, and snippets.

@adamgraham
Last active May 29, 2019 04:27
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save adamgraham/0df350dc1eba1ee90f401911ccaff153 to your computer and use it in GitHub Desktop.
Save adamgraham/0df350dc1eba1ee90f401911ccaff153 to your computer and use it in GitHub Desktop.
An extension of the iOS class UIColor to provide conversion to and from YIQ colors.
/// An extension to provide conversion to and from Y′IQ colors.
extension UIColor {
/// The Y′IQ components of a color - luma (Y′) and chroma (I,Q).
struct YIQ: Hashable {
/// The luma component of the color, in the range [0, 1] (black to white).
var Y: CGFloat
/// The orange-blue chroma component of the color, in the range [-0.596, 0.596].
var I: CGFloat
/// The purple-green chroma component of the color, in the range [-0.523, 0.523].
var Q: CGFloat
}
/// Constant values used to convert to and from Y′IQ colors.
private struct Constant {
/// The Rec.601 (standard-definition) coefficients used to calculate luma.
static let encoding: (r: CGFloat, g: CGFloat, b: CGFloat) = (0.299, 0.587, 0.114)
/// The cosine of 33°.
static let cos33: CGFloat = cos(.pi * 33.0 / 180.0)
/// The sine of 33°.
static let sin33: CGFloat = sin(.pi * 33.0 / 180.0)
/// The maximum value of the U component.
static let Umax: CGFloat = 0.436
/// The maximum value of the V component.
static let Vmax: CGFloat = 0.615
}
/// The Y′IQ components of the color using Rec.601 (standard-definition) encoding.
var yiq: YIQ {
var (r, g, b) = (CGFloat(), CGFloat(), CGFloat())
getRed(&r, green: &g, blue: &b, alpha: nil)
let k = Constant.encoding
let Y = (k.r * r) + (k.g * g) + (k.b * b)
let U = Constant.Umax * ((b - Y) / (1.0 - k.b))
let V = Constant.Vmax * ((r - Y) / (1.0 - k.r))
let I = -(U * Constant.sin33) + (V * Constant.cos33)
let Q = (U * Constant.cos33) + (V * Constant.sin33)
return YIQ(Y: Y, I: I, Q: Q)
}
/// Initializes a color from Y′IQ components.
/// - parameter yiq: The components used to initialize the color.
/// - parameter alpha: The alpha value of the color.
convenience init(_ yiq: YIQ, alpha: CGFloat = 1.0) {
let Y = yiq.Y
let U = -(yiq.I * Constant.sin33) + (yiq.Q * Constant.cos33)
let V = (yiq.I * Constant.cos33) + (yiq.Q * Constant.sin33)
let k = Constant.encoding
let kr = (V * ((1.0 - k.r) / Constant.Vmax))
let kgb = (U * ((k.b * (1.0 - k.b)) / (Constant.Umax * k.g)))
let kgr = (V * ((k.r * (1.0 - k.r)) / (Constant.Vmax * k.g)))
let kb = (U * ((1.0 - k.b) / Constant.Umax))
let r = Y + kr
let g = Y - kgb - kgr
let b = Y + kb
self.init(red: r, green: g, blue: b, alpha: alpha)
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment