How do I resize the UIImage to reduce upload image size
Swift 5.4 & Xcode 13
I was not satisfied with the solutions here, which generate an image based on a given KB size, since most of them used .jpegData(compressionQuality: x)
. This method won't work with large images, since even with compression quality set to 0.0, the large image will remain large, e.g. a 10 MB produced by portrait mode of a newer iPhone still will be above 1 MB with compressionQuality set to 0.0.
Therefore I used some answers here and rewrote a Helper Struct which converts an image in a background que:
import UIKit
struct ImageCompressor {
static func compress(image: UIImage, maxByte: Int,
completion: @escaping (UIImage?) -> ()) {
DispatchQueue.global(qos: .userInitiated).async {
guard let currentImageSize = image.jpegData(compressionQuality: 1.0)?.count else {
return completion(nil)
}
var iterationImage: UIImage? = image
var iterationImageSize = currentImageSize
var iterationCompression: CGFloat = 1.0
while iterationImageSize > maxByte && iterationCompression > 0.01 {
let percantageDecrease = getPercantageToDecreaseTo(forDataCount: iterationImageSize)
let canvasSize = CGSize(width: image.size.width * iterationCompression,
height: image.size.height * iterationCompression)
UIGraphicsBeginImageContextWithOptions(canvasSize, false, image.scale)
defer { UIGraphicsEndImageContext() }
image.draw(in: CGRect(origin: .zero, size: canvasSize))
iterationImage = UIGraphicsGetImageFromCurrentImageContext()
guard let newImageSize = iterationImage?.jpegData(compressionQuality: 1.0)?.count else {
return completion(nil)
}
iterationImageSize = newImageSize
iterationCompression -= percantageDecrease
}
completion(iterationImage)
}
}
private static func getPercantageToDecreaseTo(forDataCount dataCount: Int) -> CGFloat {
switch dataCount {
case 0..<3000000: return 0.05
case 3000000..<10000000: return 0.1
default: return 0.2
}
}
}
Compress an image to max 1 MB:
ImageCompressor.compress(image: image, maxByte: 1000000) { image in
guard let compressedImage = image else { return }
// Use compressedImage
}
}
swift ios reduce image size before upload
you can resize your image first to smaller size using these extension by resizing it by percent or width
extension UIImage {
func resizeWithPercent(percentage: CGFloat) -> UIImage? {
let imageView = UIImageView(frame: CGRect(origin: .zero, size: CGSize(width: size.width * percentage, height: size.height * percentage)))
imageView.contentMode = .ScaleAspectFit
imageView.image = self
UIGraphicsBeginImageContextWithOptions(imageView.bounds.size, false, scale)
guard let context = UIGraphicsGetCurrentContext() else { return nil }
imageView.layer.renderInContext(context)
guard let result = UIGraphicsGetImageFromCurrentImageContext() else { return nil }
UIGraphicsEndImageContext()
return result
}
func resizeWithWidth(width: CGFloat) -> UIImage? {
let imageView = UIImageView(frame: CGRect(origin: .zero, size: CGSize(width: width, height: CGFloat(ceil(width/size.width * size.height)))))
imageView.contentMode = .ScaleAspectFit
imageView.image = self
UIGraphicsBeginImageContextWithOptions(imageView.bounds.size, false, scale)
guard let context = UIGraphicsGetCurrentContext() else { return nil }
imageView.layer.renderInContext(context)
guard let result = UIGraphicsGetImageFromCurrentImageContext() else { return nil }
UIGraphicsEndImageContext()
return result
}
}
to use it just call it like this
myImage = myImage.resizeWithWidth(700)!
Now next you can still compress it using compression ratio of your choice
let compressData = UIImageJPEGRepresentation(myImage, 0.5) //max value is 1.0 and minimum is 0.0
let compressedImage = UIImage(data: compressData!)
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)
}
Resize UIImage to 200x200pt/px
Here is my code. The Image is in width 850 px and not 200 px:
func resizeImage(image: UIImage, newWidth: CGFloat) -> UIImage {
let scale = newWidth / image.size.width
let newHeight = image.size.height * scale
UIGraphicsBeginImageContext(CGSizeMake(newWidth, newHeight))
image.drawInRect(CGRectMake(0, 0, newWidth, newHeight))
let newImage = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
return newImage
}
@IBAction func chooseImage(sender: AnyObject) {
var myPickerController = UIImagePickerController()
myPickerController.sourceType = UIImagePickerControllerSourceType.PhotoLibrary
myPickerController.delegate = self;
self.presentViewController(myPickerController, animated: true, completion: nil)
}
func imagePickerController(picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [NSObject : AnyObject])
{
var imagenow = info[UIImagePickerControllerOriginalImage] as? UIImage
imageImage.image = resizeImage(imagenow!, newWidth: 200)
pimg2 = imageImage.image!
cidnew2 = textFieldCID!.text!
pname2 = textFieldName!.text
pmanu2 = textFieldMan!.text
pnick2 = textFieldNick!.text
podate2 = textFieldPODate!.text
pno2 = textFieldArtNo!.text
self.dismissViewControllerAnimated(true, completion: nil)
}
The simplest way to resize an UIImage?
The simplest way is to set the frame of your UIImageView
and set the contentMode
to one of the resizing options.
Or you can use this utility method, if you actually need to resize an image:
+ (UIImage *)imageWithImage:(UIImage *)image scaledToSize:(CGSize)newSize {
//UIGraphicsBeginImageContext(newSize);
// In next line, pass 0.0 to use the current device's pixel scaling factor (and thus account for Retina resolution).
// Pass 1.0 to force exact pixel size.
UIGraphicsBeginImageContextWithOptions(newSize, NO, 0.0);
[image drawInRect:CGRectMake(0, 0, newSize.width, newSize.height)];
UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return newImage;
}
Example usage:
#import "MYUtil.h"
…
UIImage *myIcon = [MYUtil imageWithImage:myUIImageInstance scaledToSize:CGSizeMake(20, 20)];
How to Resize image in Swift?
See my blog post, Resize image in swift and objective C, for further details.
Image resize function in swift as below.
func resizeImage(image: UIImage, targetSize: CGSize) -> UIImage? {
let size = image.size
let widthRatio = targetSize.width / size.width
let heightRatio = targetSize.height / size.height
// Figure out what our orientation is, and use that to form the rectangle
var newSize: CGSize
if(widthRatio > heightRatio) {
newSize = CGSize(width: size.width * heightRatio, height: size.height * heightRatio)
} else {
newSize = CGSize(width: size.width * widthRatio, height: size.height * widthRatio)
}
// This is the rect that we've calculated out and this is what is actually used below
let rect = CGRect(origin: .zero, size: newSize)
// Actually do the resizing to the rect using the ImageContext stuff
UIGraphicsBeginImageContextWithOptions(newSize, false, 1.0)
image.draw(in: rect)
let newImage = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
return newImage
}
Use the above function and resize image with 200*200 as below code
self.resizeImage(UIImage(named: "yourImageName")!, targetSize: CGSizeMake(200.0, 200.0))
swift3 updated
func resizeImage(image: UIImage, targetSize: CGSize) -> UIImage {
let size = image.size
let widthRatio = targetSize.width / size.width
let heightRatio = targetSize.height / size.height
// Figure out what our orientation is, and use that to form the rectangle
var newSize: CGSize
if(widthRatio > heightRatio) {
newSize = CGSize(width: size.width * heightRatio, height: size.height * heightRatio)
} else {
newSize = CGSize(width: size.width * widthRatio, height: size.height * widthRatio)
}
// This is the rect that we've calculated out and this is what is actually used below
let rect = CGRect(x: 0, y: 0, width: newSize.width, height: newSize.height)
// Actually do the resizing to the rect using the ImageContext stuff
UIGraphicsBeginImageContextWithOptions(newSize, false, 1.0)
image.draw(in: rect)
let newImage = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
return newImage!
}
How to resize UIImageView based on UIImage's size/ratio in Swift 3?
It looks like you want to resize an ImageView according to the image ratio and the container view's size, here is the example in Swift (Sorry,the former answer with a bug, I fixed it):
let containerView = UIView(frame: CGRect(x:0,y:0,width:320,height:500))
let imageView = UIImageView()
if let image = UIImage(named: "a_image") {
let ratio = image.size.width / image.size.height
if containerView.frame.width > containerView.frame.height {
let newHeight = containerView.frame.width / ratio
imageView.frame.size = CGSize(width: containerView.frame.width, height: newHeight)
}
else{
let newWidth = containerView.frame.height * ratio
imageView.frame.size = CGSize(width: newWidth, height: containerView.frame.height)
}
}
SwiftUI - how can I resize images before uploading to Firebase Storage
1. Define a function to change the image size.
How to Resize image in Swift?
func resizeImage(image: UIImage, targetSize: CGSize) -> UIImage? {
let size = image.size
let widthRatio = targetSize.width / size.width
let heightRatio = targetSize.height / size.height
var newSize: CGSize
if(widthRatio > heightRatio) {
newSize = CGSize(width: size.width * heightRatio, height: size.height * heightRatio)
} else {
newSize = CGSize(width: size.width * widthRatio, height: size.height * widthRatio)
}
let rect = CGRect(origin: .zero, size: newSize)
UIGraphicsBeginImageContextWithOptions(newSize, false, 1.0)
image.draw(in: rect)
let newImage = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
return newImage
}
2. Call that function when uploading.
func uploadImageToStorage(image: UIImage) {
if let imageData = resizeImage(image: image, targetSize: CGSize(width: 200, height: 200))?.pngData() {
let storage = Storage.storage()
let storageRef = storage.reference()
let testRef = storageRef.child("avatar/\(user.id)/avatar.png")
testRef.putData(imageData, metadata: nil) {( _, error) in
if let error = error {
print("an error has occured - \(error.localizedDescription)")
} else {
print("image uploaded successfully")
}
}
} else {
print("Coldn't unwrap/case imgae to data")
}
}
Related Topics
Create Singleton Using Gcd'S Dispatch_Once in Objective-C
Can't Use Swift Classes Inside Objective-C
Ios 9 Xcode 7 - Application Appears With Black Bars on Top and Bottom
Ios Upload Image and Text Using Http Post
How to Check If a String Contains Another String in Objective-C
Periodic iOS Background Location Updates
Swift - Get Device'S Wifi Ip Address
Delete/Reset All Entries in Core Data
Assertion Failure in Dequeuereusablecellwithidentifier:Forindexpath:
Why Is There Extra Padding At the Top of My Uitableview With Style Uitableviewstylegrouped in Ios7
How to Easily Resize/Optimize an Image Size With Ios
How to Create a Basic Uibutton Programmatically
Sending an Http Post Request on Ios
How to Deploy an Iphone Application from Xcode to a Real Iphone Device