Android 图片二次采样、质量压缩

引言:

Android系统支持几种图片(.png (preferred), .jpg (acceptable), .gif (discouraged)), 其中Bitmap位图#ffffffff,包括图片透明度Alpha和RGB,图片质量很好,每一个像素位占4个字节,如果图片很大将会占据很大的内存空间。存储在SDCard的image很小,加载进内存可能就会很大。因此,对bitmap图像进行操作,应该特别小心,可能出现内存溢出问题。为此对于大图片,应该引入该图片的二次采样生成缩略图。

一、图片二次采样

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
/**
  * 根据图片字节数组,对图片可能进行二次采样,不致于加载过大图片出现内存溢出
  * @param bytes
  * @return
  */
public  static  Bitmap getBitmapByBytes( byte [] bytes){
//对于图片的二次采样,主要得到图片的宽与高
int  width =  0 ;
int  height =  0 ;
int  sampleSize =  1 ; //默认缩放为1
BitmapFactory.Options options =  new  BitmapFactory.Options();
options.inJustDecodeBounds =  true ; //仅仅解码边缘区域
//如果指定了inJustDecodeBounds,decodeByteArray将返回为空
BitmapFactory.decodeByteArray(bytes,  0 , bytes.length, options);
//得到宽与高
height = options.outHeight;
width = options.outWidth;
//图片实际的宽与高,根据默认最大大小值,得到图片实际的缩放比例
while  ((height / sampleSize > Cache.IMAGE_MAX_HEIGHT)
|| (width / sampleSize > Cache.IMAGE_MAX_WIDTH)) {
sampleSize *=  2 ;
}
//不再只加载图片实际边缘
options.inJustDecodeBounds =  false ;
//并且制定缩放比例
options.inSampleSize = sampleSize;
return  BitmapFactory.decodeByteArray(bytes,  0 , bytes.length, options);
}
 
//默认大小
class  Cache{
     public  static  final  int  IMAGE_MAX_HEIGH= 854 ;
     public  static  final  int  IMAGE_MAX_WIDTH= 480 ;
}


二、图像质量压缩

?
1
2
3
4
5
6
7
8
9
10
11
12
13
private  Bitmap compressImage(Bitmap image) {
ByteArrayOutputStream baos =  new  ByteArrayOutputStream();
image.compress(Bitmap.CompressFormat.JPEG,  100 , baos); //质量压缩方法,这里100表示不压缩,把压缩后的数据存放到baos中
int  options =  100 ;
while  ( baos.toByteArray().length /  1024 > 100 ) { //循环判断如果压缩后图片是否大于100kb,大于继续压缩
baos.reset(); //重置baos即清空baos
image.compress(Bitmap.CompressFormat.JPEG, options, baos); //这里压缩options%,把压缩后的数据存放到baos中
options -=  10 ; //每次都减少10
}
ByteArrayInputStream isBm =  new  ByteArrayInputStream(baos.toByteArray()); //把压缩后的数据baos存放到ByteArrayInputStream中
Bitmap bitmap = BitmapFactory.decodeStream(isBm,  null null ); //把ByteArrayInputStream数据生成图片
return  bitmap;
}

三、图片按比例大小压缩(根据路径获取图片并压缩)

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
private  Bitmap getimage(String srcPath) {
BitmapFactory.Options newOpts =  new  BitmapFactory.Options();
//开始读入图片,此时把options.inJustDecodeBounds 设回true了
newOpts.inJustDecodeBounds =  true ;
Bitmap bitmap = BitmapFactory.decodeFile(srcPath,newOpts); //此时返回bm为空
newOpts.inJustDecodeBounds =  false ;
int  w = newOpts.outWidth;
int  h = newOpts.outHeight;
//现在主流手机比较多是800*480分辨率,所以高和宽我们设置为
float  hh = 800f; //这里设置高度为800f
float  ww = 480f; //这里设置宽度为480f
//缩放比。由于是固定比例缩放,只用高或者宽其中一个数据进行计算即可
int  be =  1 ; //be=1表示不缩放
if  (w > h && w > ww) { //如果宽度大的话根据宽度固定大小缩放
be = ( int ) (newOpts.outWidth / ww);
else  if  (w < h && h > hh) { //如果高度高的话根据宽度固定大小缩放
be = ( int ) (newOpts.outHeight / hh);
}
if  (be <=  0 )
be =  1 ;
newOpts.inSampleSize = be; //设置缩放比例
//重新读入图片,注意此时已经把options.inJustDecodeBounds 设回false了
bitmap = BitmapFactory.decodeFile(srcPath, newOpts);
return  compressImage(bitmap); //压缩好比例大小后再进行质量压缩
}

四、图片按比例大小压缩方法(根据Bitmap图片压缩):

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
private  Bitmap comp(Bitmap image) {
ByteArrayOutputStream baos =  new  ByteArrayOutputStream();
image.compress(Bitmap.CompressFormat.JPEG,  100 , baos);
if ( baos.toByteArray().length /  1024 > 1024 ) { //判断如果图片大于1M,进行压缩避免在生成图片(BitmapFactory.decodeStream)时溢出
baos.reset(); //重置baos即清空baos
image.compress(Bitmap.CompressFormat.JPEG,  50 , baos); //这里压缩50%,把压缩后的数据存放到baos中
}
ByteArrayInputStream isBm =  new  ByteArrayInputStream(baos.toByteArray());
BitmapFactory.Options newOpts =  new  BitmapFactory.Options();
//开始读入图片,此时把options.inJustDecodeBounds 设回true了
newOpts.inJustDecodeBounds =  true ;
Bitmap bitmap = BitmapFactory.decodeStream(isBm,  null , newOpts);
newOpts.inJustDecodeBounds =  false ;
int  w = newOpts.outWidth;
int  h = newOpts.outHeight;
//现在主流手机比较多是800*480分辨率,所以高和宽我们设置为
float  hh = 800f; //这里设置高度为800f
float  ww = 480f; //这里设置宽度为480f
//缩放比。由于是固定比例缩放,只用高或者宽其中一个数据进行计算即可
int  be =  1 ; //be=1表示不缩放
if  (w > h && w > ww) { //如果宽度大的话根据宽度固定大小缩放
be = ( int ) (newOpts.outWidth / ww);
else  if  (w < h && h > hh) { //如果高度高的话根据宽度固定大小缩放
be = ( int ) (newOpts.outHeight / hh);
}
if  (be <=  0 )
be =  1 ;
newOpts.inSampleSize = be; //设置缩放比例
//重新读入图片,注意此时已经把options.inJustDecodeBounds 设回false了
isBm =  new  ByteArrayInputStream(baos.toByteArray());
bitmap = BitmapFactory.decodeStream(isBm,  null , newOpts);
return  compressImage(bitmap); //压缩好比例大小后再进行质量压缩
}

转自:http://my.oschina.net/kooeasy/blog/478622
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值