diff options
Diffstat (limited to 'docs/html/training')
-rw-r--r-- | docs/html/training/displaying-bitmaps/cache-bitmap.jd | 4 | ||||
-rw-r--r-- | docs/html/training/displaying-bitmaps/load-bitmap.jd | 27 | ||||
-rw-r--r-- | docs/html/training/displaying-bitmaps/manage-memory.jd | 60 |
3 files changed, 53 insertions, 38 deletions
diff --git a/docs/html/training/displaying-bitmaps/cache-bitmap.jd b/docs/html/training/displaying-bitmaps/cache-bitmap.jd index ad084c2..ff9c3a0 100644 --- a/docs/html/training/displaying-bitmaps/cache-bitmap.jd +++ b/docs/html/training/displaying-bitmaps/cache-bitmap.jd @@ -188,8 +188,8 @@ appropriate place to store cached images if they are accessed more frequently, f image gallery application.</p> <p>The sample code of this class uses a {@code DiskLruCache} implementation that is pulled from the -<a href="https://android.googlesource.com/platform/libcore/+/master/luni/src/main/java/libcore/io/DiskLruCache.java">Android source</a>. Here’s updated example code that adds a disk cache in addition -to the existing memory cache:</p> +<a href="https://android.googlesource.com/platform/libcore/+/jb-mr2-release/luni/src/main/java/libcore/io/DiskLruCache.java">Android source</a>. +Here’s updated example code that adds a disk cache in addition to the existing memory cache:</p> <pre> private DiskLruCache mDiskLruCache; diff --git a/docs/html/training/displaying-bitmaps/load-bitmap.jd b/docs/html/training/displaying-bitmaps/load-bitmap.jd index 633ffd2..938901f 100644 --- a/docs/html/training/displaying-bitmaps/load-bitmap.jd +++ b/docs/html/training/displaying-bitmaps/load-bitmap.jd @@ -97,7 +97,8 @@ android.graphics.BitmapFactory.Options} object. For example, an image with resol is decoded with an {@link android.graphics.BitmapFactory.Options#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 {@link android.graphics.Bitmap.Config ARGB_8888}). Here’s -a method to calculate a the sample size value based on a target width and height:</p> +a method to calculate a sample size value that is a power of two based on a target width and +height:</p> <pre> public static int calculateInSampleSize( @@ -107,26 +108,26 @@ public static int calculateInSampleSize( final int width = options.outWidth; int inSampleSize = 1; - if (height > reqHeight || width > reqWidth) { + 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); + final int halfHeight = height / 2; + final int halfWidth = width / 2; - // 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; + // 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; } </pre> -<p class="note"><strong>Note:</strong> Using powers of 2 for {@link -android.graphics.BitmapFactory.Options#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.</p> +<p class="note"><strong>Note:</strong> 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 {@link +android.graphics.BitmapFactory.Options#inSampleSize} documentation.</p> <p>To use this method, first decode with {@link android.graphics.BitmapFactory.Options#inJustDecodeBounds} set to {@code true}, pass the options diff --git a/docs/html/training/displaying-bitmaps/manage-memory.jd b/docs/html/training/displaying-bitmaps/manage-memory.jd index 60ac2e6..0e1279e 100644 --- a/docs/html/training/displaying-bitmaps/manage-memory.jd +++ b/docs/html/training/displaying-bitmaps/manage-memory.jd @@ -56,7 +56,7 @@ bitmap is stored in native memory. It is separate from the bitmap itself, which is stored in the Dalvik heap. The pixel data in native memory is not released in a predictable manner, potentially causing an application to briefly exceed its memory limits and crash. -<strong>As of Android 3.0 (API Level 11), the pixel data is stored on the +<strong>As of Android 3.0 (API level 11), the pixel data is stored on the Dalvik heap along with the associated bitmap.</strong></li> </ul> @@ -140,27 +140,16 @@ private synchronized boolean hasValidBitmap() { <h2 id="inBitmap">Manage Memory on Android 3.0 and Higher</h2> -<p>Android 3.0 (API Level 11) introduces the +<p>Android 3.0 (API level 11) introduces the {@link android.graphics.BitmapFactory.Options#inBitmap BitmapFactory.Options.inBitmap} field. If this option is set, decode methods that take the {@link android.graphics.BitmapFactory.Options Options} object will attempt to reuse an existing bitmap when loading content. This means that the bitmap's memory is reused, resulting in improved performance, and -removing both memory allocation and de-allocation. There are some caveats in using -{@link android.graphics.BitmapFactory.Options#inBitmap}:</p> -<ul> - <li>The reused bitmap must be of the same size as the source content (to make -sure that the same amount of memory is used), and in JPEG or PNG format -(whether as a resource or as a stream).</li> - - -<li>The {@link android.graphics.Bitmap.Config configuration} of the reused bitmap -overrides the setting of -{@link android.graphics.BitmapFactory.Options#inPreferredConfig}, if set. </li> - - <li>You should always use the returned bitmap of the decode method, -because you can't assume that reusing the bitmap worked (for example, if there is -a size mismatch).</li> +removing both memory allocation and de-allocation. However, there are certain restrictions with how +{@link android.graphics.BitmapFactory.Options#inBitmap} can be used. In particular, before Android +4.4 (API level 19), only equal sized bitmaps are supported. For details, please see the +{@link android.graphics.BitmapFactory.Options#inBitmap} documentation. <h3>Save a bitmap for later use</h3> @@ -283,14 +272,39 @@ protected Bitmap getBitmapFromReusableSet(BitmapFactory.Options options) { satisfies the size criteria to be used for {@link android.graphics.BitmapFactory.Options#inBitmap}:</p> -<pre>private static boolean canUseForInBitmap( +<pre>static boolean canUseForInBitmap( Bitmap candidate, BitmapFactory.Options targetOptions) { - int width = targetOptions.outWidth / targetOptions.inSampleSize; - int height = targetOptions.outHeight / targetOptions.inSampleSize; - // Returns true if "candidate" can be used for inBitmap re-use with - // "targetOptions". - return candidate.getWidth() == width && candidate.getHeight() == height; + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) { + // From Android 4.4 (KitKat) onward we can re-use if the byte size of + // the new bitmap is smaller than the reusable bitmap candidate + // allocation byte count. + int width = targetOptions.outWidth / targetOptions.inSampleSize; + int height = targetOptions.outHeight / targetOptions.inSampleSize; + int byteCount = width * height * getBytesPerPixel(candidate.getConfig()); + return byteCount <= candidate.getAllocationByteCount(); + } + + // On earlier versions, the dimensions must match exactly and the inSampleSize must be 1 + return candidate.getWidth() == targetOptions.outWidth + && candidate.getHeight() == targetOptions.outHeight + && targetOptions.inSampleSize == 1; +} + +/** + * A helper function to return the byte usage per pixel of a bitmap based on its configuration. + */ +static int getBytesPerPixel(Config config) { + if (config == Config.ARGB_8888) { + return 4; + } else if (config == Config.RGB_565) { + return 2; + } else if (config == Config.ARGB_4444) { + return 2; + } else if (config == Config.ALPHA_8) { + return 1; + } + return 1; }</pre> </body> |