Displaying Bitmaps Efficiently -Loading Large Bitmaps Efficiently
2015-02-27 11:29
246 查看
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.
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.
This lesson walks you through decoding large bitmaps without exceeding the per application memory limit by loading a smaller subsampled version in memory.
The
provides several decoding methods (
etc.) for creating a
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
Each type of decode method has additional signatures that let you specify decoding options via the
Setting the
to
This technique allows you to read the dimensions and type of the image data prior to construction (and memory allocation) of the bitmap.
To avoid
provide you with predictably sized image data that comfortably fits within the available 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
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
To tell the decoder to subsample the image, loading a smaller version into memory, set
your
For example, an image with resolution 2048x1536 that is decoded with an
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
Here’s a method to calculate a sample size value that is a power of two based on a target width and height:
Note: A power of two value is calculated because the decoder uses a final value by rounding down to the nearest power of two, as per the
To use this method, first decode with
to
and
to
This method makes it easy to load a bitmap of arbitrarily large size into an
displays a 100x100 pixel thumbnail, as shown in the following example code:
You can follow a similar process to decode bitmaps from other sources, by substituting the appropriate
as needed.
NEXT: PROCESSING
BITMAPS OFF THE UI THREAD
devices's camera which are typically much higher resolution than the screen density of your device.
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.
This lesson walks you through decoding large bitmaps without exceeding the per application memory limit by loading a smaller subsampled version in memory.
Read Bitmap Dimensions and Type
The BitmapFactoryclass
provides several decoding methods (
, int, int, android.graphics.BitmapFactory.Options)]decodeByteArray(),
decodeFile(),
decodeResource(),
etc.) for creating a
Bitmapfrom
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
OutOfMemoryexception.
Each type of decode method has additional signatures that let you specify decoding options via the
BitmapFactory.Optionsclass.
Setting the
inJustDecodeBoundsproperty
to
truewhile decoding avoids memory allocation, returning
nullfor the bitmap object but setting
outWidth,
outHeightand
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.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, 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.
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
ImageViewor
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.
To tell the decoder to subsample the image, loading a smaller version into memory, set
inSampleSizeto
truein
your
BitmapFactory.Optionsobject.
For example, an image with resolution 2048x1536 that is decoded with an
inSampleSizeof
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 sample size value that is a power of two based on a target width and height:
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) { final int halfHeight = height / 2; final int halfWidth = width / 2; // Calculate the largest inSampleSize value that is a power of 2 and keeps both // height and width larger than the requested height and width. while ((halfHeight / inSampleSize) > reqHeight && (halfWidth / inSampleSize) > reqWidth) { inSampleSize *= 2; } } return inSampleSize; }
Note: A power of two value is calculated because the decoder uses a final value by rounding down to the nearest power of two, as per the
inSampleSizedocumentation.
To use this method, first decode with
inJustDecodeBoundsset
to
true, pass the options through and then decode again using the new
inSampleSizevalue
and
inJustDecodeBoundsset
to
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
ImageViewthat
displays a 100x100 pixel thumbnail, as shown in the following example code:
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
, int, int, android.graphics.BitmapFactory.Options)]BitmapFactory.decode*method
as needed.
NEXT: PROCESSING
BITMAPS OFF THE UI THREAD
相关文章推荐
- Displaying Bitmaps Efficiently (一)-----Loading Large Bitmaps Efficiently
- Displaying Bitmaps Efficiently (一)-----Loading Large Bitmaps Efficiently(二)
- Loading Large Bitmaps Efficiently高效加载大图(Android开发文档翻译一)
- Loading Large Bitmaps Efficiently 高效地加载大位图
- 2 Loading Large Bitmaps Efficiently(高效加载大尺寸位图)
- Training图像篇之一:Loading Large Bitmaps Efficiently
- Android有效的展示图片 (一) Loading Large Bitmaps Efficiently 有效的下载大图片
- nullnullLoading Large Bitmaps Efficiently 有效的处理较大的位图
- Loading Large Bitmaps Efficiently
- Loading Large Bitmaps Efficiently 有效的加载大图片
- 有效地加载大位图文件-Loading Large Bitmaps Efficiently
- Loading Large Bitmaps Efficiently
- 有效地加载大尺寸位图(Loading Large Bitmaps Efficiently)
- Loading Large Bitmaps Efficiently-高效的加载大位图
- Loading Large Bitmaps Efficiently [有效率的加载大尺寸的位图]
- Loading Large Bitmaps Efficiently
- [Developer Android] Loading Large Bitmaps Efficiently
- Loading Large Bitmaps Efficiently
- Loading Large Bitmaps Efficiently(官方文档)
- Loading Large Bitmaps Efficiently