Skip to content

Instantly share code, notes, and snippets.

@akshay1188
Last active June 10, 2023 16:42
Show Gist options
  • Save akshay1188/4749253 to your computer and use it in GitHub Desktop.
Save akshay1188/4749253 to your computer and use it in GitHub Desktop.
Whatsapp like image compression
- (UIImage *)compressImage:(UIImage *)image{
float actualHeight = image.size.height;
float actualWidth = image.size.width;
float maxHeight = 600.0;
float maxWidth = 800.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];
}
@rajeshm20
Copy link

useful thanks

@mikengyn
Copy link

mikengyn commented May 11, 2018

@ranand16 to improve uploading times and decrease data usage. Using a technique similar to this one I was able to save about 4-5mb on each of my photos before uploading them to my server. The images look almost identical in quality on device and I was able to shave 6-7 seconds on the time it took for the image to upload.

@ahmedAlmasri
Copy link

Migration swift 4 add extension

extension UIImage {
    
    func compressImage() -> UIImage? {
        // Reducing file size to a 10th
        var actualHeight: CGFloat = self.size.height
        var actualWidth: CGFloat = self.size.width
        let maxHeight: CGFloat = 1136.0
        let maxWidth: CGFloat = 640.0
        var imgRatio: CGFloat = actualWidth/actualHeight
        let maxRatio: CGFloat = maxWidth/maxHeight
        var compressionQuality: CGFloat = 0.5
        
        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
                compressionQuality = 1
            }
        }
        let rect = CGRect(x: 0.0, y: 0.0, width: actualWidth, height: actualHeight)
        UIGraphicsBeginImageContext(rect.size)
        self.draw(in: rect)
        guard let img = UIGraphicsGetImageFromCurrentImageContext() else {
            return nil
        }
        UIGraphicsEndImageContext()
        guard let imageData = UIImageJPEGRepresentation(img, compressionQuality) else {
            return nil
        }
        return UIImage(data: imageData)
    }

}

@fozoglu
Copy link

fozoglu commented Nov 21, 2018

Revised @ahmedAlmasri answer for swift 4.2

`
extension UIImage {

func compressImage() -> UIImage? {
    // Reducing file size to a 10th
    var actualHeight: CGFloat = self.size.height
    var actualWidth: CGFloat = self.size.width
    let maxHeight: CGFloat = 1136.0
    let maxWidth: CGFloat = 640.0
    var imgRatio: CGFloat = actualWidth/actualHeight
    let maxRatio: CGFloat = maxWidth/maxHeight
    var compressionQuality: CGFloat = 0.5
    
    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
            compressionQuality = 1
        }
    }
    let rect = CGRect(x: 0.0, y: 0.0, width: actualWidth, height: actualHeight)
    UIGraphicsBeginImageContext(rect.size)
    self.draw(in: rect)
    guard let img = UIGraphicsGetImageFromCurrentImageContext() else {
        return nil
    }
    UIGraphicsEndImageContext()
    guard let imageData = img.jpegData(compressionQuality: compressionQuality) else {
        return nil
    }
    return UIImage(data: imageData)
}

}
`

@ankit21patel
Copy link

i was implement this below code but it's show me unused give me warning :- Result of call to 'compressImage(image:)' is unused

func compressImage(image:UIImage) -> Data? {
// Reducing file size to a 10th

    var actualHeight : CGFloat = image.size.height
    var actualWidth : CGFloat = image.size.width
    let maxHeight : CGFloat = 1136.0
    let maxWidth : CGFloat = 640.0
    var imgRatio : CGFloat = actualWidth/actualHeight
    let maxRatio : CGFloat = maxWidth/maxHeight
    var compressionQuality : CGFloat = 0.5
    
    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
            compressionQuality = 1
        }
    }
    
    let rect = CGRect(x: 0.0, y: 0.0, width: actualWidth, height: actualHeight)
    UIGraphicsBeginImageContext(rect.size)
    image.draw(in: rect)
    guard let img = UIGraphicsGetImageFromCurrentImageContext() else {
        return nil
    }
    UIGraphicsEndImageContext()
    guard let imageData = img.jpegData(compressionQuality: compressionQuality)else{

        return nil
    }
    return imageData
}

@arindamIos
Copy link

great useful

@piyush23dez
Copy link

very helpful.

@GSerjo
Copy link

GSerjo commented Mar 19, 2020

swift 5

    func resize() -> Data? {
        
        let maxHeight: CGFloat = 1136
        let maxWidth: CGFloat = 640
        
        var actualHeight = self.size.height
        var actualWidth = self.size.width

        var imgRatio = actualWidth / actualHeight
        let maxRatio = maxWidth / maxHeight
        var compressionQuality : CGFloat = 0.6
        
        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
                compressionQuality = 1
            }
        }
        
        let canvas = CGSize(width: actualWidth, height: actualHeight)
        let format = imageRendererFormat
        format.opaque = true
        let result = UIGraphicsImageRenderer(size: canvas, format: format).image {
            _ in draw(in: CGRect(origin: .zero, size: canvas))
        }
        return result.jpegData(compressionQuality: compressionQuality)
    }

@diegogarciar
Copy link

Hello,
One question, from where does maxHeight and maxWidth come from? was it also taken from WhatsApp?

@GSerjo
Copy link

GSerjo commented Oct 4, 2020

Hi Diego,

maybe, a bit difficult to check (the initial version has been created 5 years ago).. in the current WhatsApp version I see 768*1024. here how you can see maxHeight and maxWidth

  • open WhatsApp on a computer
  • download an image
  • check dimensions

@diegogarciar
Copy link

Thanks, so I did that and it currently is 1280x960. But I disagree with compressionQuality = 1 in the else statement as that's the scenario where the ratios are the same, but the original image is obviously bigger, not smaller, so I do want it compressed.

@knox
Copy link

knox commented Jan 24, 2021

Resizing with UIGraphicsImageRenderer is dead simple but consumes a lot of memory. So i suggest to use CGContext instead:

extension UIImage {
    func compressedData() -> Data? {
        let maxHeight: CGFloat = 1136
        let maxWidth: CGFloat = 640

        var actualHeight = size.height
        var actualWidth = size.width

        var imgRatio = actualWidth / actualHeight
        let maxRatio = maxWidth / maxHeight
        var compressionQuality : CGFloat = 0.6

        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
                compressionQuality = 1
            }
        }

        guard let cgImage = cgImage else { return nil }

        let mutableData = NSMutableData()
        guard let imageDestinationRef = CGImageDestinationCreateWithData(mutableData as CFMutableData, kUTTypeJPEG, 1, nil) else { return nil }
        let options: NSDictionary = [
            kCGImageDestinationLossyCompressionQuality: compressionQuality
        ]
        CGImageDestinationAddImage(imageDestinationRef, cgImage, options)
        guard CGImageDestinationFinalize(imageDestinationRef) else { return nil }

        return mutableData as Data
    }
}

@YogeshPateliOS
Copy link

@knox kUTTypeJPEG deprecated

@MounikaMadishetti
Copy link

@YogeshPateliOS We can use UTType. jpeg.identifier

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment