如何从一个UIColor对象中获取红、绿、蓝(RGB)和alpha值?

59

我从这个方法中得到了一个UIColor:

- (UIColor *)getUserSelectedColor {   
    return [UIColor colorWithRed:redSlider.value green:greenSlider.value blue:blueSlider.value alpha:1.0];
}

并以以下方式获取颜色:

UIColor *selectedColor = [(ColorPickerView *)alertView getUserSelectedColor];

现在我想从selectedColor中获取红色、绿色和蓝色,以便使用这些值。我希望这些值在0到1之间。


8
顺便提一下,你应该关注命名规范。getColor有两个问题:首先它使用了Java开发者常犯的get前缀错误;其次它没有描述颜色的类型。更好的名称可能是userSelectedColor。看看UIKit命名getter和属性的方式,并效仿它们。 - PeyloW
@PeyloW,为什么userSelectedColorgetUserSelectedColor更好地描述了“颜色的种类”?请注意,没有get前缀,它们是完全相同的。我个人不理解为什么苹果建议不要使用get前缀。在某些情况下,我会使用它来实现更容易的自动完成,并避免与私有API可能发生的冲突。例如,我对UIColor进行了分类,我可以轻松地键入[UIColor get并查看所有方法的列表。如果我想要一个深红色,darkRedColor会导致问题,如果苹果也决定添加它,但getDarkRedColor不会。 - Iulian Onofrei
10个回答

120

访问SelectedColor.CGColor时崩溃的原因可能是您没有保留getColor的结果,也许您需要的是:

SelectedColor = [[(ColorPickerView *)alertView getColor] retain];

只有在使用RGB颜色空间的UIColor上,您才能获取RGB颜色分量,因为您正在使用colorWithRed:green:blue:alpha:,所以这不是问题,但如果您的代码更改,请注意此事项。

考虑到这一点,获取颜色分量非常容易:

const CGFloat* components = CGColorGetComponents(SelectedColor.CGColor);
NSLog(@"Red: %f", components[0]);
NSLog(@"Green: %f", components[1]); 
NSLog(@"Blue: %f", components[2]);
NSLog(@"Alpha: %f", CGColorGetAlpha(SelectedColor.CGColor));

像遮盖圆角之类的吗?当然可以添加一个新问题。 - PeyloW
嗨PeyloW!我使用的是同样的代码,但当我传入黑色时它返回绿色的分量。你知道这是为什么吗?你也可以在这里看到我的帖子-> https://dev59.com/sVHTa4cB1Zd3GeqPUs_F - Ganesh
1
@Ganesh - 这仅适用于 RGB 颜色,+[UIColor blackColor] 不是一个 RGB 颜色,只有一个亮度颜色分量。 - PeyloW
1
我提出了一种解决方案,考虑到非RGB颜色。 - Willster

23

此解决方案也适用于非RGB颜色,例如黑色或白色。

UIColor *color = [UIColor blackColor];
CGFloat red = 0.0, green = 0.0, blue = 0.0, alpha = 0.0;
// iOS 5
if ([color respondsToSelector:@selector(getRed:green:blue:alpha:)]) {
     [color getRed:&red green:&green blue:&blue alpha:&alpha];
} else {
     // < iOS 5
     const CGFloat *components = CGColorGetComponents(color.CGColor);
     red = components[0];
     green = components[1];
     blue = components[2];
     alpha = components[3];
}

// This is a non-RGB color
if(CGColorGetNumberOfComponents(color.CGColor) == 2) {
    CGFloat hue;
    CGFloat saturation;
    CGFloat brightness;
    [color getHue:&hue saturation:&saturation brightness:&brightness alpha:&alpha];

}

“非RGB”代码块仅适用于iOS5及以上版本。您可能希望将其标记为此类版本。 - Ivan Vučica

12

有一个Swift扩展可以解决这个问题 :)

extension UIColor {

    var rgba: (red: CGFloat, green: CGFloat, blue: CGFloat, alpha: CGFloat) {
        var red: CGFloat = 0.0
        var green: CGFloat = 0.0
        var blue: CGFloat = 0.0
        var alpha: CGFloat = 0.0
        getRed(&red, green: &green, blue: &blue, alpha: &alpha)

        return (red: red, green: green, blue: blue, alpha: alpha)
    }

    var redComponent: CGFloat {
        var red: CGFloat = 0.0
        getRed(&red, green: nil, blue: nil, alpha: nil)

        return red
    }

    var greenComponent: CGFloat {
        var green: CGFloat = 0.0
        getRed(nil, green: &green, blue: nil, alpha: nil)

        return green
    }

    var blueComponent: CGFloat {
        var blue: CGFloat = 0.0
        getRed(nil, green: nil, blue: &blue, alpha: nil)

        return blue
    }

    var alphaComponent: CGFloat {
        var alpha: CGFloat = 0.0
        getRed(nil, green: nil, blue: nil, alpha: &alpha)

        return alpha
    }
}

它与Swift 4.2兼容,也可以使用黑色、灰色等2个组件颜色。 您可以像这样访问特定的通道:

myColor.rgba.blue

或者,它的等价形式:

myColor.blueComponent

8

大多数情况下这将起作用,除非转换为RGB无法工作。

float red, green, blue, alpha;
BOOL conversionToRGBWentOk = [color getRed:&red green:&green blue:&blue alpha:&alpha];

事实上,正是这些方法的作用。不过,如果conversionToRGBWentOkNO,您就会有问题。


