How to cut the shape of a logo(png image) from another image programmatically in Swift?

4.5k views Asked by At

This is the background image

enter image description here

This is the logo

enter image description here

How can we make a image like this in Swift?

enter image description here


Update

Now I manage to use the logo as a mask and get something like this, enter image description here

Is there any way to reverse the mask?

Here is my code

let logo = UIImage(named: "logo")!
let mask = CALayer()
mask.contents = logo.CGImage
mask.frame = mImageView.layer.bounds
mImageView.layer.mask = mask
3

There are 3 answers

2
Leo Dabus On BEST ANSWER

You can do it programmatically using UIBezierPath:

// lets create a view and an image for testing
let picture = UIImage(data: try! Data(contentsOf: URL(string: "https://i.stack.imgur.com/Xs4RX.jpg")!))!

// lets create a view and an image for testing
let imageView = UIImageView(frame: CGRect(x: 0, y: 0, width: picture.size.width, height: picture.size.height))
imageView.image = picture

// now a layer for the mask
let maskLayer = CAShapeLayer()

// a path for the logo
let maskPath = CGMutablePath()

// create your logo path (I've added this circle to represent your logo path)
maskPath.addEllipse(in: CGRect(x: imageView.frame.midX - 150, y: imageView.frame.midY - 150, width: 300, height: 300))

// you will need a rectangle that covers the whole image area to intersect with your logo path
maskPath.addRect(CGRect(x: 0, y: 0, width: picture.size.width, height: picture.size.height))

// add the mask to your maskLayer
maskLayer.path = maskPath

// choose the fill rule EvenOdd
maskLayer.fillRule = kCAFillRuleEvenOdd

// add your masklayer to your view
imageView.layer.mask = maskLayer
imageView

If you need to use an image and invert the alpha of you logo programmatically you can do as follow using kCGBlendModeDestinationOut:

import UIKit

extension UIImage {
    func masked(with image: UIImage, position: CGPoint? = nil, inverted: Bool = false) -> UIImage? {
        let position = position ??
            CGPoint(x: size.width.half - image.size.width.half,
                    y: size.height.half - image.size.height.half)
        defer { UIGraphicsEndImageContext() }
        UIGraphicsBeginImageContextWithOptions(size, false, scale)
        draw(at: .zero)
        image.draw(at: position, blendMode: inverted ? .destinationOut : .destinationIn, alpha: 1)
        return UIGraphicsGetImageFromCurrentImageContext()
    }
}

let picture = UIImage(data: try! Data(contentsOf: URL(string: "https://i.stack.imgur.com/Xs4RX.jpg")!))!
let logo = UIImage(data: try! Data(contentsOf: URL(string: "https://www.dropbox.com/s/k7vk3xvcvcly1ik/chat_bubble.png?dl=1")!))!

let view = UIView(frame: UIScreen.main.bounds)
view.backgroundColor = .blue
let iv = UIImageView(frame: UIScreen.main.bounds)
iv.contentMode = .scaleAspectFill
iv.image = picture.masked(with: logo, inverted: true)
view.addSubview(iv)
0
Keoros On
let bg = UIImage(named: "bg")!
let logo = UIImage(named: "logo")!
let size = imageView.frame.size
let rect = CGRectMake(0, 0, size.width, size.height)
UIGraphicsBeginImageContext(size)
bg?.drawInRect(rect)
logo.drawInRect(rect, blendMode: kCGBlendModeDestinationOut, alpha: 1.0)
let newImage = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
imageView.image = newImage
0
Javier Calatrava Llavería On

Same as Keoros, but simplified by using an extension up. (Vote him up also!)

extension UIImageView {
func applyCutMask(image:UIImage,cutMask:UIImage) {
    let size = self.frame.size
    let rect =  CGRect(origin: CGPoint(x:0,y:0), size: size)
    UIGraphicsBeginImageContext(size)
    image.draw(in: rect)
    cutMask.draw(in: rect, blendMode: .destinationOut, alpha: 1.0)
    let newImage = UIGraphicsGetImageFromCurrentImageContext()
    UIGraphicsEndImageContext()
    self.image = newImage
}}

Usage:

imageView.applyCutMask(image: UIImage(named:"bg"), cutMask:UIImage(named:"logo"))