引言:
Android系統(tǒng)支持幾種圖片(.png (preferred), .jpg (acceptable), .gif (discouraged)), 其中Bitmap位圖#ffffffff畜侦,包括圖片透明度Alpha和RGB,圖片質(zhì)量很好,每一個像素位占4個字節(jié)已慢,如果圖片很大將會占據(jù)很大的內(nèi)存空間座掘。存儲在SDCard的image很小递惋,加載進內(nèi)存可能就會很大。因此溢陪,對bitmap圖像進行操作萍虽,應該特別小心,可能出現(xiàn)內(nèi)存溢出問題形真。為此對于大圖片杉编,應該引入該圖片的二次采樣生成縮略圖。
一、圖片二次采樣
/**
*?根據(jù)圖片字節(jié)數(shù)組邓馒,對圖片可能進行二次采樣嘶朱,不致于加載過大圖片出現(xiàn)內(nèi)存溢出
*?@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;//僅僅解碼邊緣區(qū)域
//如果指定了inJustDecodeBounds,decodeByteArray將返回為空
BitmapFactory.decodeByteArray(bytes,0,?bytes.length,?options);
//得到寬與高
height?=?options.outHeight;
width?=?options.outWidth;
//圖片實際的寬與高绒净,根據(jù)默認最大大小值见咒,得到圖片實際的縮放比例
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;
}
二、圖像質(zhì)量壓縮
private Bitmap?compressImage(Bitmap?image)?{
ByteArrayOutputStream?baos?=newByteArrayOutputStream();
image.compress(Bitmap.CompressFormat.JPEG,100,?baos);//質(zhì)量壓縮方法挂疆,這里100表示不壓縮改览,把壓縮后的數(shù)據(jù)存放到baos中
int options?=100;
while(?baos.toByteArray().length?/1024>100)?{//循環(huán)判斷如果壓縮后圖片是否大于100kb,大于繼續(xù)壓縮
baos.reset();//重置baos即清空baos
image.compress(Bitmap.CompressFormat.JPEG,?options,?baos);//這里壓縮options%,把壓縮后的數(shù)據(jù)存放到baos中
options?-=10;//每次都減少10
}
ByteArrayInputStream?isBm?=new ByteArrayInputStream(baos.toByteArray());//把壓縮后的數(shù)據(jù)baos存放到ByteArrayInputStream中
Bitmap?bitmap?=?BitmapFactory.decodeStream(isBm,null,null);//把ByteArrayInputStream數(shù)據(jù)生成圖片
return bitmap;
}
三缤言、圖片按比例大小壓縮(根據(jù)路徑獲取圖片并壓縮)
private Bitmap?getimage(String?srcPath)?{
BitmapFactory.Options?newOpts?=newBitmapFactory.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;
//現(xiàn)在主流手機比較多是800*480分辨率,所以高和寬我們設置為
float hh?=?800f;//這里設置高度為800f
float ww?=?480f;//這里設置寬度為480f
//縮放比胆萧。由于是固定比例縮放庆揩,只用高或者寬其中一個數(shù)據(jù)進行計算即可
int be?=1;//be=1表示不縮放
if(w?>?h?&&?w?>?ww)?{//如果寬度大的話根據(jù)寬度固定大小縮放
be?=?(int)?(newOpts.outWidth?/?ww);
}else if(w?<?h?&&?h?>?hh)?{//如果高度高的話根據(jù)寬度固定大小縮放
be?=?(int)?(newOpts.outHeight?/?hh);
}
if(be?<=0)
be?=1;
newOpts.inSampleSize?=?be;//設置縮放比例
//重新讀入圖片,注意此時已經(jīng)把options.inJustDecodeBounds?設回false了
bitmap?=?BitmapFactory.decodeFile(srcPath,?newOpts);
return compressImage(bitmap);//壓縮好比例大小后再進行質(zhì)量壓縮
}
四跌穗、圖片按比例大小壓縮方法(根據(jù)Bitmap圖片壓縮):
private Bitmap?comp(Bitmap?image)?{
ByteArrayOutputStream?baos?=newByteArrayOutputStream();
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%订晌,把壓縮后的數(shù)據(jù)存放到baos中
}
ByteArrayInputStream?isBm?=newByteArrayInputStream(baos.toByteArray());
BitmapFactory.Options?newOpts?=newBitmapFactory.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;
//現(xiàn)在主流手機比較多是800*480分辨率蚌吸,所以高和寬我們設置為
float hh?=?800f;//這里設置高度為800f
float ww?=?480f;//這里設置寬度為480f
//縮放比锈拨。由于是固定比例縮放,只用高或者寬其中一個數(shù)據(jù)進行計算即可
int be?=1;//be=1表示不縮放
if(w?>?h?&&?w?>?ww)?{//如果寬度大的話根據(jù)寬度固定大小縮放
be?=?(int)?(newOpts.outWidth?/?ww);
}else if(w?<?h?&&?h?>?hh)?{//如果高度高的話根據(jù)寬度固定大小縮放
be?=?(int)?(newOpts.outHeight?/?hh);
}
if(be?<=0)
be?=1;
newOpts.inSampleSize?=?be;//設置縮放比例
//重新讀入圖片羹唠,注意此時已經(jīng)把options.inJustDecodeBounds?設回false了
isBm?=newByteArrayInputStream(baos.toByteArray());
bitmap?=?BitmapFactory.decodeStream(isBm,null,?newOpts);
return compressImage(bitmap);//壓縮好比例大小后再進行質(zhì)量壓縮
}