在Swift中混合使用UIColors

Dra*_*lex 6 colors color-blending sprite-kit skspritenode swift

我有两个SKSpriteNode,它们的颜色定义如下:

colorNode[0].color = UIColor(red: 255, green: 0, blue: 0, alpha: 1)
colorNode[1].color = UIColor(red: 0, green: 255, blue: 0, alpha: 1)
Run Code Online (Sandbox Code Playgroud)

我想让第三个SKSpriteNode用前两个的混合着色,结果应该是这样的:

colorNode[2].color = UIColor(red: 255, green: 255, blue: 0, alpha: 1)
Run Code Online (Sandbox Code Playgroud)

但有没有办法添加两个UIColors?像这样 :

colorNode[2].color = colorNode[0].color + colorNode[1].color
Run Code Online (Sandbox Code Playgroud)

vac*_*ama 7

这样的事情怎么样:

func addColor(_ color1: UIColor, with color2: 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))

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

    // add the components, but don't let them go above 1.0
    return UIColor(red: min(r1 + r2, 1), green: min(g1 + g2, 1), blue: min(b1 + b2, 1), alpha: (a1 + a2) / 2)
}

func multiplyColor(_ color: UIColor, by multiplier: CGFloat) -> UIColor {
    var (r, g, b, a) = (CGFloat(0), CGFloat(0), CGFloat(0), CGFloat(0))
    color.getRed(&r, green: &g, blue: &b, alpha: &a)
    return UIColor(red: r * multiplier, green: g * multiplier, blue: b * multiplier, alpha: a)
}
Run Code Online (Sandbox Code Playgroud)

定义运算符以添加颜色并将颜色乘以Double:

func +(color1: UIColor, color2: UIColor) -> UIColor {
    return addColor(color1, with: color2)
}

func *(color: UIColor, multiplier: Double) -> UIColor {
    return multiplyColor(color, by: CGFloat(multiplier))
}
Run Code Online (Sandbox Code Playgroud)

然后你可以混合这样的颜色:

// Make orange with 50% red and 50% yellow    
let orange = .red * 0.5 + .yellow * 0.5

// Make light gray with 25% black and 75% white
let lightGray = .black * 0.25 + .white * 0.75

// Make sky blue by lightening a combination of 25% blue and 75% cyan
let skyBlue = (.blue * 0.25 + .cyan * 0.75) * 0.25 + .white * 0.75

// Make dark red by combining 50% red and 50% black
let darkRed = .red * 0.50 + .black * 0.50

// Make purple from 60% blue and 40% red
let purple = (.blue * 0.60 + .red * 0.40)

// Then make lavender from 25% purple and 75% white
let lavender = purple * 0.25 + .white * 0.75
Run Code Online (Sandbox Code Playgroud)


Ber*_*lor 6

Swift3版本,具有更多防护和细粒度调整功能的扩展:

extension UIColor {
    static func blend(color1: UIColor, intensity1: CGFloat = 0.5, color2: UIColor, intensity2: CGFloat = 0.5) -> UIColor {
        let total = intensity1 + intensity2
        let l1 = intensity1/total
        let l2 = intensity2/total
        guard l1 > 0 else { return color2}
        guard l2 > 0 else { return color1}
        var (r1, g1, b1, a1): (CGFloat, CGFloat, CGFloat, CGFloat) = (0, 0, 0, 0)
        var (r2, g2, b2, a2): (CGFloat, CGFloat, CGFloat, CGFloat) = (0, 0, 0, 0)

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

        return UIColor(red: l1*r1 + l2*r2, green: l1*g1 + l2*g2, blue: l1*b1 + l2*b2, alpha: l1*a1 + l2*a2)
    }
}
Run Code Online (Sandbox Code Playgroud)


小智 6

代码已经实现了photoshop的所有图层混合。如果对你有用,别忘了给我一个开始。玩得开心~

\n\n

GitHub: https: //github.com/Orange-W/PhotoshopBending

