android BitmapFactory.Options(總結網絡中出現的一些)

public Bitmap

 

inBitmap

 

If set, decode methods that take the Options objectwill 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 todither the decoded image.

 

public boolean

 

inInputShareable

 

This field works in conjuction withinPurgeable.

 

public boolean

 

inJustDecodeBounds

 

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

 

public boolean

 

inMutable

 

If set, decode methods will always return a mutableBitmap instead of an immutable one.

 

public boolean

 

inPreferQualityOverSpeed

 

If inPreferQualityOverSpeed is set to true, thedecoder will try to decode the reconstructed image to a higherquality even at the expense of the decoding speed.

 

publicBitmap.Config

 

inPreferredConfig

 

If this is non-null, the decoder will try to decodeinto this internal configuration.

 

public boolean

 

inPurgeable

 

If this is set to true, then the resulting bitmapwill allocate its pixels such that they can be purged if the systemneeds to reclaim memory.

 

public int

 

inSampleSize

 

If set to a value > 1, requests the decoder tosubsample the original image, returning a smaller image to savememory.

 

public boolean

 

inScaled

 

When this flag is set,if inDensity and inTargetDensity arenot 0, the bitmap will be scaled tomatch inTargetDensity whenloaded, rather than relying on the graphics system scaling it eachtime it is drawn to a Canvas.

 

public int

 

inScreenDensity

 

The pixel density of the actual screen that isbeing used.

 

public int

 

inTargetDensity

 

The pixel density of the destination this bitmapwill be drawn to.

 

public byte[]

 

inTempStorage

 

Temp storage to use for decoding.

 

public boolean

 

mCancel

 

Flag to indicate that cancel has been called onthis object.

 

public int

 

outHeight

 

The resulting height of the bitmap, set independentof the state of inJustDecodeBounds.

 

public String

 

outMimeType

 

If known, this string is set to the mimetype of thedecoded image.

 

public int

 

outWidth

 

The resulting width of the bitmap, set independentof the state of inJustDecodeBounds.

 

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

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

思路很簡單:

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

新問題又來瞭,在通過BitmapFactory.decodeFile(Stringpath)方法將突破轉成Bitmap時,遇到大一些的圖片,我們經常會遇到OOM(Out OfMemory)的問題。怎麼避免它呢?

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

 

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

If set to true, the decoderwill return null (no bitmap), but theout…

也就是說,如果我們把它設為true,那麼BitmapFactory.decodeFile(Stringpath, Optionsopt)並不會真的返回一個Bitmap給你,它僅僅會把它的寬,高取回來給你,這樣就不會占用太多的內存,也就不會那麼頻繁的發生OOM瞭。

示例代碼如下:

 

BitmapFactory.Options options = newBitmapFactory.Options();

options.inJustDecodeBounds = true;

Bitmap bmp = BitmapFactory.decodeFile(path, options);

復制代碼

 

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

 

有瞭寬,高的信息,我們怎樣在圖片不變形的情況下獲取到圖片指定大小的縮略圖呢?

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

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

 

int height = options.outHeight * 200 / options.outWidth;

options.outWidth = 200;

options.outHeight = height; 

options.inJustDecodeBounds = false;

Bitmap bmp = BitmapFactory.decodeFile(path, options);

image.setImageBitmap(bmp);

復制代碼

 

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

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

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

 

inSampleSize = options.outWidth / 200;

另外,為瞭節約內存我們還可以使用下面的幾個字段:

 

options.inPreferredConfig =Bitmap.Config.ARGB_4444;    //默認是Bitmap.Config.ARGB_8888

options.inPurgeable = true;

options.inInputShareable = true;

 

加載和顯示圖片是很消耗內存的一件事,BitmapFactory.Options 類,  允許我們定義圖片以何種方式如何讀到內存,

 

[html] 

BitmapFactory.Options bmpFactoryOptions = new BitmapFactory.Options();    

bmpFactoryOptions.inSampleSize = 8;    

Bitmap bmp = BitmapFactory.decodeFile(imageFilePath, bmpFactoryOptions);    

imv.setImageBitmap(bmp);    

上面的代碼使圖片變成原來的1/8.

[html] 

