android圖片存儲優化的心得

     在android開發過程中圖片的存儲優化是非常常見,處理不好,時常會造成圖片OOM。接下來分享一下我在開發過程中做的相應的處理,僅供各位參考,如有不足還請多多指教。

     首先我們知道圖片在app存在形式無非就是:file、stream流、bitmap!

一、接下來列出幾個圖片OOM的出現情況

    1、在一個頁面中一次性加載過多的圖片

    2、加載的圖片過大

    3、bitmap的錯誤使用

二、圖片優化的處理方式:尺寸壓縮、質量壓縮、內存複用

   在此我們先知道一張圖片的大小=圖片的寬x圖片的高x一個像素所佔的大小。

   1、尺寸壓縮

      按照一定的比例減小圖片的寬高從而減少單位尺寸的像素值,這樣的話可以改變圖片在內存中的大小。這種做法只是改變了圖片在加載時內存中的大小,但是磁盤中圖片的大小是沒有發生變化的

   代碼示例:

/** 
* @param pathUrl 文件路徑 
* @return 
*/
public Bitmap getBitmap(String pathUrl) {
    // 配置壓縮的參數
    BitmapFactory.Options options = new BitmapFactory.Options();
    // 開始讀入圖片,此時把options.inJustDecodeBounds 設爲true,方便圖片在不加載進內存的情況下獲取圖片的寬高
    options.inJustDecodeBounds = true;
    Bitmap bitmap = BitmapFactory.decodeFile(pathUrl, options);//這個時候decode的bitmap爲null
    options.inJustDecodeBounds = false;//將inJustDecodeBounds設置爲false,加載圖片數據
    //nSampleSize的作用就是可以把圖片的寬和高縮小inSampleSize倍,所佔內存縮小inSampleSize的平方
    //例如,inSampleSize = 2,則取出的縮略圖的寬和高都是原始圖片的1/2,圖片大小就爲原始大小的1/4。
    options.inSampleSize = calculateInSampleSize(options,400,100);
    bitmap = BitmapFactory.decodeFile(pathUrl, options);//重新讀出圖片
    return bitmap;
}
/**
 * @param options
 * @param reqWidth  我們期望的圖片的寬,單位px
 * @param reqHeight 我們期望的圖片的高,單位px
 * @return
 */
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 halfHeight = height / 2;
        final int halfWidth = width / 2;
        while ((halfHeight / inSampleSize) >= reqHeight && (halfWidth / inSampleSize) >= reqWidth) {
            inSampleSize *= 2;
        }
    }
    return inSampleSize;
}

   1、質量壓縮

      質量壓縮不會減少圖片的像素,它是在保持像素的前提下改變圖片的位深及透明度,來達到壓縮圖片的目的,圖片的長,寬,像素都不會改變,它只是改變磁盤中的文件大小,並不能改變加載時內存中的圖片大小

   代碼示例:

/**
 * @param bitmap bitmap
 * @param int quality
 * @return
 */
public Bitmap qualityBitmap(Bitmap bitmap, int quality){
    //quality,可以調節你壓縮的比例,但是質量壓縮對png格式這種圖片沒有作用,因爲png是無損壓縮。
    ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
    bitmap.compress(Bitmap.CompressFormat.WEBP,100,outputStream);
    while (outputStream.toByteArray().length/1024>quality){
        outputStream.reset();
        bitmap.compress(Bitmap.CompressFormat.WEBP,quality,outputStream);
        if (quality>5)quality-=5;
        else break;
    }
    ByteArrayInputStream inputStream = new ByteArrayInputStream(outputStream.toByteArray());
    BitmapFactory.Options options = new BitmapFactory.Options();
    options.inPreferredConfig=Bitmap.Config.RGB_565;
    Bitmap bitmap1 = BitmapFactory.decodeStream(inputStream, null, options);
    return bitmap1;
}

   3、內存複用inbitmap注意點

    2.3上,bitmap的數據是存儲在native的內存區域,並不是在Dalvik的內存堆上。

   3.0開始,系統在BitmapFactory.Options裏引入了inBitmap機制來配合緩存機制。如果在載入圖片時傳入了inBitmap那麼載入的圖片就是inBitmap裏的值。這樣可以統一有緩存和無緩存的載入方式。

    使用inBitmap,在4.4之前,只能重用相同大小的bitmap的內存區域,而4.4之後你可以重用任何bitmap的內存區域,只要這塊內存比將要分配內存的bitmap大就可以。

    新申請的bitmap與舊的bitmap必須有相同的解碼格式

    使用此方法需要inMutable=true,inSampleSize=1

   *例外,bitmap也可以通過縮放法壓縮(martix)、createScaledBitmap。

    以上是別人在項目過程中對圖片處理一些做法,寫的不錯,請多多指教

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章