是使用|的方法按位运算符混合两种颜色是否正确?

时间:2016-04-01 03:45:22

标签: swift colors bitwise-operators

我正在构建一个应用程序,允许用户选择两种颜色并查看混合它们的结果。例如,用户选择红色(#ff0000)和蓝色(#0000ff),结果为紫色(#ff00ff)。

我开始尝试在UIColor扩展名中编写3种方法:

  • hexColorInt转换为颜色
  • intValue返回颜色的整数表示。即hexColor
  • 的反面
  • hexDescription返回颜色的字符串表示形式,例如“#ff00ff”

以下是实现,以防万一:

public static func hexColor(hex: Int32) -> UIColor {
    return UIColor.init(red: CGFloat((hex>>16)&0xFF) / 255.0, green: CGFloat((hex>>8)&0xFF) / 255.0, blue: CGFloat(hex&0xFF) / 255.0, alpha: 1.0)
}

public func intValue() -> Int {
    var hexString = self.hexDescription()
    hexString = hexString.substringFromIndex(hexString.startIndex.successor())
    return Int(hexString, radix: 16)!
}

public func hexDescription() -> String {
    var rF: CGFloat = 0,
    gF: CGFloat = 0,
    bF: CGFloat = 0,
    aF: CGFloat = 0
    self.getRed(&rF, green: &gF, blue: &bF, alpha: &aF)
    let r = Int(rF * 255.0)
    let g = Int(gF * 255.0)
    let b = Int(bF * 255.0)

    return "#" + String(format: "%02x%02x%02x", r, g, b)
}

然后我想到如何实际混合颜色。我的第一个尝试是获得HSV值的平均值:

public func mixWith(color: UIColor) -> UIColor {
    var myHue: CGFloat = 0
    var mySat: CGFloat = 0
    var myVal: CGFloat = 0
    var otherHue: CGFloat = 0
    var otherSat: CGFloat = 0
    var otherVal: CGFloat = 0
    self.getHue(&myHue, saturation: &mySat, brightness: &myVal, alpha: nil)
    color.getHue(&otherHue, saturation: &otherSat, brightness: &otherVal, alpha: nil)

    let averageHue = (myHue + otherHue) / 2.0
    let averageSat = (mySat + otherSat) / 2.0
    let averageVal = (myVal + otherVal) / 2.0

    return UIColor(hue: averageHue, saturation: averageSat, brightness: averageVal, alpha: 1.0)
}

但这失败了。当我混合蓝色和黄色时,我得到#00ff7f,但它应该是白色的。

然后我尝试获取int值的平均值:

public func mixWith2(color: UIColor) -> UIColor {
    let average = (self.intValue() + color.intValue()) / 2
    return UIColor.hexColor(Int32(average))
}

但是,使用上述方法,蓝色混合黄色白色。

最后,我决定使用按位运算符。我测试了|,&和^。令人惊讶的是,这会返回白色!

UIColor.hexColor(Int32(UIColor.blueColor().intValue() | 
    UIColor.yellowColor().intValue()))

这样做:

UIColor.hexColor(Int32(UIColor.blueColor().intValue() ^ 
    UIColor.yellowColor().intValue()))

我做了一些其他测试,这个方法通过了所有测试!

这是一种正确的(一直给出正确的结果)混合两种颜色的方法吗?如果是的话,它是如何运作的?

1 个答案:

答案 0 :(得分:1)

简短的回答是“不,你不能”,如评论,也许最简单的混合两种颜色的方法是使用加权平均值:

activity_main.xml