简体   繁体   中英

Android: BitmapFactory.decodeByteArray - reduce image quality

This is my use case:

ByteArray ba; // Some value is assigned here
Bitmap bitmap = BitmapFactory.decodeByteArray(ba, 0, ba.length);

Because the ByteArray object is to large, an OutOfMemoryError exception is thrown at the second line, when doing:

BitmapFactory.decodeByteArray(ba, 0, ba.length);

Already tried:

ByteArray ba; // Some value is assigned here
BitmapFactory.Options options = new BitmapFactory.Options();
options.inSampleSize = 4; //or whatever value
Bitmap bitmap = BitmapFactory.decodeByteArray(ba, 0, ba.length, options);

The problem with this solution is that, using inSampleSize attribute, it avoids the OutOfMemoryError exception, but the bitmap size (dimensions: width x height) is reduced.

Instead I'm looking for something similar to this:

bitmap.compress(Bitmap.CompressFormat.JPEG, 50, stream);

At this example the quality of the bitmap is reduced, BUT its size is still the same. When I display it in an ImageView :

iv.setImageBitmap(bitmap);

It occupies the same space as the original, but with half quality.

The problem is, that in my case I cannot use bitmap.compress because my bitmap is null . That is, the compress method can be used after you have a valid Bitmap object, which is not my case.

Question:

Is there any solution using BitmapFactory.Options which can lead to the same result as bitmap.compress : lower quality , same dimensions ?

Is there any solution using BitmapFactory.Options which can lead to the same result as bitmap.compress: lower quality, same dimensions?

Not really. A Bitmap is uncompressed by its very nature.

The problem is, that in my case I cannot use bitmap.compress because my bitmap is null.

You are confusing an encoded JPEG image with a Bitmap . An encoded JPEG image is compressed. A Bitmap is not. A Bitmap always consumes memory based on the width, height, and the number of bits per pixel.

You could use a different number of bits per pixel. BitmapFactory uses ARGB_8888 (32 bits/pixel). You could switch to RGB_565 (16 bits/pixel), if your image has no alpha channel and you can live with the reduced range of colors.

Otherwise, your only option is to reduce the size (width and height) of the image.

You cannot compress the bitmap as you want.

You may already know this - But, Yes! you can find the appropriate inSampleSize by this method to maintain the quality based on the size.

public static int calculateInSampleSize(
            BitmapFactory.Options options, int reqWidth, int reqHeight) {
    // Raw height and width of image
    final int height = options.outHeight;
    final int width = options.outWidth;
    int inSampleSize = 1;

    if (height > reqHeight || width > reqWidth) {

        final int halfHeight = height / 2;
        final int halfWidth = width / 2;

        // Calculate the largest inSampleSize value that is a power of 2 and keeps both
        // height and width larger than the requested height and width.
        while ((halfHeight / inSampleSize) >= reqHeight
                && (halfWidth / inSampleSize) >= reqWidth) {
            inSampleSize *= 2;
        }
    }

    return inSampleSize;
}

This method is picked from Android Loading Large images efficiently .

You can read more about handing Bimaps here

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM