11

If i give two colors

UIColor *color1 = [UIColor blackColor];
UIColor *color2 = [UIColor whiteColor];

I should get grayColor as result, how shall I achieve it?

Sergey Kalinichenko
  • 714,442
  • 84
  • 1,110
  • 1,523
Sunil Rao
  • 800
  • 2
  • 6
  • 23
  • One more example is : If I give red and yellow colors, I should get orange color. – Sunil Rao Nov 04 '15 at 10:30
  • Get numerical averages of red, blue, green components. – El Tomato Nov 04 '15 at 10:31
  • http://stackoverflow.com/questions/398224/how-to-mix-colors-naturally-with-c Method should be the same. Just get the value of red/blue/green, with `getRed:green:blue:alpha:`, or maybe there is some work with `getHue:saturation:brightness:alpha:`. – Larme Nov 04 '15 at 10:36
  • 5
    duplicate : http://stackoverflow.com/questions/23358123/get-midcolor-from-uicolor – enzo Nov 04 '15 at 10:37

3 Answers3

13

A straightforward way of finding the "in between" is to average the four components, like this:

UIColor *color1 = [UIColor blackColor];
UIColor *color2 = [UIColor whiteColor];
CGFloat r1, r2, g1, g2, b1, b2, a1, a2;
[color1 getRed:&r1 green:&g1 blue:&b1 alpha:&a1];
[color2 getRed:&r2 green:&g2 blue:&b2 alpha:&a2];
UIColor *avg = [UIColor colorWithRed:(r1+r2)/2.0f
                              green:(g1+g2)/2.0f
                               blue:(b1+b2)/2.0f
                              alpha:(a1+a2)/2.0f];

Note that this produces a midpoint RGBA color space, which is only one of many possible color spaces. Averaging components in other color spaces will lead to a different result.

Mark Meyer
  • 3,643
  • 3
  • 23
  • 34
Sergey Kalinichenko
  • 714,442
  • 84
  • 1,110
  • 1,523
  • [`UIColor` class reference](https://developer.apple.com/library/ios/documentation/UIKit/Reference/UIColor_Class/index.html#//apple_ref/occ/instm/UIColor/getRed:green:blue:alpha:). Could be useful – Arc676 Nov 04 '15 at 10:36
  • Would this always come out with what was expected? Would there be a possibility of mixing two colours but getting a muddy colours instead of what was expected? – Fogmeister Nov 04 '15 at 12:56
  • 1
    @Fogmeister I am pretty sure that this will *not* always match the expectation, because people do not think of colors in terms of RGBA color space. Color sensitivity being highly individual, it's nearly impossible to come up with a way of satisfying everyone. – Sergey Kalinichenko Nov 04 '15 at 13:17
  • @dasblinkenlight I want multiple shaded between these two color. How can i get that ? any idea ? – Arpan Dixit Dec 01 '15 at 08:38
3

Answer in Swift 4+

func blend(colors: [UIColor]) -> UIColor {
    let componentsSum = colors.reduce((red: CGFloat(0), green: CGFloat(0), blue: CGFloat(0))) { (temp, color) in
      guard let components = color.cgColor.components else { return temp }
      return (temp.0 + components[0], temp.1 + components[1], temp.2 + components[2])
    }
    let components = (red: componentsSum.red / CGFloat(colors.count) ,
                      green: componentsSum.green / CGFloat(colors.count),
                      blue: componentsSum.blue / CGFloat(colors.count))
    return UIColor(red: components.red, green: components.green, blue: components.blue, alpha: 1)
  }

It blends as many colors as you'd like

Federico Zanetello
  • 3,321
  • 1
  • 25
  • 22
1

Here Swift implementation that safe to use. Works with colors of different color spaces, but blend in RGBA:

func + (left: UIColor, right: UIColor) -> UIColor {
    var (r1, g1, b1, a1) = (CGFloat(0), CGFloat(0), CGFloat(0), CGFloat(0))
    var (r2, g2, b2, a2) = (CGFloat(0), CGFloat(0), CGFloat(0), CGFloat(0))
    left.getRed(&r1, green: &g1, blue: &b1, alpha: &a1)
    right.getRed(&r2, green: &g2, blue: &b2, alpha: &a2)
    return UIColor(red: (r1 + r2)/2, green: (g1 + g2)/2, blue: (b1 + b2)/2, alpha: (a1 + a2)/2)
}

Using:

    view.backgroundColor = .red + .white

Old anrwer:

extension UIColor {

    func blended(with color: UIColor) -> UIColor? {
        guard cgColor.colorSpace == color.cgColor.colorSpace else { return nil }
        return UIColor(cgColor: CGColor(colorSpace: cgColor.colorSpace!, components:
            zip(cgColor.components!, color.cgColor.components!).map { ($0 + $1) / 2 }
        )!)
    }
}

But it works only with colors of one color space, otherwise it will return nil. Here example of use:

let white = UIColor(red: 1.0, green: 1.0, blue: 1.0, alpha: 1.0)
view.backgroundColor = UIColor.red.blended(with: white)
Artem Sydorenko
  • 353
  • 4
  • 8