diff options
author | Sam Judd <judds@google.com> | 2014-10-29 19:18:54 -0700 |
---|---|---|
committer | Sam Judd <judds@google.com> | 2014-10-30 07:05:09 -0700 |
commit | 88868380fb22a5dae89d8664f2daa8c99522bc74 (patch) | |
tree | f17200666f744a85ae99c88df3f798aafac553f6 /library/src/main/java/com | |
parent | b71d633d0fc091f3a4dc5615bb1f3467ca2df618 (diff) | |
download | glide-88868380fb22a5dae89d8664f2daa8c99522bc74.tar.gz |
Use sample size to acquire Bitmaps in Downsampler.
Fixes #224
Diffstat (limited to 'library/src/main/java/com')
-rw-r--r-- | library/src/main/java/com/bumptech/glide/load/resource/bitmap/Downsampler.java | 33 |
1 files changed, 24 insertions, 9 deletions
diff --git a/library/src/main/java/com/bumptech/glide/load/resource/bitmap/Downsampler.java b/library/src/main/java/com/bumptech/glide/load/resource/bitmap/Downsampler.java index e6143197..f5e17e95 100644 --- a/library/src/main/java/com/bumptech/glide/load/resource/bitmap/Downsampler.java +++ b/library/src/main/java/com/bumptech/glide/load/resource/bitmap/Downsampler.java @@ -134,14 +134,7 @@ public abstract class Downsampler implements BitmapDecoder<InputStream> { final int inHeight = inDimens[1]; final int degreesToRotate = TransformationUtils.getExifOrientationDegrees(orientation); - final int sampleSize; - if (degreesToRotate == 90 || degreesToRotate == 270) { - // If we're rotating the image +-90 degrees, we need to downsample accordingly so the image width is - // decreased to near our target's height and the image height is decreased to near our target width. - sampleSize = getSampleSize(inHeight, inWidth, outWidth, outHeight); - } else { - sampleSize = getSampleSize(inWidth, inHeight, outWidth, outHeight); - } + final int sampleSize = getRoundedSampleSize(degreesToRotate, inWidth, inHeight, outWidth, outHeight); final Bitmap downsampled = downsampleWithSize(stream, options, pool, inWidth, inHeight, sampleSize, decodeFormat); @@ -172,6 +165,26 @@ public abstract class Downsampler implements BitmapDecoder<InputStream> { } } + private int getRoundedSampleSize(int degreesToRotate, int inWidth, int inHeight, int outWidth, int outHeight) { + final int exactSampleSize; + if (degreesToRotate == 90 || degreesToRotate == 270) { + // If we're rotating the image +-90 degrees, we need to downsample accordingly so the image width is + // decreased to near our target's height and the image height is decreased to near our target width. + exactSampleSize = getSampleSize(inHeight, inWidth, outWidth, outHeight); + } else { + exactSampleSize = getSampleSize(inWidth, inHeight, outWidth, outHeight); + } + + // BitmapFactory only accepts powers of 2, so it will round down to the nearest power of two that is less than + // or equal to the sample size we provide. Because we need to estimate the final image width and height to + // re-use Bitmaps, we mirror BitmapFactory's calculation here. For bug, see issue #224. For algorithm see + // http://stackoverflow.com/a/17379704/800716. + final int powerOfTwoSampleSize = exactSampleSize == 0 ? 0 : Integer.highestOneBit(exactSampleSize - 1); + + // Although functionally equivalent to 0 for BitmapFactory, 1 is a safer default for our code than 0. + return Math.max(1, powerOfTwoSampleSize); + } + protected Bitmap downsampleWithSize(InputStream is, BitmapFactory.Options options, BitmapPool pool, int inWidth, int inHeight, int sampleSize, DecodeFormat decodeFormat) { // Prior to KitKat, the inBitmap size must exactly match the size of the bitmap we're decoding. @@ -179,8 +192,10 @@ public abstract class Downsampler implements BitmapDecoder<InputStream> { options.inSampleSize = sampleSize; options.inPreferredConfig = config; if ((options.inSampleSize == 1 || Build.VERSION_CODES.KITKAT <= Build.VERSION.SDK_INT) && shouldUsePool(is)) { + int targetWidth = (int) Math.ceil(inWidth / (double) sampleSize); + int targetHeight = (int) Math.ceil(inHeight / (double) sampleSize); // BitmapFactory will clear out the Bitmap before writing to it, so getDirty is safe. - setInBitmap(options, pool.getDirty(inWidth, inHeight, config)); + setInBitmap(options, pool.getDirty(targetWidth, targetHeight, config)); } return decodeStream(is, options); } |