Skip to content

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

Description

@owlstack

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?

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions