1. 程式人生 > >Loading Large Bitmaps Efficiently高效載入大圖(Android開發文件翻譯一)

Loading Large Bitmaps Efficiently高效載入大圖(Android開發文件翻譯一)

原文地址:http://developer.android.com/training/displaying-bitmaps/load-bitmap.html

注:我的英文水平確實有限,希望大家能夠指出不足之處:——),建議多閱讀官方文件,市場上很多書將思想講的比較少,一來就是元件和熟悉。。。簡直無語

我接下來寫的關於Android的文件基本以翻譯為主,原因有:1、個人能力有限,不想耽誤童鞋們。。

我把我個人覺得相對重要的用紅色標註了

Images come in all shapesand sizes. In many cases they are larger than required for a typicalapplication user interface (UI). For example, the system Gallery applicationdisplays photos taken using your Android devices's camera which are typicallymuch higher resolution than the screen density of your device.

圖片有各種形狀和大小。在很多場合下,對於一個典型的應用介面UI,大圖往往都要比介面所需要的圖片要大。比如,Gallery應用展示你裝置上的相機拍攝的照片,這些照片比你的裝置的螢幕密度要有更高的解析度。

Given that you are workingwith limited memory, ideally you only want to load a lower resolution versionin memory. The lower resolution version should match the size of the UIcomponent that displays it. An image with a higher resolution does not provideany visible benefit, but still takes up precious memory and incurs additionalperformance overhead due to additional on the fly scaling.

假設你的記憶體有限,理想情況下你只是希望在記憶體中載入一個更低解析度的版本。這個低解析度版本的圖片應該要匹配展示它的UI元件的大小。一個擁有高解析度的圖片不會提供任何看得到的好處,相反會佔用寶貴的記憶體並且由於額外的縮放將引發額外的效能開銷

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

這個課程將引導你在不超過應用記憶體限制情況下,通過往記憶體中載入一個更小的子樣本(我的理解是通過對大圖進行抽樣,做成一個小圖)版本完成高效decode大圖。

ReadBitmap Dimensions and Type

獲取圖片的尺寸和型別

The BitmapFactoryclass provides several decoding methods (decodeByteArray()decodeFile(),decodeResource(), etc.) for creating a Bitmapfrom various sources. Choose the most appropriate decodemethod based on your image data source. These methods attempt to allocatememory for the constructed bitmap and therefore can easily result in an OutOfMemoryexception. Each type of decode method has additionalsignatures that let you specify decoding options via the BitmapFactory.Optionsclass. Setting theinJustDecodeBoundsproperty to truewhile decoding avoids memory allocation, returning nullfor the bitmap object but setting outWidthoutHeightand outMimeType. This technique allows you to read the dimensions and typeof the image data prior to construction (and memory allocation) of the bitmap.

BitmapFactory 類為從各種資源中建立Bitmap提供了幾個編碼的方式(decodeByteArray()decodeFile(),decodeResource(), etc.)你要根據你的圖片資源選擇最合適的編碼方法。這些methods將為constructed bitmap分配記憶體,因而很容易引發outOfMemoryOOM)異常。每種編碼方式都有一個額外的符號(signatures)讓你通過BitmapFactory.Options去指定decoding options。編碼時(decoding)設定theinJustDecodeBounds屬性為true來避免分配記憶體,同時返回null給bitmap 物件,但會產生outWidthoutHeightand 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.OutOfMemoryexceptions, checkthe dimensions of a bitmap before decoding it, unless you absolutely trust the sourceto provide you with predictably sized image data that comfortably fits withinthe available memory

為了避免java.lang.OutOfMemory異常,在decoding bitmap之前獲取它的尺寸,除非你確信你提供的資源已知image data 的大小,並且能夠很好適應可用記憶體

Load aScaled Down Version into Memory

載入一個縮小的版本到記憶體中

Now that theimage dimensions are known, they can be used to decide if the full image shouldbe loaded into memory or if a subsampled version should be loaded instead. Hereare some factors to consider:

·        Estimated memory usage of loading the fullimage in memory.

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

·        Dimensions of the target ImageView or UI componentthat the image is to be loaded into.

·        Screen size and density of the currentdevice.

現在你已經知道了圖片的尺寸,他們能夠用來確定是否是把原圖載入進記憶體還是隻是載入它的抽樣版本(subsampled version),這裡有幾個因素你要考慮:

         估算載入原圖到記憶體的用量

         在你的應用有其它的記憶體需求的條件下,給出你願意給圖片分配的記憶體大小

         目標ImageView或者是圖片要載入到的UI元件的尺寸

         當前裝置的螢幕大小和密度

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

To tell thedecoder to subsample the image, loading a smaller version into memory,set inSampleSize to true inyour BitmapFactory.Options object.For example, an image with resolution 2048x1536 that is decoded with aninSampleSize of 4produces a bitmap of approximately 512x384. Loading this into memory uses0.75MB rather than 12MB for the full image (assuming a bitmap configurationof ARGB_8888). Here’s amethod to calculate a sample size value that is a power of two based on atarget width and height:

比如,載入1024*768畫素的圖片到記憶體中但最後將在ImageView中展示成一個128*96的縮圖,這沒啥子用。

要告訴decoder去抽樣(subsample)圖片,載入一個小尺寸版本的進入到記憶體中,需要在 BitmapFactory.Options 物件中設定. inSampleSize to true 。比如,一個圖片解析度為2048*1536,以inSampleSize 為4進行decode,那麼最後將產生大約512*384解析度的圖片。載入它到記憶體中只需要0.75MB而不是對於全圖的12MB(假設bitmap的編碼方式為ARGB_8888),這裡有一個方法來計算一個基於目標imgview的寬和高產生一個值為2的冪的sample size:

public static int calculateInSampleSize(
            BitmapFactory.Options options,int reqWidth,int reqHeight){
    // Raw heightand 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 keepsboth
        // height and width larger than the requested height and width.
        while ((halfHeight/ inSampleSize)> reqHeight
                && (halfWidth / inSampleSize)> reqWidth){
            inSampleSize *= 2;
        }
    }

    return inSampleSize;
}

This method makes it easyto load a bitmap of arbitrarily large size into an ImageViewthat displays a100x100 pixel thumbnail, as shown in the following example code:

這個方法讓其變地很容易去載入一個大圖到一個展示100*100畫素的縮圖的ImageView中。就想下面的程式碼顯示的一樣

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

You can follow a similarprocess to decode bitmaps from other sources, by substituting the appropriateBitmapFactory.decode*method as needed.

你能夠按照一個相似的方法從其他資源中decode bitmap,通過把BitmapFactory.decode*方法替換成你需要的

轉載請註明出處:http://blog.csdn.net/storyofliu_yu