1. 程式人生 > >BitmapFactory.Options常用的幾個引數

BitmapFactory.Options常用的幾個引數

專案中用到了載入圖片的地方,總結了一下簡單的對圖片載入處理:

BitmapFactory提供了一些decode(解碼)獲取Bitmap例項的方法,例如decodeByteArray(), decodeFile(), decodeResource()等等,我們可以使用這些方法直接讀取檔案,讀取Resourse,讀取檔案流等多種形式從而獲取Bitmap資源, 然而在構造相對應點陣圖時會嘗試分配實體記憶體,就可能存在OOM了…

**對於這個問題的解決我們可以在解碼時傳入BitmapFactory.Options標識來宣告解碼規則:**
BimapFactory.Options options = new BitmapFatory.Options
(); options.inJustDecodeBounds = true;
1.設定inJustDecodeBounds屬性,不必載入全部資源到記憶體中,而是僅僅獲取資源的邊界引數,它會返回一個值為null的Bitamp引用,從而獲取原資源的寬,高,型別等屬性值;
Google API : If set to true, the decoder will return null (no bitmap), but the out... fields will still be set, allowing the caller to query the bitmap without having to allocate the memory for its pixels.
BitmapFactory.decodeFile("filepath",options)
int height = options.outHeight;
int width = options.outWidth;
String mimetype = options.outMimeType;

在獲取到邊界引數後再做相應的邏輯來實現控制邏輯 …

 2. 實現載入可縮放的圖片資源

上面我們獲取了原始檔的具體尺寸,接下來就要處理資料了,如果我們原圖是1080*1980畫素的圖片,想要顯示在300*200畫素的View裡面,那麼我就要在解碼時來約束解碼的過程,我們需要壓縮資源,這是需要設定inSampleSize的值:

options.inSampleSize = 1;

對於inSamplesize的說明Goole API闡述:

If set to a value > 1, requests the decoder to subsample the original image, returning a smaller image to save memory. The sample size is the number of pixels in either dimension that correspond to a single pixel in the decoded bitmap. For example, inSampleSize == 4 returns an image that is 1/4 the width/height of the original, and 1/16 the number of pixels. Any value <= 1 is treated the same as 1. Note: the decoder uses a final value based on powers of 2, any other value will be rounded down to the nearest power of 2.

大概意思是:如果設定為值> 1,要求解碼器以子取樣原始影象,返回一個較小的影象以節省記憶體。樣本大小是對應於點陣圖的解碼的單個畫素中任一維的畫素數。例如,inSampleSize == 4返回一個影象是1/4原來的寬度/高度,和1/16的畫素數。任何值<= 1同等對待。注意:所述解碼器使用基於2的冪的最終值,任何其它值將被向下舍入為最接近2的冪。

然後我們通過已知的View的尺寸和原始檔的尺寸來動態修改inSamplesize的值,來自定義解碼時的取樣尺寸;

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

這樣我們就可以根據我們需要定義的條件來控制inSamplesize的動態值,如實際需求不服主要修改while(條件)即可,正確設定取樣比例後就可以知己使用控制值了:

BimapFactory.Options options = new BitmapFatory.Options();
options.inJustDecodeBounds = true;
options.inSampleSize = calculateInSampleSize(options,200,300);
options.inJustDecodeBounds = false;
Bitmap bitmap = BitamapFactory.decodeFile("filepath",options);
imageView.setIamgeBitmap(bitmap);

這樣就實現了一個主動控制圖片縮放的設定了,不會因為解碼過大的圖片而大量申請記憶體了;
NOTE: 在真正要解碼前一定要設定inJustDecodeBounds = false標識值;

3.設定解碼時圖片壓縮的色彩質量引數;

在解碼時可以設定引用Bitmap.Config的引數,用來儲存解碼後的色彩值:

options.inPreferredConfig = Bitmap.Config.ARGB_8888;
Google API 原文: If this is non-null, the decoder will try to decode into this internal configuration. If it is null, or the request cannot be met, the decoder will try to pick the best matching config based on the system's screen depth, and characteristics of the original image such as if it has per-pixel alpha (requiring a config that also does). Image are loaded with the ARGB_8888 config by default.
大致意思:如果是這種非空,解碼器將嘗試解碼成這個內部配置。如果為空,或者該請求不能被滿足,則解碼器將嘗試挑選基於所述系統的螢幕深度的最佳匹配的配置,以及諸如如果它具有每畫素的α的原始影象的特徵(要求一個配置也一樣)。圖片載入與預設ARGB_8888配置。

Android 中通常設定四種常用色彩質量引數來控制渲染的色彩的質量,在原始碼中定義了四個列舉值:

 public enum Config {
        // these native values must match up with the enum in SkBitmap.h
        /**
         * Each pixel is stored as a single translucency (alpha) channel.
         * This is very useful to efficiently store masks for instance.
         * No color information is stored.
         * With this configuration, each pixel requires 1 byte of memory.
         * 每個畫素都會作為透明的資訊儲存,一個畫素佔1個位元組;
         */
        ALPHA_8     (1),

        /**
         * Each pixel is stored on 2 bytes and only the RGB channels are
         * encoded: red is stored with 5 bits of precision (32 possible
         * values), green is stored with 6 bits of precision (64 possible
         * values) and blue is stored with 5 bits of precision.
         *
         * This configuration can produce slight visual artifacts depending
         * on the configuration of the source. For instance, without
         * dithering, the result might show a greenish tint. To get better
         * results dithering should be applied.
         *
         * This configuration may be useful when using opaque bitmaps
         * that do not require high color fidelity.
         * 每個畫素佔用2位元組,使用不需要高色彩保真度不透明點陣圖時,這個配置會更好一些;
         */
        RGB_565     (3),

        /**
         * Each pixel is stored on 2 bytes. The three RGB color channels
         * and the alpha channel (translucency) are stored with a 4 bits
         * precision (16 possible values.)
         *
         * This configuration is mostly useful if the application needs
         * to store translucency information but also needs to save
         * memory.
         *
         * It is recommended to use {@link #ARGB_8888} instead of this
         * configuration.
         *
         * Note: as of {@link android.os.Build.VERSION_CODES#KITKAT},
         * any bitmap created with this configuration will be created
         * using {@link #ARGB_8888} instead.
         *
         * @deprecated Because of the poor quality of this configuration,
         *             it is advised to use {@link #ARGB_8888} instead.
         * 每個畫素佔2位元組,應該儘可能地使用ARGB_8888配置來替換它;
         */
        ARGB_4444   (4),

        /**
         * Each pixel is stored on 4 bytes. Each channel (RGB and alpha
         * for translucency) is stored with 8 bits of precision (256
         * possible values.)
         *
         * This configuration is very flexible and offers the best
         * quality. It should be used whenever possible.
         * 每個畫素佔4個位元組...它會提供最好的圖片質量,應儘可能地使用這個引數;
         */
        ARGB_8888   (5);
    }

根據我們要呈現的效果來選擇不同的配置。