Search code examples
iosswiftswift3cgimage

SWIFT 3 - CGImage copy always nil


having this problem and trying to fix it for hours.

func changeColorByTransparent(colorMasking : [CGFloat]) {

    UIGraphicsBeginImageContext(self.symbolImageView.frame.size)
    self.symbolImageView.layer.render(in: UIGraphicsGetCurrentContext()!)
    self.symbolImageView.image = UIGraphicsGetImageFromCurrentImageContext()
    UIGraphicsEndImageContext()

    if let image = self.symbolImageView.image {
        print("image ok")
        if let cgimage = image.cgImage {
            print("cgimage ok")
            if let imageRef = cgimage.copy(maskingColorComponents: colorMasking) {
                print("imageRef ok")
                self.symbolImageView.image = UIImage(cgImage: imageRef, scale: (self.symbolImageView.image?.scale)!, orientation: (self.symbolImageView.image?.imageOrientation)!)
            }
        }
    }
}

The console give me :

image ok
cgimage ok

It always tell me that imageRef is nil but the debug find an image for symbolImageView.image and this image is in JPG. The colorMasking is like colorMasking = [222,255,222,255,222,255] so no problem neither.

Thank you very much for your time.


Solution

  • The source for copy(maskingColorComponents components: [CGFloat]) cannot have an alpha component. The way you are getting an image with UIGraphicsGetImageFromCurrentImageContext results in an alpha component.

    Try this:

    func changeColorByTransparent(imgView: UIImageView, cMask: [CGFloat]) -> UIImage? {
    
        var returnImage: UIImage?
    
        if let capImage = imgView.image {
    
            let sz = capImage.size
    
            UIGraphicsBeginImageContextWithOptions(sz, true, 0.0)
            capImage.draw(in: CGRect(origin: CGPoint.zero, size: sz))
            let noAlphaImage = UIGraphicsGetImageFromCurrentImageContext()
            UIGraphicsEndImageContext()
    
            let noAlphaCGRef = noAlphaImage?.cgImage
    
            if let imgRefCopy = noAlphaCGRef?.copy(maskingColorComponents: cMask) {
    
                returnImage = UIImage(cgImage: imgRefCopy)
    
            }
    
        }
    
        return returnImage
    
    }
    

    and call it like this:

    var cMask : [CGFloat] = []
    
    cMask = [222, 255, 222, 255, 222, 255]
    
    let newImage = changeColorByTransparent(imgView: symbolImageView, cMask: cMask)
    

    (assuming you have a UIImageVIew named "symbolImageView")

    and, to get around an odd alpha channel issue when saving the resulting image:

    func saveImageWithAlpha(theImage: UIImage, destFile: URL) -> Void {
    
        // odd but works... solution to image not saving with proper alpha channel
        UIGraphicsBeginImageContext(theImage.size)
        theImage.draw(at: CGPoint.zero)
        let saveImage = UIGraphicsGetImageFromCurrentImageContext()
        UIGraphicsEndImageContext()
    
        if let img = saveImage, let data = UIImagePNGRepresentation(img) {
    
            try? data.write(to: destFile)
    
        }
    
    }