432

I have an UIImageView called "theImageView", with UIImage in a single color (transparent background) just like the left black heart below. How can I change the tint color of this image programmatically in iOS 7 or above, as per the tint method used in the iOS 7+ Navigation Bar icons?

Can this method also work in WatchKit for an Apple Watch app?

enter image description here

Duncan Babbage
  • 18,889
  • 3
  • 50
  • 91
chewy
  • 7,828
  • 6
  • 39
  • 68
  • 4
    What do you mean "the following code is wrong", setting a `UIImage` with `UIImageRenderingModeAlwaysTemplate` and then setting `UIImageVIew`'s `tintColor` DOES work. (in my code ^^) – Vinzzz Oct 09 '13 at 14:59
  • 2
    Use a png with transparency [like this one](http://www.clker.com/cliparts/b/3/p/F/e/C/black-heart-hi.png) – Alladinian Oct 09 '13 at 15:05
  • 4
    You should really move your answer to the answer section, as I think it is the best one and most modern. – Richard Venable Oct 02 '14 at 18:39

25 Answers25

848

iOS
For an iOS app, in Swift 3, 4 or 5:

theImageView.image = theImageView.image?.withRenderingMode(.alwaysTemplate)
theImageView.tintColor = UIColor.red

For Swift 2:

theImageView.image = theImageView.image?.imageWithRenderingMode(UIImageRenderingMode.AlwaysTemplate)
theImageView.tintColor = UIColor.redColor()

Meanwhile, the modern Objective-C solution is:

theImageView.image = [theImageView.image imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate];
[theImageView setTintColor:[UIColor redColor]];

Watchkit
In WatchKit for Apple Watch apps, you can set the tint color for a template image.

  1. You must add your image to an Asset Catalog in your WatchKit App, and set the image set to be rendered as a Template Image in the Attributes Inspector. Unlike for an iPhone app, you cannot set the template rendering in code in the WatchKit Extension at present.
  2. Set that image to be used in your WKInterfaceImage in interface builder for your app
  3. Create an IBOutlet in your WKInterfaceController for the WKInterfaceImage called 'theImage'...

To then set the tint color in Swift 3 or 4:

theImage.setTintColor(UIColor.red)

Swift 2:

theImage.setTintColor(UIColor.redColor())

To then set the tint color in Objective-C:

[self.theImage setTintColor:[UIColor redColor]];

If you use a template image and do not apply a tint colour, the Global Tint for your WatchKit app will be applied. If you have not set a Global Tint, theImage will be tinted light blue by default when used as a template image.

PhillipJacobs
  • 1,924
  • 1
  • 13
  • 25
Duncan Babbage
  • 18,889
  • 3
  • 50
  • 91
  • 2
    this is the best and simple solution. – Ankish Jain Nov 17 '14 at 04:28
  • 6
    imageWithRenderingMode is too slow. In storyboard and image Assets. you can change this two also: Update the Render Mode to Template Image - thats a better solution – Katerina Oct 16 '15 at 09:28
  • Perfect, now i use this method based in your code: + (UIImageView *) tintImageView: (UIImageView *)imageView withColor: (UIColor*) color{ imageView.image = [imageView.image imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate]; [imageView setTintColor:color]; return imageView; } – Josep Escobar Jun 06 '16 at 13:25
  • is it better with image black ? – Bruno Jun 30 '16 at 18:20
  • I had to set the image in Asset Catalog to render as template in order for it to work on iOS. – duncanc4 Nov 25 '16 at 15:04
  • 2
    @Bruno image does not need to be black, no. Works with any colour. – Duncan Babbage May 17 '17 at 10:04
  • I would just avoid the force unwrapping of the optional and just use optional chaining: _theImageView.image = theImageView.image?.withRenderingMode(.alwaysTemplate)_ – prolfe Oct 08 '18 at 16:55
  • it works with any colour but black? what is happening? @@ – Anonymous-E Dec 04 '18 at 02:56
  • Hmm. That doesn't sound right, @SopheakSok. When you say it's not working, what specifically are you seeing? – Duncan Babbage Dec 05 '18 at 20:10
  • @DuncanBabbage I really don't know why it was like that, I've tried to change the colour to cyan, red, blue, green... it's working fine but when I tried the black colour, the image tint became white. so I tried fuzz method below that he's using the function as the extension and it's working right now. – Anonymous-E Dec 06 '18 at 02:04
123

Here's a category that should do the trick

@interface UIImage(Overlay)
@end

@implementation UIImage(Overlay)

- (UIImage *)imageWithColor:(UIColor *)color1
{
        UIGraphicsBeginImageContextWithOptions(self.size, NO, self.scale);
        CGContextRef context = UIGraphicsGetCurrentContext();
        CGContextTranslateCTM(context, 0, self.size.height);
        CGContextScaleCTM(context, 1.0, -1.0);
        CGContextSetBlendMode(context, kCGBlendModeNormal);
        CGRect rect = CGRectMake(0, 0, self.size.width, self.size.height);
        CGContextClipToMask(context, rect, self.CGImage);
        [color1 setFill];
        CGContextFillRect(context, rect);
        UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext();
        UIGraphicsEndImageContext();
        return newImage;
}
@end

so you would do:

theImageView.image = [theImageView.image imageWithColor:[UIColor redColor]];
iamamused
  • 2,640
  • 3
  • 22
  • 17
  • Thanks for this very valid answer, I guess my code was ok from the start, I should answer my own question and gave you a +1 regardless.. – chewy Oct 09 '13 at 15:07
119

I had to do this in Swift using an extension.

I thought I'd share how I did it:

extension UIImage {
    func imageWithColor(color1: UIColor) -> UIImage {
        UIGraphicsBeginImageContextWithOptions(self.size, false, self.scale)
        color1.setFill()

        let context = UIGraphicsGetCurrentContext() as CGContextRef
        CGContextTranslateCTM(context, 0, self.size.height)
        CGContextScaleCTM(context, 1.0, -1.0);
        CGContextSetBlendMode(context, CGBlendMode.Normal)

        let rect = CGRectMake(0, 0, self.size.width, self.size.height) as CGRect
        CGContextClipToMask(context, rect, self.CGImage)
        CGContextFillRect(context, rect)

        let newImage = UIGraphicsGetImageFromCurrentImageContext() as UIImage
        UIGraphicsEndImageContext()

        return newImage
    }
}

Usage:

theImageView.image = theImageView.image.imageWithColor(UIColor.redColor())

Swift 4

extension UIImage {
    func imageWithColor(color1: UIColor) -> UIImage {
        UIGraphicsBeginImageContextWithOptions(self.size, false, self.scale)
        color1.setFill()

        let context = UIGraphicsGetCurrentContext()
        context?.translateBy(x: 0, y: self.size.height)
        context?.scaleBy(x: 1.0, y: -1.0)
        context?.setBlendMode(CGBlendMode.normal)

        let rect = CGRect(origin: .zero, size: CGSize(width: self.size.width, height: self.size.height))
        context?.clip(to: rect, mask: self.cgImage!)
        context?.fill(rect)

        let newImage = UIGraphicsGetImageFromCurrentImageContext()
        UIGraphicsEndImageContext()

        return newImage!
    }
}

Usage:

theImageView.image = theImageView.image?.imageWithColor(color1: UIColor.red)

fulvio
  • 24,168
  • 20
  • 122
  • 198
  • 1
    FYI this didn't work for me until I moved the `color1.setFill()` right below the first line in the method `UIGraphicsBeginImageContextWithOptions(self.size, false, self.scale)`. – Aaron Jun 25 '15 at 06:33
  • @Aaron Updated based on your comment. Thanks. – fulvio Jun 26 '15 at 00:40
  • `Use of unresolved identifier "kCGBlendModeNormal"` - Error in Xcode 7.0 beta 2 – Cesare Jul 04 '15 at 13:42
  • 7
    @CeceXX use `CGBlendMode.Normal` instead – Adolfo Jul 24 '15 at 20:31
  • In watchKit is the return type still supposed to be UIImage? My extension is error free but when I call the function `theImageView.image = theImageView.image.imageWithColor(UIColor.redColor())` in my custom VC I cannot write `theImageView.image......`. There is no auto-complete. I have imported Foundation and WatchKit of course. It's inside of `awakeWithContext`. Anywhere I write `imageView` doesn't work. – Edison Mar 22 '16 at 20:11
  • 2
    You are awesome, however you might need to change it to Swift 3 – SimpuMind Feb 25 '17 at 23:03
  • 1
    @SimpiMind Provided Swift 4 instead. – fulvio Apr 27 '18 at 01:28
  • After ages I came back to this answer and tuns out I already up voted! Can't give you more! – Reimond Hill Feb 11 '20 at 12:40
109

In storyboard and image Assets. you can change this two also:

Update the Render Mode to Template Image

Update the Render Mode to Template Image in Image Assets

Update the tint Color in Views.

Update the tint Color in Views in Views

JerryZhou
  • 3,359
  • 3
  • 27
  • 44
42

Swift 4

Change tint of UIImage SVG / PDF, that work for image with unique color :

enter image description here enter image description here

import Foundation
    
// MARK: - UIImage extensions

public extension UIImage {

    //
    /// Tint Image
    ///
    /// - Parameter fillColor: UIColor
    /// - Returns: Image with tint color
    func tint(with fillColor: UIColor) -> UIImage? {
        let image = withRenderingMode(.alwaysTemplate)
        UIGraphicsBeginImageContextWithOptions(size, false, scale)
        fillColor.set()
        image.draw(in: CGRect(origin: .zero, size: size))

        guard let imageColored = UIGraphicsGetImageFromCurrentImageContext() else {
            return nil
        }
        
        UIGraphicsEndImageContext()
        return imageColored
    }
}

Change tint of UIImageView, that work for image with unique color :

enter image description here enter image description here

let imageView = UIImageView(frame: CGRect(x: 50, y: 50, width: 50, height: 50))
imageView.image = UIImage(named: "hello.png")!.withRenderingMode(.alwaysTemplate)
imageView.tintColor = .yellow

Change tint of UIImage for picture, use that :

enter image description here enter image description here

import Foundation

// MARK: - Extensions UIImage

public extension UIImage {

    /// Tint, Colorize image with given tint color
    /// This is similar to Photoshop's "Color" layer blend mode
    /// This is perfect for non-greyscale source images, and images that 
    /// have both highlights and shadows that should be preserved<br><br>
    /// white will stay white and black will stay black as the lightness of 
    /// the image is preserved
    ///
    /// - Parameter TintColor: Tint color
    /// - Returns:  Tinted image
    public func tintImage(with fillColor: UIColor) -> UIImage {
        
        return modifiedImage { context, rect in
            // draw black background - workaround to preserve color of partially transparent pixels
            context.setBlendMode(.normal)
            UIColor.black.setFill()
            context.fill(rect)
            
            // draw original image
            context.setBlendMode(.normal)
            context.draw(cgImage!, in: rect)
            
            // tint image (loosing alpha) - the luminosity of the original image is preserved
            context.setBlendMode(.color)
            fillColor.setFill()
            context.fill(rect)
            
            // mask by alpha values of original image
            context.setBlendMode(.destinationIn)
            context.draw(context.makeImage()!, in: rect)
        }
    }
    
    /// Modified Image Context, apply modification on image
    ///
    /// - Parameter draw: (CGContext, CGRect) -> ())
    /// - Returns:        UIImage
    fileprivate func modifiedImage(_ draw: (CGContext, CGRect) -> ()) -> UIImage {
        
        // using scale correctly preserves retina images
        UIGraphicsBeginImageContextWithOptions(size, false, scale)
        let context: CGContext! = UIGraphicsGetCurrentContext()
        assert(context != nil)
        
        // correctly rotate image
        context.translateBy(x: 0, y: size.height)
        context.scaleBy(x: 1.0, y: -1.0)
        
        let rect = CGRect(x: 0.0, y: 0.0, width: size.width, height: size.height)
        
        draw(context, rect)
        
        let image = UIGraphicsGetImageFromCurrentImageContext()
        UIGraphicsEndImageContext()
        return image!
    }
}
Community
  • 1
  • 1
YannSteph
  • 9,590
  • 3
  • 49
  • 46
40

If anyone care a solution without UIImageView:

// (Swift 3)
extension UIImage {
    func tint(with color: UIColor) -> UIImage {
        var image = withRenderingMode(.alwaysTemplate)
        UIGraphicsBeginImageContextWithOptions(size, false, scale)
        color.set()

        image.draw(in: CGRect(origin: .zero, size: size))
        image = UIGraphicsGetImageFromCurrentImageContext()!
        UIGraphicsEndImageContext()
        return image
    }
}
Puttin
  • 1,486
  • 22
  • 27
  • Wow, works like magic after searching for this for an hour+. Needed for: Setting an icon in an NSTextAttachment in a color different from the icon's original one. The standard answer to use a UIImageView and change its tintColor doesn't work here, because NSTextAttachment doesn't take the UIImageView. – marco Jan 26 '17 at 18:43
  • 1
    This is the best solution I have found so far especially for anyone looking for code that works with Swift 3. Great suggestion! – shashwat Feb 27 '17 at 11:36
18

With Swift

let commentImageView = UIImageView(frame: CGRectMake(100, 100, 100, 100))
commentImageView.image = UIImage(named: "myimage.png")!.imageWithRenderingMode(UIImageRenderingMode.AlwaysTemplate)
commentImageView.tintColor = UIColor.blackColor()
addSubview(commentImageView)
Esqarrouth
  • 35,175
  • 17
  • 147
  • 154
8

For swift 3 purposes

theImageView.image = theImageView.image!.withRenderingMode(.alwaysTemplate)
theImageView.tintColor = UIColor.red
aturan23
  • 2,494
  • 3
  • 16
  • 37
DairySeeker
  • 276
  • 3
  • 6
5

Try this

http://robots.thoughtbot.com/designing-for-ios-blending-modes

or

- (void)viewDidLoad
{
[super viewDidLoad];

UILabel *label = [[UILabel alloc] initWithFrame:CGRectMake(10, 30, 300, 50)];
label.numberOfLines = 0;
label.font = [UIFont systemFontOfSize:13];
label.text = @"These checkmarks use the same gray checkmark image with a tintColor applied to the image view";
[self.view addSubview:label];

[self _createImageViewAtY:100 color:[UIColor purpleColor]];
}

- (void)_createImageViewAtY:(int)y color:(UIColor *)color {
UIImage *image = [[UIImage imageNamed:@"gray checkmark.png"] imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate];
UIImageView *imageView = [[UIImageView alloc] initWithImage:image];
CGRect frame = imageView.frame;
frame.origin.x = 100;
frame.origin.y = y;
imageView.frame = frame;

if (color)
    imageView.tintColor = color;

[self.view addSubview:imageView];
}
EI Captain v2.0
  • 21,360
  • 10
  • 76
  • 103
yazh
  • 699
  • 10
  • 15
4

For tinting the image of a UIButton

let image1 = "ic_shopping_cart_empty"
btn_Basket.setImage(UIImage(named: image1)?.withRenderingMode(.alwaysTemplate), for: .normal)
btn_Basket.setImage(UIImage(named: image1)?.withRenderingMode(.alwaysTemplate), for: .selected)
btn_Basket.imageView?.tintColor = UIColor(UIColor.Red)
shim
  • 7,170
  • 10
  • 62
  • 95
Firas Shrourou
  • 557
  • 5
  • 19
3

Take benefit of Extension in Swift :-

extension UIImageView {
    func changeImageColor( color:UIColor) -> UIImage
    {
        image = image!.withRenderingMode(.alwaysTemplate)
        tintColor = color
        return image!
    }
}

   //Change color of logo 
   logoImage.image =  logoImage.changeImageColor(color: .red)

enter image description here

Shrawan
  • 6,372
  • 4
  • 24
  • 40
3

iOS

Solution for doing it from Interface Builder, set templateImage param in keyPath and choose your tint color from IB

extension UIImageView {

// make template image with tint color
var templateImage: Bool {
    set {
        if newValue, let image = self.image {
            let newImage = image.withRenderingMode(.alwaysTemplate)
            self.image = newImage
        }
    } get {
        return false
    }
}

}

shim
  • 7,170
  • 10
  • 62
  • 95
Hakob
  • 41
  • 4
3

With iOS 13 and above, you can simply use

let image = UIImage(named: "Heart")?.withRenderingMode(.alwaysTemplate)
if #available(iOS 13.0, *) {
   imageView.image = image?.withTintColor(UIColor.white)
}
KingofBliss
  • 14,909
  • 6
  • 47
  • 71
