Android獲取圖片壓縮后的Bitmap避免OOM

版權(quán)聲明:本文源自簡書tianma,轉(zhuǎn)載請務(wù)必注明出處: http://www.lxweimin.com/p/2f1ce7d0d64c

OOM即Out Of Memory的簡稱,Android平臺避免OOM異常的發(fā)生是非常有必要的。而在Android中加載大量大圖便可能會導(dǎo)致OOM異常的出現(xiàn),解決的辦法之一就是加載圖片之前對圖片進(jìn)行壓縮然后再獲取圖片對應(yīng)的Bitmap對象,那么應(yīng)該如何操作呢?如下:

    /**
     * 通過圖片的絕對路徑來獲取對應(yīng)的壓縮后的Bitmap對象
     */
    public static Bitmap getCompressedBitmap(String filePath, int requireWidth,
            int requireHeight) {
        // 第一次解析將inJustDecodeBounds設(shè)置為true,用以獲取圖片大小,并且不需要將Bitmap對象加載到內(nèi)存中
        BitmapFactory.Options options = new BitmapFactory.Options();
        options.inJustDecodeBounds = true;
        BitmapFactory.decodeFile(filePath, options); // 第一次解析
        // 計(jì)算inSampleSize的值,并且賦值給Options.inSampleSize
        options.inSampleSize = calculateInSampleSize(options, requireWidth,
                requireHeight);
        // 使用獲取到的inSampleSize再次解析圖片
        options.inJustDecodeBounds = false;
        return BitmapFactory.decodeFile(filePath, options);
    }

    /**
     * 通過圖片資源id獲取圖片對應(yīng)的壓縮后的Bitmap對象
     */
    public static Bitmap getCompressedBitmap(Resources res, int resId, int requiredWidth, int requiredHeight) {
        
        BitmapFactory.Options options = new BitmapFactory.Options();
        options.inJustDecodeBounds = true;
        
        BitmapFactory.decodeResource(res, resId, options);// 第一次解析
        options.inSampleSize = calculateInSampleSize(options, requiredWidth,
                requiredHeight);
        
        options.inJustDecodeBounds = false;
        return BitmapFactory.decodeResource(res, resId, options);// 第一次解析
    }
    
    /**
     * 計(jì)算壓縮的inSampleSize的值,該值會在寬高上都進(jìn)行壓縮(也就是壓縮前后比例是inSampleSize的平方倍)
     */
    private static int calculateInSampleSize(BitmapFactory.Options options,
            int requireWidth, int requireHeight) {
        // 獲取源圖片的實(shí)際的寬度和高度
        int realWidth = options.outWidth;
        int realHeight = options.outHeight;

        int inSampleSize = 1;
        if (realWidth > requireWidth || realHeight > requireHeight) {
            // 計(jì)算出實(shí)際的寬高與目標(biāo)寬高的比例
            int widthRatio = Math.round((float) realWidth
                    / (float) requireWidth);
            int heightRatio = Math.round((float) realHeight
                    / (float) requireHeight);
            // 選擇寬高比例最小的值賦值給inSampleSize,這樣可以保證最終圖片的寬高一定會大于或等于目標(biāo)的寬高
            inSampleSize = widthRatio < heightRatio ? widthRatio : heightRatio;
        }
        return inSampleSize;
    }

以上代碼中,有一點(diǎn)值得商榷
到底是要讓圖片顯示完全還是讓圖片寬高和需要的寬高一致呢?
如果需要讓圖片寬高和需要的寬高一致的話,就選擇比率小的:

inSampleSize = widthRatio < heightRatio ? widthRatio : heightRatio;

如果需要讓圖片顯示完全的話,就選擇比率大的:

inSampleSize = widthRatio > heightRatio ? widthRatio : heightRatio;

如果兩者都要兼顧的話,就讓方法多設(shè)置參數(shù),讓調(diào)用者決定去吧! :)

參考鏈接:
Displaying Bitmaps Efficiently
Android高效加載大圖、多圖解決方案,有效避免程序OOM

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

推薦閱讀更多精彩內(nèi)容