How can I modify a UIColor's hue, brightness and saturation?

14,097

Solution 1

You can call getHue:saturation:brightness:alpha: on your color, then adjust the values, then create a new color with your adjusted components using +[UIColor colorWithHue:saturation:brightness:alpha:]

CGFloat hue, saturation, brightness, alpha ;
BOOL ok = [ <color> getHue:&hue saturation:&saturation brightness:&brightness alpha:&alpha ] ;
if ( !ok ) { 
    // handle error 
}
// ... adjust components..

UIColor * newColor = [ UIColor colorWithHue:hue saturation:saturation brightness:brightness alpha:alpha ] ;

Solution 2

Here is swift UIColor extension you might find useful:

extension UIColor {

    func modified(withAdditionalHue hue: CGFloat, additionalSaturation: CGFloat, additionalBrightness: CGFloat) -> UIColor {

        var currentHue: CGFloat = 0.0
        var currentSaturation: CGFloat = 0.0
        var currentBrigthness: CGFloat = 0.0
        var currentAlpha: CGFloat = 0.0

        if self.getHue(&currentHue, saturation: &currentSaturation, brightness: &currentBrigthness, alpha: &currentAlpha){
            return UIColor(hue: currentHue + hue,
                           saturation: currentSaturation + additionalSaturation,
                           brightness: currentBrigthness + additionalBrightness,
                           alpha: currentAlpha)
        } else {
            return self
        }
    }
}

Solution 3

Unfortunately it's quite a hassle to change any of the hsba or rgba values of a UIColor by default. Using HandyUIKit (install it via Carthage) makes your life a lot easier:

import HandyUIKit  

// each line creates a new UIColor object with the new value
color.change(.hue,        to: 0.1)
color.change(.brightness, to: 0.2)
color.change(.saturation, to: 0.3)
color.change(.alpha,      to: 0.4)

// chaining them returns a single new object with all values changed
color.change(.hue,        to: 0.5)
     .change(.brightness, to: 0.6)
     .change(.saturation, to: 0.7)

There are also options to apply relative changes:

// create a new UIColor object with hue & brightness increased by 0.2
color.change(.hue,        by: 0.2)
     .change(.brightness, by: 0.2)

The library also adds some other handy UI features into your project – checkout its README on GitHub for more details.

I hope it helps!

Solution 4

One important note not yet mentioned here is that your UIColor should be in extended RGB space. Depending on how your color is originally created this function may return false if it's just RGB.

Secondly, I made a variant on @ambientlight's answer to make the API just a little more slick. You can adjust 1 or all properties.

extension UIColor {

    public func adjust(hueBy hue: CGFloat = 0, saturationBy saturation: CGFloat = 0, brightnessBy brightness: CGFloat = 0) -> UIColor {

        var currentHue: CGFloat = 0.0
        var currentSaturation: CGFloat = 0.0
        var currentBrigthness: CGFloat = 0.0
        var currentAlpha: CGFloat = 0.0

        if getHue(&currentHue, saturation: &currentSaturation, brightness: &currentBrigthness, alpha: &currentAlpha) {
            return UIColor(hue: currentHue + hue,
                       saturation: currentSaturation + saturation,
                       brightness: currentBrigthness + brightness,
                       alpha: currentAlpha)
        } else {
            return self
        }
    }
}
Share:
14,097
s6luwJ0A3I
Author by

s6luwJ0A3I

please delete me

Updated on June 09, 2022

Comments

  • s6luwJ0A3I
    s6luwJ0A3I almost 2 years

    Lets say I have a UIColor

    UIColor *color = [UIColor redColor];
    

    Now I want to modify the saturation/hue/brigthness, how do I do that? I did read the documentation but i'm still really confused

    I want to modify the UIColor I made ([UIColor redColor]) not initiate a new color with some preferences. How do I modify it retaining the original. I do know about thecolorWithHue:saturation:brightness:alpha: method, I need to update an existing color's properties, keeping the red color.

  • s6luwJ0A3I
    s6luwJ0A3I about 11 years
    Thanks a lot for your answer, it worked! I'l just accept it in a min (Stackoverflow says i have to wait)
  • zhoujinhao
    zhoujinhao about 11 years
    colorWithHue:saturation:brightness:alpha: Creates and returns a color object using the specified opacity and HSB color space component values. This method used for make a color with HSB color space , like RGB color space. Can't change a red color to other color.
  • nielsbot
    nielsbot about 11 years
    This works, however it doesn't meet your requirement that it be the same color object. But what you want isn't possible. UIColor is immutable--so you will always have to create a new color object.
  • Lukas Knuth
    Lukas Knuth about 11 years
    A simple line(s) of code is not considered a good answer. Please also explain why you did what and how this is helping.
  • ZygD
    ZygD almost 9 years
    Provided code might help, but in order to make it a good answer you should also describe/explain why/how exactly does your code solve the problem.
  • Arvind Rajpurohit
    Arvind Rajpurohit almost 9 years
    in first two line it describe image size and image rect. cgcontext is use to create a context in core graphics.after that 5th line is image uyou want to apply hue and rect of image . after that blend mode which is important.after that ui colorWithHue in which pass value of hue ,saturation,brightness and alpha to get proper effect give 1.0 value of alpha.and at end set uicolor.create bezerpath or u can directly give cgcontextsetfill(context). At the end create imageref and put that image in uiimage .AT the end alway in choreographics release cgimageRef against memory issue.
  • ZygD
    ZygD almost 9 years
    It's always better to put relevant info inside the answer, as not everyone, if they have a similar problem, will dig into comments. Also, what did you mean by choreographics?
  • Charles Robertson
    Charles Robertson over 7 years
    @nielsbot I like your concise use of BOOL to kill 2 birds with one stone, so to speak. Excellent answer...