Android進階練習 – 高效顯示Bitmap(高效載入較大的 Bitmaps)

來源:互聯網
上載者:User

高效載入較大的 Bitmaps
     圖片有各種形狀和各種大小,在很多情況下,圖片的實際大小都比圖片在應用中所顯示的大小要大的多,比如Android系統內建的 
Gallery
  應用顯示的照片實際的解析度通常比手機裝置的密度要高很多      考慮到我們是在開發一款記憶體使用量受限的應用,理想的情況下,我們只是想把一個低解析度版本的位元影像載入記憶體,一般來說這個低解析度版本的位元影像要跟UI元件實際需要顯示的大小相符。一張高解析度的圖片並不會給我們帶來任何明顯的好處,但卻會佔用寶貴的記憶體資源和產生額外的效能開銷 擷取Bitmap的尺寸大小和類型
     
BitmapFactory 類為我們提供了幾種decoding方法(
decodeByteArray()

decodeFile()
,
decodeResource()
, etc)來從不同的來源建立出 
Bitmap ,如何選擇最恰當的decode方法取決於你的圖片資料來源,這些方法都會去嘗試申請記憶體來構建Bitmap對象,所有很容易就會導致一個
OutOfMemory  異常,每種類型的decode方法都有額外的簽名來讓你通過
 
BitmapFactory.Options 類來指定decoding選項,當我們decoding的時候把
inJustDecodeBounds 屬性設定為
true 可以避免申請記憶體,雖然會返回一個
null Bitmap對象 ,但是會為我們傳入的
BitmapFactory.Options  對象設定
 
outWidth

outHeight
 and 
outMimeType 等屬性的值,這個技術可以讓你在構建Bitmap對象之前事Crowdsourced Security Testing道它的大小和類型

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
 
 異常,
在decoding Bitmap之前你有必要去檢測Bitmap的大小和類型,除非你真的是非常清楚你要decoding的Bitmap的大小,還有這個大小要適合當前應用記憶體環境
載入‘縮小版’的Bitmap到記憶體
     現在我們已經知道了Bitmap的大小,這將有助於我們來決策是載入整張Bitmap還是載入'縮小版'的Bitmap,這裡有一些因素需要進行考慮             一、
載入整張圖片預計要使用多少記憶體             二、
在考慮到其它方面記憶體需要的情況下,你想把多少數量的記憶體給Bitmap使用             三、
用於顯示Bitmap的
 
ImageView
 控制項或其它UI元件的大小             四、
當前裝置螢幕的大小和密度       例如,一點都不值得載入
1024x768
 
 像素的圖片到記憶體中,而最終只在
128x96
 像素大小的
 
ImageView
 控制項上顯示              我們應該告訴decoder,映像需要進行抽樣,載入一個更小號的Bitmap到記憶體中,設定
 
BitmapFactory.Options 對象的
 
inSampleSize 屬性為
true 。例如,一張解析度為
2048x1536 像素的圖片,如果decode的時候把
inSampleSize   設定為4,那麼得到的最終圖片的大小大約為
512x384 ,載入記憶體耗費0.75M而不是載入整張時的12M (假設位元影像的配置為
 
ARGB_8888) ,下面有一個在目標高和寬基礎上計算
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) {        if (width > height) {            inSampleSize = Math.round((float)height / (float)reqHeight);        } else {            inSampleSize = Math.round((float)width / (float)reqWidth);        }    }    return inSampleSize;}
NOTE :   inSampleSize  值是2的冪的話,對於decoder來說會更快和更高效。然而,如果你想把調整過大小的位元影像緩衝到記憶體或硬碟上時,依然非常有意義decoding最合適的位元影像大小,這樣有助於節省記憶體或節省硬碟空間
下面是一個擷取位元影像的方法
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);}

這個方法可以很容易的做到在任意顯示尺寸大小的UI元件中去載入一張位元影像

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

在其他的
BitmapFactory.decode*
 
 系列的decode方法中以上擷取位元影像的技術也是需要的






 

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.