Swift'de bir UIImage'ı nasıl renklendirebilirim?


103

Adlı bir resmim var arrowWhite. Bu resmi siyaha boyamak istiyorum.

func attachDropDownArrow() -> NSMutableAttributedString {
    let image:UIImage = UIImage(named: "arrowWhite.png")!
    let attachment = NSTextAttachment()
    attachment.image = image
    attachment.bounds = CGRectMake(2.25, 2, attachment.image!.size.width - 2.25, attachment.image!.size.height - 2.25)
    let attachmentString = NSAttributedString(attachment: attachment)
    let myString = NSMutableAttributedString(string: NSString(format: "%@", self.privacyOptions[selectedPickerRow]) as String)
    myString.appendAttributedString(attachmentString)
    return myString
}

Bu görüntüyü içeri almak istiyorum blackColour.
tintColorçalışmıyor...


Arayüz Oluşturucu'dan yapılabilir, bkz. @Harry Bloom oldukça aşağıda
Andy Weinstein

Yanıtlar:


196

Swift 4 ve 5

extension UIImageView {
  func setImageColor(color: UIColor) {
    let templateImage = self.image?.withRenderingMode(.alwaysTemplate)
    self.image = templateImage
    self.tintColor = color
  }
}

Şöyle arayın:

let imageView = UIImageView(image: UIImage(named: "your_image_name"))
imageView.setImageColor(color: UIColor.purple)

Swift 3, 4 veya 5 için Alternativ

extension UIImage {

    func maskWithColor(color: UIColor) -> UIImage? {
        let maskImage = cgImage!

        let width = size.width
        let height = size.height
        let bounds = CGRect(x: 0, y: 0, width: width, height: height)

        let colorSpace = CGColorSpaceCreateDeviceRGB()
        let bitmapInfo = CGBitmapInfo(rawValue: CGImageAlphaInfo.premultipliedLast.rawValue)
        let context = CGContext(data: nil, width: Int(width), height: Int(height), bitsPerComponent: 8, bytesPerRow: 0, space: colorSpace, bitmapInfo: bitmapInfo.rawValue)!

        context.clip(to: bounds, mask: maskImage)
        context.setFillColor(color.cgColor)
        context.fill(bounds)

        if let cgImage = context.makeImage() {
            let coloredImage = UIImage(cgImage: cgImage)
            return coloredImage
        } else {
            return nil
        }
    }

}

Swift 2.3 için

extension UIImage {
func maskWithColor(color: UIColor) -> UIImage? {

    let maskImage = self.CGImage
    let width = self.size.width
    let height = self.size.height
    let bounds = CGRectMake(0, 0, width, height)

    let colorSpace = CGColorSpaceCreateDeviceRGB()
    let bitmapInfo = CGBitmapInfo(rawValue: CGImageAlphaInfo.PremultipliedLast.rawValue)
    let bitmapContext = CGBitmapContextCreate(nil, Int(width), Int(height), 8, 0, colorSpace, bitmapInfo.rawValue) //needs rawValue of bitmapInfo

    CGContextClipToMask(bitmapContext, bounds, maskImage)
    CGContextSetFillColorWithColor(bitmapContext, color.CGColor)
    CGContextFillRect(bitmapContext, bounds)

    //is it nil?
    if let cImage = CGBitmapContextCreateImage(bitmapContext) {
        let coloredImage = UIImage(CGImage: cImage)

        return coloredImage

    } else {
        return nil
    } 
 }
}

Şöyle arayın:

let image = UIImage(named: "your_image_name")
testImage.image =  image?.maskWithColor(color: UIColor.blue)

8
İyi bir başlangıç, ancak sonuç grenli. Aşağıda @Darko'nun da bahsettiği gibi bunun ölçek ve diğer parametreleri hesaba katmadığınız için olduğuna inanıyorum.
TruMan1

1
benim için aynı - pikselli görüntü
Async

