UIImageSwiftExtensions icon indicating copy to clipboard operation
UIImageSwiftExtensions copied to clipboard

ResizeImage() does not work for PNG images, only JPG.

Open owlstack opened this issue 6 years ago • 0 comments

I have an app that allows the user to access photos on their phone and upload them to the app for processing.

The code snippet below works for most images but I noticed for one image, the app crashes and I get the exception Fatal error: Unexpectedly found nil while unwrapping an Optional value.

It crashes on this object bitmap:CGContext inside resizedImage() function where the forced unwrap is set. I found out that the image is a PNG image while the other images I'm working with are JPG and it works just fine.

import Foundation
import UIKit

extension UIImage {
    func isLandscape() -> Bool {
        return size.width > size.height
    }

    func isPortrait() -> Bool {
        return !isLandscape()
    }
        func getPixelColor(pos: CGPoint) -> UIColor {
            let pixelData = self.cgImage!.dataProvider!.data
            let data: UnsafePointer<UInt8> = CFDataGetBytePtr(pixelData)

            let pixelInfo: Int = ((Int(self.size.width) * Int(pos.y)) + Int(pos.x)) * 4

            let r = CGFloat(data[pixelInfo]) / CGFloat(255.0)
            let g = CGFloat(data[pixelInfo+1]) / CGFloat(255.0)
            let b = CGFloat(data[pixelInfo+2]) / CGFloat(255.0)
            let a = CGFloat(data[pixelInfo+3]) / CGFloat(255.0)

            return UIColor(red: r, green: g, blue: b, alpha: a)
        }
    func resizedImage(newSize:CGSize, interpolationQuality quality:CGInterpolationQuality) -> UIImage {
        var drawTransposed = false

        switch(self.imageOrientation) {
        case .left: break
        case .leftMirrored: break
        case .right: break
        case .rightMirrored:
            drawTransposed = true
        default:
            drawTransposed = false
        }

        return self.resizedImage(
            newSize: newSize,
            transform: self.transformForOrientation(newSize: newSize),
            drawTransposed: drawTransposed,
            interpolationQuality: quality
        )
    }
    func resizedImage(
        newSize:CGSize,
        transform:CGAffineTransform,
        drawTransposed transpose:Bool,
        interpolationQuality quality:CGInterpolationQuality
        ) -> UIImage {
        let newRect:CGRect = CGRect(x: 0, y: 0, width: newSize.width, height: newSize.height).integral
        let transposedRect:CGRect = CGRect(x: 0, y: 0, width: newRect.size.width, height: newRect.size.height)
        let imageRef:CGImage = self.cgImage!

        // build a context that's the same dimensions as the new size
        let bitmap:CGContext = CGContext(
            data: nil,
            width: Int(newRect.size.width),
            height: Int(newRect.size.height),
            bitsPerComponent: imageRef.bitsPerComponent,
            bytesPerRow: 0,
            space: imageRef.colorSpace!,
            bitmapInfo: imageRef.bitmapInfo.rawValue
            )! //This is where the code crashes. 

        // rotate and/or flip the image if required by its orientation
        bitmap.concatenate(transform)

        // set the quality level to use when rescaling
        bitmap.interpolationQuality = quality

        // draw into the context; this scales the image
        bitmap.draw(imageRef, in: transpose ? transposedRect : newRect)

        // get the resized image from the context and a UIImage
        let newImageRef:CGImage = bitmap.makeImage()!
        let newImage = UIImage(cgImage: newImageRef)

        return newImage
    }
    func transformForOrientation(newSize:CGSize) -> CGAffineTransform {
        let transform:CGAffineTransform = .identity
        switch (self.imageOrientation) {
        case .down: break          // EXIF = 3
        case .downMirrored:  // EXIF = 4
            transform.translatedBy(x: newSize.width, y: newSize.height)
            transform.rotated(by: .pi)
        case .left: break          // EXIF = 6
        case .leftMirrored:  // EXIF = 5
            transform.translatedBy(x: newSize.width, y: 0)
            transform.rotated(by: .pi/2)
        case .right: break         // EXIF = 8
        case .rightMirrored: // EXIF = 7
            transform.translatedBy(x: 0, y: newSize.height)
            transform.rotated(by: -.pi/2)
        default:
            break
        }

        switch(self.imageOrientation) {
        case .upMirrored: break    // EXIF = 2
        case .downMirrored:  // EXIF = 4
            transform.translatedBy(x: newSize.width, y: 0)
            transform.scaledBy(x: -1, y: 1)
        case .leftMirrored: break  // EXIF = 5
        case .rightMirrored: // EXIF = 7
            transform.translatedBy(x: newSize.height, y: 0)
            transform.scaledBy(x: -1, y: 1)
        default:
            break
        }

        return transform
    }

}

What can I do to make sure the above supports PNG as well?

owlstack avatar Jun 06 '19 03:06 owlstack