Change particular color in image including shades

Viewed 58

I would like to specifically change the UIImage color to any color (excluding the gray borders and lines and preserving the shading effect), using an extension method as shown below:

extension UIImage {
   func replaceFillColorTo(_ color: UIColor) {
      // what should I do in here?
   }
}

I would like the result to be as shown below: enter image description here

The white shirt is the input and each colored shirt is the output using different colors.

2 Answers

The most straight-forward way to do this is to generate your "template" image with transparency / alpha levels.

For example:

enter image description here

I used this image - had to do a little editing so it's close to your image... (if you download it you can see the transparency matches the above):

enter image description here

Then we can change the background color of the imageView, and get these results:

enter image description here enter image description here enter image description here enter image description here enter image description here

and this example code to produce the screen-caps above:

class ViewController: UIViewController {
    
    let imgView = UIImageView()
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        view.backgroundColor = .systemYellow
        
        guard let img = UIImage(named: "vShirt")
        else { return }
        
        imgView.translatesAutoresizingMaskIntoConstraints = false
        view.addSubview(imgView)
        
        let g = view.safeAreaLayoutGuide
        NSLayoutConstraint.activate([
            imgView.leadingAnchor.constraint(equalTo: g.leadingAnchor, constant: 20.0),
            imgView.trailingAnchor.constraint(equalTo: g.trailingAnchor, constant: -20.0),
            imgView.centerYAnchor.constraint(equalTo: g.centerYAnchor),
            imgView.heightAnchor.constraint(equalTo: imgView.widthAnchor, multiplier: img.size.height / img.size.width)
        ])
        
        imgView.image = img
        
        imgView.backgroundColor = .white
        
        let colors: [UIColor] = [
            .white,
            .systemGreen,
            .systemBlue,
            .systemPink,
            .yellow,
        ]
        let stackView = UIStackView()
        stackView.distribution = .fillEqually
        stackView.translatesAutoresizingMaskIntoConstraints = false
        view.addSubview(stackView)
        NSLayoutConstraint.activate([
            stackView.bottomAnchor.constraint(equalTo: g.bottomAnchor, constant: -20.0),
            stackView.leadingAnchor.constraint(equalTo: g.leadingAnchor, constant: 20.0),
            stackView.trailingAnchor.constraint(equalTo: g.trailingAnchor, constant: -20.0),
            stackView.heightAnchor.constraint(equalToConstant: 50.0),
        ])
        colors.forEach { c in
            let v = UIView()
            v.backgroundColor = c
            v.layer.borderColor = UIColor.black.cgColor
            v.layer.borderWidth = 1
            stackView.addArrangedSubview(v)
            let t = UITapGestureRecognizer(target: self, action: #selector(colorTap(_:)))
            v.addGestureRecognizer(t)
        }
    }
    
    @objc func colorTap(_ g: UITapGestureRecognizer) {
        guard let v = g.view else { return }
        imgView.backgroundColor = v.backgroundColor
    }
}
let image = UIImage(named: "Swift")?.withRenderingMode(.alwaysTemplate)
let imageView = UIImageView(image: image)
imageView.tintColor = .systemPink

You are not able to change the colour of a UIImage(). You are able to change the TINT.

Here is a resource for you to review. https://sarunw.com/posts/how-to-change-uiimage-color-in-swift/

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
    }
}

}

Perhaps this function will also help you.

Related