在开发app的过程中 当图片的尺寸较大或者是图片的数量较多时 就容易出现OOM异常(内存溢出)
为了解决这个问题需要对图片进行处理。图片的处理包括两方面 质量压缩(不改变图片的尺寸)和尺寸压缩
(相当于像素压缩) 质量压缩一般用于上传大图片之前的处理 可以节省流量; 尺寸压缩一般生成缩略图
二次采样分别是那两次?采样的目的是什么?
1.第一次采样
第一次采样主要获得图片的压缩比例 例如:存在一张图片200*200,想要将这张图片的压缩后显示在50*50的
ImageView中,那么压缩比例就是4,这个4如何获得呢? 先加载图片的边界到内存中 加载边界的操作相对不会
耗损太多的内存 加载到内存后 就可以获取该图片的宽高参数 然后根据图片的宽度和高度在结合控件的宽度和
高度计算出压缩比例
根据加载到内存中的图片 宽高计算出压缩比例
2.第二次采样
第二次采样在第一次采样的基础上 将第一次采样的压缩比例结果作为参数传递给bitmapFactory对象,这样 在加载图片时系统就不会将整张图片加载进来 而是只会加载该图片的一张缩略图 提高加载的速度 节省内存
public class MainActivity extends AppCompatActivity {
private ImageView ivOne,ivTwo;
private String path="http://pic.58pic.com/58pic/13/69/96/34z58PICEYh_1024.jpg";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ivOne= (ImageView) findViewById(R.id.iv_one);
ivTwo= (ImageView) findViewById(R.id.iv_two);
loadImage();
}
//网络加载图片
public void loadImage(){
new Thread(new Runnable() {
@Override
public void run() {
if(HttpUtils.isNetWorkConn(MainActivity.this)){
byte[] buff=HttpUtils.getHttpResult(path);
final Bitmap bm= BitmapFactory.decodeByteArray(buff,0,buff.length);
final Bitmap bitmap=BitmapUtil.ParserBitmap(300,300,buff,
Bitmap.Config.ARGB_4444);
//委托的形式
runOnUiThread(new Runnable() {
@Override
public void run() {
ivOne.setImageBitmap(bm);
ivTwo.setImageBitmap(bitmap);
}
});
}
}
}).start();
}
}
public class BitmapUtil {
/**
* 灵活的方法:获取期望的宽和高.
* 图片实际的宽与高,根据默认最大大小值,得到图片实际的缩放比例
* @param maxPrimary
* @param maxSecondary
* @param actualPrimary
* @param actualSecondary
* @return
*/
private static int getResizedDimension(int maxPrimary, int maxSecondary,
int actualPrimary, int actualSecondary) {
// If no dominant value at all, just return the actual.
if (maxPrimary == 0 && maxSecondary == 0) {
return actualPrimary;
}
// If primary is unspecified, scale primary to match secondary's scaling
// ratio.
if (maxPrimary == 0) {
double ratio = (double) maxSecondary / (double) actualSecondary;
return (int) (actualPrimary * ratio);
}
if (maxSecondary == 0) {
return maxPrimary;
}
double ratio = (double) actualSecondary / (double) actualPrimary;
int resized = maxPrimary;
if (resized * ratio > maxSecondary) {
resized = (int) (maxSecondary / ratio);
}
return resized;
}
//计算最佳采样率的方法.actualWidth=120,actualHeight=120,desiredWidth=100,desiredHeight=100
public static int findBestSampleSize(int actualWidth, int actualHeight,
int desiredWidth, int desiredHeight) {
//1.73
double wr = (double) actualWidth / desiredWidth;
//1.73
double hr = (double) actualHeight / desiredHeight;
//1.73
double ratio = Math.min(wr, hr);
float n = 1.0f;
while ((n * 2) <= ratio) {
n *= 2;
}
return (int) n;
}
/**
* 图片二次采样的方法 图片的像素压缩 修改图片的宽度/高度 图片按照比例大小进行压缩
* @param maxWidth
* @param maxHeight
* @param data
* @param config
* @return
*/
public static Bitmap ParserBitmap(int maxWidth,int maxHeight,
byte[] data,Bitmap.Config config){
Bitmap bm=null;
//第一次采样
BitmapFactory.Options options=new BitmapFactory.Options();
if(maxWidth==0 && maxHeight==0){
//设置图片的位数 rgb_565 rgb_4444 rgb_8888
options.inPreferredConfig=config;
bm=BitmapFactory.decodeByteArray(data,0,data.length,options);
}else{
//该属性设置为true表示只加载图片的边框 不会加载图片的具体像素点 测量边界
options.inJustDecodeBounds=true;
//第一次加载图片 只加载图片的边框 并不加载像素点
BitmapFactory.decodeByteArray(data,0,data.length,options);
//图片的真实的宽度和高度 原图
int trueWidth=options.outWidth;
int trueHeight=options.outHeight;
Log.i("tag","原图的宽度:"+trueWidth+",原图的高度:"+trueHeight);
//期望的宽度和高度
int desWidth=getResizedDimension(maxWidth,maxHeight,trueWidth,trueHeight);
int desHeight=getResizedDimension(maxHeight,maxWidth,trueHeight,trueWidth);
// int desWidth=300;
// int desHeight=500;
Log.i("tag","期望的宽度:"+desWidth+",期望的高度:"+desHeight);
//至此第一次采样结束 开始第二次采样
//第二次采样不仅只是加载图片的边缘
options.inJustDecodeBounds=false;
//inSampleSize 设置图片的采样率 获取压缩比例
options.inSampleSize=findBestSampleSize(trueWidth,trueHeight,desWidth,desHeight);
Log.i("tag","----options.inSampleSize-----"+ options.inSampleSize);
//生成临时的bitmap对象
Bitmap tempBitmap=BitmapFactory.decodeByteArray(data,0,data.length,options);
if(tempBitmap!=null || tempBitmap.getWidth()>desWidth
|| tempBitmap.getHeight()>desHeight){
//创建压缩后的bitmap对象
bm=tempBitmap.createScaledBitmap(tempBitmap,desWidth,desHeight,true);
tempBitmap.recycle();
}else{
bm=tempBitmap;
}
}
return bm;
}
}