I have made a helper struct
in Swift that creates circular icons from a PNG image (a white icon on transparent background) and a background UIColor
. These variables are user-definable in my app, and the created icons are used in notifications and Spotlight, for example.
The PNG images are named iconA.png
, iconB.png
etc. and are all a standard 100-points square. The default image is a fully transparent one called iconEmpty.png
. I wanted to provide a CGSize
argument so that I could use this method for other purposes as well, should the need arise.
It works as expected, but I am wondering how it might be improved or made more efficient, as I am not very experienced with drawing contexts.
import UIKit
struct IconMaker {
func makeIcon(with color: UIColor, size: CGSize, icon: UIImage = UIImage(named: "iconEmpty.png")!) -> UIImage {
// Make solid color background
let rect = CGRect(x: 0, y: 0, width: size.width, height: size.height)
UIGraphicsBeginImageContextWithOptions(size, false, UIScreen.main.scale)
color.setFill()
UIRectFill(rect)
let backgroundImage: UIImage = UIGraphicsGetImageFromCurrentImageContext()!
UIGraphicsEndImageContext()
// Add other image (which has transparency)
UIGraphicsBeginImageContextWithOptions(size, false, UIScreen.main.scale)
backgroundImage.draw(in: rect, blendMode: .normal, alpha: 1)
icon.draw(in: rect, blendMode: .normal, alpha: 1)
let newImage: UIImage = UIGraphicsGetImageFromCurrentImageContext()!
UIGraphicsEndImageContext()
// Circular mask
let cornerRadius = newImage.size.height/2
UIGraphicsBeginImageContextWithOptions(size, false, UIScreen.main.scale)
let bounds = CGRect(origin: CGPoint.zero, size: size)
UIBezierPath(roundedRect: bounds, cornerRadius: cornerRadius).addClip()
newImage.draw(in: bounds)
let finalImage = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
return finalImage!
}
}