在 Swift 中,通过将颜色与透明颜色叠加来计算没有透明度的颜色

Hix*_*eld 5 colors swift

颜色叠加

  • 我有一个原始的 UIView,它有一个非透明的颜色orgColor
  • 这是由overlayColor具有透明度(alpha 通道)的覆盖 UIView 覆盖的。

鉴于这两种颜色orgColoroverlayColor我如何计算calculatedColor应该有任何透明度但在屏幕上完全相同的颜色,然后就好像两个视图实际上会重叠一样?

我为此编写了一个骨架函数(以显示原理)。但不知道如何计算(我在堆栈溢出上找到了几篇关于颜色混合的帖子,但实际上没有一个会删除结果中的透明度......):

func calculateColor(orgColor: UIColor, overlayColor: 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))

    orgColor.getRed(&r1, green: &g1, blue: &b1, alpha: &a1)
    overlayColor.getRed(&r2, green: &g2, blue: &b2, alpha: &a2)

    //how to put the alpha in the r g b? and integrate the overlay r g b?

    return color
}
Run Code Online (Sandbox Code Playgroud)

vac*_*ama 5

叠加颜色 ( a2) 的 Alpha 告诉您颜色占总数的百分比,并(1 - a2)告诉您原始颜色占的百分比。由此看来,这是一个简单的计算:

func calculateColor(orgColor: UIColor, overlayColor: UIColor) -> UIColor {
    // Helper function to clamp values to range (0.0 ... 1.0)
    func clampValue(_ v: CGFloat) -> CGFloat {
        guard v > 0 else { return  0 }
        guard v < 1 else { return  1 }
        return v
    }

    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))

    orgColor.getRed(&r1, green: &g1, blue: &b1, alpha: &a1)
    overlayColor.getRed(&r2, green: &g2, blue: &b2, alpha: &a2)

    // Make sure the input colors are well behaved
    // Components should be in the range (0.0 ... 1.0)
    r1 = clampValue(r1)
    g1 = clampValue(g1)
    b1 = clampValue(b1)

    r2 = clampValue(r2)
    g2 = clampValue(g2)
    b2 = clampValue(b2)
    a2 = clampValue(a2)

    let color = UIColor(  red: r1 * (1 - a2) + r2 * a2,
                        green: g1 * (1 - a2) + g2 * a2,
                         blue: b1 * (1 - a2) + b2 * a2,
                        alpha: 1)

    return color
}
Run Code Online (Sandbox Code Playgroud)

直观上看,这是正确的。如果叠加颜色完全不透明 ( a2 == 1),则结果将是叠加颜色。如果叠加颜色完全透明 ( a2 == 0),则结果将是原始颜色。如果叠加颜色的 Alpha 为0.5,您将得到正好位于两种颜色中间的混合颜色。


在操场上测试它:

// Make these colors anything you want
let c1 = UIColor(red: 27/255, green: 155/255, blue: 199/255, alpha: 1.0)
let c2 = UIColor(red: 188/255, green: 13/255, blue: 51/255, alpha: 0.37)

let c3 = calculateColor(orgColor: c1, overlayColor: c2)

let view1 = UIView(frame: CGRect(x: 0, y: 0, width: 100, height: 100))
let view2 = UIView(frame: CGRect(x: 0, y: 0, width: 100, height: 100))

view1.backgroundColor = c1
view2.backgroundColor = c2

// Overlay view2 onto view1
view1.addSubview(view2)

// view3 has the calculated color
let view3 = UIView(frame: CGRect(x: 100, y: 0, width: 100, height: 100))
view3.backgroundColor = c3

// display the views side by side in view4
let view4 = UIView(frame: CGRect(x: 0, y: 0, width: 200, height: 100))
view4.addSubview(view1)
view4.addSubview(view3)

// display this view and see that the two halves match
view4
Run Code Online (Sandbox Code Playgroud)

游乐场输出:

游乐场输出