天天看點

淺談BitmapFactory.Options的使用

                                                                                                                         public Bitmap                                                                                                                                                                                                                                       inBitmap                   If set, decode methods that take the Options object will attempt to reuse this bitmap when loading content.
public int inDensity The pixel density to use for the bitmap.
public boolean inDither If dither is true, the decoder will attempt to dither the decoded image.
public boolean inInputShareable This field works in conjuction with inPurgeable.
public boolean inJustDecodeBounds If set to true, the decoder will return null (no bitmap), but the out…
public boolean inMutable If set, decode methods will always return a mutable Bitmap instead of an immutable one.
public boolean inPreferQualityOverSpeed If inPreferQualityOverSpeed is set to true, the decoder will try to decode the reconstructed image to a higher quality even at the expense of the decoding speed.
publicBitmap.Config inPreferredConfig If this is non-null, the decoder will try to decode into this internal configuration.
public boolean inPurgeable If this is set to true, then the resulting bitmap will allocate its pixels such that they can be purged if the system needs to reclaim memory.
public int inSampleSize If set to a value > 1, requests the decoder to subsample the original image, returning a smaller image to save memory.
public boolean inScaled When this flag is set, if inDensity and inTargetDensity are not 0, the bitmap will be scaled to match inTargetDensity when loaded, rather than relying on the graphics system scaling it each time it is drawn to a Canvas.
public int inScreenDensity The pixel density of the actual screen that is being used.
public int inTargetDensity The pixel density of the destination this bitmap will be drawn to.
public byte[] inTempStorage Temp storage to use for decoding.
public boolean mCancel Flag to indicate that cancel has been called on this object.
public int outHeight The resulting height of the bitmap, set independent of the state of inJustDecodeBounds.
public String outMimeType If known, this string is set to the mimetype of the decoded image.
public int outWidth The resulting width of the bitmap, set independent of the state of inJustDecodeBounds.

這個表格是從android sdk文檔裡摘出來的,簡單看一下說明就明白是什麼意思了。

下面我們回到我們的主題上來:怎樣擷取圖檔的大小?

思路很簡單:

首先我們把這個圖檔轉成Bitmap,然後再利用Bitmap的getWidth()和getHeight()方法就可以取到圖檔的寬高了。

新問題又來了,在通過BitmapFactory.decodeFile(String path)方法将突破轉成Bitmap時,遇到大一些的圖檔,我們經常會遇到OOM(Out Of Memory)的問題。怎麼避免它呢?

這就用到了我們上面提到的BitmapFactory.Options這個類。

BitmapFactory.Options這個類,有一個字段叫做 inJustDecodeBounds 。SDK中對這個成員的說明是這樣的:

If set to true, the decoder will return null (no bitmap), but the out…

也就是說,如果我們把它設為true,那麼BitmapFactory.decodeFile(String path, Options opt)并不會真的傳回一個Bitmap給你,它僅僅會把它的寬,高取回來給你,這樣就不會占用太多的記憶體,也就不會那麼頻繁的發生OOM了。

示例代碼如下:

  1. BitmapFactory.Options options = new BitmapFactory.Options();
  2. options.inJustDecodeBounds = true;
  3. Bitmap bmp = BitmapFactory.decodeFile(path, options);

複制代碼

這段代碼之後,options.outWidth 和 options.outHeight就是我們想要的寬和高了。

有了寬,高的資訊,我們怎樣在圖檔不變形的情況下擷取到圖檔指定大小的縮略圖呢?

比如我們需要在圖檔不變形的前提下得到寬度為200的縮略圖。

那麼我們需要先計算一下縮放之後,圖檔的高度是多少 

  1. int height = options.outHeight * 200 / options.outWidth;
  2. options.outWidth = 200;
  3. options.outHeight = height; 
  4. options.inJustDecodeBounds = false;
  5. Bitmap bmp = BitmapFactory.decodeFile(path, options);
  6. image.setImageBitmap(bmp);

複制代碼

這樣雖然我們可以得到我們期望大小的ImageView

但是在執行BitmapFactory.decodeFile(path, options);時,并沒有節約記憶體。要想節約記憶體,還需要用到BitmapFactory.Options這個類裡的 inSampleSize 這個成員變量。

我們可以根據圖檔實際的寬高和我們期望的寬高來計算得到這個值。

  1. inSampleSize = options.outWidth / 200;

另外,為了節約記憶體我們還可以使用下面的幾個字段:

  1. options.inPreferredConfig = Bitmap.Config.ARGB_4444;    // 預設是Bitmap.Config.ARGB_8888
  2. options.inPurgeable = true;
  3. options.inInputShareable = true;