Android Bitmap压缩策略
admin
2023-02-10 00:20:27
0
一、为什么Bitmap需要高效加载?

现在的高清大图,动辄就要好几M,而Android对单个应用所施加的内存限制,只有
小几十M,如16M,这导致加载Bitmap的时候很容易出现内存溢出。如下异常信
息,便是在开发中经常需要的:

java.lang.OutofMemoryError:bitmap size exceeds VM budget

为了解决这个问题,就出现了Bitmap的高效加载策略。其实核心思想很简单。假设
通过ImageView来显示图片,很多时候ImageView并没有原始图片的尺寸那么大,
这个时候把整个图片加载进来后再设置给ImageView,显然是没有必要的,因为
ImageView根本没办法显示原始图片。这时候就可以按一定的采样率来将图片缩小
后再加载进来,这样图片既能在ImageView显示出来,又能降低内存占用从而在一
定程度上避免OOM,提高了Bitmap加载时的性能

二、Bitmap高效加载的具体方式
1.加载Bitmap的方式

Bitmap在Android中指的是一张图片。通过BitmapFactory类提供的四类方法:
decodeFile,decodeResource,decodeStreamdecodeByteArray,分别从文件系统,
资源,输入流和字节数组中加载出一个Bitmap对象,其中
decodeFile,decodeResource又间接调用了decodeStream方法,这四类方法最终是
在Android的底层实现的,对应着BitmapFactory类的几个native方法。

2.BitmapFactory.Options的参数

inSampleSize参数
上述四类方法都支持BitmapFactory.Options参数,而Bitmap的按一定采样率进行缩
放就是通过BitmapFactory.Options参数实现的,主要用到了inSampleSize参数,即
采样率。通过对inSampleSize的设置,对图片的像素的高和宽进行缩放。

inSampleSize=1,即采样后的图片大小为图片的原始大小。小于1,也按照1来计
算。 当inSampleSize>1,即采样后的图片将会缩小,缩放比例为1/(inSampleSize
的二次方)。

例如: 一张1024 ×1024像素的图片,采用ARGB8888格式存储,那么内存大小
1024×1024×4=4M。如果inSampleSize=2,那么采样后的图片内存大小:
512×512×4=1M。

注意: 官方文档支出,inSampleSize的取值应该总是2的指数,如1,2,4,8等。
如果外界传入的inSampleSize的值不为2的指数,那么系统会向下取整并选择一个
最接近2的指数来代替。比如3,系统会选择2来代替。当时经验证明并非在所有
Android版本上都成立。

关于inSampleSize取值的注意事项: 通常是根据图片宽高实际的大小/需要的宽高
大小,分别计算出宽和高的缩放比。但应该取其中最小的缩放比,避免缩放图片太
小,到达指定控件中不能铺满,需要拉伸从而导致模糊。

例如: ImageView的大小是100×100像素,而图片的原始大小为200×300,那么宽
的缩放比是2,高的缩放比是3。如果最终inSampleSize=2,那么缩放后的图片大小
100×150,仍然合适ImageView。如果inSampleSize=3,那么缩放后的图片大小小
ImageView所期望的大小,这样图片就会被拉伸而导致模糊。

inJustDecodeBounds参数
我们需要获取加载的图片的宽高信息,然后交给inSampleSize参数选择缩放比缩
放。那么如何能先不加载图片却能获得图片的宽高信息,通过
inJustDecodeBounds=true,然后加载图片就可以实现只解析图片的宽高信息,并
不会真正的加载图片,所以这个操作是轻量级的。当获取了宽高信息,计算出缩放
比后,然后在将inJustDecodeBounds=false,再重新加载图片,就可以加载缩放后
的图片。

注意: BitmapFactory获取的图片宽高信息和图片的位置以及程序运行的设备有
关,比如同一张图片放在不同的drawable目录下或者程序运行在不同屏幕密度的设
备上,都可能导致BitmapFactory获取到不同的结果,和Android的资源加载机制
有关

