一. BitmapFactory.Options 中inSampleSize的取值問題
關於inSampleSize的取值問題Google已經給出了一個推薦的算法:(https://developer.android.com/topic/performance/graphics/load-bitmap)
public static int calculateInSampleSize( BitmapFactory.Options options, int reqWidth, int reqHeight) { // Raw height and width of image final int height = options.outHeight; final int width = options.outWidth; int inSampleSize = 1; if (height > reqHeight || width > reqWidth) { final int halfHeight = height / 2; final int halfWidth = width / 2; // Calculate the largest inSampleSize value that is a power of 2 and keeps both // height and width larger than the requested height and width. while ((halfHeight / inSampleSize) >= reqHeight && (halfWidth / inSampleSize) >= reqWidth) { inSampleSize *= 2; } } return inSampleSize; }
實際測試下還好,基本可以滿足不OOM的需求,但是隱隱覺得當inSampleSize的值很大的時候,圖片的壓縮質量會不會太嚴重?比如說App內中的相冊功能,采用這個算法放大的時候,圖片會不會變得很不清楚?一時也沒有找到特別好的壓縮算法。
二. 圖片的放置問題
按照Google給出的示例代碼,使用inSampleSize前要先把 options.inJustDecodeBounds = true; 設置成true:
public static Bitmap decodeSampledBitmapFromResource(Resources res, int resId, int reqWidth, int reqHeight) { // First decode with inJustDecodeBounds=true to check dimensions final BitmapFactory.Options options = new BitmapFactory.Options(); options.inJustDecodeBounds = true; BitmapFactory.decodeResource(res, resId, options); // Calculate inSampleSize options.inSampleSize = calculateInSampleSize(options, reqWidth, reqHeight); // Decode bitmap with inSampleSize set options.inJustDecodeBounds = false; return BitmapFactory.decodeResource(res, resId, options); }
然后再計算出inSampleSize,最后再進行decode,個人覺得這段代碼還是有缺陷,拿我的手機來說吧,分辨率是1440*2560, 需要顯示的ImageView寬度是1440*810,需要加載的圖片是1920*1080,通過上面Google的算法,算出inSampleSize的值為1,我把圖片放置到xxxhdpi和xxhdpi的時候圖片可以正常顯示,但是我把圖片放到mdpi和raw文件夾下的時候,程序一運行就Crash了,因為inSampleSize的默認值就是1,等於沒有做任何處理,但是系統在加載時卻會對圖片再進行放大,一旦需要申請的字節數過多,系統就直接Crash了:
java.lang.RuntimeException: Canvas: trying to draw too large(132710400bytes) bitmap.
所以我覺得為了保險起見,最好在上面的代碼中加上這么一句: options.inScaled = false;
public static Bitmap decodeSampledBitmapFromResource(Resources res, int resId, int reqWidth, int reqHeight) { // First decode with inJustDecodeBounds=true to check dimensions final BitmapFactory.Options options = new BitmapFactory.Options(); options.inJustDecodeBounds = true; BitmapFactory.decodeResource(res, resId, options); // Calculate inSampleSize options.inSampleSize = calculateInSampleSize(options, reqWidth, reqHeight); // Decode bitmap with inSampleSize set options.inJustDecodeBounds = false;
options.inScaled = false; return BitmapFactory.decodeResource(res, resId, options); }
保證不管我放置在任何文件夾,圖片都不會被縮放。