2

Swift 3 version of extension answer from fuzz

func imageWithColor(color: UIColor) -> UIImage {
    UIGraphicsBeginImageContextWithOptions(self.size, false, self.scale)
    color.setFill()

    let context = UIGraphicsGetCurrentContext()! as CGContext
    context.translateBy(x: 0, y: self.size.height)
    context.scaleBy(x: 1.0, y: -1.0);
    context.setBlendMode(.normal)

    let rect = CGRect(x: 0, y: 0, width: self.size.width, height: self.size.height) as CGRect
    context.clip(to: rect, mask: self.cgImage!)
    context.fill(rect)

    let newImage = UIGraphicsGetImageFromCurrentImageContext()! as UIImage
    UIGraphicsEndImageContext()

    return newImage
}
shim
  • 7,170
  • 10
  • 62
  • 95
Bryan
  • 1,265
  • 1
  • 15
  • 32
1

There is a native method for UIImage since iOS 13

let image = yourImage.withTintColor(.systemRed)
beryllium
  • 29,214
  • 15
  • 99
  • 123
1

Also, for the above answers, in iOS 13 and later there is a clean way

let image = UIImage(named: "imageName")?.withTintColor(.white, renderingMode: .alwaysTemplate)
mustafa
  • 349
  • 4
  • 12
