title: Colorize a UIImage in Swift
body: <p>I am trying to write an helper function that applies a color mask to a given image. My function has to set all opaque pixels of an image to the same color. </p>
  
  <p>Here is what I have so far :</p>
  
  <pre><code>extension UIImage {
  
      func applyColorMask(color: UIColor, context: CIContext) -&gt; UIImage {
  
          guard let cgImageInput = self.cgImage else {
              print("applyColorMask: \(self) has no cgImage attribute.")
              return self
          }
  
          // Throw away existing colors, and fill the non transparent pixels with the input color
          // s.r = dot(s, redVector), s.g = dot(s, greenVector), s.b = dot(s, blueVector), s.a = dot(s, alphaVector)
          // s = s + bias
          let colorFilter = CIFilter(name: "CIColorMatrix")!
          let ciColorInput = CIColor(cgColor: color.cgColor)
          colorFilter.setValue(CIVector(x: 0, y: 0, z: 0, w: 0), forKey: "inputRVector")
          colorFilter.setValue(CIVector(x: 0, y: 0, z: 0, w: 0), forKey: "inputGVector")
          colorFilter.setValue(CIVector(x: 0, y: 0, z: 0, w: 0), forKey: "inputBVector")
          colorFilter.setValue(CIVector(x: 0, y: 0, z: 0, w: 1), forKey: "inputAVector")
          colorFilter.setValue(CIVector(x: ciColorInput.red, y: ciColorInput.green, z: ciColorInput.blue, w: 0), forKey: "inputBiasVector")
          colorFilter.setValue(CIImage(cgImage: cgImageInput), forKey: kCIInputImageKey)
  
          if let cgImageOutput = context.createCGImage(colorFilter.outputImage!, from: colorFilter.outputImage!.extent) {
              return UIImage(cgImage: cgImageOutput)
          } else {
              print("applyColorMask: failed to apply filter to \(self)")
              return self
          }
      }
  }
  </code></pre>
  
  <p>The code works fine for black and white but not what I expected when applying  funnier colors. See the original image and the screenshots below: the same color is used for the border and for the image. Though they're different. My function is doing wrong. Did I miss something in the filter matrix ?</p>
  
  <p>The original image (there's white dot at the center):</p>
  
  <p><a href="https://i.stack.imgur.com/fCQOl.png" rel="nofollow noreferrer"><img src="https://i.stack.imgur.com/fCQOl.png" alt="Original pictures"></a></p>
  
  <p>From top to bottom: The image filtered with <code>UIColor(1.0, 1.0, 1.0, 1.0)</code> inserted into a UIImageView which has borders of the same color. Then the same with <code>UIColor(0.6, 0.5, 0.4, 1.0)</code>. And finally with <code>UIColor(0.2, 0.5, 1.0, 1.0)</code></p>
  
  <p><a href="https://i.stack.imgur.com/4IAsa.png" rel="nofollow noreferrer"><img src="https://i.stack.imgur.com/4IAsa.png" alt="Screenshot"></a></p>
  
  <hr>
  
  <p><strong>EDIT</strong></p>
  
  <p>Running <a href="https://github.com/rhoeper/Filterpedia-Swift4" rel="nofollow noreferrer">Filterpedia</a> gives me the same result. My understanding of the CIColorMatrix filter may be wrong then. The <a href="https://developer.apple.com/library/content/documentation/GraphicsImaging/Reference/CoreImageFilterReference/index.html#//apple_ref/doc/filter/ci/CIColorMatrix" rel="nofollow noreferrer">documentation</a> says:</p>
  
  <blockquote>
    <p>This filter performs a matrix multiplication, as follows, to transform
    the color vector:</p>
    
    <ul>
    <li>s.r = dot(s, redVector) </li>
    <li>s.g = dot(s, greenVector) </li>
    <li>s.b = dot(s, blueVector) </li>
    <li>s.a = dot(s, alphaVector) </li>
    <li>s = s + bias</li>
    </ul>
  </blockquote>
  
  <p>Then, let say I throw up all RGB data with (0,0,0,0) vectros, and then pass (0.5, 0, 0, 0) mid-red as the bias vector; I would expect my image to have all its fully opaque pixels to (127, 0, 0). The screenshots below shows that it is slightly lighter (red=186):</p>
  
  <p><a href="https://i.stack.imgur.com/RQQVK.png" rel="nofollow noreferrer"><img src="https://i.stack.imgur.com/RQQVK.png" alt="Fliterpedia screenshot"></a></p>
  
  <p>Here is some pseudo code I want to do:</p>
  
  <pre><code>// image "im" is a vector of pixels
  // pixel "p" is struct of rgba values
  // color "col" is the input color or a struct of rgba values
  for (p in im) {
      p.r = col.r
      p.g = col.g
      p.b = col.b
      // Nothing to do with the alpha channel
  }
  </code></pre>