UIImageSwiftExtensions
UIImageSwiftExtensions copied to clipboard
ResizeImage() does not work for PNG images, only JPG.
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?