Swift 3'te benim için mükemmel çalıştı. Teşekkürler !!
oscar castellon

4
Ölçeklemeyi ve yönü korumaz.
Shailesh

dahili uzantı, işlev herkese açık olmalıdır
Shivam Pokhriyal

89

Şablon modundaUIImage otomatik olarak işlenen bir elde etmek için yerleşik bir yöntem vardır . Bu, görüntüyü renklendirmek için görünümün tintColor'unu kullanır:

let templateImage = originalImage.imageWithRenderingMode(UIImageRenderingModeAlwaysTemplate)
myImageView.image = templateImage
myImageView.tintColor = UIColor.orangeColor()

3
Bu en iyi cevap - daha fazla bilgi Apple Docs'da bulunabilir - developer.apple.com/library/content/documentation/…
Mark

6
İşleme modu için Swift 3 sözdizimine buradan bakın: stackoverflow.com/a/24145287/448718
Phil_Ken_Sebben

6
imageview kullanımı açık, ancak biz sadece UIImage istiyoruz
djdance

3
UIImageView nesnelerinden bağımsız olarak UIImage nesneleriyle çalışıyorsanız bir çözüm değildir. Bu yalnızca UIImageView'a erişiminiz varsa çalışır
Pez

MyImageView bir UIButton olduğunda bile harika çalışıyor
daxh

43

Öncelikle, görüntünün oluşturma özelliğini .xcassets klasöründe "Şablon Görüntüsü" olarak değiştirmeniz gerekir. Daha sonra UIImageView örneğinizin renk tonu özelliğini şu şekilde değiştirebilirsiniz:

imageView.tintColor = UIColor.whiteColor()

görüntü açıklamasını buraya girin


1
Bir noktada tintColorkaldırıldı UIImagemı? Bu cevap beni heyecanlandırdı ama iOS 10'da yok gibi görünüyor
Travis Griggs

1
Merhaba @TravisGriggs. Üzgünüm, cevabımı biraz daha açıklayıcı olacak şekilde düzenledim, tintColor özelliği UIImageView'da değil UIImageView'da
Harry Bloom

Tx, bu çok havalı! Not: Renk Tonu, ImageView denetçisinin Görünüm bölümünde biraz daha aşağıda görünür. Daha net olmak gerekirse.
Andy Weinstein

31

Bunu yaptım çünkü diğer yanıtlar çözünürlüğü kaybediyor veya UIImage ile değil UIImageView ile çalışıyor veya gereksiz eylemler içeriyor:

Hızlı 3

extension UIImage {

