1

I have a color UIColor(displayP3Red: 1, green: 0, blue: 0.8, alpha: 1). I want to create a desaturated version of this — with the same hue and brightness, but less saturation, like half the saturation of the original. How do I do this?

Kartick Vaddadi
  • 4,818
  • 6
  • 39
  • 55

2 Answers2

0

It should be straightforward given you can compute the Normalised Primary Matrix (NPM) of DCI-P3: the middle row of the NPM represents the Luminance factors. I will illustrate this using Colour, it assumes that you are using linear values:

import numpy as np
import colour

# Computing the sRGB Luminance Equation, you should be familiar with the 
# resulting Luminance factors.
print(colour.RGB_luminance_equation(
    colour.sRGB_COLOURSPACE.primaries, 
    colour.sRGB_COLOURSPACE.whitepoint))
# Y = 0.212639005872(R) + 0.715168678768(G) + 0.0721923153607(B)

# Computing the DCI-P3 Luminance Equation.
print(colour.RGB_luminance_equation(
    colour.DCI_P3_COLOURSPACE.primaries, 
    colour.DCI_P3_COLOURSPACE.whitepoint))
# Y = 0.209491677913(R) + 0.721595254161(G) + 0.0689130679262(B)

# Computing Luminance of given RGB colour, this is assuming it is representing linear values.
DCI_P3_LUMINANCE_FACTORS = np.array([0.209491677913, 0.721595254161, 0.0689130679262])
RGB = np.array([1.0, 0.0, 0.8])
Y = np.dot(RGB, DCI_P3_LUMINANCE_FACTORS)
print(Y)
# 0.264622132254

With Y representing the Luminance of your given colour, if you wanted to desaturate at 50% you could do something like that:

lerp(RGB, [Y, Y, Y], 0.5)

Kel Solaar
  • 3,660
  • 1
  • 23
  • 29
  • Is there a way to do this in iOS? Thanks. – Kartick Vaddadi Apr 07 '17 at 13:28
  • Very likely, what you really just need is being able to do a dot product and a linear interpolation. – Kel Solaar Apr 07 '17 at 20:42
  • BTW, Python signals an error saying colour is not found in import colour. What MacPorts module must I install? I'm using Python 3.6. I already installed numpy, because that was giving an error too. Thanks. – Kartick Vaddadi Apr 08 '17 at 03:00
  • @VaddadiKartick: Colour is a regular Python package, you can get it either from pip or Anaconda (recommended): http://colour-science.org/installation-guide/ – Kel Solaar Apr 09 '17 at 20:49
  • Would be nice for the downvoters to explain why they downvote. – Kel Solaar May 08 '19 at 10:10
  • 1
    I didn't downvote it, but maybe others did because the question was about iOS and the answer wasn't. Still, they should've appreciated your effort and given constructive feedback rather than a drive-by downvote. – Kartick Vaddadi May 09 '19 at 05:06
  • I did not realise that UIColor was an iOS specific class, so to me the question was generic. It might be worth adding an iOS tag? – Kel Solaar May 09 '19 at 10:41
  • 1
    Done. Also added a link to the iOS documentation to clarify. Sorry that it wasn't clear the first time. – Kartick Vaddadi May 13 '19 at 01:25
0
extension UIColor {    
  // Calling this with 0.5 as argument returns a color whose saturation is 50% of that of the receiver.
  func desaturatedBy(fraction: CGFloat) -> UIColor {
    var hue: CGFloat = 0
    var saturation: CGFloat = 0
    var brightness: CGFloat = 0
    var alpha: CGFloat = 0
    let success = getHue(&hue, saturation: &saturation, brightness: &brightness, alpha: &alpha)
    assert(success)

    saturation *= fraction

    return UIColor(hue: hue, saturation: saturation, brightness: brightness, alpha: alpha)
  }
}

This works because the getter returns HSB in the extended sRGB color space, and UIColor's initialiser takes HSB in the extended sRGB color space, too. So we don't need to do any color space conversion.

Kartick Vaddadi
  • 4,818
  • 6
  • 39
  • 55