1
谢谢,你的解决方案是我见过的最好的。 - Yunus Nedim Mehel
1
但它会在我的iOS4.3模拟器上导致崩溃。它是IOS5+兼容的。 - Yunus Nedim Mehel

4

我认为你应该在这里看一下,阅读Ars指南,学习如何扩展UIColor类以支持访问颜色组件。


2

你只需要简单地执行这个操作

CGFloat red,green,blue,alpha;

[UIColorobject getRed:&red green:&green blue:&blue alpha:&alpha];

在红色、绿色、蓝色和透明度上,您可以得到RGB值。

如果您有任何问题,请问......

谢谢。


1
这段代码应该适用于RGB和灰度图像:
CGFloat *components = (CGFloat *) CGColorGetComponents(<UIColor instance>.CGColor);
if(CGColorGetNumberOfComponents(<UIColor instance>.CGColor) == 2)
{
  //assuming it is grayscale - copy the first value
  components[2] = components[1] = components[0];
}

1

我认为这是一种可行的方法。如果您还需要使用alpha参数,可以像对R、G和B进行插值一样从输入中插值alpha。

- (UIColor *)getColorBetweenColor:(UIColor *)color1 andColor:(UIColor *)color2 percentage:(CGFloat)percent {
    CGFloat red1, green1, blue1, alpha1;
    CGFloat red2, green2, blue2, alpha2;

    [color1 getRed:&red1 green:&green1 blue:&blue1 alpha:&alpha1];
    [color2 getRed:&red2 green:&green2 blue:&blue2 alpha:&alpha2];

    double resultRed = red1 + percent * (red2 - red1);
    double resultGreen = green1 + percent * (green2 - green1);
    double resultBlue = blue1 + percent * (blue2 - blue1);

    return [UIColor colorWithRed:resultRed green:resultGreen blue:resultBlue alpha:1];
}

0

这里是我为此和其他颜色控件制作的一些有用的宏:

在您的情况下,您只需要使用

getRGBA(myColor, red, green, blue, alpha);

NSLog(@"Red Value: %f", red);
NSLog(@"Blue Value: %f", green);
NSLog(@"Green Value: %f", blue);

宏:

#define rgba(r,g,b,a) [UIColor colorWithRed:((float)(r))/255.0f green:((float)(g))/255.0f blue:((float)(b))/255.0f alpha:a]
#define rgb(r,g,b) rgba(r, g, b, 1.0f)

#define rgbaf(r,g,b,a) [UIColor colorWithRed:(r) green:(g) blue:(b) alpha:a]
#define rgbf(r,g,b) rgbaf(r, g, b, 1.0f)

#define rgba_fromColor(__color, __r, __g, __b, __a) \
CGFloat __r, __g, __b, __a;\
UIColor *__unpackedColor = [NSKeyedUnarchiver unarchiveObjectWithData:[NSKeyedArchiver archivedDataWithRootObject:__color]];/*Bring system colors into compatible color-space (e.g. DarkGrayColor)*/\
[__unpackedColor getRed:&__r green:&__g blue:&__b alpha:&__a];
#define getRGBA(__color, __r, __g, __b, __a) rgba_fromColor(__color, __r, __g, __b, __a)

#define getRed(__color)  (\
(^float (void){\
rgba_fromColor(__color, r, g, b, a);\
return r;\
})()\
)

#define getGreen(__color)  (\
(^float (void){\
rgba_fromColor(__color, r, g, b, a);\
return g;\
})()\
)

#define getBlue(__color)  (\
(^float (void){\
rgba_fromColor(__color, r, g, b, a);\
return b;\
})()\
)

#define getAlpha(__color)  (\
(^float (void){\
rgba_fromColor(__color, r, g, b, a);\
return a;\
})()\
)










#define hsba(h,s,b,a) [UIColor colorWithHue:((float)(h))/360.0f saturation:((float)(s))/100.0f brightness:((float)(b))/100.0f alpha:a]
#define hsb(h,s,b) hsba(h, s, b, 1.0f)

#define hsbaf(h,s,b,a) [UIColor colorWithHue:(h) saturation:(s) brightness:(b) alpha:a]
#define hsbf(h,s,b) rgbaf(h, s, b, 1.0f)

#define hsba_fromColor(__color, __h, __s, __b, __a) \
CGFloat __h, __s, __b, __a;\
UIColor *__unpackedColor = [NSKeyedUnarchiver unarchiveObjectWithData:[NSKeyedArchiver archivedDataWithRootObject:__color]];/*Bring system colors into compatible color-space (e.g. DarkGrayColor)*/\
[__unpackedColor getHue:&__h saturation:&__s brightness:&__b alpha:&__a];
#define getHSBA(__color, __h, __s, __b, __a) hsba_fromColor(__color, __h, __s, __b, __a)

#define getHue(__color)  (\
(^float (void){\
hsba_fromColor(__color, h, s, b, a);\
return h;\
})()\
)

#define getSaturation(__color)  (\
(^float (void){\
hsba_fromColor(__color, h, s, b, a);\
return s;\
})()\
)

#define getBrightness(__color)  (\
(^float (void){\
hsba_fromColor(__color, h, s, b, a);\
return b;\
})()\
)

/*
///already defined in RGBA macros
#define getAlpha(__color)  (\
(^float (void){\
hsba_fromColor(__color, h, s, b, a);\
return a;\
})()\
)
*/

0
只需像示例中所示添加属性ColorLiteral。 Xcode将提示您选择整个颜色列表。
self.view.backgroundColor = ColorLiteral 

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接