Can I mix two UIColor together?
Asked Answered
M

7

10

I have colorA which is [UIColor blueColor], and colorB, which is [UIColor redColor]. Is this possible for me to render a [UIColor purple]? How can it be implemented? Thanks.

Millda answered 30/10, 2012 at 4:42 Comment(2)
I assume that you tried calling CGColorGetComponents, averaging them up, and then making a color from the components, right?Rumormonger
CAGradientLayer *gradiant = [CAGradientLayer layer]; gradiant.frame = self.view.bounds; gradiant.colors = [NSArray arrayWithObjects:(id)[[UIColor colorWithRed:0.90 green:0.99 blue:1.0 alpha:1] CGColor],(id)[[UIColor colorWithRed:0.52 green:0.96 blue:0.98 alpha:1] CGColor], nil]; [self.view.layer insertSublayer:gradiant atIndex:0];Gage
D
0

You can't mix two UIColors directly as you mention in your question. Anyways there is an example to mix two colors using other schemes. The link for same is as follows:

Link Here

Diphyodont answered 30/10, 2012 at 4:50 Comment(1)
To present a link is not an answer. Besides, the project where the link points to doesn't succeed very well with the mixing.Shad
E
32

Inelegant, but it works:

UIColor* blend( UIColor* c1, UIColor* c2, float alpha )
{
    alpha = MIN( 1.f, MAX( 0.f, alpha ) );
    float beta = 1.f - alpha;
    CGFloat r1, g1, b1, a1, r2, g2, b2, a2;
    [c1 getRed:&r1 green:&g1 blue:&b1 alpha:&a1];
    [c2 getRed:&r2 green:&g2 blue:&b2 alpha:&a2];
    CGFloat r = r1 * beta + r2 * alpha;
    CGFloat g = g1 * beta + g2 * alpha;
    CGFloat b = b1 * beta + b2 * alpha;
    return [UIColor colorWithRed:r green:g blue:b alpha:1.f];
}

More elegant:

UIColor+Extensions.h:

@interface UIColor (Extensions)

- (UIColor*)blendWithColor:(UIColor*)color2 alpha:(CGFloat)alpha2;

@end

UIColor+Extensions.m:

@implementation UIColor (Extensions)

- (UIColor*)blendWithColor:(UIColor*)color2 alpha:(CGFloat)alpha2
{
    alpha2 = MIN( 1.0, MAX( 0.0, alpha2 ) );
    CGFloat beta = 1.0 - alpha2;
    CGFloat r1, g1, b1, a1, r2, g2, b2, a2;
    [self getRed:&r1 green:&g1 blue:&b1 alpha:&a1];
    [color2 getRed:&r2 green:&g2 blue:&b2 alpha:&a2];
    CGFloat red     = r1 * beta + r2 * alpha2;
    CGFloat green   = g1 * beta + g2 * alpha2;
    CGFloat blue    = b1 * beta + b2 * alpha2;
    CGFloat alpha   = a1 * beta + a2 * alpha2;
    return [UIColor colorWithRed:red green:green blue:blue alpha:alpha];
}

@end

Swift 3/4:

extension UIColor
{
func mixin(infusion:UIColor, alpha:CGFloat) -> UIColor {
    let alpha2 = min(1.0, max(0, alpha))
    let beta = 1.0 - alpha2

    var r1:CGFloat = 0, r2:CGFloat = 0
    var g1:CGFloat = 0, g2:CGFloat = 0
    var b1:CGFloat = 0, b2:CGFloat = 0
    var a1:CGFloat = 0, a2:CGFloat = 0
    if getRed(&r1, green: &g1, blue: &b1, alpha: &a1) &&
        infusion.getRed(&r2, green: &g2, blue: &b2, alpha: &a2)
    {
        let red     = r1 * beta + r2 * alpha2;
        let green   = g1 * beta + g2 * alpha2;
        let blue    = b1 * beta + b2 * alpha2;
        let alpha   = a1 * beta + a2 * alpha2;
        return UIColor(red: red, green: green, blue: blue, alpha: alpha)
    }
    // epique de las failuree
    return self
}
}
Esau answered 19/9, 2013 at 19:38 Comment(6)
UIColor* purple = [[UIColor blueColor] blendWithColor:[UIColor redColor] alpha:0.5];Esau
@Esau Great answer. Would like to ask: can you please give some explanation to the methods above such as the use of beta and alpha here and the calculations applied on them? I am just a curious beast that instead of just using something that works, I would like to know why. I already +1'ed days ago. Wish I could do that again. Thanks in advance.Mansfield
@Mansfield Thanks! alpha2 is the alpha factor applied to the color2 -- that is, alpha2 = 0.0 makes color2 "transparent" and alpha2 = 1.0 makes color2 fully opaque (obscuring the self color). alpha2 is clamped between 0.0 and 1.0 to avoid any side-effects due to bad alpha2 values. Then, beta is just the "alpha" for color1. I chose "beta" instead of alpha1 to make the value stand out more clearly in the code.Esau
NOTE this only works for colors in the RGB space. For example, this will not work on [UIColor whiteColor] as that is not in RGB.Pew
@Esau So alpha2 is a2? Edit: if I get it right, it is more like the level of blending and not related to transparencyHubbub
You should definetly take gamma into account by squaring each component and then square rooting the final valuesHearsay
P
4

