Episode #406

Tinting an Image Using Masks

5 minutes
Published on August 15, 2019
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])

This episode uses Xcode 10.2.1, Swift 5.0.

Want more? Subscribers can view all 585 episodes. New episodes are released regularly.

Subscribe to get access →