    public func maskWithColor(color: UIColor) -> UIImage {

        UIGraphicsBeginImageContextWithOptions(self.size, false, self.scale)
        let context = UIGraphicsGetCurrentContext()!

        let rect = CGRect(origin: CGPoint.zero, size: size)

        color.setFill()
        self.draw(in: rect)

        context.setBlendMode(.sourceIn)
        context.fill(rect)

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

}

4
buradaki en iyi cevap, aynı görüntü yönünü ve kalitesini
korur

Evet, yukarıdaki tüm cevapları test ettim ve bu gerçekten ölçeği hesaba katıyor, bu yüzden size pikselli e'ler vermeyecek UIImage. Gerçekten güzel cevap, teşekkürler!
Guilherme Matuella

21

Bu işlev, bunu başarmak için çekirdek grafikleri kullanır.

func overlayImage(color: UIColor) -> UIImage {
    UIGraphicsBeginImageContextWithOptions(self.size, false, UIScreen.main.scale)
    let context = UIGraphicsGetCurrentContext()

    color.setFill()

    context!.translateBy(x: 0, y: self.size.height)
    context!.scaleBy(x: 1.0, y: -1.0)

    context!.setBlendMode(CGBlendMode.colorBurn)
    let rect = CGRect(x: 0, y: 0, width: self.size.width, height: self.size.height)
    context!.draw(self.cgImage!, in: rect)

    context!.setBlendMode(CGBlendMode.sourceIn)
    context!.addRect(rect)
    context!.drawPath(using: CGPathDrawingMode.fill)

    let coloredImage = UIGraphicsGetImageFromCurrentImageContext()
    UIGraphicsEndImageContext()

    return coloredImage
}

8
Bu, diğer ilk iki cevabın yanlış olduğu durumlarda işe yarar.
chrysb

4
Evet, bu mükemmel çalışıyor. maskWithColor uzantısı çalışır ancak bu görmezden gelir, scalebu nedenle görüntü yüksek çözünürlüklü cihazlarda net görünmez.
Moin Uddin

Bu mükemmel çalışıyor !! Bir uzantı kullanıyoruz ve iyi çalışıyor. Diğer çözümler ölçeği görmezden geliyor ...
Javi Campaña

17

UIImage rengini istediğiniz gibi değiştirmek için hızlı 4.2 için (düz renk)

extension UIImage {
    func imageWithColor(color: UIColor) -> UIImage {
        UIGraphicsBeginImageContextWithOptions(self.size, false, self.scale)
        color.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!
    }
}

Nasıl kullanılır

self.imgVw.image = UIImage(named: "testImage")?.imageWithColor(UIColor.red)

10

UIImage'da bir uzantı oluşturun:

/// UIImage Extensions
extension UIImage {
    func maskWithColor(color: UIColor) -> UIImage {

        var maskImage = self.CGImage
        let width = self.size.width
        let height = self.size.height
        let bounds = CGRectMake(0, 0, width, height)

        let colorSpace = CGColorSpaceCreateDeviceRGB()
        let bitmapInfo = CGBitmapInfo(CGImageAlphaInfo.PremultipliedLast.rawValue)
        let bitmapContext = CGBitmapContextCreate(nil, Int(width), Int(height), 8, 0, colorSpace, bitmapInfo)

        CGContextClipToMask(bitmapContext, bounds, maskImage)
        CGContextSetFillColorWithColor(bitmapContext, color.CGColor)
        CGContextFillRect(bitmapContext, bounds)

        let cImage = CGBitmapContextCreateImage(bitmapContext)
        let coloredImage = UIImage(CGImage: cImage)

        return coloredImage!
    }
}

O zaman bunu şu şekilde kullanabilirsiniz:

image.maskWithColor(UIColor.redColor())

1
Bu scale, orientationve diğer parametrelerini yok sayar UIImage.
Nikolai Ruhe

10

İK çözümünü en yararlı buldum ancak Swift 3 için biraz uyarladım

extension UIImage {

    func maskWithColor( color:UIColor) -> UIImage {

         UIGraphicsBeginImageContextWithOptions(self.size, false, UIScreen.main.scale)
         let context = UIGraphicsGetCurrentContext()!

         color.setFill()

         context.translateBy(x: 0, y: self.size.height)
         context.scaleBy(x: 1.0, y: -1.0)

         let rect = CGRect(x: 0.0, y: 0.0, width: self.size.width, height: self.size.height)
         context.draw(self.cgImage!, in: rect)

         context.setBlendMode(CGBlendMode.sourceIn)
         context.addRect(rect)
         context.drawPath(using: CGPathDrawingMode.fill)

         let coloredImage = UIGraphicsGetImageFromCurrentImageContext()
         UIGraphicsEndImageContext()

         return coloredImage!
    }
}

Bu, ölçeği dikkate alır ve ayrıca diğer bazı çözümler gibi daha düşük çözünürlüklü bir görüntü üretmez. Kullanım:

image = image.maskWithColor(color: .green )

Bu kesinlikle kullanılacak uygulama (bu sayfadaki diğerlerinden anlaşılması güç).
Scott Corscadden

Ekstra güvenli olmak için kuvvet çözücüleri if-lets veya bir koruyucuya sarılmalıdır.
Chris Paveglio

6

@ Nikolai Ruhe cevabından Swift 3 uzatma sarmalayıcı.

extension UIImageView {