Ask each input color for its RGBA components using -[UIColor getRed:green:blue:alpha:]. Average the components from each, and create a new color using +[UIColor colorWithRed:green:blue:alpha:].

Paragrapher answered 30/10, 2012 at 4:48 Comment(7)
Note: make sure you divide the red: green: blue: paremeters by 256.0Pacifically
@TeenDev That would be a mistake, since getRed:green:blue:alpha: returns values between 0 and 1, and colorWithRed:green:blue:alpha: takes values between 0 and 1.Paragrapher
Oh ok, colorWithRed:green:blue if you pass numbers above 1 then you need to divide by 256.0 (since general RGB spectrums online are specified in > 1)..... that is a problem I always face when trying to insert RGB numbers in!Pacifically
@Pacifically you mean 255.0 not 256.0Indevout
There are 256 color ints but it starts at 0 so the range is 0-255 (which is 256 int values in total). But 255 = max(RGB) and 1 = max(component) and 255/255 = 1.Indevout
Color components are not 8 bit integers. How do you think a 30 bit (10 bit per component) display is going to work if you only have 8 bit integers?Drank
This answer is terrible anyway. I should have recommended averaging hue, saturation and brightness, not red, green, and blue. You get much better results if you operate in HSV space.Paragrapher
R
4

Swift5 UIColor Extension

extension UIColor {
    func add(_ overlay: UIColor) -> UIColor {
        var bgR: CGFloat = 0
        var bgG: CGFloat = 0
        var bgB: CGFloat = 0
        var bgA: CGFloat = 0
        
        var fgR: CGFloat = 0
        var fgG: CGFloat = 0
        var fgB: CGFloat = 0
        var fgA: CGFloat = 0
        
        self.getRed(&bgR, green: &bgG, blue: &bgB, alpha: &bgA)
        overlay.getRed(&fgR, green: &fgG, blue: &fgB, alpha: &fgA)
        
        let r = fgA * fgR + (1 - fgA) * bgR
        let g = fgA * fgG + (1 - fgA) * bgG
        let b = fgA * fgB + (1 - fgA) * bgB
        
        return UIColor(red: r, green: g, blue: b, alpha: 1.0)
    }
    
    static func +(lhs: UIColor, rhs: UIColor) -> UIColor {
        return lhs.add(rhs)
    }
}

Usage

let opacity: CGFloat = 0.6
let start = UIColor.red
let end = UIColor.blue
let combined = start.withAlphaComponent(opacity) + end.withAlphaComponent(1-opacity)
Ragucci answered 7/8, 2020 at 7:38 Comment(0)
D
1

Since it is 2020 now, and we have "Dark Mode" available, many "colours" are not just colours anymore, but automatically adapt to color changes. They are created by calling UIColor(dynamicProvider: ...).

You should check if both colors are dynamic colors, and if they are, return a dynamic color. Mixing one dynamic color and a non-dynamic color doesn't really make sense, so in that case return a non-dynamic color.

Drank answered 7/8, 2020 at 8:5 Comment(0)
D
0

You can't mix two UIColors directly as you mention in your question. Anyways there is an example to mix two colors using other schemes. The link for same is as follows:

Link Here

Diphyodont answered 30/10, 2012 at 4:50 Comment(1)
To present a link is not an answer. Besides, the project where the link points to doesn't succeed very well with the mixing.Shad
O
0

I always use just simple average version extension method:

func addSabiVersion(overlay: UIColor) -> UIColor {
    var bgR: CGFloat = 0
    var bgG: CGFloat = 0
    var bgB: CGFloat = 0
    var bgA: CGFloat = 0
    
    var fgR: CGFloat = 0
    var fgG: CGFloat = 0
    var fgB: CGFloat = 0
    var fgA: CGFloat = 0
    
    self.getRed(&bgR, green: &bgG, blue: &bgB, alpha: &bgA)
    overlay.getRed(&fgR, green: &fgG, blue: &fgB, alpha: &fgA)
    
    // Make averega OF RGB -> WORKS GREAT! :-)
    let r = (fgR + bgR) / 2
    let g = (fgG + bgG) / 2
    let b = (fgB + bgB) / 2
    
    return UIColor(red: r, green: g, blue: b, alpha: 1)
}
Oxheart answered 3/9, 2024 at 10:38 Comment(0)
C
-1

If you want to use purple color then its not a big deal.All the UIColor are rgb color.You can simply pass the RGB value for each color and can get the desired color.Use this link to convert hex value of any color to convert in UIColor. http://www.touch-code-magazine.com/web-color-to-uicolor-convertor/

like #color code for green is #008400: [UIColor colorWithRed:0 green:0.518 blue:0 alpha:1] /#008400/

Caitlin answered 30/10, 2012 at 4:52 Comment(0)

© 2022 - 2025 — McMap. All rights reserved.