android 有效加載大型Bitmap - 開發文檔翻譯

由於本人英文能力實在有限,不足之初敬請諒解

本博客只要沒有註明“轉”,那麼均爲原創,轉貼請註明本博客鏈接鏈接

 

Loading Large Bitmaps Efficiently

有效加載大型Bitmap

 

Images come in all shapes and sizes. 

圖片的形狀和尺寸是各種各樣的

 

In many cases they are larger than required for a typical application user interface (UI). 

For example, the system Gallery application displays photos taken using your Android devices's camera which are typically much higher resolution than the screen density of your device.

很多情況中,他們都大於典型應用UI所需要的

例如,系統Gallery應用顯示使用你的Android設備的camera拍出的照片,它們分辨率都遠大於你的設備的屏幕密度

 

Given that you are working with limited memory, ideally you only want to load a lower resolution version in memory. 

The lower resolution version should match the size of the UI component that displays it. 

An image with a higher resolution does not provide any visible benefit, but still takes up precious memory and incurs additional performance overhead due to additional on the fly scaling.

由於你在一個有限內存的設備上工作,理想情況下,你只是想在內存中加載一個低分辨率的版本

這個低分辨率的版本應該正好與顯示它的UI組件大小匹配

一個高分辨率的圖像不會提供任何可見的好處,但是仍然會佔據非常大的內存並且會引起額外的性能開銷

 

This lesson walks you through decoding large bitmaps without exceeding the per application memory limit by loading a smaller subsampled version in memory.

這一課將給你展示通過在內存中加載一個小一些的子樣版本來解碼大bitmap而不會超過每一個應用內存限制

 

Read Bitmap Dimensions and Type

讀取bitmap尺寸與類型

 

The BitmapFactory class provides several decoding methods (decodeByteArray(), decodeFile(), decodeResource(), etc.) for creating a Bitmap from various sources. 

Choose the most appropriate decode method based on your image data source. 

These methods attempt to allocate memory for the constructed bitmap and therefore can easily result in an OutOfMemory exception. 

Each type of decode method has additional signatures that let you specify decoding options via the BitmapFactory.Options class. 

Setting the inJustDecodeBounds property to true while decoding avoids memory allocation, returning null for the bitmap object but setting outWidth, outHeight and outMimeType. This technique allows you to read the dimensions and type of the image data prior to construction (and memory allocation) of the bitmap.

BitmapFactory類提供幾種解碼方法(decodeByteArray(), decodeFile(), decodeResource()等等)從資源中來建立一個bitmap

基於你的圖片數據源選字最恰當的解碼方式

這些方法試圖爲構建bitmap分配內存,因而可能很容易的導致一個OutOfMemory異常

每種解碼方法都有額外的簽名好讓你通過BitmapFactory.Options指定解碼選項

當解碼的時候,設置屬性inJustDecodeBounds=true來避免內存分配,返回值爲null,但是設置了BitmapFactory.Options的outWidth, outHeight 和 outMimeType屬性。

這種技術允許你在建立bitmap之前,讀取圖片數據的尺寸和類型 

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;

To avoid java.lang.OutOfMemory exceptions, check the dimensions of a bitmap before decoding it, unless you absolutely trust the source to provide you with predictably sized image data that comfortably fits within the available memory.

爲了避免java.lang.OutOfMemory異常,在解碼bitmap之前檢查他的尺寸,除非你絕對信任提供給你的圖片資源的大小是可知的,正好在可用內存範圍內的

 

Load a Scaled Down Version into Memory

加載一個按比例比縮小版本的到內存中

Now that the image dimensions are known, they can be used to decide if the full image should be loaded into memory or if a subsampled version should be loaded instead. 

Here are some factors to consider:

現在圖片尺寸知道了,它們可以用於判斷全圖是否應該被加載到內存,或者應該加載子樣版本

下面一些因素需要考慮: 

 

Estimated memory usage of loading the full image in memory.

Amount of memory you are willing to commit to loading this image given any other memory requirements of your application.

Dimensions of the target ImageView or UI component that the image is to be loaded into.

Screen size and density of the current device.

For example, it’s not worth loading a 1024x768 pixel image into memory if it will eventually be displayed in a 128x96 pixel thumbnail in an ImageView.

評估加載全圖所使用的內存

基於你的應用中任何其他內存需求,加載這個圖片你願意提供多少內存

圖片要加載到的目標ImageView或者其他UI組件的尺寸

當前設備的屏幕尺寸和密度

例如,如果圖片最終是要在一個ImageView中顯示爲一個128x96像素的縮略圖,那麼加載一張1024x768像素圖片到內存中是不值得的

 

To tell the decoder to subsample the image, loading a smaller version into memory, set inSampleSize to true in your BitmapFactory.Options object. 

For example, an image with resolution 2048x1536 that is decoded with an inSampleSize of 4 produces a bitmap of approximately 512x384. 

Loading this into memory uses 0.75MB rather than 12MB for the full image (assuming a bitmap configuration of ARGB_8888). 

Here’s a method to calculate a the sample size value based on a target width and height:

在你的BitmapFactory.Options對象中設置inSampleSize=true,可以告訴解碼器把圖片子樣話,加載一個小版本到內存中

例如,一個分辨率爲2048x1536的圖片,使用inSampleSize=4進行編碼,產出的bitmap大致爲512x384. 

一個基於目標寬高的方法來計算樣本大小的值

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) {
 
        // Calculate ratios of height and width to requested height and width
        final int heightRatio = Math.round((float) height / (float) reqHeight);
        final int widthRatio = Math.round((float) width / (float) reqWidth);
 
        // Choose the smallest ratio as inSampleSize value, this will guarantee
        // a final image with both dimensions larger than or equal to the
        // requested height and width.
        inSampleSize = heightRatio < widthRatio ? heightRatio : widthRatio;
    }
 
    return inSampleSize;
}

Note: Using powers of 2 for inSampleSize values is faster and more efficient for the decoder. 

However, if you plan to cache the resized versions in memory or on disk, it’s usually still worth decoding to the most appropriate image dimensions to save space.

注意:解碼時使用2的方冪設置inSampleSize,速度和效率都更好一些

然而,如果你打算緩存調整過的圖片版本到內存或者到磁盤中,通常還是需要解碼到最合適的圖片大小來節省空間

 

To use this method, first decode with inJustDecodeBounds set to true, pass the options through and then decode again using the new inSampleSize value and inJustDecodeBounds set to false:

使用這個方法,首先設置inJustDecodeBounds=true來解碼,傳遞這個選項,然後使用新的inSampleSize值並且設置inJustDecodeBounds=false再解碼一次 

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

This method makes it easy to load a bitmap of arbitrarily large size into an ImageView that displays a 100x100 pixel thumbnail, as shown in the following example code:

這個方法使得加載一個任意大小的圖片到一個ImageView顯示一個100x100像素的縮略圖變得容易,就像下面示例代碼展示的那樣

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

You can follow a similar process to decode bitmaps from other sources, by substituting the appropriate BitmapFactory.decode* method as needed.

根據需要通過替換恰當的BitmapFactory.decode*方法,你可以效仿出一個簡單的過程來從其他資源中解碼bitmap

 

 

原文地址如下,英文水平實在有限,希望拍磚同時能給予指正。

http://developer.android.com/training/displaying-bitmaps/load-bitmap.html

 

 

轉貼請保留以下鏈接

本人blog地址

http://su1216.iteye.com/

http://blog.csdn.net/su1216/

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