图片压缩
1.基本概念用法
Bitmap是安卓最主要图像处理类,通过Bitmap可以获得图片相关信息,进行裁剪、缩放等操作。
安卓的BitmapFactory工厂类提供了常用的生成Bitmap方式,如下
BitmapFactory.decodeByteArray(); //通过二进制流解析
BitmapFactory.decodeFile();//通过文件路径解析
BitmapFactory.decodeResource();//通过资源文件解析
BitmapFactory.decodeStream();//通过流解析
2.压缩方式
Bitmap在加载到虚拟机的过程中,如果源资源过大,多张加载时会造成内存溢出,因此对照片的处理压缩非常重要。
BitmapFactory.Options 此类用于解码Bitmap时的各种参数控制。
inJustDecodeBounds 该属性设置为true,解析的时候不会返回bitmap,只会返回bitmap的尺寸,通过这个属性获取原始bitmap的宽高。
inPreferredConfig 该属性设置色彩模式。ALPHA_8 代表8位Alpha位图,ARGB_4444 代表16位ARGB位图,ARGB_8888 代表32位ARGB位图,RGB_565 代表16位RGB位图。RGB_565这个模式一个像素只占用2个byte,推荐使用。
inSampleSize 该属性为压缩比例,数值越大压缩比例越大,该值不能小于1。
public static Bitmap compress(byte[] bytes,int targetW,int targetH){
BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true;
options.inPreferredConfig =Bitmap.Config.RGB_565;
BitmapFactory.decodeByteArray(bytes,0,bytes.length,options);
//获取图片原始宽高
int originalW = options.outWidth;
int originalH = options.outHeight;
//图片压缩
options.inSampleSize = getSimpleSize(originalW,originalH,targetW,targetH);
options.inJustDecodeBounds = false;
return BitmapFactory.decodeByteArray(bytes,0,bytes.length,options);
}
如果原始图片宽度大于高度,以最大宽度为基准,原始宽度/期望宽度,得到压缩比例
private static int getSimpleSize(int originalW, int originalH, int targetW, int targetH) {
int simpleSize = 1;
if (originalW > originalH && originalW > targetW) {
simpleSize = originalW / targetW;
} else if (originalW < originalH && originalH > targetH) {
simpleSize = originalH / targetH;
}
if (simpleSize <= 0) {
simpleSize = 1;
}
return simpleSize;
}
缓存策略
1.缓存方式
(1)LruCache 内存缓存,这种方式会将数据暂存在内存里,当app后台彻底清除后,内存也会清除
(2)DisLruCache 硬盘缓存 ,这种是将缓存数据保存硬盘里,依赖第三方平台
2.内存缓存使用
LruCache是安卓自带的内存缓存机制,内部采用LInkedHashMap实现,可以根据系统动态调整内存大小,这种方式可以有效的提高图片在app中的显示效率
创建SimpleImageLoader工具类,LruCache以图片下载url为Key,初始化按照虚拟机分配内存的1/8配置缓存大小
private LruCache<String, Bitmap> mLruCache;
private SimpleImageLoader(){
int maxSize = (int) (Runtime.getRuntime().maxMemory() / 8);
mLruCache = new LruCache<String,Bitmap>(maxSize){
@Override
protected int sizeOf(String key, Bitmap value) {
return value.getByteCount();
}
};
}
展示图片,首先获取内存缓存中数据,如果没有网络请求图片数据
public void displayImage(Context context,ImageView imageView, String url){
Bitmap bitmap = getBitmapFromCache(url);
if(bitmap!=null){
imageView.setImageBitmap(bitmap);
}else {
downLoadImage(context,imageView,url);
}
}
通过已保存的url键值对获取Bitmap缓存信息
private Bitmap getBitmapFromCache(String url){
return mLruCache.get(url);
}
下载框架的成功回调,将压缩的图片保存到内存中
public void onResponse(Call call, Response response) throws IOException {
byte[] bytes = response.body().bytes();
Bitmap bitmap = BitmapUtils.compress(bytes,imageView.getWidth(),imageView.getHeight());
putBitmapToCache(bitmap,url);
}
保存Bitmap到LruCache中
private void putBitmapToCache(Bitmap bitmap,String url){
if(bitmap!=null){
mLruCache.put(url,bitmap);
}
}