Skip to content

Instantly share code, notes, and snippets.

@HT154
Created June 6, 2017 17:00
Show Gist options
  • Save HT154/816de03a83155c7847802b7b5dc85b00 to your computer and use it in GitHub Desktop.
Save HT154/816de03a83155c7847802b7b5dc85b00 to your computer and use it in GitHub Desktop.
Realm Color Extension
import Foundation
import RealmSwift
import SpriteKit
public typealias Color = Int64
public extension Color {
public static let white = Color(0xffffffff)
public static let black = Color(0x000000ff)
public static let clear = Color(0x00000000)
public static let red = Color(0xff0000ff)
public static let green = Color(0x00ff00ff)
public static let blue = Color(0x0000ffff)
static let bitmapInfo = CGImageAlphaInfo.premultipliedLast.rawValue | CGBitmapInfo.byteOrder32Little.rawValue
private var uint: UInt32 {
get { return UInt32(truncatingBitPattern: self) }
set { self = Int64(exactly: newValue)! }
}
public init(_ r: UInt8, _ g: UInt8, _ b: UInt8, _ a: UInt8 = 0xff) {
self.init((UInt32(r) << 24) | (UInt32(g) << 16) | (UInt32(b) << 8) | (UInt32(a) << 0))
}
public init(_ color: SKColor) {
var r: CGFloat = 0
var g: CGFloat = 0
var b: CGFloat = 0
var a: CGFloat = 0
color.getRed(&r, green: &g, blue: &b, alpha: &a)
self.init(UInt8(r * 0xff), UInt8(g * 0xff), UInt8(b * 0xff), UInt8(a * 0xff))
}
public init?(hexString: String) {
var hex = hexString.trimmingCharacters(in: .whitespacesAndNewlines)
if hex.hasPrefix("#") {
hex = hex.substring(from: hex.index(after: hex.startIndex))
}
if (hex.range(of: "(^[0-9A-Fa-f]{6}$)|(^[0-9A-Fa-f]{3}$)|(^[0-9A-Fa-f]{8}$)|(^[0-9A-Fa-f]{4}$)", options: [.regularExpression]) != nil) {
var r: UInt8, g: UInt8, b: UInt8, a: UInt8
if hex.characters.count == 6 || hex.characters.count == 8 {
r = UInt8(Scanner(string: hex[0..<2]).scanHexInt()!) & 0xff
g = UInt8(Scanner(string: hex[2..<4]).scanHexInt()!) & 0xff
b = UInt8(Scanner(string: hex[4..<6]).scanHexInt()!) & 0xff
if hex.characters.count == 8 {
a = UInt8(Scanner(string: hex[6..<8]).scanHexInt()!) & 0xff
} else {
a = 0xff
}
} else if hex.characters.count == 3 || hex.characters.count == 4 {
r = UInt8(Scanner(string: hex[0]).scanHexInt()!) & 0xf * 0x11
g = UInt8(Scanner(string: hex[1]).scanHexInt()!) & 0xf * 0x11
b = UInt8(Scanner(string: hex[2]).scanHexInt()!) & 0xf * 0x11
if hex.characters.count == 4 {
a = UInt8(Scanner(string: hex[3]).scanHexInt()!) & 0xf * 0x11
} else {
a = 0xff
}
} else {
return nil
}
self.init((UInt32(r) << 24) | (UInt32(g) << 16) | (UInt32(b) << 8) | (UInt32(a) << 0))
} else {
return nil
}
}
public typealias ChannelInfo = (mask: UInt32, offset: UInt32)
public var info: (r: ChannelInfo, g: ChannelInfo, b: ChannelInfo, a: ChannelInfo) {
return (r: (mask: 0xff000000, offset: 24),
g: (mask: 0x00ff0000, offset: 16),
b: (mask: 0x0000ff00, offset: 8),
a: (mask: 0x000000ff, offset: 0))
}
private func decode(_ info: ChannelInfo) -> UInt8 {
return UInt8((uint & info.mask) >> info.offset)
}
private func encode(_ info: ChannelInfo, value: UInt8) -> UInt32 {
return (uint & ~info.mask) | (UInt32(value) << info.offset)
}
public var r: UInt8 {
get { return decode(info.r) }
set { uint = encode(info.r, value: newValue) }
}
public var g: UInt8 {
get { return decode(info.g) }
set { uint = encode(info.g, value: newValue) }
}
public var b: UInt8 {
get { return decode(info.b) }
set { uint = encode(info.b, value: newValue) }
}
public var a: UInt8 {
get { return decode(info.a) }
set { uint = encode(info.a, value: newValue) }
}
public var hsba: (h: Double, s: Double, b: Double, a: Double) {
get {
let r = Double(self.r) / 0xff
let g = Double(self.g) / 0xff
let b = Double(self.b) / 0xff
let a = Double(self.a) / 0xff
let M = Swift.max(r, g, b)
let m = Swift.min(r, g, b)
let C = M - m
let v = M
let s = v == 0 ? 0 : C / v
if C == 0 {
return (Double.nan, s, v, a)
}
let h: Double
switch M {
case r: h = ((g - b) / C).truncatingRemainder(dividingBy: 6)
case g: h = (b - r) / C + 2
case b: h = (r - g) / C + 4
default: h = 0
}
return (h * 60, s, v, a)
}
set {
let H = newValue.h / 6
let C = newValue.b * newValue.s
let X = C * (1 - abs(H.truncatingRemainder(dividingBy: 2) - 1))
let rgb1: (r: Double, g: Double, b: Double)
switch H {
case 0...1: rgb1 = (C, X, 0)
case 1...2: rgb1 = (X, C, 0)
case 2...3: rgb1 = (0, C, X)
case 3...4: rgb1 = (0, X, C)
case 4...5: rgb1 = (X, 0, C)
case 5..<6: rgb1 = (C, 0, X)
default: rgb1 = (0, 0, 0)
}
let m = newValue.b - C
r = UInt8((rgb1.r + m) * 0xff)
g = UInt8((rgb1.g + m) * 0xff)
b = UInt8((rgb1.b + m) * 0xff)
a = UInt8(a * 0xff)
}
}
public var hexString: String {
get {
return "#" + String(format: "%02x%02x%02x", r, g, b) + (a == 0xff ? "" : String(format: "%02x", a))
}
set {
if let n = Color(hexString: newValue) {
self = n
}
}
}
public var skColor: SKColor {
return SKColor(red: CGFloat(r) / 0xff, green: CGFloat(g) / 0xff, blue: CGFloat(b) / 0xff, alpha: CGFloat(a) / 0xff)
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment