swift - Is the method of using the | bitwise operator to mix two colours correct? -
i building app allows users select 2 colors , see result of mixing them. example, user selects red (#ff0000) , blue (#0000ff) , result purple (#ff00ff).
i started trying writing 3 methods in uicolor
extension:
hexcolor
convertsint
colorintvalue
returns color's integer representation. i.e. reverse ofhexcolor
hexdescription
returns string representation of color, such "#ff00ff"
here implementations, in case needed:
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) }
then thought how can mix colors. first try average of hsv values:
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) }
but failed. when mix blue , yellow, #00ff7f should white.
then try average of int values:
public func mixwith2(color: uicolor) -> uicolor { let average = (self.intvalue() + color.intvalue()) / 2 return uicolor.hexcolor(int32(average)) }
but again, blue mix yellow not white using above method.
at end, decided use bitwise operators. tested |, & , ^. surprisingly, returns white!
uicolor.hexcolor(int32(uicolor.bluecolor().intvalue() | uicolor.yellowcolor().intvalue()))
and this:
uicolor.hexcolor(int32(uicolor.bluecolor().intvalue() ^ uicolor.yellowcolor().intvalue()))
i did other tests , method passed of them!
is correct (gives correct result time) method of mixing 2 colors? if yes, how work?
the short answer "no can't" in comments, perhaps easiest way of blending 2 colors using weighted average:
extension uicolor { func blend(rhs:uicolor, midpoint left:cgfloat = 0.50) -> nscolor { let right = 1.0 - left var lr : cgfloat = 0 var lg : cgfloat = 0 var lb : cgfloat = 0 var la : cgfloat = 0 getred(&lr, green: &lg, blue: &lb, alpha: &la) var rr : cgfloat = 0 var rg : cgfloat = 0 var rb : cgfloat = 0 var ra : cgfloat = 0 rhs.getred(&rr, green: &rg, blue: &rb, alpha: &ra) return uicolor( red: lr * left + rr * right, green: lg * left + rg * right, blue: lb * left + rb * right, alpha: la * left + ra * right ) } }
Comments
Post a Comment