有没有将UIColor转换为色调、饱和度和亮度的函数?

24

我可以使用RGB值设置UIColor:

[UIColor colorWithRed:0.53 green:0.37 blue:0.11 alpha:1.00];

我可以使用HSB值设置UIColor:

[UIColor colorWithHue:0.10 saturation:0.16 brightness:0.13 alpha:1.00];

我也可以将它转换回RGB:

CGFloat* colors = CGColorGetComponents(Color1.CGColor);

我应该如何从UIColor获取HSB?


1
可能是http://stackoverflow.com/questions/9142427/uicolor-conversion-from-rgb-to-hsv-set-brightness-to-uicolor的重复问题。https://dev59.com/g07Sa4cB1Zd3GeqP21xt http://stackoverflow.com/questions/1050874/how-do-i-convert-rgb-into-hsv-in-cocoa-touch也提供了解决方案。 - He Shiming
4个回答

47

使用 UIColor 的方法:getHue:saturation:brightness:alpha:

来自 Apple 文档:
"返回在 HSB 颜色空间中构成颜色的组件。"

- (BOOL)getHue:(CGFloat *)hue saturation:(CGFloat *)saturation brightness:(CGFloat *)brightness alpha:(CGFloat *)alpha

例子:

UIColor *testColor = [UIColor colorWithRed:0.53 green:0.37 blue:0.11 alpha:1.00];

CGFloat hue;
CGFloat saturation;
CGFloat brightness;
CGFloat alpha;
BOOL success = [testColor getHue:&hue saturation:&saturation brightness:&brightness alpha:&alpha];
NSLog(@"success: %i hue: %0.2f, saturation: %0.2f, brightness: %0.2f, alpha: %0.2f", success, hue, saturation, brightness, alpha);

NSLog输出:

成功:1 色调:0.10,饱和度:0.79,亮度:0.53,不透明度:1.00

这是由@WhiteTiger提供的方法的修正版本:

// Test values
CGFloat red = 0.53;
CGFloat green = 0.37;
CGFloat blue = 0.11;

CGFloat hue = 0;
CGFloat saturation = 0;
CGFloat brightness = 0;

CGFloat minRGB = MIN(red, MIN(green,blue));
CGFloat maxRGB = MAX(red, MAX(green,blue));

if (minRGB==maxRGB) {
    hue = 0;
    saturation = 0;
    brightness = minRGB;
} else {
    CGFloat d = (red==minRGB) ? green-blue : ((blue==minRGB) ? red-green : blue-red);
    CGFloat h = (red==minRGB) ? 3 : ((blue==minRGB) ? 1 : 5);
    hue = (h - d/(maxRGB - minRGB)) / 6.0;
    saturation = (maxRGB - minRGB)/maxRGB;
    brightness = maxRGB;
}
NSLog(@"hue: %0.2f, saturation: %0.2f, value: %0.2f", hue, saturation, brightness);

NSLog输出:

色调:0.10,饱和度:0.79,亮度:0.53


2
但是这个功能只能在5.0版本中启用。 - WhiteTiger
现在超过75%的iOS用户使用5.0版本,购买和/或更新应用程序的用户比例更高。如果需要低于5.0版本,请更新您的问题。 - zaph
你的变量完美运作,现在我正在使用iOS 5设备,据我所知它不会在之前的版本上工作?如果我需要iOS,我必须使用WhiteTiger的变量吗? - Horhe Garcia
1
WhiteTiger变体适用于任何iOS版本,而Apple的getHue:saturation:brightness:alpha:变体适用于iOS 5+。我之所以将WhiteTiger变体添加到我的答案中,仅是因为早期的WhiteTiger版本存在错误,现在已经纠正。 - zaph
你可以可能找到一个 Xcode 扩展,Alcatraz 是一个 Xcode 扩展管理器。 - zaph
显示剩余2条评论

28

这里有一个不错的方法,使用 Swift 的特性(扩展、计算属性和元组)在几行代码中完成相同的操作。

