Android 中關於載入Bitmap知識點
阿新 • • 發佈:2019-01-09
在安卓開發中遇到載入圖片是很平常的事情,圖片即bitmap,但是Android對於每一個應用程式只分配了16M的記憶體空間,所以在載入比較大點的bitmap的時候很容易,會出現OOM異常。
android 中載入圖片的類BitmapFactary,提供了四類方法:decodeStream,decodeFile,decodeResource,decodeByteArray四種方法。其中decodeFile,decodeResource間接呼叫了decodeStream。
如何避免OOM異常其實核心是BitmapFactory。options來縮放圖片,主要用到inSampleSize引數即取樣率。
獲取取樣率流程,
1 將BitmapFactory.options.inJustDecodebounds = true; 載入圖片,它只加載圖片寬高,不載入圖片真正資訊。
2 執行BitmapFactory.decodeResource等方法。
3 通過 BitmapFactory.options.outHeigt,及outWidth,然後與目標的view的大小獲取inSampleSize (inSampleSize = 1 不縮放,inSampleSize =2 ,縮放四倍);
4 將BitmapFactory.options.inJustDecodebounds = false; 重新載入圖片。
具體程式碼如下:
/** * 通過uri獲取圖片並進行壓縮 * * @param uri */ public static Bitmap getBitmapFormUri(Context ac, Uri uri,int w,int h) throws IOException { InputStream input = ac.getContentResolver().openInputStream(uri); BitmapFactory.Options onlyBoundsOptions = new BitmapFactory.Options(); onlyBoundsOptions.inJustDecodeBounds = true; onlyBoundsOptions.inDither = true;//optional onlyBoundsOptions.inPreferredConfig = Bitmap.Config.ARGB_8888;//optional BitmapFactory.decodeStream(input, null, onlyBoundsOptions); input.close(); int originalWidth = onlyBoundsOptions.outWidth; int originalHeight = onlyBoundsOptions.outHeight; if ((originalWidth == -1) || (originalHeight == -1)) return null; int be = 1;//be=1表示不縮放 be = calculateInSampleSize(onlyBoundsOptions,w,h); BitmapFactory.Options bitmapOptions = new BitmapFactory.Options(); bitmapOptions.inSampleSize = be;//設定縮放比例 bitmapOptions.inDither = true;//optional bitmapOptions.inPreferredConfig = Bitmap.Config.ARGB_8888;//optional input = ac.getContentResolver().openInputStream(uri); Bitmap bitmap = BitmapFactory.decodeStream(input, null, bitmapOptions); input.close(); return compressImage(bitmap);//再進行質量壓縮 }
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;
}
/**
* 質量壓縮方法
*
* @param image
* @return
*/
public static 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
//第一個引數 :圖片格式 ,第二個引數: 圖片質量,100為最高,0為最差 ,第三個引數:儲存壓縮後的資料的流
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;
}