-
-
Save akshay1188/4749253 to your computer and use it in GitHub Desktop.
- (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]; | |
} |
Modified for Swift 3
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 = UIImageJPEGRepresentation(img, compressionQuality)else{
return nil
}
return imageData
}
the compression using pa algorithm? whether the method is lossy or lossless
why would someone use this technique on the client side( for swift )? It will be better to use this compression technique on the server side after the user uploads the image to server. Keep both the original and lower version of the image to use lower quality at thumbnails and original size at the time of some real use. Also this method would allow users to access images at lower bandwidth.
Can someone give the same method using javascript(node) (one may use Jimp or imagemagick)??
useful thanks
@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.
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)
}
}
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)
}
}
`
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
}
great useful
very helpful.
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)
}
Hello,
One question, from where does maxHeight
and maxWidth
come from? was it also taken from WhatsApp?
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
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.
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
}
}
@knox kUTTypeJPEG deprecated
@YogeshPateliOS We can use UTType. jpeg.identifier
decompress ? you already have the uncompressed image right? whats the use case?
Once you compress the image data is changed..there is no option to get the original image back..