這幾天做的項目中有個圖檔上傳子產品,上傳部分用的是xutils架構上傳前自動對圖檔進行了壓縮處理。但使用者還是一直反應上傳特别慢,主要是因為現在手機一般一張圖檔都特别大,沒處理或者處理不夠的話會嚴重影響使用者體驗,于是研究了下Android的圖檔壓縮部分:
一:圖檔壓縮相關的概念(參考:http://blog.csdn.net/cherry609195946/article/details/9264409)
1.Android中圖檔的存在形式有三種:
a.File的形式存在于硬碟中。
b.在記憶體中存在有兩種形式,一種是流,一種是bitmap
2.廣義所說的圖檔壓縮包括兩種方式:品質壓縮和大小壓縮
品質壓縮:通說說就是将圖檔儲存為File時候進行壓縮,讓其大小變小。主要用在網絡上傳圖檔時候友善上傳伺服器。但其記憶體中大小并未改變,甚至 會變大。
大小壓縮:圖檔從本地讀取時候轉換成bitmap過程中進行壓縮處理,通過設定采樣率減少圖檔的像素,達到對記憶體中bitmap進行壓縮,減少占用記憶體
二:壓縮部分的代碼
品質壓縮:
<span style="font-size:14px;">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
options -= 10;//每次都減少10
image.compress(Bitmap.CompressFormat.JPEG, options, baos);//這裡壓縮options%,把壓縮後的資料存放到baos中
}
ByteArrayInputStream isBm = new ByteArrayInputStream(baos.toByteArray());//把壓縮後的資料baos存放到ByteArrayInputStream中
Bitmap bitmap = BitmapFactory.decodeStream(isBm, null, null);//把ByteArrayInputStream資料生成圖檔
return bitmap;
//傳回的bitmap所占記憶體并沒減少。。
// Generate compressed image file 儲存成File形式
FileOutputStream fos = new FileOutputStream(outPath);
fos.write(os.toByteArray());
fos.flush();
fos.close();
}</span>
大小壓縮;
a.計算壓縮比例
<span style="font-size:14px;">public static int calculateInSampleSize(BitmapFactory.Options options,int reqWidth, int reqHeight) {
final int height = options.outHeight; //圖檔的原始高 寬
final int width = options.outWidth;
int inSampleSize = 1;
if (height > reqHeight || width > reqWidth) {
final int heightRatio = Math.round((float) height/ (float) reqHeight);
final int widthRatio = Math.round((float) width / (float) reqWidth);
inSampleSize = heightRatio < widthRatio ? heightRatio : widthRatio;
}
return inSampleSize;
}</span>
b.開始壓縮
// 根據路徑獲得圖檔并壓縮,傳回bitmap用于顯示
<span style="font-size:14px;"> public static Bitmap getSmallBitmap(String filePath) {
final BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true;
//inJustDecodeBounds設定為true,可以不把圖檔讀到記憶體中,但依然可以計算出圖檔的大小
BitmapFactory.decodeFile(filePath, options);
// Calculate inSampleSize
options.inSampleSize = calculateInSampleSize(options, 480, 800);
// Decode bitmap with inSampleSize set
options.inJustDecodeBounds = false;
//此時傳回的就是已經被壓縮的bitmap。。可以用于顯示在界面上
return BitmapFactory.decodeFile(filePath, options);
}</span>
總結:一般圖檔壓縮處理是先進行大小壓縮,在進行品質壓縮互相結合方式。
Thanks:
http://www.360doc.com/content/14/0428/17/11800748_372972179.shtml