\n\n
import Foundation\nimport UIKit\n\nextension UIColor {\n    // MARK: - \xe5\xb8\xb8\xe7\x94\xa8\xe5\x8f\xa0\xe5\x9b\xbe\n    // Alpha Blending \xe5\x89\x8d\xe6\x99\xaf\xe8\x89\xb2\xe5\x8f\xa0\xe5\x9b\xbe\n    func blendAlpha(coverColor: UIColor) -> UIColor {\n        let c1 = coverColor.rgbaTuple()\n        let c2 = self.rgbaTuple()\n\n        let c1r = CGFloat(c1.r)\n        let c1g = CGFloat(c1.g)\n        let c1b = CGFloat(c1.b)\n\n        let c2r = CGFloat(c2.r)\n        let c2g = CGFloat(c2.g)\n        let c2b = CGFloat(c2.b)\n\n        // \xe5\x89\x8d\xe6\x99\xaf\xe8\x89\xb2\xe5\x8f\xa0\xe5\x9b\xbe\xe5\x85\xac\xe5\xbc\x8f\n        let r = c1r * c1.a + c2r  * (1 - c1.a)\n        let g = c1g * c1.a + c2g  * (1 - c1.a)\n        let b = c1b * c1.a + c2b  * (1 - c1.a)\n\n        return UIColor.init(red: r/255.0, green: g/255.0, blue: b/255.0, alpha: 1.0)\n    }\n\n\n    // MARK: - \xe5\x8e\xbb\xe4\xba\xae\xe5\xba\xa6\xe5\x9e\x8b\n    /// Darken \xe5\x8f\x98\xe6\x9a\x97  B<=A: C=B; B>=A: C=A\n    func blendDarken(coverColor: UIColor,alpha: CGFloat = 1.0) -> UIColor {\n        return blendProcedure(coverColor: coverColor, alpha: alpha) { return ($0 <= $1) ? $0 : $1 }\n    }\n\n    /// Multiply \xe6\xad\xa3\xe7\x89\x87\xe5\x8f\xa0\xe5\xba\x95 C = A*B\n    func blendMultiply(coverColor: UIColor,alpha: CGFloat = 1.0) -> UIColor {\n        return blendProcedure(coverColor: coverColor, alpha: alpha) { return $0 * $1 }\n    }\n\n    /// Color Burn \xe9\xa2\x9c\xe8\x89\xb2\xe5\x8a\xa0\xe6\xb7\xb1 C=1-(1-B)/A\n    func blendColorBurn(coverColor: UIColor,alpha: CGFloat = 1.0) -> UIColor {\n        return blendProcedure(coverColor: coverColor, alpha: alpha) { return 1 - (1 - $0) / $1 }\n    }\n\n    /// Linear Burn \xe7\xba\xbf\xe6\x80\xa7\xe5\x8a\xa0\xe6\xb7\xb1 C=A+B-1\n    func blendLinearBurn(coverColor: UIColor,alpha: CGFloat = 1.0) -> UIColor {\n        return blendProcedure(coverColor: coverColor, alpha: alpha) { return ($1 + $0) - 1.0 }\n    }\n\n    // MARK: - \xe5\x8e\xbb\xe6\x9a\x97\xe5\x9e\x8b\n    /// Lighten \xe5\x8f\x98\xe4\xba\xae   B>=A: C=B; B<=A: C=A\n    func blendLighten(coverColor: UIColor,alpha: CGFloat = 1.0) -> UIColor {\n        return blendProcedure(coverColor: coverColor, alpha: alpha) { return ($0 >= $1) ? $0 : $1 }\n    }\n\n    /// Screen \xe6\xbb\xa4\xe8\x89\xb2 C=1-(1-A)*(1-B), \xe4\xb9\x9f\xe5\x8f\xaf\xe4\xbb\xa5\xe5\x86\x99\xe6\x88\x90 1-C=(1-A)*(1-B)\n    func blendScreen(coverColor: UIColor,alpha: CGFloat = 1.0) -> UIColor {\n        return blendProcedure(coverColor: coverColor, alpha: alpha) { return 1 - (1 - $1) * (1 - $0) }\n    }\n\n    /// Color Dodge \xe9\xa2\x9c\xe8\x89\xb2\xe5\x87\x8f\xe6\xb7\xa1 C=B/(1-A)\n    func blendColorDodge(coverColor: UIColor,alpha: CGFloat = 1.0) -> UIColor {\n        return blendProcedure(coverColor: coverColor, alpha: alpha) {\n            if $1 >= 1.0 { return $1 }\n            else { return min(1.0, $0 / (1 - $1)) }\n        }\n    }\n\n    /// Linear Dodge \xe7\xba\xbf\xe6\x80\xa7\xe5\x87\x8f\xe6\xb7\xa1 C=A+B\n    func blendLinearDodge(coverColor: UIColor,alpha: CGFloat = 1.0) -> UIColor {\n        return blendProcedure(coverColor: coverColor, alpha: alpha) { return min(1, $1 + $0) }\n    }\n\n\n    // MARK: - \xe6\xba\xb6\xe5\x90\x88\xe5\x9e\x8b\n    /// Overlay \xe5\x8f\xa0\xe5\x8a\xa0 B<=0.5: C=2*A*B; B>0.5: C=1-2*(1-A)*(1-B)\n    func blendOverlay(coverColor: UIColor,alpha: CGFloat = 1.0) -> UIColor {\n        return blendProcedure(coverColor: coverColor, alpha: alpha) {\n            if $0 <= 0.5 { return 2 * $1 * $0 }\n            else { return 1 - 2 * (1 - $1) * (1 - $0) }\n        }\n    }\n\n    /// Soft Light \xe6\x9f\x94\xe5\x85\x89 A<=0.5: C=(2*A-1)*(B-B*B)+B; A>0.5: C=(2*A-1)*(sqrt(B)-B)+B\n    func blendSoftLight(coverColor: UIColor,alpha: CGFloat = 1.0) -> UIColor {\n        return blendProcedure(coverColor: coverColor, alpha: alpha) {\n            if $1 <= 0.5 { return (2 * $1 - 1) * ($0 - $0 * $0) + $0 }\n            else { return (2 * $1 - 1)*( sqrt($0) - $0) + $0 }\n        }\n    }\n\n    /// Hard Light \xe5\xbc\xba\xe5\x85\x89 A<=0.5: C=2*A*B; A>0.5: C=1-2*(1-A)*(1-B)\n    func blendHardLight(coverColor: UIColor,alpha: CGFloat = 1.0) -> UIColor {\n        return blendProcedure(coverColor: coverColor, alpha: alpha) {\n            if $1 <= 0.5 { return 2 * $1 * $0 }\n            else { return 1 - 2 * (1 - $1) * (1 - $0) }\n        }\n    }\n\n    /// Vivid Light \xe4\xba\xae\xe5\x85\x89 A<=0.5: C=1-(1-B)/(2*A); A>0.5: C=B/(2*(1-A))\n    func blendVividLight(coverColor: UIColor,alpha: CGFloat = 1.0) -> UIColor {\n        return blendProcedure(coverColor: coverColor, alpha: alpha) {\n            if $1 <= 0.5 { return self.fitIn((1 - (1 - $0) / (2 * $1)), ceil: 1.0) }\n            else { return self.fitIn($0 / (2 * (1 - $1)), ceil: 1.0) }\n        }\n    }\n\n    /// Linear Light \xe7\xba\xbf\xe6\x80\xa7\xe5\x85\x89 C=B+2*A-1\n    func blendLinearLight(coverColor: UIColor,alpha: CGFloat = 1.0) -> UIColor {\n        return blendProcedure(coverColor: coverColor, alpha: alpha) { return self.fitIn($0 + 2 * $1 - 1, ceil: 1.0) }\n    }\n\n    /// Pin Light \xe7\x82\xb9\xe5\x85\x89\n    /// B<2*A-1:     C=2*A-1\n    /// 2*A-1<B<2*A: C=B\n    /// B>2*A:       C=2*A\n    func blendPinLight(coverColor: UIColor,alpha: CGFloat = 1.0) -> UIColor {\n        return blendProcedure(coverColor: coverColor, alpha: alpha) {\n            if $0 <= 2 * $1 - 1 { return 2 * $1 - 1 }\n            else if (2 * $1 - 1 < $0) && ($0 < 2 * $1) { return $0}\n            else { return 2 * $1 }\n        }\n    }\n\n    /// Hard Mix \xe5\xae\x9e\xe8\x89\xb2\xe6\xb7\xb7\xe5\x90\x88A<1-B: C=0; A>1-B: C=1\n    func blendHardMix(coverColor: UIColor,alpha: CGFloat = 1.0) -> UIColor {\n        return blendProcedure(coverColor: coverColor, alpha: alpha) {\n            if $1 <= 1 - $0 { return 0 }\n            else { return 1 }\n        }\n    }\n\n    // MARK: - \xe8\x89\xb2\xe5\xb7\xae\xe5\x9e\x8b\n    /// Difference \xe5\xb7\xae\xe5\x80\xbc C=|A-B|\n    func blendDifference(coverColor: UIColor,alpha: CGFloat = 1.0) -> UIColor {\n        return blendProcedure(coverColor: coverColor, alpha: alpha) { fabs($1 - $0) }\n    }\n\n    /// Exclusion \xe6\x8e\x92\xe9\x99\xa4 C = A+B-2*A*B\n    func blendExclusion(coverColor: UIColor,alpha: CGFloat = 1.0) -> UIColor {\n        return blendProcedure(coverColor: coverColor, alpha: alpha) { $1 + $0 - 2 * $1 * $0  }\n    }\n\n    /// \xe5\x87\x8f\xe5\x8e\xbb C=A-B\n    func blendMinus(coverColor: UIColor,alpha: CGFloat = 1.0) -> UIColor {\n        return blendProcedure(coverColor: coverColor, alpha: alpha) { $1 - $0 }\n    }\n\n    /// \xe5\x88\x92\xe5\x88\x86 C=A/B\n    func blendDivision(coverColor: UIColor,alpha: CGFloat = 1.0) -> UIColor {\n        return blendProcedure(coverColor: coverColor, alpha: alpha) {\n            if $0 == 0{\n                return 1.0\n            }else {\n                return self.fitIn($1 / $0, ceil: 1.0)\n            }\n        }\n    }\n\n    // MARK: \xe5\xa4\x84\xe7\x90\x86\xe5\x87\xbd\xe6\x95\xb0\n    func blendProcedure(\n        coverColor: UIColor,\n        alpha: CGFloat,\n        procedureBlock: ((_ baseValue: CGFloat,_ topValue: CGFloat) -> CGFloat)?\n        ) -> UIColor {\n        let baseCompoment = self.rgbaTuple()\n        let topCompoment = coverColor.rgbaTuple()\n\n        // \xe8\xaf\xa5\xe5\xb1\x82\xe9\x80\x8f\xe6\x98\x8e\xe5\xba\xa6\n        let mixAlpha = alpha * topCompoment.a + (1.0 - alpha) * baseCompoment.a\n\n        // RGB \xe5\x80\xbc\n        let mixR = procedureBlock?(\n            baseCompoment.r / 255.0,\n            topCompoment.r / 255.0)\n            ?? (baseCompoment.r) / 255.0\n\n        let mixG = procedureBlock?(\n            baseCompoment.g / 255.0,\n            topCompoment.g / 255.0)\n            ?? (baseCompoment.g) / 255.0\n\n        let mixB = procedureBlock?(\n            baseCompoment.b / 255.0,\n            topCompoment.b / 255.0)\n            ?? baseCompoment.b / 255.0\n\n\n        return UIColor.init(red:   fitIn(mixR),\n                            green: fitIn(mixG),\n                            blue:  fitIn(mixB),\n                            alpha: mixAlpha)\n    }\n\n    // \xe9\x98\xb2\xe6\xad\xa2\xe8\xb6\x8a\xe7\x95\x8c\n    func fitIn(_ value: CGFloat, ceil: CGFloat = 255) -> CGFloat { return max(min(value,ceil),0) }\n    func fitIn(_ value: Double, ceil: CGFloat = 255) -> CGFloat { return fitIn(CGFloat(value), ceil: ceil) }\n\n    // \xe8\xbf\x94\xe5\x9b\x9e RBGA\n    func rgbaTuple() -> (r: CGFloat, g: CGFloat, b: CGFloat,a: CGFloat) {\n        var r: CGFloat = 0\n        var g: CGFloat = 0\n        var b: CGFloat = 0\n        var a: CGFloat = 0\n        self.getRed(&r, green: &g, blue: &b, alpha: &a)\n        r = r * 255\n        g = g * 255\n        b = b * 255\n\n        return ((r),(g),(b),a)\n    }\n}\n
Run Code Online (Sandbox Code Playgroud)\n