Improving Image Compression – What We’ve Learned from Whatsapp
Anyone who has used Whatsapp has observed how quickly images can be shared even if they are large files.
By large files, I mean high resolution images often ranging from 1-4 MB. For example, the iPhone 4S, with an 8MP camera takes fairly large photos: 3264×2448 pixels (8MP means 8 million pixels). But when you share these images through Whatsapp, it compresses the images which allows for incredibly fast sharing.
I was playing around with a wide variety of image sizes to learn how Whatsapp compresses them.
For example, an image with dimensions 3264×2448 (3 MB) is converted to an image with dimensions 800×600 (~70KB).
When compressing images, the aspect ratio is maintained. i.e the resulting compressed image has same aspect ratio as the original image. In the above case, an aspect ratio of 4:3.
I tried images with different dimensions: 3264×2448, 1280×720, 1280×1024, 1024×768, 480×360, and 400×300.
One thing that I noticed was the images with dimensions greater than 800×600 were scaled down to a maximum resolution of 800×600 (smaller images weren’t scaled).
This chart outlines the results:
Original Resolution (size) | Compressed Resolution (size) |
---|---|
1280×720 (421 KB) | 800×450 (45 KB) |
1280×1024 (153 KB) | 800×640 (84 KB) |
1024×768 (137 KB) | 800×600 (64 KB) |
3264×2448 (3 MB) | 800×600 (69 KB) |
800×600 (226 KB) | 800×600 (68 KB) |
480×360 (30 KB) | 480×360 (21 KB) |
400×300 (24 KB) | 400×300 (22 KB) |
It is clear from the last three entries that in addition to being scaled down, images are compressed by Whatsapp when they’re saved to JPG.
After playing around a bit with UIImageJPEGRepresentation ( UIImage *image, CGFloat compressionQuality)
, I found that the compressionQuality was 50% or a factor 0.5.
With some assistance from stackoverflow, I was able to construct a function in Objective-C that compresses the images exactly like Whatsapp does. I even compared the results with Whatsapp compressed images and they were identical.
Here’s the function I created:
(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];
}
You can find the above code on GitHub.
good analysis !!
thx !
your effort answer to a question i had. so this is why pix shared by whatsapp are just shit when you view them as shared media on ipad…
they could make a function that let choose the receiver how the pic must look, like original or resized..
if in good resolution like 3Mg pixel just hold them for 24h before to delete them.
Totally agree with you bro! They need an option to send the ORIGINAL file
yes absolutely rite..they have to do some changes with watsapp as orginal pics are getting bully if they do so everyone’s pics will show with high quality.
Dude, i fucking love you! Your code just solved a problem i had in my app, to send a pic to the server.
can you tel what is the advantage of maintaining the same aspect ratio while compressing??
Seriously?? Isn’t that obvious?? If aspect ratio is not kept same the whole pic would look either compressed from sides or elongated..
Hi man!! Nice work!! But just a question, do you know where can a try to find something to modify the whatsapp compression on iOS app. Thanks a lot
Thank you so much for this one! Saved me a lot of time reproducing WhatsApp compressing method!
I heard that telegram sends images without scaling them.
So that means I can get into whatsapp scripting to alter the compression to have no compression at all? If so, pls tell me how to find the pathway thanks
How to get selected image from gallery in android app??
Please reply..
Demo Please
What namespace can be used?
This code is awesome thank you: below is the code in swift:
@IBAction func signUp(sender: AnyObject) {
let imageData = UIImagePNGRepresentation(self.profilePic.image)
let image = UIImage(data: imageData)
func compressImage(image:UIImage) -> NSData {
// Reducing file size to a 10th
var actualHeight : CGFloat = image.size.height
var actualWidth : CGFloat = image.size.width
var maxHeight : CGFloat = 1136.0
var maxWidth : CGFloat = 640.0
var imgRatio : CGFloat = actualWidth/actualHeight
var maxRatio : CGFloat = maxWidth/maxHeight
var compressionQuality : CGFloat = 0.5
if (actualHeight > maxHeight || actualWidth > maxWidth){
if(imgRatio maxRatio){
//adjust height according to maxWidth
imgRatio = maxWidth / actualWidth;
actualHeight = imgRatio * actualHeight;
actualWidth = maxWidth;
}
else{
actualHeight = maxHeight;
actualWidth = maxWidth;
compressionQuality = 1;
}
}
var rect = CGRectMake(0.0, 0.0, actualWidth, actualHeight);
UIGraphicsBeginImageContext(rect.size);
image.drawInRect(rect)
var img = UIGraphicsGetImageFromCurrentImageContext();
let imageData = UIImageJPEGRepresentation(img, compressionQuality);
UIGraphicsEndImageContext();
return imageData;
}
let compressedImage = compressImage(image!)
let picture = PFFile(name: “image.png”, data: compressedImage)
PFUser.currentUser()!.setObject(picture, forKey: “profilePic”)
PFUser.currentUser()!.saveInBackgroundWithBlock {
(success: Bool, error: NSError?) -> Void in
if (success) {
println(“image has been saved”)
} else {
println(“image failed”)
}
}
}
Does Whatsapp compress all video files as well?
Any idea if this is still true after the introduction of retina and other HD devices?
By the way, thanks heaps for this research and the code. Very useful!!!
There are many online tools like compress.photos where you can compress the images without loosing the quality of image.
Pingback: How to compress - Resize image on iOS - BlogoSfera
Great tutorial! Solved my problem with my app! Continue Helping!
I converted it to swift:
func compressImage(image: UIImage) -> UIImage {
var actualHeight : CGFloat = image.size.height
var actualWidth : CGFloat = image.size.width
var maxHeight : CGFloat = 600.0
var maxWidth : CGFloat = 800.0
var imgRatio : CGFloat = actualWidth/actualHeight
var maxRatio : CGFloat = maxWidth/maxHeight
var compressionQuality : CGFloat = 0.5 //50 percent compression
if ((actualHeight > maxHeight) || (actualWidth > maxWidth)){
if(imgRatio maxRatio){
//adjust height according to maxWidth
imgRatio = maxWidth / actualWidth;
actualHeight = imgRatio * actualHeight;
actualWidth = maxWidth;
}
else{
actualHeight = maxHeight;
actualWidth = maxWidth;
}
}
var rect = CGRectMake(0.0, 0.0, actualWidth, actualHeight)
UIGraphicsBeginImageContext(rect.size)
image.drawInRect(rect)
var img : UIImage = UIGraphicsGetImageFromCurrentImageContext()
var imageData = UIImageJPEGRepresentation(img, compressionQuality)
UIGraphicsEndImageContext()
return UIImage(data: imageData)!
}
Best app to share stickers in whatsapp!!
https://play.google.com/store/apps/details?id=com.whatsappsmileys.stickers&hl=en