Search code examples
iosswiftuiimageuitabbarcontrolleruitabbaritem

Low Quality TabBarItem Image


I have a tabbarcontroller and for one of the tabbaritem images, it displays blurry and of low quality. As this image is a profile image and can vary from user input, I have helper functions to assist in squaring, resizing and rounding the image.

I couldn't come across any SO answers that resolved this issue, any thoughts would be appreciated.

extension UIImage {

    var roundMyImage: UIImage {
        let rect = CGRect(origin:CGPoint(x: 0, y: 0), size: self.size)
        UIGraphicsBeginImageContextWithOptions(self.size, false, 0)
        UIBezierPath(
            roundedRect: rect,
            cornerRadius: self.size.height
            ).addClip()
        self.draw(in: rect)
        return UIGraphicsGetImageFromCurrentImageContext()!
    }
    
    func resizeMyImage(newWidth: CGFloat) -> UIImage {
        let scale = newWidth / self.size.width
        let newHeight = self.size.height * scale
        UIGraphicsBeginImageContext(CGSize(width: newWidth, height: newHeight))

        self.draw(in: CGRect(x: 0, y: 0, width: newWidth, height: newHeight))
        let newImage = UIGraphicsGetImageFromCurrentImageContext()
        UIGraphicsEndImageContext()

        return newImage!
    }
    
    func squareMyImage() -> UIImage {
        UIGraphicsBeginImageContext(CGSize(width: self.size.width, height: self.size.width))

        self.draw(in: CGRect(x: 0, y: 0, width: self.size.width, height: self.size.width))

        let newImage = UIGraphicsGetImageFromCurrentImageContext()
        UIGraphicsEndImageContext()

        return newImage!
    }
}

let newImage: UIImage = someImage.squareMyImage().resizeMyImage(newWidth: 24).roundMyImage.withRenderingMode(.alwaysOriginal)
            firstTabNav.tabBarItem.image = newImage
            firstTabNav.tabBarItem.selectedImage = newImage

Solution

  • UIGraphicsBeginImageContext with no options gives you a context with the scale set to 1.0 - for retina screens this is not what you want. If you use UIGraphicsBeginImageContextWithOptions you can pass 0.0 for scale, and according to the docs: "If you specify a value of 0.0, the scale factor is set to the scale factor of the device’s main screen" - you seem to have inconsistent scale values in squareMyImage, roundMyImage & resizeMyImage