Built.io Blog

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 800x600 (smaller images weren't scaled).

This chart outlines the results:

Original Resolution (size) Compressed Resolution (size)
1280x720 (421 KB) 800x450 (45 KB)
1280x1024 (153 KB) 800x640 (84 KB)
1024x768 (137 KB) 800x600 (64 KB)
3264x2448 (3 MB) 800x600 (69 KB)
800x600 (226 KB) 800x600 (68 KB)
480x360 (30 KB) 480x360 (21 KB)
400x300 (24 KB) 400x300 (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:

<code>(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;
            actualHeight = maxHeight;
            actualWidth = maxWidth;
    CGRect rect = CGRectMake(0.0, 0.0, actualWidth, actualHeight);
    [image drawInRect:rect];
    UIImage *img = UIGraphicsGetImageFromCurrentImageContext();
    NSData *imageData = UIImageJPEGRepresentation(img, compressionQuality);
    return [UIImage imageWithData:imageData];

You can find the above code on GitHub.

Like what you read? Join our community to get more technical information, chances to win prizes, and more: built.io/community

Popular Posts

Subscribe to our blog