Android 图片处理系列--计算图片缩放数inSampleSize,避免oom

在Android开发中经常遇到由于图片的问题导致oom的问题,out of memery有木有~好在我用的是nunux ,app分配了192m的内存,有木有~相比虚拟机的16m,32m的内存,这个机器上开发应用怎一个霸气~

很怀恋那些在我第一部android手机samsung galaxy i5700开发程序的日子。

google官方在develop的training模块有个模块专门讲述了图片处理,写得自然特别棒,还附带了一个Bitmapfun的例子,霸气

地址:http://developer.android.com/training/displaying-bitmaps/index.html

先做个简单的计算:在ARGB_8888标准下 ,一枚2592x1936摄像头拍出的照片 大小 2592*1936*4/1024/1024 = 19.14MB 一张照片就19M,面对越来越高像素的摄像头,越来越大的照片,如何才能有效显示图片避免oom?

那这里先抛出下整体的思路

Android图片处理:

1、你要估算下加载图片所需的内存(**图片在服务端处理会比在客户端来得直接,这就是为什么很多图片模块的设计都是先显示小图,点击再去获取大图**)

2、计算应用的其他部分与当前图片所占用内存比(**能合理的分配图片内存,高效的显示**)

3、**今天的重点***计算合理的Imageview(显示图片的组件)所需的Dimension ( **通俗的讲就是任何一种不确定的图片,显示多大合适**)

4、了解当前设备的dip物理密度和屏幕大小

5、....


Target: 计算合理的(避免oom)imageview显示的Dimension

先上段代码:

                      BitmapFactory.Options opts = new BitmapFactory.Options();
opts.inSampleSize = 1;
while (true) {
try {
      bitmap = BitmapFactory.decodeFile(path, opts)
      ImgeViews.setImageBitmap(bitmap);
break;
} catch (OutOfMemoryError e) {
e.printStackTrace();
opts.inSampleSize++;
continue;
} catch (Exception e) {
e.printStackTrace();
bitmap = null;
}
}

     简单解释下,inSampleSize的值(缩放图片的比率,越大,缩放越大,2的平方效率最高,比如inSampleSize = 2,则显示图片长为原来的1/2,宽为1/2),这段代码写了一个循环,如果catch到oom的异常,inSampleSize的值动态变大。

代码很简单,能避免oom~

再上一段代码:

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,保障最后imageview的dimension比request的大
            inSampleSize = heightRatio < widthRatio ? heightRatio : widthRatio;

//计算原始图片总像素
            final float totalPixels = width * height;
            // Anything more than 2x the requested pixels we'll sample down further

//所需总像素*2,长和宽的根号2倍
            final float totalReqPixelsCap = reqWidth * reqHeight * 2;

//如果遇到很长,或者是很宽的图片时,这个算法比较有用 
            while (totalPixels / (inSampleSize * inSampleSize) > totalReqPixelsCap) {
                inSampleSize++;
            }
        }
        return inSampleSize;
    }

 读者是不是感觉似曾相识,不错这是BitmapFun例子里面的一段代码

  解释下:当原始图像的高和宽大于所需高度和宽度时,//算出长宽比后去比例小的作为inSamplesize,保障最后imageview的dimension比request的大,如果遇到长宽差异比较大的图片,可使用上述算法保障图片大小

 在计算inSampleSize时,不要忘了

  options.inJustDecodeBounds = true;

算好后

 options.inJustDecodeBounds = false;

代码如下:

public static Bitmap decodeSampledBitmapFromResource(Resources res, int resId,
        int reqWidth, int reqHeight) {

    // 设置inJustDecodeBounds=true 检查dimensions
    final BitmapFactory.Options options = new BitmapFactory.Options();
    options.inJustDecodeBounds = true;
    BitmapFactory.decodeResource(res, resId, options);

    // 计算inSampleSize
    options.inSampleSize = calculateInSampleSize(options, reqWidth, reqHeight);


    // Decode bitmap with inSampleSize set
    options.inJustDecodeBounds = false;
    return BitmapFactory.decodeResource(res, resId, options);
}

    










 

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值