Skip to content

Instantly share code, notes, and snippets.

@JKalash
Created December 29, 2016 15:43
Show Gist options
  • Save JKalash/698c3d708dc1e54aed868dea00b9fcf7 to your computer and use it in GitHub Desktop.
Save JKalash/698c3d708dc1e54aed868dea00b9fcf7 to your computer and use it in GitHub Desktop.
Converts to and from HSV to RGB color spaces
//
// RGBtoHSV.swift
// Stalkie
//
// Created by Joseph Kalash on 12/29/16.
// Copyright © 2016 Joseph Kalash. All rights reserved.
//
struct RGB {
//Percent
let r: CGFloat // [0,1]
let g: CGFloat // [0,1]
let b: CGFloat // [0,1]
static func hsv(r: CGFloat, g: CGFloat, b: CGFloat) -> HSV {
let min = r < g ? (r < b ? r : b) : (g < b ? g : b)
let max = r > g ? (r > b ? r : b) : (g > b ? g : b)
let v = max
let delta = max - min
guard delta > 0.00001 else { return HSV(h: 0, s: 0, v: max) }
guard max > 0 else { return HSV(h: -1, s: 0, v: v) } // Undefined, achromatic grey
let s = delta / max
let hue: (CGFloat, CGFloat) -> CGFloat = { max, delta -> CGFloat in
if r == max { return (g-b)/delta } // between yellow & magenta
else if g == max { return 2 + (b-r)/delta } // between cyan & yellow
else { return 4 + (r-g)/delta } // between magenta & cyan
}
let h = hue(max, delta) * 60 // In degrees
return HSV(h: (h < 0 ? h+360 : h) , s: s, v: v)
}
static func hsv(rgb: RGB) -> HSV {
return hsv(r: rgb.r, g: rgb.g, b: rgb.b)
}
var hsv: HSV { return RGB.hsv(rgb: self) }
}
struct RGBA {
let a: CGFloat
let rgb: RGB
init(r: CGFloat, g: CGFloat, b: CGFloat, a: CGFloat) {
self.a = a
self.rgb = RGB(r: r, g: g, b: b)
}
}
struct HSV {
let h: CGFloat // Angle in degrees [0,360] or -1 as Undefined
let s: CGFloat // Percent [0,1]
let v: CGFloat // Percent [0,1]
static func rgb(h: CGFloat, s: CGFloat, v: CGFloat) -> RGB {
if s == 0 { return RGB(r: v, g: v, b: v) } // Achromatic grey
let angle = (h >= 360 ? 0 : h)
let sector = angle / 60 // Sector
let i = floor(sector)
let f = sector - i // Factorial part of h
let p = v * (1 - s)
let q = v * (1 - (s * f))
let t = v * (1 - (s * (1 - f)))
switch(i) {
case 0:
return RGB(r: v, g: t, b: p)
case 1:
return RGB(r: q, g: v, b: p)
case 2:
return RGB(r: p, g: v, b: t)
case 3:
return RGB(r: p, g: q, b: v)
case 4:
return RGB(r: t, g: p, b: v)
default:
return RGB(r: v, g: p, b: q)
}
}
static func rgb(hsv: HSV) -> RGB { return rgb(h: hsv.h, s: hsv.s, v: hsv.v) }
var rgb: RGB { return HSV.rgb(hsv: self)}
/// Returns a normalized point with x=h and y=v
var point: CGPoint { return CGPoint(x: h/360, y: v) }
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment