How to apply a tintColor to a UIImage?

IosObjective CUibuttonUiimage

Ios Problem Overview


I have a UIImage that is a small symbol that is all black. The UIImage is getting set in a custom UIButton subclass I have. Is it possible to have the image to apply the tintColor to it, so instead of the black image it changes colors to whatever the tintColor is?

I'm just trying to avoid creating new assets.

// here I want defaultImageName (that is black) to use the tintColor (that is white)
[self setImage:[UIImage imageNamed:defaultImageName] forState:UIControlStateNormal];

Ios Solutions


Solution 1 - Ios

If you are just supporting iOS 7 you can use tintColor and UIImageRenderingModeAlwaysTemplate

This article covers that:

https://www.captechconsulting.com/blogs/ios-7-tutorial-series-tint-color-and-easy-app-theming

If you need to support an earlier version you may want to consider this thread

https://stackoverflow.com/questions/1117211/how-would-i-tint-an-image-programatically-on-the-iphone

Solution 2 - Ios

Swift 4, copy-paste solution

@IBOutlet weak var iconImageView: UIImageView!
iconImageView.image = UIImage(imageLiteralResourceName: "myImageName").withRenderingMode(.alwaysTemplate)
iconImageView.tintColor = UIColor.red

Solution 3 - Ios

On iOS 13+ you can use the following:

UIImage(named: "img_name")?.withTintColor(.red)

https://developer.apple.com/documentation/uikit/uiimage/3327300-withtintcolor

Solution 4 - Ios

Try this:

func tinted(with color: UIColor) -> UIImage? {
    defer { UIGraphicsEndImageContext() }
    UIGraphicsBeginImageContextWithOptions(self.size, false, self.scale)
    color.set()
    self.withRenderingMode(.alwaysTemplate).draw(in: CGRect(origin: .zero, size: self.size))
    return UIGraphicsGetImageFromCurrentImageContext()
}

For example:

button.setImage(UIImage(systemName: "checkmark.circle")?.tinted(with: .systemGray), for: .normal)

Solution 5 - Ios

Here's how I use tint colors and opacities in IOS 9 with Swift -

//apply a color to an image
//ref - http://stackoverflow.com/questions/28427935/how-can-i-change-image-tintcolor
//ref - https://www.captechconsulting.com/blogs/ios-7-tutorial-series-tint-color-and-easy-app-theming
func getTintedImage() -> UIImageView {
    
    var image :UIImage
    var imageView :UIImageView
    
    image = UIImage(named: "someAsset")!
    let size  : CGSize = image.size
    let frame : CGRect = CGRectMake((UIScreen.mainScreen().bounds.width-86)/2, 600, size.width, size.height)
    
    let redCover : UIView = UIView(frame: frame)
    
    redCover.backgroundColor = UIColor.redColor()
    redCover.layer.opacity = 0.75
    
    imageView = UIImageView();
    imageView.image = image.imageWithRenderingMode(UIImageRenderingMode.Automatic)
    
    imageView.addSubview(redCover)
    
    return imageView
}

Solution 6 - Ios

Why not use image filtering

btn.setImage(image, for: UIControl.State.normal)
btn.setImage(image.disabled, for: UIControl.State.disabled)
 

Use CoreImage to do image filter

extension UIImage
{
    /// Create a grayscale image with alpha channel. Is 5 times faster than grayscaleImage().
    /// - Returns: The grayscale image of self if available.
    var disabled: UIImage?
    {
        // Create image rectangle with current image width/height * scale
        let pixelSize = CGSize(width: self.size.width * self.scale, height: self.size.height * self.scale)
        let imageRect = CGRect(origin: CGPoint.zero, size: pixelSize)
        // Grayscale color space
         let colorSpace: CGColorSpace = CGColorSpaceCreateDeviceGray()
        
            // Create bitmap content with current image size and grayscale colorspace
        let bitmapInfo = CGBitmapInfo(rawValue: CGImageAlphaInfo.none.rawValue)
        if let context: CGContext = CGContext(data: nil, width: Int(pixelSize.width), height: Int(pixelSize.height), bitsPerComponent: 8, bytesPerRow: 0, space: colorSpace, bitmapInfo: bitmapInfo.rawValue)
            {
                // Draw image into current context, with specified rectangle
                // using previously defined context (with grayscale colorspace)
                guard let cg = self.cgImage else{
                    return nil
                }
                context.draw(cg, in: imageRect)
                // Create bitmap image info from pixel data in current context
                if let imageRef: CGImage = context.makeImage(){
                    let bitmapInfoAlphaOnly = CGBitmapInfo(rawValue: CGImageAlphaInfo.alphaOnly.rawValue)
                    
                    guard let context = CGContext(data: nil, width: Int(pixelSize.width), height: Int(pixelSize.height), bitsPerComponent: 8, bytesPerRow: 0, space: colorSpace, bitmapInfo: bitmapInfoAlphaOnly.rawValue) else{
                        return nil
                    }
                    context.draw(cg, in: imageRect)
                    if let mask: CGImage = context.makeImage() {
                        // Create a new UIImage object
                        if let newCGImage = imageRef.masking(mask){
                            // Return the new grayscale image
                            return UIImage(cgImage: newCGImage, scale: self.scale, orientation: self.imageOrientation)
                        }
                    }
                    
                }
            }

        
        // A required variable was unexpected nil
        return nil
    }
}

Of course, in Swift 5

Solution 7 - Ios

Swift5 Extension

extension UIImage {
    var template: UIImage? {
         return self.withRenderingMode(.alwaysTemplate)
    }
}

Usage:

  • UIImageView

    let imgView = UIImageView()
    imgView.tintColor = UIColor.red
    imgView.image = UIImage(named: "IMAGE_NAME_HERE")?.template
    
  • UIButton

    let button = UIButton(type: .custom)
    button.tintColor = UIColor.red
    button.setImage(UIImage(named: "IMAGE_NAME_HERE")?.template, for: .normal)
    

Solution 8 - Ios

Use this simple extension to UIImageView

@IBInspectable var tintedColor: UIColor{
    get{
        return tintColor
    }
    set{
        image = image?.withRenderingMode(.alwaysTemplate)
        tintColor = newValue
    }
}

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionaahrensView Question on Stackoverflow
Solution 1 - Iosmadmik3View Answer on Stackoverflow
Solution 2 - IoszgorawskiView Answer on Stackoverflow
Solution 3 - Iosbarola_mesView Answer on Stackoverflow
Solution 4 - IosjqgsninimoView Answer on Stackoverflow
Solution 5 - IosJ-DizzleView Answer on Stackoverflow
Solution 6 - Iosblack_pearlView Answer on Stackoverflow
Solution 7 - IosLi JinView Answer on Stackoverflow
Solution 8 - IosMilind ChaudharyView Answer on Stackoverflow