Android有效的處理Bitmap,減少內存

Android有效的處理Bitmap,減少內存

圖片可能會有不同的大小。在許多情況下,圖片的大小會超出我們需要的大小。例如,我們的Camera應用,我們所拍的照片的大小遠大於屏幕顯示的大小

假如你的應用被限制瞭內存使用,顯而易見,你會選擇加載一個低分辨率的圖片。這張低分辨率的圖片應該匹配屏幕的尺寸。更高分辨率的圖像沒有提供任何可見的好處,但仍占用寶貴的內存,而且由於額外的動態縮放,會帶來額外的性能開銷。

本篇文章教你通過加載一個小尺寸的圖片樣本,來修飾一張大圖,並且沒有超過應用的內存限制。

原文地址https://wear.techbrood.com/training/displaying-bitmaps/load-bitmap.html

獲取圖片的類型尺寸

BitmapFactory這個類提供瞭幾種解碼方法(例如:decodeByteArray(),decodeFile(),decodeResource());我們在加載圖片的額時候,圖片可能有很多種來源,我們選擇合適的一種方法解碼圖片。下面提供瞭方法:為已經創建好的Bitmap重新分配內存,這樣就可以很好的解決內存溢出(OutOfMemory Exception) 的問題。每種解碼方法都有一些標識位,你可以通過配置BitmapFactory.Options這些標識位來實現。設置inJustDecodeBounds的屬性為true的時候,我們解碼的時候不分配內存,返回的Bitmap為null,但是我們設置瞭outWidth,outHeight和outMimeType。這種技術可以預先獲取到Bitmap的大小數據和類型數據。

BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true;
BitmapFactory.decodeResource(getResources(), R.id.myimage, options);
int imageHeight = options.outHeight;
int imageWidth = options.outWidth;
String imageType = options.outMimeType;

為瞭避免java.lang.OutOfMemory exceptions,在解碼圖片之前,預先檢查Bitmap的大小,除非你有絕對的把握你的bitmap有合適的大小,並且在內存限制大小范圍之內。

加載縮放的圖片到內存

現在,我們知道瞭圖片的尺寸,我們就可以決定是使用該尺寸的圖片,還是使用另外一個樣本。線面有一些因素是我們要註意的:

估計加載整個圖像所占用的內存 你可以接收的內存使用量和你程序可以使用的內存 你放該圖片的ImageView的尺寸或者其他UI組件的尺寸 屏幕的大小
例如,我們不值得將大小為1024×768 pixel的圖片放到128*96 pixel的縮略圖控件(ImageVIew)裡面。
我們得使用圖片的一個更小的樣本加載到內存裡面,在BitmapFactory.Options裡面設置inSampleSize為true。例如,我們想把一張2048*1536的圖片解碼為隻有1/4大小的圖片512*384,加載到內存裡賣年隻有0.75MB的大小,遠遠小宇原圖12MB的大小(使用ARGB_8888通道的圖片)。這裡有一種計算樣本圖片的方法,根據目標圖片的寬度和高度width和height:

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;
}

Note: A power of two value is calculated because the decoder uses a final value by rounding down to the nearest power of two, as per the inSampleSize documentation.

我們在使用該方法的時候,首先設置inJustDecodeBounds為true,然後我們計算inSample的值,然後設置inJustDecodeBounds為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;
    return BitmapFactory.decodeResource(res, resId, options);
}

這種方法可以幫助我們輕松有效的加載一張100*100的縮略圖片:

mImageView.setImageBitmap(
    decodeSampledBitmapFromResource(getResources(), R.id.myimage, 100, 100));

你也可以通過相同的方法解碼一張從其他路徑獲取到的圖片,通過使用BitmapFactory.decode* as
need。
下面還有幾篇從android Developer上面翻譯過來的,感覺挺有用的,加個關註吧,(*^__^*)
嘻嘻

發佈留言

發佈留言必須填寫的電子郵件地址不會公開。 必填欄位標示為 *