iosuiimageviewcgimage

Why CGImage size changed after resize with transparent background? And how to lower the memory cost?


I want to enlarge an image and fill the space with white color.

    func resizeImageWithTransparentBackground(originalImage: UIImage, targetSize: CGSize) -> UIImage? {

        let originalSize = originalImage.size
        let widthRatio = originalSize.width / targetSize.width
        let heightRatio = originalSize.height / targetSize.height

        var newSize = CGSizeZero
        //scale width or height
        if widthRatio - heightRatio >= 0.01 {
            newSize = CGSize(width: originalSize.width, height: originalSize.width)
        } else {
            newSize = CGSize(width: originalSize.height, height: originalSize.height)
        }
         
        UIGraphicsBeginImageContextWithOptions(newSize, false, 0.0)
        UIColor.white.setFill()
        UIRectFill(CGRect(origin: .zero, size: newSize))
        
        // Center the original image
        let originX = (newSize.width - originalSize.width) / 2
        let originY = (newSize.height - originalSize.height) / 2
        let rect = CGRect(x: originX, y: originY, width: originalSize.width, height: originalSize.height)
        CGBitmapInfo(rawValue: 0)
        
        originalImage.draw(in: rect)
        
        let resizedImage = UIGraphicsGetImageFromCurrentImageContext()
        
        UIGraphicsEndImageContext()
        
        return resizedImage
    }

But the CGImage size has changed:

enter image description here

Another side effect is that it cost high memory. Why this happen and how can I solve this?

Thanks


Solution

  • The size of the resulting image is enlarged by 3x3. You supplied 0.0 to the scale in UIGraphicsBeginImageContextWithOptions which means it will use scale factor or your device's main screen, which appears to be 3 in your case. If you want to keep the same size as the original image, set the scale parameter to 1.0.

    If you want to keep the result image same size as the original image, you should get the scale from originalImage and supply that to the UIGraphicsBeginImageContextWithOptions function. Which @Rob pointed out is not necessarily 1.0.

    The difference in alpha and byte ordering is because the original image doesn't have an alpha channel. By setting the opaque boolean flag to false the image context is created with an alpha channel. Since you are creating a full white background, it is safe to set the opaque flag to YES or true.

    See the developer documentation: https://developer.apple.com/documentation/uikit/1623912-uigraphicsbeginimagecontextwitho?language=objc