Downsampler.java revision e81c2c3c8fe1533de8ba8137ea831a42378b35a9
1f536bbbd4bf2024926574c5ed99b3e6251c6ff44njnpackage com.bumptech.glide.resize.load; 2f536bbbd4bf2024926574c5ed99b3e6251c6ff44njn 3f536bbbd4bf2024926574c5ed99b3e6251c6ff44njnimport static com.bumptech.glide.resize.load.ImageHeaderParser.ImageType; 4f536bbbd4bf2024926574c5ed99b3e6251c6ff44njnimport static com.bumptech.glide.resize.load.ImageHeaderParser.ImageType.PNG_A; 5f536bbbd4bf2024926574c5ed99b3e6251c6ff44njnimport static com.bumptech.glide.resize.load.ImageHeaderParser.ImageType.JPEG; 6f536bbbd4bf2024926574c5ed99b3e6251c6ff44njnimport static com.bumptech.glide.resize.load.ImageHeaderParser.ImageType.PNG; 7f536bbbd4bf2024926574c5ed99b3e6251c6ff44njn 8f536bbbd4bf2024926574c5ed99b3e6251c6ff44njnimport android.annotation.TargetApi; 9f536bbbd4bf2024926574c5ed99b3e6251c6ff44njnimport android.graphics.Bitmap; 10b3a1e4bffbdbbf38304f216af405009868f43628sewardjimport android.graphics.BitmapFactory; 11f536bbbd4bf2024926574c5ed99b3e6251c6ff44njnimport android.os.Build; 12f536bbbd4bf2024926574c5ed99b3e6251c6ff44njnimport android.util.Log; 13f536bbbd4bf2024926574c5ed99b3e6251c6ff44njnimport com.bumptech.glide.resize.RecyclableBufferedInputStream; 14f536bbbd4bf2024926574c5ed99b3e6251c6ff44njnimport com.bumptech.glide.resize.bitmap_recycle.BitmapPool; 15f536bbbd4bf2024926574c5ed99b3e6251c6ff44njnimport java.io.IOException; 16f536bbbd4bf2024926574c5ed99b3e6251c6ff44njnimport java.util.EnumSet; 17f536bbbd4bf2024926574c5ed99b3e6251c6ff44njnimport java.util.Set; 18f536bbbd4bf2024926574c5ed99b3e6251c6ff44njn 19f536bbbd4bf2024926574c5ed99b3e6251c6ff44njn/** 20f536bbbd4bf2024926574c5ed99b3e6251c6ff44njn * A base class with methods for loading and decoding images from InputStreams. 21f536bbbd4bf2024926574c5ed99b3e6251c6ff44njn */ 22f536bbbd4bf2024926574c5ed99b3e6251c6ff44njnpublic abstract class Downsampler { 23f536bbbd4bf2024926574c5ed99b3e6251c6ff44njn private static final String TAG = "Downsampler"; 24f536bbbd4bf2024926574c5ed99b3e6251c6ff44njn 25f536bbbd4bf2024926574c5ed99b3e6251c6ff44njn private static final Set<ImageType> TYPES_THAT_USE_POOL = EnumSet.of(JPEG, PNG_A, PNG); 26f536bbbd4bf2024926574c5ed99b3e6251c6ff44njn private final String id = getClass().toString(); 27f536bbbd4bf2024926574c5ed99b3e6251c6ff44njn 28f536bbbd4bf2024926574c5ed99b3e6251c6ff44njn /** 29f536bbbd4bf2024926574c5ed99b3e6251c6ff44njn * Load and scale the image uniformly (maintaining the image's aspect ratio) so that the dimensions of the image 30f536bbbd4bf2024926574c5ed99b3e6251c6ff44njn * will be greater than or equal to the given width and height. 31f536bbbd4bf2024926574c5ed99b3e6251c6ff44njn * 32f536bbbd4bf2024926574c5ed99b3e6251c6ff44njn */ 33f536bbbd4bf2024926574c5ed99b3e6251c6ff44njn public static Downsampler AT_LEAST = new Downsampler() { 34f536bbbd4bf2024926574c5ed99b3e6251c6ff44njn @Override 35f536bbbd4bf2024926574c5ed99b3e6251c6ff44njn protected int getSampleSize(int inWidth, int inHeight, int outWidth, int outHeight) { 36f536bbbd4bf2024926574c5ed99b3e6251c6ff44njn return Math.min(inHeight / outHeight, inWidth / outWidth); 37f536bbbd4bf2024926574c5ed99b3e6251c6ff44njn } 38f536bbbd4bf2024926574c5ed99b3e6251c6ff44njn }; 39f536bbbd4bf2024926574c5ed99b3e6251c6ff44njn 40f536bbbd4bf2024926574c5ed99b3e6251c6ff44njn /** 41535fb1b49a80f2e880f755ee618381de3e222ddfflorian * Load and scale the image uniformly (maintaining the image's aspect ratio) so that the dimensions of the image 42f536bbbd4bf2024926574c5ed99b3e6251c6ff44njn * will be less than or equal to the given width and height. 43265aae7509903e05e907ff0ea4eb2da9446b9763njn * 448eb8bab992e3998c33770b0cdb16059a8b918a06sewardj */ 456e340c7a2c09971ac5ead854c40bbc0491b67636sewardj public static Downsampler AT_MOST = new Downsampler() { 46af839f52d74df156d655201a889954133ab01be7njn @Override 47af839f52d74df156d655201a889954133ab01be7njn protected int getSampleSize(int inWidth, int inHeight, int outWidth, int outHeight) { 48f1c91e04aa395a74092e26da815dbde4d769ee0asewardj return Math.max(inHeight / outHeight, inWidth / outWidth); 498eb8bab992e3998c33770b0cdb16059a8b918a06sewardj } 506e340c7a2c09971ac5ead854c40bbc0491b67636sewardj }; 51af839f52d74df156d655201a889954133ab01be7njn 52af839f52d74df156d655201a889954133ab01be7njn /** 53f1c91e04aa395a74092e26da815dbde4d769ee0asewardj * Load the image at its original size 54f1c91e04aa395a74092e26da815dbde4d769ee0asewardj * 556e340c7a2c09971ac5ead854c40bbc0491b67636sewardj */ 56af839f52d74df156d655201a889954133ab01be7njn public static Downsampler NONE = new Downsampler() { 57af839f52d74df156d655201a889954133ab01be7njn @Override 58f1c91e04aa395a74092e26da815dbde4d769ee0asewardj protected int getSampleSize(int inWidth, int inHeight, int outWidth, int outHeight) { 59cae0cc22b83ffb260ee8379e92099c5a701944cbcarll return 0; 602c48c7b0a453d32375a4df17e153011b797ef28csewardj } 612c48c7b0a453d32375a4df17e153011b797ef28csewardj }; 622c48c7b0a453d32375a4df17e153011b797ef28csewardj 63f1c91e04aa395a74092e26da815dbde4d769ee0asewardj private static final int MARK_POSITION = 5 * 1024 * 1024; //5mb, max possible, not preallocated 64582d58245637ab05272d89fb94b12fd0f18fa0f8carll 65582d58245637ab05272d89fb94b12fd0f18fa0f8carll /** 66582d58245637ab05272d89fb94b12fd0f18fa0f8carll * Load the image for the given InputStream. If a recycled Bitmap whose dimensions exactly match those of the image 67582d58245637ab05272d89fb94b12fd0f18fa0f8carll * for the given InputStream is available, the operation is much less expensive in terms of memory. 68582d58245637ab05272d89fb94b12fd0f18fa0f8carll * 6959570ffbe31930ab4d678754daaeec0715117a3dsewardj * Note - this method will throw an exception of a Bitmap with dimensions not matching those of the image for the 7059570ffbe31930ab4d678754daaeec0715117a3dsewardj * given InputStream is provided. 7159570ffbe31930ab4d678754daaeec0715117a3dsewardj * 7259570ffbe31930ab4d678754daaeec0715117a3dsewardj * @param bis An InputStream to the data for the image 7359570ffbe31930ab4d678754daaeec0715117a3dsewardj * @param options The options to pass to {@link BitmapFactory#decodeStream(java.io.InputStream, android.graphics.Rect, android.graphics.BitmapFactory.Options)} 74f0c1250e324f6684757c6a15545366447ef1d64fsewardj * @param pool A pool of recycled bitmaps 75f0c1250e324f6684757c6a15545366447ef1d64fsewardj * @param outWidth The width the final image should be close to 76f0c1250e324f6684757c6a15545366447ef1d64fsewardj * @param outHeight The height the final image should be close to 77f0c1250e324f6684757c6a15545366447ef1d64fsewardj * @return A new bitmap containing the image from the given InputStream, or recycle if recycle is not null 78f0c1250e324f6684757c6a15545366447ef1d64fsewardj */ 79f76d27a697a7b0bf3b84490baf60623fc96a23afnjn public Bitmap downsample(RecyclableBufferedInputStream bis, BitmapFactory.Options options, BitmapPool pool, int outWidth, int outHeight) { 80f76d27a697a7b0bf3b84490baf60623fc96a23afnjn bis.mark(MARK_POSITION); 81f76d27a697a7b0bf3b84490baf60623fc96a23afnjn int orientation = 0; 82f76d27a697a7b0bf3b84490baf60623fc96a23afnjn try { 83f76d27a697a7b0bf3b84490baf60623fc96a23afnjn orientation = new ImageHeaderParser(bis).getOrientation(); 84b5b87408c0c99f9f6938d8cd921e2a5f420577c4sewardj } catch (IOException e) { 85b5b87408c0c99f9f6938d8cd921e2a5f420577c4sewardj e.printStackTrace(); 86b5b87408c0c99f9f6938d8cd921e2a5f420577c4sewardj } 87b5b87408c0c99f9f6938d8cd921e2a5f420577c4sewardj try { 88b5b87408c0c99f9f6938d8cd921e2a5f420577c4sewardj bis.reset(); 895db15403e889d4db339b342bc2a824ef0bfaa654sewardj } catch (IOException e) { 905db15403e889d4db339b342bc2a824ef0bfaa654sewardj e.printStackTrace(); 915db15403e889d4db339b342bc2a824ef0bfaa654sewardj } 925db15403e889d4db339b342bc2a824ef0bfaa654sewardj 935db15403e889d4db339b342bc2a824ef0bfaa654sewardj final int[] inDimens = getDimensions(bis, options); 945db15403e889d4db339b342bc2a824ef0bfaa654sewardj final int inWidth = inDimens[0]; 955db15403e889d4db339b342bc2a824ef0bfaa654sewardj final int inHeight = inDimens[1]; 965db15403e889d4db339b342bc2a824ef0bfaa654sewardj 975db15403e889d4db339b342bc2a824ef0bfaa654sewardj final int degreesToRotate = ImageResizer.getExifOrientationDegrees(orientation); 985db15403e889d4db339b342bc2a824ef0bfaa654sewardj final int sampleSize; 995db15403e889d4db339b342bc2a824ef0bfaa654sewardj if (degreesToRotate == 90 || degreesToRotate == 270) { 1004df0bfc0614379192c780c944415dc420d9cfe8epetarj //if we're rotating the image +-90 degrees, we need to downsample accordingly so the image width is 1014df0bfc0614379192c780c944415dc420d9cfe8epetarj //decreased to near our target's height and the image height is decreased to near our target width 1024df0bfc0614379192c780c944415dc420d9cfe8epetarj sampleSize = getSampleSize(inHeight, inWidth, outWidth, outHeight); 1034df0bfc0614379192c780c944415dc420d9cfe8epetarj } else { 1044df0bfc0614379192c780c944415dc420d9cfe8epetarj sampleSize = getSampleSize(inWidth, inHeight, outWidth, outHeight); 1054df0bfc0614379192c780c944415dc420d9cfe8epetarj } 1064df0bfc0614379192c780c944415dc420d9cfe8epetarj 1074df0bfc0614379192c780c944415dc420d9cfe8epetarj final Bitmap downsampled = downsampleWithSize(bis, options, pool, inWidth, inHeight, sampleSize); 1084df0bfc0614379192c780c944415dc420d9cfe8epetarj final Bitmap rotated = ImageResizer.rotateImageExif(downsampled, pool, orientation); 1094df0bfc0614379192c780c944415dc420d9cfe8epetarj 1104df0bfc0614379192c780c944415dc420d9cfe8epetarj if (downsampled != rotated && !pool.put(downsampled)) { 111112711afefcfcd43680c7c4aa8d38ef180e8811esewardj downsampled.recycle(); 112112711afefcfcd43680c7c4aa8d38ef180e8811esewardj } 113112711afefcfcd43680c7c4aa8d38ef180e8811esewardj 114112711afefcfcd43680c7c4aa8d38ef180e8811esewardj return rotated; 115112711afefcfcd43680c7c4aa8d38ef180e8811esewardj } 116112711afefcfcd43680c7c4aa8d38ef180e8811esewardj 117112711afefcfcd43680c7c4aa8d38ef180e8811esewardj protected Bitmap downsampleWithSize(RecyclableBufferedInputStream bis, BitmapFactory.Options options, BitmapPool pool, int inWidth, int inHeight, int sampleSize) { 118112711afefcfcd43680c7c4aa8d38ef180e8811esewardj if (sampleSize > 1) { 119f536bbbd4bf2024926574c5ed99b3e6251c6ff44njn options.inSampleSize = sampleSize; 120f1c91e04aa395a74092e26da815dbde4d769ee0asewardj } else { 121f536bbbd4bf2024926574c5ed99b3e6251c6ff44njn // cannot reuse bitmaps when decoding images that are not PNG or JPG. 122f536bbbd4bf2024926574c5ed99b3e6251c6ff44njn // look at : https://groups.google.com/forum/#!msg/android-developers/Mp0MFVFi1Fo/e8ZQ9FGdWdEJ 123f536bbbd4bf2024926574c5ed99b3e6251c6ff44njn if (shouldUsePool(bis)) { 124af839f52d74df156d655201a889954133ab01be7njn setInBitmap(options, pool.get(inWidth, inHeight, getConfig(bis))); 125af839f52d74df156d655201a889954133ab01be7njn } 126af839f52d74df156d655201a889954133ab01be7njn } 127f536bbbd4bf2024926574c5ed99b3e6251c6ff44njn return decodeStream(bis, options); 128af839f52d74df156d655201a889954133ab01be7njn } 129af839f52d74df156d655201a889954133ab01be7njn 130af839f52d74df156d655201a889954133ab01be7njn private boolean shouldUsePool(RecyclableBufferedInputStream bis) { 13185665ca6fa29dd64754dabe50eb98f25896e752acerion bis.mark(1024); 132af839f52d74df156d655201a889954133ab01be7njn try { 133af839f52d74df156d655201a889954133ab01be7njn final ImageType type = new ImageHeaderParser(bis).getType(); 134af839f52d74df156d655201a889954133ab01be7njn return TYPES_THAT_USE_POOL.contains(type); 135cae0cc22b83ffb260ee8379e92099c5a701944cbcarll } catch (IOException e) { 1362c48c7b0a453d32375a4df17e153011b797ef28csewardj e.printStackTrace(); 1372c48c7b0a453d32375a4df17e153011b797ef28csewardj } finally { 1382c48c7b0a453d32375a4df17e153011b797ef28csewardj try { 13959570ffbe31930ab4d678754daaeec0715117a3dsewardj bis.reset(); 1401dbd3376656236debf5d35a9b5d8a507a6c307f0sewardj } catch (IOException e) { 14159570ffbe31930ab4d678754daaeec0715117a3dsewardj e.printStackTrace(); 14259570ffbe31930ab4d678754daaeec0715117a3dsewardj } 143f0c1250e324f6684757c6a15545366447ef1d64fsewardj } 144f0c1250e324f6684757c6a15545366447ef1d64fsewardj return false; 1450345188cc1524a809b8d7fe8785e1da098d9cbe4sewardj } 1460345188cc1524a809b8d7fe8785e1da098d9cbe4sewardj 147b5b87408c0c99f9f6938d8cd921e2a5f420577c4sewardj private Bitmap.Config getConfig(RecyclableBufferedInputStream bis) { 148b5b87408c0c99f9f6938d8cd921e2a5f420577c4sewardj Bitmap.Config result = Bitmap.Config.RGB_565; 149b5b87408c0c99f9f6938d8cd921e2a5f420577c4sewardj bis.mark(1024); //we probably only need 25, but this is safer (particularly since the buffer size is > 1024) 150b5b87408c0c99f9f6938d8cd921e2a5f420577c4sewardj try { 151ccb843b2ba2c176708bfa1764ca8e4db31722e90florian result = new ImageHeaderParser(bis).hasAlpha() ? Bitmap.Config.ARGB_8888 : Bitmap.Config.RGB_565; 1525db15403e889d4db339b342bc2a824ef0bfaa654sewardj } catch (IOException e) { 1535db15403e889d4db339b342bc2a824ef0bfaa654sewardj e.printStackTrace(); 1545db15403e889d4db339b342bc2a824ef0bfaa654sewardj } finally { 1555db15403e889d4db339b342bc2a824ef0bfaa654sewardj try { 1564df0bfc0614379192c780c944415dc420d9cfe8epetarj bis.reset(); 1574df0bfc0614379192c780c944415dc420d9cfe8epetarj } catch (IOException e) { 1584df0bfc0614379192c780c944415dc420d9cfe8epetarj e.printStackTrace(); 1594df0bfc0614379192c780c944415dc420d9cfe8epetarj } 160112711afefcfcd43680c7c4aa8d38ef180e8811esewardj } 161112711afefcfcd43680c7c4aa8d38ef180e8811esewardj return result; 162112711afefcfcd43680c7c4aa8d38ef180e8811esewardj } 163112711afefcfcd43680c7c4aa8d38ef180e8811esewardj 164f536bbbd4bf2024926574c5ed99b3e6251c6ff44njn /** 165f536bbbd4bf2024926574c5ed99b3e6251c6ff44njn * Get some id that uniquely identifies the downsample for use as part of a cache key 166f536bbbd4bf2024926574c5ed99b3e6251c6ff44njn * @return A unique String 167f536bbbd4bf2024926574c5ed99b3e6251c6ff44njn */ 1687821e2ed55ac6c2303eb51a06bafd5baada2423dsewardj public String getId() { 169f536bbbd4bf2024926574c5ed99b3e6251c6ff44njn return id; 170af839f52d74df156d655201a889954133ab01be7njn } 171cda2f0fbda4c4b2644babc830244be8aed95de1dnjn 1728eb8bab992e3998c33770b0cdb16059a8b918a06sewardj /** 173ccb843b2ba2c176708bfa1764ca8e4db31722e90florian * Determine the amount of downsampling to use for a load given the dimensions of the image to be downsampled and 174f536bbbd4bf2024926574c5ed99b3e6251c6ff44njn * the dimensions of the view/target the image will be displayed in. 1757821e2ed55ac6c2303eb51a06bafd5baada2423dsewardj * 176e2d1e670d412ff85c824ba5c043161816b9e26bdsewardj * @see BitmapFactory.Options#inSampleSize 1771dbd3376656236debf5d35a9b5d8a507a6c307f0sewardj * 1781dbd3376656236debf5d35a9b5d8a507a6c307f0sewardj * @param inWidth The width of the image to be downsampled 1791dbd3376656236debf5d35a9b5d8a507a6c307f0sewardj * @param inHeight The height of the image to be downsampled 1801dbd3376656236debf5d35a9b5d8a507a6c307f0sewardj * @param outWidth The width of the view/target the image will be displayed in 1811dbd3376656236debf5d35a9b5d8a507a6c307f0sewardj * @param outHeight The height of the view/target the imag will be displayed in 1821dbd3376656236debf5d35a9b5d8a507a6c307f0sewardj * @return An integer to pass in to {@link BitmapFactory#decodeStream(java.io.InputStream, android.graphics.Rect, android.graphics.BitmapFactory.Options)} 1831dbd3376656236debf5d35a9b5d8a507a6c307f0sewardj */ 1841dbd3376656236debf5d35a9b5d8a507a6c307f0sewardj protected abstract int getSampleSize(int inWidth, int inHeight, int outWidth, int outHeight); 1851dbd3376656236debf5d35a9b5d8a507a6c307f0sewardj 1861dbd3376656236debf5d35a9b5d8a507a6c307f0sewardj /** 1871dbd3376656236debf5d35a9b5d8a507a6c307f0sewardj * A method for getting the dimensions of an image from the given InputStream 1881dbd3376656236debf5d35a9b5d8a507a6c307f0sewardj * 18959570ffbe31930ab4d678754daaeec0715117a3dsewardj * @param bis The InputStream representing the image 19059570ffbe31930ab4d678754daaeec0715117a3dsewardj * @param options The options to pass to {@link BitmapFactory#decodeStream(java.io.InputStream, android.graphics.Rect, android.graphics.BitmapFactory.Options)} 19159570ffbe31930ab4d678754daaeec0715117a3dsewardj * @return an array containing the dimensions of the image in the form {width, height} 19259570ffbe31930ab4d678754daaeec0715117a3dsewardj */ 19359570ffbe31930ab4d678754daaeec0715117a3dsewardj public int[] getDimensions(RecyclableBufferedInputStream bis, BitmapFactory.Options options) { 19459570ffbe31930ab4d678754daaeec0715117a3dsewardj options.inJustDecodeBounds = true; 19559570ffbe31930ab4d678754daaeec0715117a3dsewardj decodeStream(bis, options); 196e2d1e670d412ff85c824ba5c043161816b9e26bdsewardj options.inJustDecodeBounds = false; 197e2d1e670d412ff85c824ba5c043161816b9e26bdsewardj return new int[] { options.outWidth, options.outHeight }; 1981f0d814045aba94e01e62e04e968ca8b970b3d44cerion } 199e2d1e670d412ff85c824ba5c043161816b9e26bdsewardj 200e2d1e670d412ff85c824ba5c043161816b9e26bdsewardj 201e2d1e670d412ff85c824ba5c043161816b9e26bdsewardj private Bitmap decodeStream(RecyclableBufferedInputStream bis, BitmapFactory.Options options) { 202e2d1e670d412ff85c824ba5c043161816b9e26bdsewardj if (options.inJustDecodeBounds) { 203e2d1e670d412ff85c824ba5c043161816b9e26bdsewardj bis.mark(MARK_POSITION); //this is large, but jpeg headers are not size bounded so we need 204e2d1e670d412ff85c824ba5c043161816b9e26bdsewardj //something large enough to minimize the possibility of not being able to fit 205e2d1e670d412ff85c824ba5c043161816b9e26bdsewardj //enough of the header in the buffer to get the image size so that we don't fail 206e2d1e670d412ff85c824ba5c043161816b9e26bdsewardj //to load images. The BufferedInputStream will create a new buffer of 2x the 207e2d1e670d412ff85c824ba5c043161816b9e26bdsewardj //original size each time we use up the buffer space without passing the mark so 208e2d1e670d412ff85c824ba5c043161816b9e26bdsewardj //this is a maximum bound on the buffer size, not a default. Most of the time we 209e2d1e670d412ff85c824ba5c043161816b9e26bdsewardj //won't go past our pre-allocated 16kb 210e2d1e670d412ff85c824ba5c043161816b9e26bdsewardj } 211e2d1e670d412ff85c824ba5c043161816b9e26bdsewardj 212e2d1e670d412ff85c824ba5c043161816b9e26bdsewardj final Bitmap result = BitmapFactory.decodeStream(bis, null, options); 213e2d1e670d412ff85c824ba5c043161816b9e26bdsewardj 214e2d1e670d412ff85c824ba5c043161816b9e26bdsewardj try { 215e2d1e670d412ff85c824ba5c043161816b9e26bdsewardj if (options.inJustDecodeBounds) { 216e2d1e670d412ff85c824ba5c043161816b9e26bdsewardj bis.reset(); 2172c36d4285afacafc10232e2f70978e0519216138sewardj bis.clearMark(); 218e2d1e670d412ff85c824ba5c043161816b9e26bdsewardj } else { 2192c48c7b0a453d32375a4df17e153011b797ef28csewardj bis.close(); 2202c48c7b0a453d32375a4df17e153011b797ef28csewardj } 2212c48c7b0a453d32375a4df17e153011b797ef28csewardj } catch (IOException e) { 2222c48c7b0a453d32375a4df17e153011b797ef28csewardj if (Log.isLoggable(TAG, Log.ERROR)) { 2232c48c7b0a453d32375a4df17e153011b797ef28csewardj Log.e(TAG, "Exception loading inDecodeBounds=" + options.inJustDecodeBounds 2242c48c7b0a453d32375a4df17e153011b797ef28csewardj + " sample=" + options.inSampleSize, e); 225a3551be497f6c4afc5dfbbbcd7c7a955a68fb22bsewardj } 226a3551be497f6c4afc5dfbbbcd7c7a955a68fb22bsewardj } 227a3551be497f6c4afc5dfbbbcd7c7a955a68fb22bsewardj 228a3551be497f6c4afc5dfbbbcd7c7a955a68fb22bsewardj return result; 229a3551be497f6c4afc5dfbbbcd7c7a955a68fb22bsewardj } 2300daa4e31a3407ce0b0db8a90be8dd14bd8eccb35florian 2310daa4e31a3407ce0b0db8a90be8dd14bd8eccb35florian @TargetApi(11) 2320daa4e31a3407ce0b0db8a90be8dd14bd8eccb35florian private static void setInBitmap(BitmapFactory.Options options, Bitmap recycled) { 2330daa4e31a3407ce0b0db8a90be8dd14bd8eccb35florian if (Build.VERSION.SDK_INT >= 11) { 234e2d1e670d412ff85c824ba5c043161816b9e26bdsewardj options.inBitmap = recycled; 235e2d1e670d412ff85c824ba5c043161816b9e26bdsewardj } 236e2d1e670d412ff85c824ba5c043161816b9e26bdsewardj } 237e2d1e670d412ff85c824ba5c043161816b9e26bdsewardj} 238e2d1e670d412ff85c824ba5c043161816b9e26bdsewardj