Android 中关于加载Bitmap知识点

 在安卓开发中遇到加载图片是很平常的事情,图片即bitmap,但是Android对于每一个应用程序只分配了16M的内存空间,所以在加载比较大点的bitmap的时候很容易,会出现OOM异常。


android 中加载图片的类BitmapFactary,提供了四类方法:decodeStream,decodeFile,decodeResource,decodeByteArray四种方法。其中decodeFile,decodeResource间接调用了decodeStream。

如何避免OOM异常其实核心是BitmapFactory。options来缩放图片,主要用到inSampleSize参数即采样率。

获取采样率流程,


1  将BitmapFactory.options.inJustDecodebounds = true;  加载图片,它只加载图片宽高,不加载图片真正信息。

2  执行BitmapFactory.decodeResource等方法。

3 通过   BitmapFactory.options.outHeigt,及outWidth,然后与目标的view的大小获取inSampleSize (inSampleSize = 1 不缩放,inSampleSize =2 ,缩放四倍);

4 将BitmapFactory.options.inJustDecodebounds = false; 重新加载图片。



具体代码如下:

/**
     * 通过uri获取图片并进行压缩
     *
     * @param uri
     */
    public static Bitmap getBitmapFormUri(Context  ac, Uri uri,int w,int h) throws  IOException {
        InputStream input = ac.getContentResolver().openInputStream(uri);
        BitmapFactory.Options onlyBoundsOptions = new BitmapFactory.Options();
        onlyBoundsOptions.inJustDecodeBounds = true;
        onlyBoundsOptions.inDither = true;//optional
        onlyBoundsOptions.inPreferredConfig = Bitmap.Config.ARGB_8888;//optional
        BitmapFactory.decodeStream(input, null, onlyBoundsOptions);
        input.close();
        int originalWidth = onlyBoundsOptions.outWidth;
        int originalHeight = onlyBoundsOptions.outHeight;
        if ((originalWidth == -1) || (originalHeight == -1))
            return null;
        int be = 1;//be=1表示不缩放
        be = calculateInSampleSize(onlyBoundsOptions,w,h);
        BitmapFactory.Options bitmapOptions = new BitmapFactory.Options();
        bitmapOptions.inSampleSize = be;//设置缩放比例
        bitmapOptions.inDither = true;//optional
        bitmapOptions.inPreferredConfig = Bitmap.Config.ARGB_8888;//optional
        input = ac.getContentResolver().openInputStream(uri);
        Bitmap bitmap = BitmapFactory.decodeStream(input, null, bitmapOptions);
        input.close();
        return compressImage(bitmap);//再进行质量压缩
    }

 public static 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 heightRatio = Math.round((float) height / (float) reqHeight);
            final int widthRatio = Math.round((float) width / (float) reqWidth);

            inSampleSize = heightRatio < widthRatio ? heightRatio : widthRatio;
        }
        return inSampleSize;
    }

 /**
     * 质量压缩方法
     *
     * @param image
     * @return
     */
    public static Bitmap compressImage(Bitmap image) {

        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        image.compress(Bitmap.CompressFormat.JPEG, 100, baos);//质量压缩方法,这里100表示不压缩,把压缩后的数据存放到baos中
        int options = 100;
        while (baos.toByteArray().length / 1024 > 100) {  //循环判断如果压缩后图片是否大于100kb,大于继续压缩
            baos.reset();//重置baos即清空baos
            //第一个参数 :图片格式 ,第二个参数: 图片质量,100为最高,0为最差  ,第三个参数:保存压缩后的数据的流
            image.compress(Bitmap.CompressFormat.JPEG, options, baos);//这里压缩options%,把压缩后的数据存放到baos中
            options -= 10;//每次都减少10
        }
        ByteArrayInputStream isBm = new ByteArrayInputStream(baos.toByteArray());//把压缩后的数据baos存放到ByteArrayInputStream中
        Bitmap bitmap = BitmapFactory.decodeStream(isBm, null, null);//把ByteArrayInputStream数据生成图片
        return bitmap;
    }


猜你喜欢

转载自blog.csdn.net/yan822/article/details/53763436