Search code examples
swiftcocoanscolor

How to guarantee that an NSColor has enough saturation?


I need to guarantee that a color has enough saturation.

I made this extension to NSColor but my tests give me weird values: tempColor always seems to have lots of saturation.

So basically my function always returns self?

Where's my mistake?

I've also tried without converting to NSCalibratedRGBColorSpace but that didn't help and the input color can be of different type anyway.

extension NSColor {
    func withMinimumSaturation(minimumSaturation: CGFloat) -> NSColor {
        // color could be hue/rgb/other so we convert to rgb
        if var tempColor = self.colorUsingColorSpaceName(NSCalibratedRGBColorSpace) {
            // prepare the values
            var hue: CGFloat = 0.0
            var saturation: CGFloat = 0.0
            var brightness: CGFloat = 0.0
            var alpha: CGFloat = 0.0
            // populate the values
            tempColor.getHue(&hue, saturation: &saturation, brightness: &brightness, alpha: &alpha)
            // if color is not enough saturated
            if saturation < minimumSaturation {
                // return same color with more saturation
                return NSColor(calibratedHue: hue, saturation: minimumSaturation, brightness: brightness, alpha: alpha)
            }
        }
        // if detection fails, return same color
        return self
    }
}

Usage:

let source = myColorFromAListOfColors // NSColor
let guaranteed = source.withMinimumSaturation(0.15)

EDIT: actually it works. I've accepted Aaron's answer because it helped me understand the situation (I was comparing the colors with their redComponents and they were often similar).


Solution

  • Your method seems fine.

    For colors with very low saturation, it returns a different color:

    enter image description here

    If I increase the minimum saturation from 0.15 to something more significant, like 0.45, the change is more significant:

    enter image description here

    So, this method works as I expect it would. I'm guessing you just need to tweak that 0.15 input to get the results you want.

    It may help you to log the old and new saturations for debugging:

    if saturation < minimumSaturation {
        // return same color with more saturation
        println("New saturation: \(minimumSaturation)")
    
        return NSColor(calibratedHue: hue, saturation: minimumSaturation, brightness: brightness, alpha: alpha)
    } else {
        println("Discarding saturation: \(saturation)")
    }