    func maskWith(color: UIColor) {
        guard let tempImage = image?.withRenderingMode(.alwaysTemplate) else { return }
        image = tempImage
        tintColor = color
    }

}

Bunun için de kullanılabilir UIButton, örneğin:

button.imageView?.maskWith(color: .blue)

5

Swift 4

 let image: UIImage? =  #imageLiteral(resourceName: "logo-1").withRenderingMode(.alwaysTemplate)
    topLogo.image = image
    topLogo.tintColor = UIColor.white

4

Bu uzantıyı kodunuza ekleyin ve film şeridinin kendisinde görüntü rengini değiştirin.

Swift 4 ve 5:

extension UIImageView {
    @IBInspectable
    var changeColor: UIColor? {
        get {
            let color = UIColor(cgColor: layer.borderColor!);
            return color
        }
        set {
            let templateImage = self.image?.withRenderingMode(.alwaysTemplate)
            self.image = templateImage
            self.tintColor = newValue
        }
    }
}

Storyboard Önizlemesi:

görüntü açıklamasını buraya girin



1

Hızlı 3

21 Haziran 2017

Verilen resmi Alfa Kanalı ile maskelemek için CALayer kullanıyorum

import Foundation


extension UIImage {

    func maskWithColor(color: UIColor) -> UIImage? {
    
        let maskLayer = CALayer()
        maskLayer.bounds = CGRect(x: 0, y: 0, width: size.width, height: size.height)
        maskLayer.backgroundColor = color.cgColor
        maskLayer.doMask(by: self)
        let maskImage = maskLayer.toImage()
        return maskImage
    }

}


extension CALayer {
    func doMask(by imageMask: UIImage) {
        let maskLayer = CAShapeLayer()
        maskLayer.bounds = CGRect(x: 0, y: 0, width: imageMask.size.width, height: imageMask.size.height)
        bounds = maskLayer.bounds
        maskLayer.contents = imageMask.cgImage
        maskLayer.frame = CGRect(x: 0, y: 0, width: frame.size.width, height: frame.size.height)
        mask = maskLayer
    }

    func toImage() -> UIImage?
    {
        UIGraphicsBeginImageContextWithOptions(bounds.size,
                                               isOpaque,
                                               UIScreen.main.scale)
        guard let context = UIGraphicsGetCurrentContext() else {
            UIGraphicsEndImageContext()
            return nil
        }
        render(in: context)
        let image = UIGraphicsGetImageFromCurrentImageContext()
        UIGraphicsEndImageContext()
        return image
    }
}

1

@ Kuzdu'dan ölçek ve Oryantasyonlu Swift 3 versiyonu cevap

extension UIImage {

    func mask(_ color: UIColor) -> UIImage? {
        let maskImage = cgImage!

        let width = (cgImage?.width)!
        let height = (cgImage?.height)!
        let bounds = CGRect(x: 0, y: 0, width: width, height: height)

        let colorSpace = CGColorSpaceCreateDeviceRGB()
        let bitmapInfo = CGBitmapInfo(rawValue: CGImageAlphaInfo.premultipliedLast.rawValue)
        let context = CGContext(data: nil, width: Int(width), height: Int(height), bitsPerComponent: 8, bytesPerRow: 0, space: colorSpace, bitmapInfo: bitmapInfo.rawValue)!

        context.clip(to: bounds, mask: maskImage)
        context.setFillColor(color.cgColor)
        context.fill(bounds)

        if let cgImage = context.makeImage() {
            let coloredImage = UIImage.init(cgImage: cgImage, scale: scale, orientation: imageOrientation)
            return coloredImage
        } else {
            return nil
        }
    }
}

1

Hızlı 4.

Düz renkli bir görüntü oluşturmak için bu uzantıyı kullanın

extension UIImage {   

    public func coloredImage(color: UIColor) -> UIImage? {
        return coloredImage(color: color, size: CGSize(width: 1, height: 1))
    }

