我该如何改变UIImage的颜色?

52
我希望不仅改变UIImage的背景色,而是更改整个图像的颜色。但问题是: 我只能更改背景色。

3
你真的需要更详细地解释一下你试图做什么。 - picknick
一个图像视图显示一张图片,那么当你说“改变颜色”时,你的意思是什么? - Cthutu
1
修改了我的帖子。希望它现在可以被理解。 - Studie
8个回答

130

接受的答案是正确的,但对于 UIImageView,有一种更加简单的方法:

Obj-C:

UIImage *image = [UIImage imageNamed:@"foo.png"];
theImageView.image = [image imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate];
[theImageView setTintColor:[UIColor redColor]];

Swift 2:

let theImageView = UIImageView(image: UIImage(named:"foo")!.imageWithRenderingMode(UIImageRenderingMode.AlwaysTemplate))
theImageView.tintColor = UIColor.redColor()

Swift 3:

let theImageView = UIImageView(image: UIImage(named:"foo")!.withRenderingMode(.alwaysTemplate))
theImageView.tintColor = UIColor.red

完美的答案,但我们可以只填充内部框架并不改变UIImage的边框颜色吗? - Yogesh Suthar
@YogeshSuthar 你所说的“border color”是什么意思? - skywinder
@skywinder,有没有办法检测颜色并更改特定的颜色? 比如我有一张由白色和红色组成的图片。我只想更改图片中的白色部分。这可行吗? - Mrugesh Tank
@MrugeshTank,使用这种方法是不行的。它只是从图像创建掩模并用颜色填充。所以你需要一些高级图像处理库来实现该功能。 - skywinder
@MrugeshTank OpenCV 是最先进的库,适用于那些情况。 - skywinder
显示剩余3条评论

64
UIImage *image = [UIImage imageNamed:@"triangle.png"];

CGRect rect = CGRectMake(0, 0, image.size.width, image.size.height);
UIGraphicsBeginImageContext(rect.size);
CGContextRef context = UIGraphicsGetCurrentContext();
CGContextClipToMask(context, rect, image.CGImage);
CGContextSetFillColorWithColor(context, [[UIColor redColor] CGColor]);
CGContextFillRect(context, rect);
UIImage *img = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();

UIImage *flippedImage = [UIImage imageWithCGImage:img.CGImage 
                                            scale:1.0 orientation: UIImageOrientationDownMirrored];

yourUIImageView.image = flippedImage;

1
我已经修改了答案,但下次请确保您的问题表述清楚易懂。这次真的很难理解你的要求。 - Lloyd18
谢谢。我只是在浏览这个,试图理解它。我有一个问题是它是如何开始翻转的? - GreenKiwi
因为最后两个字符串。 - Lloyd18
很好的答案。但是即使在Retina设备上,它仅选择非Retina图像? - nicktones
@nicktones:从给定的示例中删除“.png”后缀。这样可以让应用程序确定哪个图像是适当的,而不是被告知要使用哪个图像(这类似于“triangle@2x.png”)。 - James Nelson
显示剩余4条评论

12

适用于Swift 3.2和4版本

extension UIImageView{
    func changePngColorTo(color: UIColor){
        guard let image =  self.image else {return}
        self.image = image.withRenderingMode(.alwaysTemplate)
        self.tintColor = color
    }
}

使用:

self.yourImageView.changePngColorTo(color: .red)

1
这并不会改变UIImage的颜色,而是ImageView使用不同的颜色进行渲染。 - Steve Kuo

8

详情

  • Xcode 10.2.1 (10E1001),Swift 5

方法一:UIImage 扩展

来源:https://dev59.com/qV4d5IYBdhLWcg3wG_aH#40177870

extension UIImage {

    convenience init?(imageName: String) {
        self.init(named: imageName)
        accessibilityIdentifier = imageName
    }

    // https://dev59.com/qV4d5IYBdhLWcg3wG_aH#40177870
    func imageWithColor (newColor: UIColor?) -> UIImage? {

        if let newColor = newColor {
            UIGraphicsBeginImageContextWithOptions(size, false, scale)

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

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

            newColor.setFill()
            context.fill(rect)

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

        if let accessibilityIdentifier = accessibilityIdentifier {
            return UIImage(imageName: accessibilityIdentifier)
        }

        return self
    }
}

用法

let imageView = UIImageView(frame: CGRect(x: 40, y: 250, width: 40, height: 40))
view.addSubview(imageView)
// Set color
imageView.image = UIImage(imageName: "Apple")?.imageWithColor(newColor: UIColor.blue)
// Reset color
//imageView.image = imageView.image?.imageWithColor(newColor: nil)

Way 2. Extension UIImageView

extension UIImageView {