0

Now i use this method based in Duncan Babbage response:

+ (UIImageView *) tintImageView: (UIImageView *)imageView withColor: (UIColor*) color{
    imageView.image = [imageView.image imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate];
    [imageView setTintColor:color];
    return imageView;
}
Josep Escobar
  • 416
  • 4
  • 11
0

You can use this in Swift 3 if you have an image to replace the clear button

func addTextfieldRightView(){

    let rightViewWidth:CGFloat = 30

    let viewMax = self.searchTxt.frame.height
    let buttonMax = self.searchTxt.frame.height - 16

    let buttonView = UIView(frame: CGRect(
        x: self.searchTxt.frame.width - rightViewWidth,
        y: 0,
        width: viewMax,
        height: viewMax))

    let myButton = UIButton(frame: CGRect(
        x: (viewMax - buttonMax) / 2,
        y: (viewMax - buttonMax) / 2,
        width: buttonMax,
        height: buttonMax))

    myButton.setImage(UIImage(named: "BlueClear")!, for: .normal)

    buttonView.addSubview(myButton)

    let clearPressed = UITapGestureRecognizer(target: self, action: #selector(SearchVC.clearPressed(sender:)))
    buttonView.isUserInteractionEnabled = true
    buttonView.addGestureRecognizer(clearPressed)

    myButton.addTarget(self, action: #selector(SearchVC.clearPressed(sender:)), for: .touchUpInside)

    self.searchTxt.rightView = buttonView
    self.searchTxt.rightViewMode = .whileEditing
}
0

Subclass which can be used from code and Interface Builder as well:

@implementation TintedImageView

- (instancetype)initWithFrame:(CGRect)frame {
    self = [super initWithFrame:frame];
    if (self) {
        [self setup];
    }
    return self;
}

- (instancetype)initWithCoder:(NSCoder *)aDecoder {
    self = [super initWithCoder:aDecoder];
    if (self) {
        [self setup];
    }
    return self;
}

-(void)setup {
    self.image = [self.image imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate];
}

@end
0

This is my UIImage extension and you can directly use changeTintColor function for an image.

extension UIImage {

    func changeTintColor(color: UIColor) -> UIImage {
        var newImage = self.withRenderingMode(.alwaysTemplate)
        UIGraphicsBeginImageContextWithOptions(self.size, false, newImage.scale)
        color.set()
        newImage.draw(in: CGRect(x: 0.0, y: 0.0, width: self.size.width, height: self.size.height))
        newImage = UIGraphicsGetImageFromCurrentImageContext()!
        UIGraphicsEndImageContext()
        return newImage
    }

    func changeColor(color: UIColor) -> UIImage {
        let backgroundSize = self.size
        UIGraphicsBeginImageContext(backgroundSize)
        guard let context = UIGraphicsGetCurrentContext() else {
            return self
        }
        var backgroundRect = CGRect()
        backgroundRect.size = backgroundSize
        backgroundRect.origin.x = 0
        backgroundRect.origin.y = 0

        var red: CGFloat = 0
        var green: CGFloat = 0
        var blue: CGFloat = 0
        var alpha: CGFloat = 0
        color.getRed(&red, green: &green, blue: &blue, alpha: &alpha)
        context.setFillColor(red: red, green: green, blue: blue, alpha: alpha)
        context.translateBy(x: 0, y: backgroundSize.height)
        context.scaleBy(x: 1.0, y: -1.0)
        context.clip(to: CGRect(x: 0.0, y: 0.0, width: self.size.width, height: self.size.height),
                 mask: self.cgImage!)
        context.fill(backgroundRect)

        var imageRect = CGRect()
        imageRect.size = self.size
        imageRect.origin.x = (backgroundSize.width - self.size.width) / 2
        imageRect.origin.y = (backgroundSize.height - self.size.height) / 2

        context.setBlendMode(.multiply)
        context.draw(self.cgImage!, in: imageRect)

        let newImage = UIGraphicsGetImageFromCurrentImageContext()
        UIGraphicsEndImageContext()
        return newImage!
    }

}

Example usage like this

let image = UIImage(named: "sample_image")
imageView.image = image.changeTintColor(color: UIColor.red)

And you can use change changeColor function to change the image color

abdullahselek
  • 6,297
  • 2
  • 39
  • 32
0

profileImageView.image = theImageView.image!.withRenderingMode(.alwaysTemplate)
profileImageView.tintColor = UIColor.green

OR

First select Particular image in image asset and then select reddened as Template instead of Default and after that write line. profileImageView.tintColor = UIColor.green

0

if you have any id for the SVG image, you can fill the colours with respect to the ID.

    let image = SVGKImage(named: "iconName")
    let svgIMGV = SVGKFastImageView(frame: self.imgView.frame)
         svgIMGV.image = image
          svgIMGV.fillTintColor(colorImage: UIColor.red, iconID: "Bank")
// Add in extension SVGKImageView
extension SVGKImageView {
 func fillTintColor(colorImage: UIColor, iconID: String) {
        if self.image != nil && self.image.caLayerTree != nil {
            print(self.image.caLayerTree.sublayers)
            guard let sublayers = self.image.caLayerTree.sublayers else { return }
            fillRecursively(sublayers: sublayers, color: colorImage, iconID: iconID)
        }
    }

     private func fillRecursively(sublayers: [CALayer], color: UIColor, iconID: String, hasFoundLayer: Bool) {
        var isLayerFound = false
        for layer in sublayers {
            if let l = layer as? CAShapeLayer {

                print(l.name)                
                //IF you want to color the specific shapelayer by id else remove the l.name  == "myID"  validation
                if let name =  l.name,  hasFoundLayer == true && name == "myID" {
                    self.colorThatImageWIthColor(color: color, layer: l)
                    print("Colouring FInished")
                }
            } else {
                if layer.name == iconID {
                    if let innerSublayer = layer.sublayers as? [CAShapeLayer] {
                        fillRecursively(sublayers: innerSublayer, color: color, iconID: iconID, hasFoundLayer: true )
                        print("FOund")
                    }
                } else {
                    if let l = layer as? CALayer, let sub = l.sublayers {
                        fillRecursively(sublayers: sub, color: color, iconID: iconID, hasFoundLayer: false)
                    }
                }
            }

        }
    }

    func colorThatImageWIthColor(color: UIColor, layer: CAShapeLayer) {
        if layer.strokeColor != nil {
            layer.strokeColor = color.cgColor
        }
        if layer.fillColor != nil {
            layer.fillColor = color.cgColor
        }
    }

}

OR Checkout this example.

https://github.com/ravisfortune/SVGDEMO

K Ravi Kumar
  • 51
  • 1
  • 2
0
let navHeight = self.navigationController?.navigationBar.frame.height;
let menuBtn = UIButton(type: .custom)
menuBtn.frame = CGRect(x: 0, y: 0, width: 45, height: navHeight!)     
menuBtn.setImage(UIImage(named:"image_name")!.withRenderingMode(.alwaysTemplate), for: .normal)        
menuBtn.tintColor = .black
delabahan
  • 39
  • 4
0

Swift 5

Redrawing image with background and fill color

extension UIImage {
  func withBackground(color: UIColor, fill fillColor: UIColor) -> UIImage {
    UIGraphicsBeginImageContextWithOptions(size, true, scale)
    
    guard let ctx = UIGraphicsGetCurrentContext(), let image = cgImage else { return self }
    defer { UIGraphicsEndImageContext() }
    
    ctx.concatenate(CGAffineTransform(a: 1, b: 0, c: 0, d: -1, tx: 0, ty: size.height))
    
    let rect = CGRect(origin: .zero, size: size)
    
    // draw background
    ctx.setFillColor(color.cgColor)
    ctx.fill(rect)
    
    // draw image with fill color
    ctx.clip(to: rect, mask: image)
    ctx.setFillColor(fillColor.cgColor)
    ctx.fill(rect)
    
    return UIGraphicsGetImageFromCurrentImageContext() ?? self
  }
}
dimpiax
  • 9,648
  • 2
  • 51
  • 41
0

Here's a simple extension that works for Swift 5:

extension UIImageView {

func setImageTintColor(_ color: UIColor) {
    let tintedImage = self.image?.withRenderingMode(.alwaysTemplate)
    self.image = tintedImage
    self.tintColor = color
  }
}

Usage:

myImageView.setImageTintColor(.systemBlue)
WaliD
  • 53
  • 6