    public func coloredImage(color: UIColor, size: CGSize) -> UIImage? {

        UIGraphicsBeginImageContextWithOptions(size, false, 0)

        color.setFill()
        UIRectFill(CGRect(origin: CGPoint(), size: size))

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

        return image
    }
}

NavigationBar.setBackgroundImage ve Swift 5'te benim için mükemmel çalıştı. Teşekkürler!
Jesse

1

İOS 13 yayınlayın, bunun gibi bir şey kullanabilirsiniz

arrowWhiteImage.withTintColor(.black, renderingMode: .alwaysTemplate)

1

Uzantı işlevi ekle:

extension UIImageView {
    func setImage(named: String, color: UIColor) {
        self.image = #imageLiteral(resourceName: named).withRenderingMode(.alwaysTemplate)
        self.tintColor = color
    }
}

Gibi kullanın:

anyImageView.setImage(named: "image_name", color: .red)

0

İşte İK çözümünün hızlı 3 versiyonu.

func overlayImage(color: UIColor) -> UIImage? {
    UIGraphicsBeginImageContextWithOptions(self.size, false, UIScreen.main.scale)
    let context = UIGraphicsGetCurrentContext()

    color.setFill()

    context!.translateBy(x: 0, y: self.size.height)
    context!.scaleBy(x: 1.0, y: -1.0)

    context!.setBlendMode(CGBlendMode.colorBurn)
    let rect = CGRect(x: 0, y: 0, width: self.size.width, height: self.size.height)
    context!.draw(self.cgImage!, in: rect)

    context!.setBlendMode(CGBlendMode.sourceIn)
    context!.addRect(rect)
    context!.drawPath(using: CGPathDrawingMode.fill)

    let coloredImage = UIGraphicsGetImageFromCurrentImageContext()
    UIGraphicsEndImageContext()

    return coloredImage
}

-1

Darko'nun cevabını mapView açıklamaları için özel pinlerin renklendirilmesinde çok yararlı bulduğum, ancak Swift 3 için bazı dönüşümler yapmak zorunda kaldığım için, güncellenmiş kodu yanıtı için tavsiyemle paylaşacağımı düşündüm:

extension UIImage {
    func maskWithColor(color: UIColor) -> UIImage {

        var maskImage = self.CGImage
        let width = self.size.width
        let height = self.size.height
        let bounds = CGRect(x: 0, y: 0, width: width, height: height)

        let colorSpace = CGColorSpaceCreateDeviceRGB()
        let bitmapInfo = CGBitmapInfo(rawValue: CGImageAlphaInfo.premultipliedLast.rawValue)
        let bitmapContext = CGContext(data: nil, width: Int(width), height: Int(height), bitsPerComponent: 8, bytesPerRow: 0, space: colorSpace, bitmapInfo: bitmapInfo.rawValue)

        bitmapContext!.clip(to: bounds, mask: maskImage!)
        bitmapContext!.setFillColor(color.cgColor)
        bitmapContext!.fill(bounds)

        let cImage = bitmapContext!.makeImage()
        let coloredImage = UIImage(CGImage: cImage)

        return coloredImage!
    }
}

-2

: Burada bulduğu uzantısı değiştirdiniz Github Özü , için Swift 3ben UIImage için bir uzantısı bağlamında test ettik ki.

func tint(with color: UIColor) -> UIImage 
{
   UIGraphicsBeginImageContext(self.size)
   guard let context = UIGraphicsGetCurrentContext() else { return self }

   // flip the image
   context.scaleBy(x: 1.0, y: -1.0)
   context.translateBy(x: 0.0, y: -self.size.height)

   // multiply blend mode
   context.setBlendMode(.multiply)

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

   // create UIImage
   guard let newImage = UIGraphicsGetImageFromCurrentImageContext() else { return self }
   UIGraphicsEndImageContext()

   return newImage
}
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.