压缩指定大小的BitMap

版权声明:本文为博主原创文章,转载必须注明出处!! https://blog.csdn.net/qq_34902522/article/details/78654170

序言

在开发中,我们常常会遇到构造图片,加载显示图片的情况。我们可以使用BitMapFactory的decode xxx 方法来构造BitMap对象。但现在普遍照片的质量,像素都很高,如果直接把照片拿来使用,加载到内存,就会很容易造成内存泄漏。也有浪费的嫌疑,比如我程序中只需要,200*200的图像,却是用2048x1536的图加载进去,这就不很浪费,很没有必要么,下面就将说明,如何对BitMap进行压缩处理,得到想要的尺寸的图片。

未处理的图片大小

我们想来看一下没有经过压缩处理的图片的大小。

Bitmap bitmap = BitmapFactory.decodeFile(imagePath);
                    //默认的图片格式是Bitmap.Config.ARGB_8888
                    Log.e(TAG, "onActivityResult: 图片的宽:" + bitmap.getWidth() + "--图片的高:"
                            + bitmap.getHeight() + "--图片大小:" + bitmap.getWidth() * bitmap.getHeight() * 4 / 1024 / 1024 + "M");

这里默认是图片格式是ARGB_8888所以一个像素是占32位,8位等于1个字节,所以一个像素占4个字节内存。此时输出的log信息是:

E/MainActivity: onActivityResult: 图片的宽:1680--图片的高:1050--图片大小:6M

压缩处理成指定大小的图片

代码如下:

BitmapFactory.Options options = new BitmapFactory.Options();
                    options.inJustDecodeBounds = true;
                    BitmapFactory.decodeFile(imagePath, options);
                    Log.e(TAG, "onActivityResult: 压缩之前图片的宽:" + options.outWidth + "--压缩之前图片的高:"
                            + options.outHeight + "--压缩之前图片大小:" + options.outWidth * options.outHeight * 4 / 1024 / 1024 + "M");

                    options.inSampleSize = calculateInSampleSize(options, 200, 200);
                    Log.e(TAG, "onActivityResult: inSampleSize:"+ options.inSampleSize);
                    options.inJustDecodeBounds = false;
                    Bitmap afterCompressBm = BitmapFactory.decodeFile(imagePath, options);
                    //默认的图片格式是Bitmap.Config.ARGB_8888
                    Log.e(TAG, "onActivityResult: 图片的宽:" + afterCompressBm.getWidth() + "--图片的高:"
                            + afterCompressBm.getHeight() + "--图片大小:" + afterCompressBm.getWidth() * afterCompressBm.getHeight() * 4 / 1024 / 1024 + "M");

private int calculateInSampleSize(BitmapFactory.Options options, int reqWidth, int reqHeight) {
        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;

            while ((halfHeight / inSampleSize) >= reqHeight
                    && (halfWidth / inSampleSize) >= reqWidth) {
                inSampleSize *= 2;
            }
        }

        return inSampleSize;
    }

log输出结果如下:

E/MainActivity: onActivityResult: 压缩之前图片的宽:1680--压缩之前图片的高:1050--压缩之前图片大小:6M
E/MainActivity: onActivityResult: inSampleSize:4
E/MainActivity: onActivityResult: 图片的宽:420--图片的高:263--图片大小:0M

我们看到图片的大小就变得很小了,这样就不会占很大的内存导致内存泄漏问题。这里我们可以着重看一下calculateInSampleSize这个方法的逻辑。内部代码逻辑不难,就是通过我们传入的想要的图片宽高值来计算inSampleSize的大小。这里我们通过log发现输出的inSampleSize值为4。此刻就表示,图片的宽变为原来的四分之一,高变为原来的四分之一。整张照片的像素就变为原来的16分之一。这样就达到了压缩的效果。

显示效果对比

压缩前,原图:

压缩前(图片进行过裁剪,图片大小可能有些许误差)

压缩后,图片:

压缩后(图片进行过裁剪,图片大小可能有些许误差)

补充

这里默认的图片格式是Bitmap.Config.ARGB_8888,我们也可以改变图片格式来对图片进行减小。这里补充下各种格式对应的字节大小:
- ARGB_8888 ->一个像素点占32位->4个字节
- RGB_565 ->一个像素点占16位->2个字节
- ARGB_4444 ->占16位->2个字节
- RGBA_F16 ->64位->8个字节
- ALPHA_8 ->不存储颜色信息,只存储透明度->一个像素占1个字节

猜你喜欢

转载自blog.csdn.net/qq_34902522/article/details/78654170