加载巨图
问题:
遇到过这样一个问题,加载一张巨图,例如10万×10万的图,不能压缩,如何避免产生内存溢出。
思考:
首先,看到这个问题之后,可以确定的是,一定不能够直接将图片加载到内存当中,否则一定会内存溢出;
其次,最容易想到的就是将图片分片加载,既然是巨图,那么手机小小的屏幕肯定无法一次性全部显示完全,我们可以只显示一定的区域,配合上下左右的手势,再不断的更新这个区域。
如果想要实现上述的想法,需要解决两个问题:
1)图片不加载到内存,怎样获取宽和高;
2)区域加载图片;
第一个问题,我们可以使用BitmapFactory.decodeStream(inputStream,null,cfgOption)的方法,将cfgOption的inJustDecodeBounds属性设置为true,意思是解码bitmap,但是并不会将bitmap加载到内存当中;
第二个问题,可以使用BitmapRegionDecoder,指定一个区域,然后将这个区域解码成一个bitmap;
解决方案
InputStream inputStream = getAssets().open("large.jpg");
//1.获取大图的宽高
BitmapFactory.Options cfgOption = new BitmapFactory.Options();
cfgOption.inJustDecodeBounds = true;//设置为true,只获取图片的信息,而不降图片加载到内存
Bitmap bit = BitmapFactory.decodeStream(inputStream,null,cfgOption);//返回的bit为null
int width = cfgOption.outWidth;
int height = cfgOption.outHeight;
//2.获取区域大图的bitmap
BitmapRegionDecoder bitmapRegionDecoder = BitmapRegionDecoder.newInstance(inputStream,false);
BitmapFactory.Options options = new BitmapFactory.Options();
options.inPreferredConfig = Bitmap.Config.RGB_565;
Rect rect = new Rect(width / 2 - 100, height / 2 - 100, width / 2 + 100, height / 2 + 100);
Bitmap bitmap = bitmapRegionDecoder.decodeRegion(rect, options);
//3.显示bitmap
image.setImageBitmap(bitmap);
在上面的代码当中,当inJustDecodeBounds设置为true,decodeStream返回就是null,此时解码的bitmap并不会加载到内存当中,只会将图片的信息存放在cfgOption当中。
第二步获取区域大图,我们只需要实现一些手势,根据手势计算出当前的rect,然后在使用BitmapRegionDecoder获取rect对应的bitmap就可以了。