Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Compress bitmap to a specific byte size in Android

Is there a way to compress Bitmap to a specific byte size? For example, 1.5MB. The matter is all the examples I have seen so far were resizing width and height, but my requirement is to resize the bytes. Is that possible? Also, what is the most straightforward and right way to compress the Bitmap? I am quite novice to this topic and would like to go right direction from the beginning.

like image 270
sunflower20 Avatar asked Oct 15 '25 14:10

sunflower20


2 Answers

Here's a helper class I created. This compresses the bitmap both by width/height then by max file size. It's not an exact science to shrink an image to 1.5mb, but what it does is if the image is larger than required, it compresses the bitmap using jpeg and reduces the quality by 80%. Once the file size is less than the required size, it returns the bitmap in a byte array.

public static byte[] getCompressedBitmapData(Bitmap bitmap, int maxFileSize, int maxDimensions) {
    Bitmap resizedBitmap;
    if (bitmap.getWidth() > maxDimensions || bitmap.getHeight() > maxDimensions) {
        resizedBitmap = getResizedBitmap(bitmap,
                                         maxDimensions);
    } else {
        resizedBitmap = bitmap;
    }

    byte[] bitmapData = getByteArray(resizedBitmap);

    while (bitmapData.length > maxFileSize) {
        bitmapData = getByteArray(resizedBitmap);
    }
    return bitmapData;
}

public static Bitmap getResizedBitmap(Bitmap image, int maxSize) {
    int width = image.getWidth();
    int height = image.getHeight();

    float bitmapRatio = (float) width / (float) height;
    if (bitmapRatio > 1) {
        width = maxSize;
        height = (int) (width / bitmapRatio);
    } else {
        height = maxSize;
        width = (int) (height * bitmapRatio);
    }
    return Bitmap.createScaledBitmap(image,
                                     width,
                                     height,
                                     true);
}

private static byte[] getByteArray(Bitmap bitmap) {
    ByteArrayOutputStream bos = new ByteArrayOutputStream();

    bitmap.compress(Bitmap.CompressFormat.JPEG,
                    80,
                    bos);

    return bos.toByteArray();
}
like image 96
tim.paetz Avatar answered Oct 17 '25 04:10

tim.paetz


You can calculate the size of a bitmap quite easily by width * height * bytes per pixel = size

Where bytes per pixel is defined by your color model say RGBA_F16 is 8 bytes while ARGB_8888 is 4 bytes and so on. With this you should be able to figure out what width and height and color encoding you want for your image.

See https://developer.android.com/reference/android/graphics/Bitmap.Config for the bit values.

Also see https://developer.android.com/topic/performance/graphics/manage-memory for more about bitmap memory management.

like image 32
leonardkraemer Avatar answered Oct 17 '25 03:10

leonardkraemer