How do I resize the UIImage to reduce upload image size
Xcode 9 • Swift 4 or later
edit/update: For iOS10+ We can use UIGraphicsImageRenderer. For older Swift syntax check edit history.
extension UIImage { func resized(withPercentage percentage: CGFloat, isOpaque: Bool = true) -> UIImage? { let canvas = CGSize(width: size.width * percentage, height: size.height * percentage) let format = imageRendererFormat format.opaque = isOpaque return UIGraphicsImageRenderer(size: canvas, format: format).image { _ in draw(in: CGRect(origin: .zero, size: canvas)) } } func resized(toWidth width: CGFloat, isOpaque: Bool = true) -> UIImage? { let canvas = CGSize(width: width, height: CGFloat(ceil(width/size.width * size.height))) let format = imageRendererFormat format.opaque = isOpaque return UIGraphicsImageRenderer(size: canvas, format: format).image { _ in draw(in: CGRect(origin: .zero, size: canvas)) } }}
Usage:
let image = UIImage(data: try! Data(contentsOf: URL(string:"http://i.stack.imgur.com/Xs4RX.jpg")!))!let thumb1 = image.resized(withPercentage: 0.1)let thumb2 = image.resized(toWidth: 72.0)
This is the way which i followed to resize image.
-(UIImage *)resizeImage:(UIImage *)image{ float actualHeight = image.size.height; float actualWidth = image.size.width; float maxHeight = 300.0; float maxWidth = 400.0; float imgRatio = actualWidth/actualHeight; float maxRatio = maxWidth/maxHeight; float compressionQuality = 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; } } CGRect rect = CGRectMake(0.0, 0.0, actualWidth, actualHeight); UIGraphicsBeginImageContext(rect.size); [image drawInRect:rect]; UIImage *img = UIGraphicsGetImageFromCurrentImageContext(); NSData *imageData = UIImageJPEGRepresentation(img, compressionQuality); UIGraphicsEndImageContext(); return [UIImage imageWithData:imageData];}
Using this method my image having 6.5 MB reduced to 104 KB.
Swift 4 code:
func resize(_ image: UIImage) -> UIImage { var actualHeight = Float(image.size.height) var actualWidth = 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 = CGRect(x: 0.0, y: 0.0, width: CGFloat(actualWidth), height: CGFloat(actualHeight)) UIGraphicsBeginImageContext(rect.size) image.draw(in: rect) let img = UIGraphicsGetImageFromCurrentImageContext() let imageData = img?.jpegData(compressionQuality: CGFloat(compressionQuality)) UIGraphicsEndImageContext() return UIImage(data: imageData!) ?? UIImage()}
In case someone is looking for resizing image to less than 1MB with Swift 3 and 4.
Just copy&paste this extension:
extension UIImage {func resized(withPercentage percentage: CGFloat) -> UIImage? { let canvasSize = CGSize(width: size.width * percentage, height: size.height * percentage) UIGraphicsBeginImageContextWithOptions(canvasSize, false, scale) defer { UIGraphicsEndImageContext() } draw(in: CGRect(origin: .zero, size: canvasSize)) return UIGraphicsGetImageFromCurrentImageContext()}func resizedTo1MB() -> UIImage? { guard let imageData = UIImagePNGRepresentation(self) else { return nil } var resizingImage = self var imageSizeKB = Double(imageData.count) / 1000.0 // ! Or devide for 1024 if you need KB but not kB while imageSizeKB > 1000 { // ! Or use 1024 if you need KB but not kB guard let resizedImage = resizingImage.resized(withPercentage: 0.9), let imageData = UIImagePNGRepresentation(resizedImage) else { return nil } resizingImage = resizedImage imageSizeKB = Double(imageData.count) / 1000.0 // ! Or devide for 1024 if you need KB but not kB } return resizingImage}}
And use:
let resizedImage = originalImage.resizedTo1MB()
Edit:Please note it's blocking UI, so move to background thread if you think it's the right way for your case.