Bitmap高效加载图片

  一、什么是Bitmap
   Bitmap在Android中指一张图,格式不定。BitmapFactory提供了四类方法:decodeFile.decodeResource
 decodeStream和decodeByteArray,分别支持从文件,资源,输入流以及字节数组加载出一个bitmap对象,
 其中decodeFile和decodeResource间接调用了decodeStream。
   二、高效加载的核心原理
     怎么高效地加载Bitmap,可以说之加载所需尺寸就行了,一般来说原始图片都比显示出来的图片要大,
 越大的图片加速度、效率就会越低,那么我们在加载之前对图片进行缩放处理,这样使得效率提高,而且
 可以在一定程度上避免OOM我们通过BitmapFactory.Options来缩放图片,主要是其中的inSampleSize参数,
 即采样率。当inSampleSize为1时,采样后的图片大小为原始大小;当inSampleSize为2时,那么采样后的宽
 高均为原图的1/2,而像素数为原图的1/4,内存占用也为原图的1/4,在Goole官方文档中还指出
 inSampleSize的取值应该总为2的指数,比如:1,2,4,8...如果不为2的指数那么系统会自动向下取整并选择
 一个最接近2的指数来代替。
   三、实际开发中的意外情况
    另外考虑以下实际情况,假设我们用ImageView来显示图片,当ImageView的大小为100x100像素,而图片
 原始大小为200x200,那么只需将采样率inSampleSize设置为2即可,但是如果图片大小为200x300呢?如果采
 样率选择2,那么缩放后片大小为100x150,也可以继续用ImageView,如果采样率为3,那么缩放后图片大小
 就会小于ImageView,所期望的大小,那么图片会被自动拉伸而导致模糊
    (ImageView底层代码原理,当加载的资源与本身大小不一样时,会自动调用requestLayout(),然后调用
  父节点的requestLayout()重新布局,在此过程中会自动对资源进行缩放拉伸处理)
  四、过程
    获取采样率
    1.将BitmapFactory.Options的inJustDecodeBounds参数设置为false,并加载图片(为了测量图片宽高)
    2.从BitmapFactory.Options中取出图片的原始宽高信息(存放在options参数中)
    3.根据采样率的规则并结合目标View的所需大小计算出采样率inSampleSize。
    4.将BitmapFactory.Options的inJustDecodeBounds参数设置为false,并重新加载图片
	注释:当inJustDecodeBounds为true时,只会解析图片的宽高信息,而不去加载图片
    代码如下:
	
public class MainActivity extends AppCompatActivity {

    private ImageView im_1;
    private ImageView im_2;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        im_1 = (ImageView) findViewById(R.id.im_1);
        im_2= (ImageView) findViewById(R.id.im_2);

        im_1.setBackgroundResource(R.drawable.tiantang);
        im_2.setImageBitmap(decodeSampledBitmapFromResources(getResources(),R.drawable.tiantang,100,100));

    }

    private Bitmap decodeSampledBitmapFromResources(Resources res,int resId,int reqWidth,int reqHeight){
        //1.找到BitmapFactory实例
        BitmapFactory.Options options = new BitmapFactory.Options();
        //2.设置inJustDecodeBounds参数为True
        options.inJustDecodeBounds = true;
        //3.得到BitmapFactory加载进来的图片
        BitmapFactory.decodeResource(res, resId, options);

        //4.计算缩放比
        options.inSampleSize =calculateInSampleSize(options,reqWidth,reqHeight);

        options.inJustDecodeBounds =false;
        return BitmapFactory.decodeResource(res,resId,options);
    }

    private int calculateInSampleSize(BitmapFactory.Options options,int reqWidth,int reqHeight){
        int height = options.outHeight;
        int width = options.outWidth;

        int inSampleSize =1;
        //当图片宽高其中一个大于要求宽高
        if(height>reqHeight||width >reqWidth){
            int halfHeight = height/2;
            int halfWidth = width/2;
            //循环直到得到合适的采样率
            while((halfHeight/inSampleSize)>=reqHeight && (halfWidth/inSampleSize)>=reqWidth){
                inSampleSize *=2;
            }
        }
     return inSampleSize;
    }
}


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章