Android圖片質量壓縮以及縮圖生成
1、圖片的質量壓縮
圖片的質量壓縮是指,僅僅壓縮圖片檔案的大小,但當圖片載入到記憶體中時,佔用的記憶體大小並沒有太大變化。可以通過質量壓縮,加快圖片上傳的速度。
程式碼如下:
/**
*將檔案壓縮後覆蓋原始檔
*/
public static void compressImage(File file) {
Bitmap bitmap=BitmapFactory.decodeFile(file.getAbsolutePath());
ByteArrayOutputStream baos = new ByteArrayOutputStream();
bitmap.compress(Bitmap.CompressFormat.JPEG, 80 , baos);// 質量壓縮方法,這裡100表示不壓縮,把壓縮後的資料存放到baos中
int options = 80;//先壓縮到80%
while (baos.toByteArray().length / 1024 > 200) { // 迴圈判斷如果壓縮後圖片是否大於200kb,大於繼續壓縮
if (options <= 0) {//有的圖片過大,可能當options小於或者等於0時,它的大小還是大於目標大小,於是就會發生異常,異常的原因是options超過規定值。所以此處需要判斷一下
break;
}
baos.reset();// 重置baos即清空baos
options -= 10;// 每次都減少10
bitmap.compress(Bitmap.CompressFormat.JPEG, options, baos);
}
try {
FileOutputStream fos = new FileOutputStream(file);
fos.write(baos.toByteArray());
fos.close();
baos.close();
} catch (Exception e) {
e.printStackTrace();
}
}
通過上述程式碼,可以將2.5M的圖片壓縮到200KB左右,並且圖片的清晰度差別不大,但是需要注意的是,這改變的只是圖片檔案的大小,並不能改變載入此圖片的記憶體大小。所以對於此類圖片,在載入的時候也是需要注意的,避免OOM異常。需要注意的是,上述程式碼執行時,還是需要時間的,所以最好放在子執行緒中執行。
2、縮圖生成
縮圖生成的圖片會改變記憶體佔用的大小,所以一般不需要顯示全圖情況,可以用縮圖去展示,減少程式記憶體損耗。
程式碼如下:
/**
* 獲取縮圖
* @param imagePath:檔案路徑
* @param width:縮圖寬度
* @param height:縮圖高度
* @return
*/
public static Bitmap getImageThumbnail(String imagePath, int width, int height) {
BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true; //關於inJustDecodeBounds的作用將在下文敘述
Bitmap bitmap = BitmapFactory.decodeFile(imagePath, options);
int h = options.outHeight;//獲取圖片高度
int w = options.outWidth;//獲取圖片寬度
int scaleWidth = w / width; //計算寬度縮放比
int scaleHeight = h / height; //計算高度縮放比
int scale = 1;//初始縮放比
if (scaleWidth < scaleHeight) {//選擇合適的縮放比
scale = scaleWidth;
} else {
scale = scaleHeight;
}
if (scale <= 0) {//判斷縮放比是否符合條件
be = 1;
}
options.inSampleSize = scale;
// 重新讀入圖片,讀取縮放後的bitmap,注意這次要把inJustDecodeBounds 設為 false
options.inJustDecodeBounds = false;
bitmap = BitmapFactory.decodeFile(imagePath, options);
// 利用ThumbnailUtils來建立縮圖,這裡要指定要縮放哪個Bitmap物件
bitmap = ThumbnailUtils.extractThumbnail(bitmap, width, height,ThumbnailUtils.OPTIONS_RECYCLE_INPUT);
return bitmap;
}
通過上述程式碼載入圖片的縮圖,將會有效的避免OOM異常。在這裡需要解釋下options.inJustDecodeBounds這個屬性,當options.inJustDecodeBounds設定為true時,通過BitmapFactory.decodeFile去載入圖片,將不會正真地返回bitmap,也就是說此時的bitmap為null。它的作用是將圖片的相關資訊,例如圖片寬高,大小等資訊帶到options中,方便我們後續計算圖片的寬高比。
當我們計算好寬高比後,通過options.inSampleSize來設定縮放比例,然後將options.inJustDecodeBounds的值設定為false,再通過BitmapFactory.decodeFile去載入圖片就能獲取真正的bitmap物件了。最後通過ThumbnailUtils.extractThumbnail來獲取最終的縮圖。需要說明的是,ThumbnailUtils.OPTIONS_RECYCLE_INPUT表示回收建立縮圖時的資源。
或許有的朋友覺得既然已經通過BitmapFactory.decodeFile的方式處理過了,為什麼還需要ThumbnailUtils.extractThumbnail來再處理一次呢。首先,僅僅通過之前的處理,最終的縮圖的寬高還是和我們設定的大小有點出入的,所以用ThumbnailUtils再處理一次。可能又會有人說了,為什麼不直接使用ThumbnailUtils來生成縮圖呢?因為使用ThumbnailUtils是需要傳入bitmap的,試問有沒有這樣的情況,圖片太大,導致在載入圖片的時候直接就OOM了,那還怎麼使用ThumbnailUtils呢?
本人Android菜鳥一枚,如有錯誤,歡迎指正,謝謝大家!