3.高效加载Bitmap的流程

①将BitmapFactory.OptionsinJustDecodeBounds参数设为true并加载图片。
②从BitmapFactory.Options中取出图片的原始宽高信息,它们对应于outWidth
outHeight参数。

③根据采样率的规则并结合目标View的所需大小计算出采样率inSampleSize
④将BitmapFactory.OptionsinJustDecodeBounds参数设为false,然后重新加载
图片。

三、Bitmap高效加载的代码实现
  public static Bitmap decodeSampledBitmapFromResource(Resources res, int resId, int reqWidth, int reqHeight){
     BitmapFactory.Options options = new BitmapFactory.Options();
     options.inJustDecodeBounds = true;
     //加载图片
     BitmapFactory.decodeResource(res,resId,options);
     //计算缩放比
     options.inSampleSize = calculateInSampleSize(options,reqHeight,reqWidth);
     //重新加载图片
     options.inJustDecodeBounds =false;
     return BitmapFactory.decodeResource(res,resId,options);
  }

  private static int calculateInSampleSize(BitmapFactory.Options options, int reqHeight, int reqWidth) {
     int height = options.outHeight;
     int width = options.outWidth;
     int inSampleSize = 1;
     if(height>reqHeight||width>reqWidth){
         int halfHeight = height/2;
         int halfWidth = width/2;
         //计算缩放比,是2的指数
         while((halfHeight/inSampleSize)>=reqHeight&&(halfWidth/inSampleSize)>=reqWidth){
               inSampleSize*=2;
         }
     }

     return inSampleSize;
  }

这个时候就可以通过如下方式高效加载图片:

  mImageView.setImageBitmap(decodeSampledBitmapFromResource(getResources(),R.mipmap.ic_launcher,100,100);

除了BitmapFactorydecodeResource方法,其他方法也可以类似实现。

更多内容详情请关注我的GitHub:https://github.com/xiangjiana/Android-MS

相关内容

热门资讯

数学之外的邓煜:INTJ、知乎... 在23日于美国费城宾夕法尼亚州会展中心举行的2026年国际数学家大会开幕式上,中国数学家邓煜、王虹获...
新晋菲尔兹奖得主,当天宣布加入... 刚拿到数学界最高荣誉,转头就宣布:我要去OpenAI了。Jacob Tsimerman,这位领奖台上...
竞逐百亿赛道,北京十条政策卡位... 从基础模型到框架性能、推理效率、行业应用,半年来北京以智能体为牵引不断精进。作为我国AI发展的引领者...
共促数智交融 共启丝路新篇—... 本报记者 亓玉昆7月22日,2026年世界互联网大会数字丝路发展论坛在陕西西安举行。论坛以“智汇丝路...
赛里木湖景区通报“工作人员殴打... 2026年7月23日17时许,赛里木湖景区入口处发生多名景区工作人员殴打旅游车司机事件,我们深感痛心...
继英伟达黄仁勋后,AMD苏姿丰... IT之家 7 月 24 日消息,随着中国开源 AI 模型的不断变强,近期美国业界出现了关于 AI 是...
辰奕智能获得实用新型专利授权:... 证券之星消息,根据天眼查APP数据显示辰奕智能(301578)新获得一项实用新型专利授权,专利名为“...
湖南湘江新区文化创意产业出海观... 中新网长沙7月23日电(胡语桐)在日本大型量贩门店的货架上,中国研发的视频创意软件实体产品陈列其中;...
中国数学家首次获得的菲尔兹奖“... 当地时间7月23日上午,2026年国际数学家大会在美国费城开幕,现场揭晓2026年菲尔兹奖得主。中国...
猪周期反转,这次可能来真的 市场过去几年关于猪周期的很多认知,现在需要重新审视了。过去几年,越来越多人相信:随着规模化养殖企业不...