    var imageColor: UIColor? {
        set (newValue) {
            guard let image = image else { return }
            if newValue != nil {
                self.image = image.withRenderingMode(.alwaysTemplate)
                tintColor = newValue
            } else {
                self.image = image.withRenderingMode(.alwaysOriginal)
                tintColor = UIColor.clear
            }
        }
        get { return tintColor }
    }
}

用法

let imageView = UIImageView(frame: CGRect(x: 40, y: 250, width: 40, height: 40))
view.addSubview(imageView)
imageView.image = UIImage(imageName: "Apple")
// Set color
imageView.imageColor = UIColor.green
// Reset color
//imageView.imageColor = nil

完整示例

别忘了在这里粘贴所有在上面放置的代码

import UIKit

class ImageView: UIImageView {
    enum ImageColorTransformType {
        case none, imageExtension, imageViewExtension
    }
    var imageColorTransformType = ImageColorTransformType.none
}

class ViewController: UIViewController {

    weak var colorSwitchButton: UIBarButtonItem?

    private var imageViews = [ImageView]()
    private var appleImage: UIImage { return UIImage(imageName: "apple")! }
    private var redAppleImage: UIImage { return UIImage(imageName: "red_apple")! }

    override func viewDidLoad() {
        super.viewDidLoad()
        createNewImageView(x: 40, y:100, image:appleImage, imageColorTransformType: .none)
        createNewImageView(x: 100, y:100, image:appleImage, imageColorTransformType: .imageExtension)
        createNewImageView(x: 160, y:100, image:appleImage, imageColorTransformType: .imageViewExtension)

        createNewImageView(x: 40, y:160, image:redAppleImage, imageColorTransformType: .none)
        createNewImageView(x: 100, y:160, image:redAppleImage, imageColorTransformType: .imageExtension)
        createNewImageView(x: 160, y:160, image:redAppleImage, imageColorTransformType: .imageViewExtension)

        let buttonItem = UIBarButtonItem(title: "switch", style: .plain, target: self,
                                         action: #selector(colorSwitchButtonTouchedUpInside(_:)))
        navigationItem.rightBarButtonItem = buttonItem
        colorSwitchButton = buttonItem
        useOriginalColors = false
    }

    private func createNewImageView(x:CGFloat, y: CGFloat, image: UIImage, imageColorTransformType: ImageView.ImageColorTransformType) {
        let imageView = ImageView(frame: CGRect(x: x, y: y, width: 40, height: 40))
        imageView.image = image
        imageView.imageColorTransformType = imageColorTransformType
        imageViews.append(imageView)
        view.addSubview(imageView)
    }

    private var _useOriginalColors = false
    private var useOriginalColors: Bool {
        set(value) {
            _useOriginalColors = value
            if (value) {
                navigationItem.title = "Original colors"
                for imageView in imageViews {
                    switch imageView.imageColorTransformType {
                    case .imageExtension: imageView.image = imageView.image?.imageWithColor(newColor: nil)
                    case .imageViewExtension: imageView.imageColor = nil
                    case .none: break
                    }
                }
            } else {
                navigationItem.title = "Template colors"
                for imageView in imageViews {
                    switch imageView.imageColorTransformType {
                    case .imageExtension: imageView.image = imageView.image?.imageWithColor(newColor: UIColor.blue)
                    case .imageViewExtension: imageView.imageColor = UIColor.green
                    case .none: break
                    }
                }
            }
        }
        get { return _useOriginalColors }
    }

    @objc func colorSwitchButtonTouchedUpInside(_ sender: Any) { useOriginalColors = !useOriginalColors }
}

故事板

进入图片描述

结果

进入图片描述 进入图片描述


4
你也可以使用以下代码在Swift中实现这一点:
// language: Swift
let tintedImage = UIImageView(image: UIImage(named:"whatever")!.imageWithRenderingMode(UIImageRenderingMode.AlwaysTemplate))

tintedImage.tintColor = UIColor.redColor()

3

Swift + Interface builder(故事板)

如果您在界面生成器中添加了UIImageView:

myIcon.image = myIcon.image!.withRenderingMode(UIImageRenderingMode.alwaysTemplate)
myIcon.tintColor = UIColor.red // your color

这里的myIcon是你的故事板中的一个出口,例如:@IBOutlet weak var myIcon: UIImageView!


1

更改UIImageView中图像的颜色:

public extension UIImageView {
    func tintImage(color: UIColor) {
        image = image?.tint(color: color)
    }
}

Just call the method:

imageView.tintImage(color: .red)

0

补充skywinder所说的答案

你也可以在按钮上执行这个操作:

UIImage *image = [UIImage imageNamed:@"foo.png"];
[myButton setImage:[image imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate] forState:UIControlStateNormal];
[myButton setTintColor:[UIColor redColor]];

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接