BitmapFactory: inSampleSize 的一些思考


一. 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); }

保證不管我放置在任何文件夾,圖片都不會被縮放。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM