-
-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #1 from spacenation/hsv
HSV and RGB colors
- Loading branch information
Showing
15 changed files
with
191 additions
and
27 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1 +1 @@ | ||
## Color | ||
## Colors |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
import Foundation | ||
|
||
public extension HSVColor { | ||
func maxComponentOffset(with color: HSVColor) -> UInt8 { | ||
[self.hue - color.hue, self.saturation - color.saturation, self.value - color.value].max() ?? 0 | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
import Foundation | ||
|
||
extension Collection where Element == HSVColor { | ||
public func dominantColor(saturationRange: ClosedRange<UInt8> = UInt8.min...UInt8.max, valueUnitRange: ClosedRange<UInt8> = UInt8.min...UInt8.max) -> HSVColor? { | ||
let filteredColors = filter { saturationRange.contains($0.saturation) && valueUnitRange.contains($0.value) } | ||
let colorBins = Dictionary(grouping: filteredColors) { $0.hue } | ||
|
||
guard colorBins.count != 0 else { return nil } | ||
|
||
if let dominantBin = colorBins.max(by: { $0.key > $1.key }) { | ||
let elementsCount: Int = dominantBin.value.count | ||
let saturationSum: Int = dominantBin.value.reduce(0) { $0 + Int($1.saturation) } | ||
let valueSum: Int = dominantBin.value.reduce(0) { $0 + Int($1.value) } | ||
let averageSaturation = UInt8(saturationSum / elementsCount) | ||
let averageValue = UInt8(valueSum / elementsCount) | ||
return HSVColor(hue: dominantBin.key, saturation: averageSaturation, value: averageValue) | ||
} else { | ||
return nil | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,43 @@ | ||
import Foundation | ||
|
||
extension HSVColor { | ||
public init(red: UInt8, green: UInt8, blue: UInt8) { | ||
var hueDegrees: Float = 0 | ||
var unitSaturation: Float | ||
var unitValue: Float | ||
|
||
let unitRed = Float(red) / Float(UInt8.max) | ||
let unitGreen = Float(green) / Float(UInt8.max) | ||
let unitBlue = Float(blue) / Float(UInt8.max) | ||
|
||
let unitMax = max(unitRed, unitGreen, unitBlue) | ||
let unitMin = min(unitRed, unitGreen, unitBlue) | ||
let unitDelta = unitMax - unitMin | ||
|
||
if unitMax == 0 { | ||
unitSaturation = 0 | ||
} else { | ||
unitSaturation = (unitMax - unitMin) / unitMax | ||
} | ||
|
||
unitValue = unitMax | ||
|
||
if unitDelta == 0 { | ||
hueDegrees = 0 | ||
} else if unitMax == unitRed { | ||
hueDegrees = 60 * ((unitGreen - unitBlue) / unitDelta) | ||
} else if unitMax == unitGreen { | ||
hueDegrees = 60 * ((unitBlue - unitRed) / unitDelta + 2) | ||
} else if unitMax == unitBlue { | ||
hueDegrees = 60 * ((unitRed - unitGreen) / unitDelta + 4) | ||
} | ||
|
||
if hueDegrees < 0 { | ||
hueDegrees += 360 | ||
} | ||
|
||
let unitHue = hueDegrees / 360.0 | ||
|
||
self.init(hueUnit: unitHue, saturationUnit: unitSaturation, valueUnit: unitValue) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
import Foundation | ||
|
||
public extension HSVColor { | ||
/// Initializes a new Color struct with the provided HSV color parameters | ||
/// | ||
/// - parameter hueUnit: The 360 degrees hue represented as Float from 0.0 to 1.0 | ||
/// - parameter saturationUnit: The saturation represented as Float from 0.0 to 1.0 | ||
/// - parameter valueUnit: The value represented as Float from 0.0 to 1.0 | ||
/// - returns: `HSVColor` struct | ||
init(hueUnit: Float, saturationUnit: Float, valueUnit: Float) { | ||
self.hue = UInt8(Float(UInt8.max) * max(0, min(hueUnit, 1))) | ||
self.saturation = UInt8(Float(UInt8.max) * max(0, min(saturationUnit, 1))) | ||
self.value = UInt8(Float(UInt8.max) * max(0, min(valueUnit, 1))) | ||
} | ||
} | ||
|
||
public extension HSVColor { | ||
var unitHue: Float { | ||
get { Float(hue) / Float(UInt8.max) } | ||
set { hue = UInt8(Float(UInt8.max) * max(0, min(newValue, 1))) } | ||
} | ||
|
||
var unitSaturation: Float { | ||
get { Float(saturation) / Float(UInt8.max) } | ||
set { saturation = UInt8(Float(UInt8.max) * max(0, min(newValue, 1))) } | ||
} | ||
|
||
var unitValue: Float { | ||
get { Float(value) / Float(UInt8.max) } | ||
set { value = UInt8(Float(UInt8.max) * max(0, min(newValue, 1))) } | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
import Foundation | ||
|
||
public struct HSVColor: Hashable, Codable { | ||
public var hue: UInt8 | ||
public var saturation: UInt8 | ||
public var value: UInt8 | ||
} | ||
|
File renamed without changes.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
import Foundation | ||
|
||
public extension RGBColor { | ||
/// Initializes a new Color struct with the provided RGB color parameters | ||
/// | ||
/// - parameter redUnit: Red component represented as Float from 0.0 to 1.0 | ||
/// - parameter greenUnit: Green component represented as Float from 0.0 to 1.0 | ||
/// - parameter blueUnit: The blue component represented as Float from 0.0 to 1.0 | ||
/// - returns: `RGBColor` struct | ||
init(redUnit: Float, greenUnit: Float, blueUnit: Float) { | ||
self.red = UInt8(Float(UInt8.max) * max(0, min(redUnit, 1))) | ||
self.green = UInt8(Float(UInt8.max) * max(0, min(greenUnit, 1))) | ||
self.blue = UInt8(Float(UInt8.max) * max(0, min(blueUnit, 1))) | ||
} | ||
} | ||
|
||
public extension RGBColor { | ||
var unitRed: Float { | ||
get { Float(red) / Float(UInt8.max) } | ||
set { red = UInt8(Float(UInt8.max) * max(0, min(newValue, 1))) } | ||
} | ||
|
||
var unitGreen: Float { | ||
get { Float(green) / Float(UInt8.max) } | ||
set { green = UInt8(Float(UInt8.max) * max(0, min(newValue, 1))) } | ||
} | ||
|
||
var unitBlue: Float { | ||
get { Float(blue) / Float(UInt8.max) } | ||
set { blue = UInt8(Float(UInt8.max) * max(0, min(newValue, 1))) } | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
import Foundation | ||
|
||
public struct RGBColor: Hashable, Codable { | ||
public var red: UInt8 | ||
public var green: UInt8 | ||
public var blue: UInt8 | ||
} |
This file was deleted.
Oops, something went wrong.
19 changes: 19 additions & 0 deletions
19
Tests/ColorsTests/HSVColorTests/HSVColorDominantColorsTests.swift
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
import XCTest | ||
@testable import Colors | ||
|
||
final class HSVColorDominantColorsTests: XCTestCase { | ||
func testHSVColorDominantColorsTests() { | ||
let colors = [ | ||
HSVColor(hue: 1, saturation: 128, value: 255), | ||
HSVColor(hue: 2, saturation: 255, value: 255), | ||
HSVColor(hue: 1, saturation: 126, value: 0), | ||
HSVColor(hue: 1, saturation: 0, value: 0) | ||
] | ||
|
||
XCTAssert(colors.dominantColor(saturationRange: 50...255) == HSVColor(hue: 1, saturation: 127, value: 127)) | ||
} | ||
|
||
static var allTests = [ | ||
("testHSVColorDominantColorsTests", testHSVColorDominantColorsTests), | ||
] | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
import XCTest | ||
@testable import Colors | ||
|
||
final class HSVColorTests: XCTestCase { | ||
func testHSVColorRGBInitTests() { | ||
XCTAssert(HSVColor(hue: 0, saturation: 0, value: 0) == HSVColor(red: 0, green: 0, blue: 0)) | ||
XCTAssert(HSVColor(hue: 0, saturation: 0, value: 127) == HSVColor(red: 127, green: 127, blue: 127)) | ||
XCTAssert(HSVColor(hue: 0, saturation: 0, value: 255) == HSVColor(red: 255, green: 255, blue: 255)) | ||
} | ||
|
||
static var allTests = [ | ||
("testHSVColorRGBInitTests", testHSVColorRGBInitTests), | ||
] | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters