Android中如何加载一张大图?

Android中加载大图片往往导致内存溢出,也就是OOM,这是为什么呢?因为android操作系统给每个应用程序分配了有限的内存,比如笔者测试的真机为应用程序分配的最大内存为96M(可以通过Runtime.getRuntime().maxMemory()函数获取到
),而Bitmap对象在内存中所占空间大小与图片本身的像素有关的。默认情况下,bitmap是ARGB_8888类型的,ARGB_8888是什么意思呢?ARGB8888:分别用8个bit来记录每个像素的A(透明度)、R(红色)、G(绿色)、B(蓝色)数据,就是常说的32bit位图,也就是每个像素占了4个字节,如果一张4000*4000的图片转化为bitmap对象,其所占内存空间算法为:4000*4000*4/(1024*1024)=61M(约数)。所以,如果在操作bitmap前不进行压缩,那么加载几张大图,就有可能导致内存溢出。
图片压缩主要分为质量压缩和尺寸压缩。通过算法同化了图片中的一些某个点附近相近的像素,以达到降低质量减少文件大小的目的,但它其实只能实现对file的构成影响,对加载这个图片出来的bitmap内存是无法节省的,因为质量压缩没有改变图片的像素,所以bitmap所占内存不变。
下面介绍这两种压缩技术的具体运用。
一、尺寸压缩:
BitmapFactory.Options类中有两个很重要的属性:inJustDecodeBounds和inSampleSize
。把inJustDecodeBounds属性设置为true就可以让解析方法禁止为bitmap分配内存,返回值也不再是一个Bitmap对象,而是null。虽然Bitmap是null了,但是BitmapFactory.Options的outWidth、outHeight和outMimeType属性都会被赋值。这个技巧让我们可以在加载图片之前就获取到图片的长宽值和MIME类型,从而根据情况对图片进行压缩。inSampleSize就是压缩的倍数,若inSampleSize=
1,表示不压缩,若为2,则表示压缩为原来尺寸的二分之一。
为了确定inSampleSize的大小,就要确定原来图片的大小和目标图片的比例,看代码:

 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的值,这样可以保证最终图片的宽和高
            // 一定都会大于等于目标的宽和高。
            inSampleSize = heightRatio < widthRatio ? heightRatio : widthRatio;
        }
        return inSampleSize;
    }

确定inSampleSize的大小后,便可调用

//尺寸压缩
    public static Bitmap compressBitmapFromResBySize(Resources res, int resId,
                                                         int reqWidth, int reqHeight) {
        // 第一次解析将inJustDecodeBounds设置为true,来获取图片大小
        final BitmapFactory.Options options = new BitmapFactory.Options();
        options.inJustDecodeBounds = true;
        BitmapFactory.decodeResource(res, resId, options);
        // 调用上面定义的方法计算inSampleSize值
        options.inSampleSize = calculateInSampleSize(options, reqWidth, reqHeight);
        // 使用获取到的inSampleSize值再次解析图片
        options.inJustDecodeBounds = false;
        return BitmapFactory.decodeResource(res, resId, options);

    }

二、质量压缩
质量压缩虽然不能改变bitmap 的内存大小,但是压缩后,保存在硬盘或者上传网络时,图片大小会变小,故有利于保存在硬盘或者上传服务器。

/**
     * 质量压缩
     * @param bitmap
     * @return
     */
    public static Bitmap compressBitmapByQuality(Bitmap bitmap){
        ByteArrayOutputStream bos = new ByteArrayOutputStream();
        bitmap.compress(Bitmap.CompressFormat.JPEG, 60, bos);
        ByteArrayInputStream bis = new ByteArrayInputStream(bos.toByteArray());
        System.out.println("bis====="+bis.available());
        return BitmapFactory.decodeStream(bis);
    }

“`

  • 4
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值