extension UIColor {
  var hsba: (h: CGFloat, s: CGFloat, b: CGFloat, a: CGFloat) {
    var hsba: (h: CGFloat, s: CGFloat, b: CGFloat, a: CGFloat) = (0, 0, 0, 0)
    self.getHue(&(hsba.h), saturation: &(hsba.s), brightness: &(hsba.b), alpha: &(hsba.a))
    return hsba
  }
}

Swift 3.2 / 4小更新

在Swift 3.2 / 4中,使用先前的代码会触发一个新的警告,因为您在同一次对getHue的调用中多次修改了hsba变量。

同时访问参数'hsba',但修改需要独占访问; 考虑将其复制到本地变量。

extension UIColor {
    var hsba: (h: CGFloat, s: CGFloat, b: CGFloat, a: CGFloat) {
        var h: CGFloat = 0, s: CGFloat = 0, b: CGFloat = 0, a: CGFloat = 0
        self.getHue(&h, saturation: &s, brightness: &b, alpha: &a)
        return (h: h, s: s, b: b, a: a)
    }
}

使用: self.inputUIImage?.getColors({(颜色)中 let hue = colors.primaryColor.hsba.h self.hueFilter?.hue = hue }) - drpawelo
谢谢,将这段代码打包为一个具有元组返回的扩展是非常好和有用的。 - Dan Rosenstark
1
你能给一个如何使用这个(Swift 3.1)的例子吗? - Tom

4

请注意这只是一个草稿,但如果您的版本低于5.0,您可以尝试此代码。

...
CGFloat computedH = 0;
CGFloat computedS = 0;
CGFloat computedV = 0;

CGFloat minRGB = MIN(r, MIN(g,b));
CGFloat maxRGB = MAX(r, MAX(g,b));

if (minRGB==maxRGB) {
   computedH = 0;
   computedS = 0;
   computedV = minRGB;
} else {
   double d = (r==minRGB) ? g-b : ((b==minRGB) ? r-g : b-r);
   double h = (r==minRGB) ? 3 : ((b==minRGB) ? 1 : 5);
   computedH = (60*(h - d/(maxRGB - minRGB))) / 360.;
   computedS = ((maxRGB - minRGB)/maxRGB);
   computedV = maxRGB;
}
...

注释:如果值已经是CGFloat,则行r=r/255.; g=g/255.; b=b/255.;是不必要的。最终的computedV需要除以360.0才能得到在0.0到1.0区间内的值。double类型可能更适合使用CGFloat - zaph
我纠正了你的转换程序,并将其与一个测试用例一起添加到我的答案中。 - zaph
有太多的除以360,computedScomputedV是不正确的。只有色调需要除以360,因为它是一个角度。 - zaph

1
只需使用以下代码片段,您就可以完全摆脱rgba和hsba转换。
extension UIColor {

/**
 Decomposes UIColor to its RGBA components
 */
var rgbColor: RGBColor {
    get {
        var red: CGFloat = 0, green: CGFloat = 0, blue: CGFloat = 0, alpha: CGFloat = 0
        self.getRed(&red, green: &green, blue: &blue, alpha: &alpha)
        return RGBColor(red: red, green: green, blue: blue, alpha: alpha)
    }
}

/**
 Decomposes UIColor to its HSBA components
 */
var hsbColor: HSBColor {
    var h: CGFloat = 0, s: CGFloat = 0, b: CGFloat = 0, a: CGFloat = 0
    self.getHue(&h, saturation: &s, brightness: &b, alpha: &a)
    return HSBColor(hue: h, saturation: s, brightness: b, alpha: a)
}

/**
 Holds the CGFloat values of HSBA components of a color
 */
public struct HSBColor {
    var hue: CGFloat
    var saturation: CGFloat
    var brightness: CGFloat
    var alpha: CGFloat

    var uiColor: UIColor {
        get {
            return UIColor(hue: hue, saturation: saturation, brightness: brightness, alpha: alpha)
        }
    }
}

/**
 Holds the CGFloat values of RGBA components of a color
 */
public struct RGBColor {
    var red: CGFloat
    var green: CGFloat
    var blue: CGFloat
    var alpha: CGFloat

    var uiColor: UIColor {
        get {
            return UIColor(red: red, green: green, blue: blue, alpha: alpha)
        }
    }
}
}

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