peetonn
peetonn

Reputation: 3052

UIImage masking doesn't work (Swift, iOS 10)

Trying to mask an image with my custom mask. I think I follow the ideas correctly, but for some reason, image isn't get masked. Instead, masked image, created after masking, contains original cropped image as the mask wasn't applied.

Here's the Swift playground code which one can use in order to test my code (image and mask are attached, just drop them to the resources folder):

import UIKit

extension UIImage {
    static func resizeImage(image: UIImage, width: CGFloat) -> UIImage {
        let scale = width / image.size.width
        let newHeight = round(image.size.height * scale)
        UIGraphicsBeginImageContextWithOptions(CGSize(width:width, height:newHeight), false, image.scale)

        image.draw(in: CGRect(origin: CGPoint(x:0, y:0), size: CGSize(width: width, height: newHeight)))
        let newImage = UIGraphicsGetImageFromCurrentImageContext()
        UIGraphicsEndImageContext()

        return newImage!
    }

    static func resizeImage(image: UIImage, height: CGFloat) -> UIImage {
        let scale = height / image.size.height
        let newWidth = round(image.size.width * scale)
        UIGraphicsBeginImageContextWithOptions(CGSize(width:newWidth, height:height), false, image.scale)
        image.draw(in: CGRect(origin: CGPoint(x:0, y:0), size: CGSize(width: newWidth, height: height)))
        let newImage = UIGraphicsGetImageFromCurrentImageContext()
        UIGraphicsEndImageContext()

        return newImage!
    }
}

let image = UIImage(named: "image.jpg")!
var mask = UIImage(named: "mask.jpg")!

let k1 = image.size.width / image.size.height
let k2 = mask.size.width / mask.size.height

if k1 >= k2
{
    mask = UIImage.resizeImage(image: mask, height: image.size.height)
}
else
{
    mask = UIImage.resizeImage(image: mask, width: image.size.width)
}

image
mask

let center = CGPoint(x: image.size.width/2, y: image.size.height/2)
let croppingRect = CGRect(x: abs(image.size.width-mask.size.width)/2*image.scale,
                                  y: abs(image.size.height-mask.size.height)/2*image.scale,
                                  width: mask.size.width*image.scale,
                                  height: mask.size.height*image.scale).integral
let maskReference = mask.cgImage!
let imageReference = image.cgImage!.cropping(to: croppingRect)!
let imageMask = CGImage(maskWidth: maskReference.width,
                        height: maskReference.height,
                        bitsPerComponent: maskReference.bitsPerComponent,
                        bitsPerPixel: maskReference.bitsPerPixel,
                        bytesPerRow: maskReference.bytesPerRow,
                        provider: maskReference.dataProvider!, decode: nil, shouldInterpolate: true)

imageMask?.colorSpace
imageMask?.alphaInfo

let maskedReference = imageReference.masking(imageMask!)
let maskedImage = UIImage(cgImage:maskedReference!, scale: image.scale, orientation: image.imageOrientation)

mask image

Upvotes: 1

Views: 738

Answers (1)

Ahmadreza
Ahmadreza

Reputation: 7232

Swift 4+

let icon = UIImageView(image: YOURIMAGE)
icon.frame = CGRect(x:100, y: 100, width: 100, height: 100)
icon.layer.masksToBounds = true
let maskView = UIImageView()
maskView.image = YOURMASKIMAGE
maskView.frame = icon.bounds
icon.mask = maskView
icon.contentMode = .scaleToFill
icon.clipsToBounds = true
view.addSubview(icon)

Upvotes: 1

Related Questions