iosswiftcalayermask

Reverse a CALayer mask


enter image description hereI am trying to use a CALayer with an image as contents for masking a UIView. For the mask I have complex png image. If I apply the image as a view.layer.mask I get the opposite behaviour of what I want. Is there a way to reverse the CAlayer? Here is my code:

layerMask = CALayer()
guard let layerMask = layerMask else { return }    
layerMask.contents = #imageLiteral(resourceName: "mask").cgImage
view.layer.mask = layerMask
// What I would like to to is
view.layer.mask = layerMask.inverse. // <---

I have seen several posts on reverse CAShapeLayers and Mutable paths, but nothing where I can reverse a CALayer. What I could do is reverse the image in Photoshop so that the alpha is inverted, but the problem with that is that I won't be able to create an image with the exact size to fit all screen sizes. I hope it does make sense.


Solution

  • What I would do is construct the mask in real time. This is easy if you have a black image of the logo. Using standard techniques, you can draw the logo image into an image that you construct in real time, so that you are in charge of the size of the image and the size and placement of logo within it. Using a "Mask To Alpha" CIFilter, you can then convert the black to transparent for use as a layer mask.

    So, to illustrate. Here's the background image: this is what we want to see wherever we punch a hole in the foreground:

    enter image description here

    Here's the foreground image, lying on top of the background and completely hiding it:

    enter image description here

    Here's the logo, in black (ignore the grey, which represents transparency):

    enter image description here

    Here's the logo drawn in code into a white background of the correct size:

    enter image description here

    And finally, here's that same image converted into a mask with the Mask To Alpha CIFilter and attached to the foreground image view as its mask:

    enter image description here

    Okay, I could have chosen my images a little better, but this is what I had lying around. You can see that wherever there was black in the logo, we are punching a hole in the foreground image and seeing the background image, which I believe is exactly what you said you wanted to do.

    The key step is the last one, namely the conversion of the black-on-white image of the logo (im) to a mask; here's how I did that:

        let cim = CIImage(image:im)
        let filter = CIFilter(name:"CIMaskToAlpha")!
        filter.setValue(cim, forKey: "inputImage")
        let out = filter.outputImage!
        let cgim = CIContext().createCGImage(out, from: out.extent)
        let lay = CALayer()
        lay.frame = self.iv.bounds
        lay.contents = cgim
        self.iv.layer.mask = lay