//imv = (ImageView) findViewById(R.id.ReturnedImageView);    

        Display currentDisplay = getWindowManager().getDefaultDisplay();    

        int dw = currentDisplay.getWidth();    

        int dh = currentDisplay.getHeight();    

          try    

       {    

        BitmapFactory.Options bmpFactoryOptions = new BitmapFactory.Options();    

        bmpFactoryOptions.inJustDecodeBounds = true;    

        Bitmap bmp = BitmapFactory.decodeStream(getContentResolver().    

                openInputStream(imageFileUri), null,  bmpFactoryOptions);    

    

        int heightRatio = (int)Math.ceil(bmpFactoryOptions.outHeight/(float)dh);    

        int widthRatio = (int)Math.ceil(bmpFactoryOptions.outWidth/(float)dw);    

    

        Log.v("HEIGHRATIO", ""+heightRatio);    

        Log.v("WIDTHRATIO", ""+widthRatio);    

    

        if (heightRatio > 1 && widthRatio > 1)    

        {    

            bmpFactoryOptions.inSampleSize =  heightRatio > widthRatio ? heightRatio:widthRatio;    

        }    

        bmpFactoryOptions.inJustDecodeBounds = false;    

        bmp = BitmapFactory.decodeStream(getContentResolver().    

                openInputStream(imageFileUri), null,  bmpFactoryOptions);    

           returnedImageView.setImageBitmap(bmp);    

       }    

       catch (FileNotFoundException e)    

       {    

           Log.v("ERROR", e.toString());    

    

       }    

上面的代碼讓圖片根據窗口大小改變

bmpFactoryOptions.inJustDecodeBounds = true; 這一行讓代碼隻解碼圖片的Bounds

 

如果設置為真,譯碼器將返回null(沒有圖),但是……領域仍將被設置,允許調用者來查詢圖而無需為其像素分配內存。

 

1.inSampleSize(設置縮放為原來的四分之一)

[html]  

BitmapFactory.Options opts = new BitmapFactory.Options();  

opts.inSampleSize = <span style="background-color:rgb(255,204,153)">4</span>;  

Bitmap bitmap = BitmapFactory.decodeFile(imageFile, opts);  

2.inJustDecodeBounds

[html]  

BitmapFactory.Options opts = new BitmapFactory.Options();  

opts.inJustDecodeBounds = true;  

Bitmap bitmap = BitmapFactory.decodeFile(imageFile, opts);  

設置inJustDecodeBounds為true後,decodeFile並不分配空間,但可計算出原始圖片的長度和寬度,即opts.width和opts.height。有瞭這兩個參數,再通過一定的算法,即可得到一個恰當的inSampleSize。

綜合上述(1,2),完整代碼是

[html]  

public static Bitmap createImageThumbnail(String filePath){    

     Bitmap bitmap = null;    

     BitmapFactory.Options opts = new BitmapFactory.Options();    

     opts.inJustDecodeBounds = true;    

     BitmapFactory.decodeFile(filePath, opts);    

    

     opts.inSampleSize = computeSampleSize(opts, -1, 128*128);    

     opts.inJustDecodeBounds = false;    

    

     try {    

         bitmap = BitmapFactory.decodeFile(filePath, opts);    

     }catch (Exception e) {    

        // TODO: handle exception    

    }    

    return bitmap;    

}    

    

public static int computeSampleSize(BitmapFactory.Options options, int minSideLength, int maxNumOfPixels) {    

    int initialSize = computeInitialSampleSize(options, minSideLength, maxNumOfPixels);    

    int roundedSize;    

    if (initialSize <= 8) {    

        roundedSize = 1;    

        while (roundedSize < initialSize) {    

            roundedSize <<= 1;    

        }    

    } else {    

        roundedSize = (initialSize + 7) / 8 * 8;    

    }    

    return roundedSize;    

}    

    

private static int computeInitialSampleSize(BitmapFactory.Options options,int minSideLength, int maxNumOfPixels) {    

    double w = options.outWidth;    

    double h = options.outHeight;    

    int lowerBound = (maxNumOfPixels == -1) ? 1 : (int) Math.ceil(Math.sqrt(w * h / maxNumOfPixels));    

    int upperBound = (minSideLength == -1) ? 128 :(int) Math.min(Math.floor(w / minSideLength), Math.floor(h / minSideLength));    

    if (upperBound < lowerBound) {    

        // return the larger one when there is no overlapping zone.    

        return lowerBound;    

    }    

    if ((maxNumOfPixels == -1) && (minSideLength == -1)) {    

        return 1;    

    } else if (minSideLength == -1) {    

        return lowerBound;    

    } else {    

        return upperBound;    

    }    

}    

 

 

發佈留言