Tinting an Image Using Masks

Episode #406 | 5 minutes | published on August 15, 2019 | Uses Xcode-10.2.1, Swift-5.0
Free Video
Sometimes we need to create variants of our icons. This can be done by using template images and using a UIImageView with a tintColor change, however sometimes this isn't feasible. We can use our icons along with a mask to create new images of whatever color we want. In this episode we'll use UIGraphicsImageRenderer to quickly draw a new dimmed image for a highlighted button state.

Tinting an Image

We will start by creating an extension on UIImage that will take a color and return a new UIImage. The source image will be used as a mask, using the alpha channel only to decide what pixels actually get drawn.

We will use cgImage property and initialize a renderer using UIGraphicsImageRenderer. Next, we will create a context from renderer and map the mask into the specified bounds using clip. Next we will set the fill color and fill the context with the selected color.

func tint(color: UIColor) -> UIImage {
    let maskImage = cgImage
    let bounds = CGRect(origin: .zero, size: size)

    let renderer = UIGraphicsImageRenderer(size: size)
    return renderer.image { context in
        let cgContext = context.cgContext
        cgContext.clip(to: bounds, mask: maskImage!)
        color.setFill()
        cgContext.fill(bounds)
    }
}

Using the Tint Image

In PlayerViewController, we will replace our pauseImage with a dimmed purple color tintedImage for the highlighted button states.

let tintedImage = pauseImage?.tint(color: Theme.Colors.purpleDimmed)
playPauseButton.setImage(tintedImage, for: [.selected, .highlighted])
blog comments powered by Disqus