How to compress of reduce the size of an image before uploading to Parse as PFFile? (Swift)
Yes you can use UIImageJPEGRepresentation
instead of UIImagePNGRepresentation
to reduce your image file size. You can just create an extension UIImage as follow:
Xcode 8.2 • Swift 3.0.2
extension UIImage { enum JPEGQuality: CGFloat { case lowest = 0 case low = 0.25 case medium = 0.5 case high = 0.75 case highest = 1 } /// Returns the data for the specified image in JPEG format. /// If the image object’s underlying image data has been purged, calling this function forces that data to be reloaded into memory. /// - returns: A data object containing the JPEG data, or nil if there was a problem generating the data. This function may return nil if the image has no data or if the underlying CGImageRef contains data in an unsupported bitmap format. func jpeg(_ quality: JPEGQuality) -> Data? { return UIImageJPEGRepresentation(self, quality.rawValue) }}
edit/update:
Xcode 10 Swift 4.2
extension UIImage { enum JPEGQuality: CGFloat { case lowest = 0 case low = 0.25 case medium = 0.5 case high = 0.75 case highest = 1 } /// Returns the data for the specified image in JPEG format. /// If the image object’s underlying image data has been purged, calling this function forces that data to be reloaded into memory. /// - returns: A data object containing the JPEG data, or nil if there was a problem generating the data. This function may return nil if the image has no data or if the underlying CGImageRef contains data in an unsupported bitmap format. func jpeg(_ jpegQuality: JPEGQuality) -> Data? { return jpegData(compressionQuality: jpegQuality.rawValue) }}
Usage:
if let imageData = image.jpeg(.lowest) { print(imageData.count)}
If you want to limit size of image to some concrete value u can do as follow:
import UIKitextension UIImage { // MARK: - UIImage+Resize func compressTo(_ expectedSizeInMb:Int) -> UIImage? { let sizeInBytes = expectedSizeInMb * 1024 * 1024 var needCompress:Bool = true var imgData:Data? var compressingValue:CGFloat = 1.0 while (needCompress && compressingValue > 0.0) { if let data:Data = UIImageJPEGRepresentation(self, compressingValue) { if data.count < sizeInBytes { needCompress = false imgData = data } else { compressingValue -= 0.1 } } } if let data = imgData { if (data.count < sizeInBytes) { return UIImage(data: data) } } return nil } }
//image compressionfunc resizeImage(image: UIImage) -> UIImage { var actualHeight: Float = Float(image.size.height) var actualWidth: Float = Float(image.size.width) let maxHeight: Float = 300.0 let maxWidth: Float = 400.0 var imgRatio: Float = actualWidth / actualHeight let maxRatio: Float = maxWidth / maxHeight let compressionQuality: Float = 0.5 //50 percent compression if actualHeight > maxHeight || actualWidth > maxWidth { if imgRatio < maxRatio { //adjust width according to maxHeight imgRatio = maxHeight / actualHeight actualWidth = imgRatio * actualWidth actualHeight = maxHeight } else if imgRatio > maxRatio { //adjust height according to maxWidth imgRatio = maxWidth / actualWidth actualHeight = imgRatio * actualHeight actualWidth = maxWidth } else { actualHeight = maxHeight actualWidth = maxWidth } } let rect = CGRectMake(0.0, 0.0, CGFloat(actualWidth), CGFloat(actualHeight)) UIGraphicsBeginImageContext(rect.size) image.drawInRect(rect) let img = UIGraphicsGetImageFromCurrentImageContext() let imageData = UIImageJPEGRepresentation(img!,CGFloat(compressionQuality)) UIGraphicsEndImageContext() return UIImage(data: imageData!)!}