Skip to content

Instantly share code, notes, and snippets.

@adamgraham
Last active June 21, 2021 22:47
Show Gist options
  • Save adamgraham/5c7cb9c3b775622fc7d24cbf23b18456 to your computer and use it in GitHub Desktop.
Save adamgraham/5c7cb9c3b775622fc7d24cbf23b18456 to your computer and use it in GitHub Desktop.
An extension of the iOS class UIColor to provide conversion to and from YUV colors.
/// An extension to provide conversion to and from Y′UV colors.
extension UIColor {
/// The Y′UV components of a color - luma (Y′) and chroma (U,V).
struct YUV: Hashable {
/// The luma component of the color, in the range [0, 1] (black to white).
var Y: CGFloat
/// The blue-difference chroma component of the color, in the range [-0.436, 0.436].
var U: CGFloat
/// The red-difference chroma component of the color, in the range [-0.615, 0.615].
var V: CGFloat
}
/// Constant values used to convert to and from Y′UV 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 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′UV components of the color using Rec.601 (standard-definition) encoding.
var yuv: YUV {
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))
return YUV(Y: Y, U: U, V: V)
}
/// Initializes a color from Y′UV components.
/// - parameter yuv: The components used to initialize the color.
/// - parameter alpha: The alpha value of the color.
convenience init(_ yuv: YUV, alpha: CGFloat = 1.0) {
let Y = yuv.Y
let U = yuv.U
let V = yuv.V
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