diff --git a/Sources/LibMakeColors/Model/Color+HSV.swift b/Sources/LibMakeColors/Model/Color+HSV.swift new file mode 100644 index 0000000..8b9383f --- /dev/null +++ b/Sources/LibMakeColors/Model/Color+HSV.swift @@ -0,0 +1,36 @@ +extension Color { + init(hue: Int, saturation: UInt8, value: UInt8, alpha: UInt8 = 0xFF) { + let degrees = abs(hue % 360) + + let s = Double(saturation) / 0xFF + let v = Double(value) / 0xFF + let C = s * v + let X = C * (1 - abs((Double(degrees) / 60).truncatingRemainder(dividingBy: 2) - 1)) + let m = v - C + + let result: (r: Double, g: Double, b: Double) + switch degrees { + case 0..<60: + result = (C, X, 0) + case 60..<120: + result = (X, C, 0) + case 120..<180: + result = (0, C, X) + case 180..<240: + result = (0, X, C) + case 240..<300: + result = (X, 0, C) + case 300..<360: + result = (C, 0, X) + default: + fatalError("Degrees out of range") + } + + self.init( + red: UInt8(((result.r + m) * 0xFF).rounded()), + green: UInt8(((result.g + m) * 0xFF).rounded()), + blue: UInt8(((result.b + m) * 0xFF).rounded()), + alpha: alpha + ) + } +} diff --git a/Tests/MakeColorsTests/ColorHSVTest.swift b/Tests/MakeColorsTests/ColorHSVTest.swift new file mode 100644 index 0000000..d7bd9dc --- /dev/null +++ b/Tests/MakeColorsTests/ColorHSVTest.swift @@ -0,0 +1,39 @@ +@testable import LibMakeColors +import XCTest + +final class ColorHSVTest: XCTestCase { + func testHSV0Degrees() { + let color = Color(hue: 0, saturation: 0xFF, value: 0xFF) + XCTAssertEqual(color, Color(red: 0xFF, green: 0, blue: 0)) + } + + func testHSV60Degrees() { + let color = Color(hue: 60, saturation: 0xFF, value: 0xFF) + XCTAssertEqual(color, Color(red: 0xFF, green: 0xFF, blue: 0)) + } + + func testHSV120Degrees() { + let color = Color(hue: 120, saturation: 0xFF, value: 0xFF) + XCTAssertEqual(color, Color(red: 0, green: 0xFF, blue: 0)) + } + + func testHSV180Degrees() { + let color = Color(hue: 180, saturation: 0xFF, value: 0xFF) + XCTAssertEqual(color, Color(red: 0, green: 0xFF, blue: 0xFF)) + } + + func testHSV240Degrees() { + let color = Color(hue: 240, saturation: 0xFF, value: 0xFF) + XCTAssertEqual(color, Color(red: 0, green: 0, blue: 0xFF)) + } + + func testHSV300Degrees() { + let color = Color(hue: 300, saturation: 0xFF, value: 0xFF) + XCTAssertEqual(color, Color(red: 0xFF, green: 0, blue: 0xFF)) + } + + func testHSV360Degrees() { + let color = Color(hue: 360, saturation: 0xFF, value: 0xFF) + XCTAssertEqual(color, Color(red: 0xFF, green: 0, blue: 0)) + } +}