Kevin Bastien
Kevin Bastien

Reputation: 11

Masking an image in Swift 2.0

I have searched everywhere and found a few examples on how to mask an image, but none of them seem to work for me... I am running on iOS9 and using Swift2.0

Right now this is what I have:

class func maskImage(background: UIImage, withMask mask: UIImage) -> UIImage {

    let bitmapInfo = CGBitmapInfo(rawValue: CGImageAlphaInfo.PremultipliedLast.rawValue).rawValue
    let colorSpace = CGColorSpaceCreateDeviceRGB()!
    let context = CGBitmapContextCreate(nil, CGImageGetWidth(mask.CGImage), CGImageGetHeight(mask.CGImage), 8, 0, colorSpace, bitmapInfo)

    CGContextDrawImage(context, CGRectMake(0, 0, mask.size.width * mask.scale, mask.size.height * mask.scale), mask.CGImage)

    let maskRef: CGImageRef = CGBitmapContextCreateImage(context)!
    let masked: CGImageRef = CGImageCreateWithMask(background.CGImage, maskRef)!

    let icon: UIImage = UIImage(CGImage: masked, scale: mask.scale, orientation: mask.imageOrientation)

    return icon
}

I am passing two pngs in and getting the error: EXC_BAD_INSTRUCTION on the line where I initialize masked. I don't have enough rep to post the image.

I am probably missing something super simple, but would love your help. Thank you!

Upvotes: 1

Views: 2270

Answers (3)

e3495026
e3495026

Reputation: 79

With Swift 3.0 we have had the great name change.... so this appears to function now after some renaming... and cleaning... based on this example: ( https://www.innofied.com/implementing-image-masking-in-ios/ )

       func maskImage(image:UIImage, mask:UIImage )->UIImage{

            let imageReference = (image.cgImage)!
            let maskReference = (mask.cgImage)!

            let imageMask = CGImage.init(
                maskWidth: maskReference.width
                ,height: maskReference.height
                ,bitsPerComponent: maskReference.bitsPerComponent
                ,bitsPerPixel: maskReference.bitsPerPixel
                ,bytesPerRow: maskReference.bytesPerRow
                ,provider: maskReference.dataProvider!
                ,decode: nil
                ,shouldInterpolate: true
            )


            return (UIImage(cgImage:(imageReference.masking(imageMask!))!))
        }

Upvotes: 1

Island Wave
Island Wave

Reputation: 180

In case anybody stumbles across this same situation and is looking for a clean solution, here's a function to mask an image. It works for .jpg, .png and .gif images.

    func maskImage(image:UIImage, mask:(UIImage))->UIImage{

    let imageReference = image.CGImage
    let maskReference = mask.CGImage

    let imageMask = CGImageMaskCreate(CGImageGetWidth(maskReference),
                                      CGImageGetHeight(maskReference),
                                      CGImageGetBitsPerComponent(maskReference),
                                      CGImageGetBitsPerPixel(maskReference),
                                      CGImageGetBytesPerRow(maskReference),
                                      CGImageGetDataProvider(maskReference), nil, true)

    let maskedReference = CGImageCreateWithMask(imageReference, imageMask)

    let maskedImage = UIImage(CGImage:maskedReference!)

    return maskedImage
}

Add the following declaration lines in your viewDidLoad() or init() as needed :

let image = UIImage(named: "image.png")
let maskingImage = UIImage(named: "mask.png")
let imageView = UIImageView(image: maskingImage)
imageView.image = maskImage(image!, mask: maskingImage!)

Thanks to Manish Kumar's solution Implementing Image Masking in iOS

Upvotes: 0

user4812000
user4812000

Reputation: 1053

I am also running the latest versions and had a lot of trouble with this. I was finally able to use the below code to crop part of an image and overlay a puzzle piece with an image mask.

import UIKit
import CoreGraphics

class ViewController2: UIViewController {

@IBOutlet var imageView: UIImageView!

var p1PosX: CGFloat = 0.0
var p1PosY: CGFloat = 0.0
var p1Width: CGFloat = 0.0
var p1Height: CGFloat = 0.0

override func viewDidLoad() {
    super.viewDidLoad()

    let panda = UIImage(named: "panda.jpeg")!
    let puzzle1 = UIImage(named: "PP-4-1.gif")!

    //Crop
    let contextSize: CGSize = panda.size
    let rect = CGRect(x: 0, y: 0, width: 200, height: 200)

    p1PosX = 0
    p1PosY = 0
    p1Width = contextSize.width / 2
    p1Height = contextSize.height / 2
    let rect1: CGRect = CGRectMake(p1PosX, p1PosY, 350, 350)
    let imageRef1: CGImageRef = CGImageCreateWithImageInRect(panda.CGImage, rect1)!
    let panda1: UIImage = UIImage(CGImage: imageRef1, scale: panda.scale, orientation: panda.imageOrientation)
    imageView.image = panda1

    //Mask
    UIGraphicsBeginImageContext(imageView.frame.size)
    panda1.drawInRect(rect)
    puzzle1.drawInRect(CGRectMake(0, 0, imageView.frame.size.width , imageView.frame.size.height), blendMode: CGBlendMode.DestinationIn, alpha: 1.0)
    let newImage = UIGraphicsGetImageFromCurrentImageContext()
    UIGraphicsEndImageContext()
    imageView.image = newImage
   } 
}

Upvotes: 0

Related Questions