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 converts int color
  • intvalue returns color's integer representation. i.e. reverse of hexcolor
  • 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

Popular posts from this blog

java - Static nested class instance -

c# - Bluetooth LE CanUpdate Characteristic property -

JavaScript - Replace variable from string in all occurrences -