1. 程式人生 > >Android 中關於載入Bitmap知識點

Android 中關於載入Bitmap知識點

 在安卓開發中遇到載入圖片是很平常的事情,圖片即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;
    }