DecodeTask.java revision 40662f4b39e795d9c64502b13036e7c37fa2d373
193a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein/* 293a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein * Copyright (C) 2013 The Android Open Source Project 393a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein * 493a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein * Licensed under the Apache License, Version 2.0 (the "License"); 593a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein * you may not use this file except in compliance with the License. 693a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein * You may obtain a copy of the License at 793a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein * 893a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein * http://www.apache.org/licenses/LICENSE-2.0 993a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein * 1093a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein * Unless required by applicable law or agreed to in writing, software 1193a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein * distributed under the License is distributed on an "AS IS" BASIS, 1293a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1393a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein * See the License for the specific language governing permissions and 1493a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein * limitations under the License. 1593a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein */ 1693a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein 1793a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzsteinpackage com.android.bitmap; 1893a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein 1993a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzsteinimport android.content.res.AssetFileDescriptor; 2093a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzsteinimport android.graphics.Bitmap; 2193a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzsteinimport android.graphics.BitmapFactory; 2293a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzsteinimport android.graphics.BitmapRegionDecoder; 2393a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzsteinimport android.graphics.Rect; 2493a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzsteinimport android.os.AsyncTask; 2593a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzsteinimport android.util.Log; 2693a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein 2793a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzsteinimport com.android.bitmap.util.BitmapUtils; 2893a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzsteinimport com.android.bitmap.util.Exif; 2993a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzsteinimport com.android.bitmap.util.RectUtils; 3093a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzsteinimport com.android.bitmap.util.Trace; 3193a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein 3293a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzsteinimport java.io.IOException; 3393a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzsteinimport java.io.InputStream; 3493a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein 3593a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein/** 3693a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein * Decodes an image from either a file descriptor or input stream on a worker thread. After the 3793a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein * decode is complete, even if the task is cancelled, the result is placed in the given cache. 3893a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein * A {@link DecodeCallback} client may be notified on decode begin and completion. 3993a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein * <p> 4093a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein * This class uses {@link BitmapRegionDecoder} when possible to minimize unnecessary decoding 4193a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein * and allow bitmap reuse on Jellybean 4.1 and later. 4293a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein * <p> 4393a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein * GIFs are supported, but their decode does not reuse bitmaps at all. The resulting 4493a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein * {@link ReusableBitmap} will be marked as not reusable 4593a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein * ({@link ReusableBitmap#isEligibleForPooling()} will return false). 4693a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein */ 4793a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzsteinpublic class DecodeTask extends AsyncTask<Void, Void, ReusableBitmap> { 4893a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein 4940662f4b39e795d9c64502b13036e7c37fa2d373Sam Blitzstein private final RequestKey mKey; 5093a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein private final int mDestW; 5193a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein private final int mDestH; 5293a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein private final DecodeCallback mDecodeCallback; 5393a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein private final BitmapCache mCache; 5493a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein private final BitmapFactory.Options mOpts = new BitmapFactory.Options(); 5593a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein 5693a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein private ReusableBitmap mInBitmap = null; 5793a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein 5893a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein private static final boolean CROP_DURING_DECODE = true; 5993a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein 6093a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein private static final String TAG = DecodeTask.class.getSimpleName(); 6193a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein private static final boolean DEBUG = false; 6293a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein 6393a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein /** 6493a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein * Callback interface for clients to be notified of decode state changes and completion. 6593a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein */ 6693a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein public interface DecodeCallback { 6793a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein /** 6893a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein * Notifies that the async task's work is about to begin. Up until this point, the task 6993a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein * may have been preempted by the scheduler or queued up by a bottlenecked executor. 7093a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein * <p> 7193a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein * N.B. this method runs on the UI thread. 7293a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein */ 7340662f4b39e795d9c64502b13036e7c37fa2d373Sam Blitzstein void onDecodeBegin(RequestKey key); 7493a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein /** 7593a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein * The task is now complete and the ReusableBitmap is available for use. Clients should 7693a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein * double check that the request matches what the client is expecting. 7793a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein */ 7840662f4b39e795d9c64502b13036e7c37fa2d373Sam Blitzstein void onDecodeComplete(RequestKey key, ReusableBitmap result); 7993a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein /** 8040662f4b39e795d9c64502b13036e7c37fa2d373Sam Blitzstein * The task has been canceled, and {@link #onDecodeComplete(RequestKey, ReusableBitmap)} 8140662f4b39e795d9c64502b13036e7c37fa2d373Sam Blitzstein * will not be called. 8293a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein */ 8340662f4b39e795d9c64502b13036e7c37fa2d373Sam Blitzstein void onDecodeCancel(RequestKey key); 8493a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein } 8593a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein 8640662f4b39e795d9c64502b13036e7c37fa2d373Sam Blitzstein public DecodeTask(RequestKey key, int w, int h, DecodeCallback view, 8793a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein BitmapCache cache) { 8893a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein mKey = key; 8993a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein mDestW = w; 9093a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein mDestH = h; 9193a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein mDecodeCallback = view; 9293a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein mCache = cache; 9393a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein } 9493a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein 9593a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein @Override 9693a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein protected ReusableBitmap doInBackground(Void... params) { 9793a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein // enqueue the 'onDecodeBegin' signal on the main thread 9893a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein publishProgress(); 9993a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein 10093a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein return decode(); 10193a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein } 10293a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein 10393a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein public ReusableBitmap decode() { 10493a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein if (isCancelled()) { 10593a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein return null; 10693a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein } 10793a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein 10893a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein ReusableBitmap result = null; 10993a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein AssetFileDescriptor fd = null; 11093a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein InputStream in = null; 11193a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein try { 11293a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein final boolean isJellyBeanOrAbove = android.os.Build.VERSION.SDK_INT 11393a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein >= android.os.Build.VERSION_CODES.JELLY_BEAN; 11493a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein // This blocks during fling when the pool is empty. We block early to avoid jank. 11593a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein if (isJellyBeanOrAbove) { 11693a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein Trace.beginSection("poll for reusable bitmap"); 11793a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein mInBitmap = mCache.poll(); 11893a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein Trace.endSection(); 11993a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein 12093a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein if (isCancelled()) { 12193a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein return null; 12293a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein } 12393a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein } 12493a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein 12593a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein Trace.beginSection("create fd and stream"); 12693a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein fd = mKey.createFd(); 12793a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein Trace.endSection(); 12893a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein if (fd == null) { 12993a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein in = reset(in); 13093a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein if (in == null) { 13193a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein return null; 13293a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein } 13393a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein } 13493a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein 13593a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein Trace.beginSection("get bytesize"); 13693a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein final long byteSize; 13793a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein if (fd != null) { 13893a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein byteSize = fd.getLength(); 13993a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein } else { 14093a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein byteSize = -1; 14193a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein } 14293a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein Trace.endSection(); 14393a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein 14493a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein Trace.beginSection("get orientation"); 14593a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein final int orientation; 14693a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein if (mKey.hasOrientationExif()) { 14793a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein if (fd != null) { 14893a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein // Creating an input stream from the file descriptor makes it useless 14993a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein // afterwards. 15093a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein Trace.beginSection("create fd and stream"); 15193a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein final AssetFileDescriptor orientationFd = mKey.createFd(); 15293a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein in = orientationFd.createInputStream(); 15393a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein Trace.endSection(); 15493a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein } 15593a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein orientation = Exif.getOrientation(in, byteSize); 15693a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein if (fd != null) { 15793a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein try { 15893a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein // Close the temporary file descriptor. 15993a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein in.close(); 16093a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein } catch (IOException ignored) { 16193a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein } 16293a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein } 16393a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein } else { 16493a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein orientation = 0; 16593a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein } 16693a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein final boolean isNotRotatedOr180 = orientation == 0 || orientation == 180; 16793a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein Trace.endSection(); 16893a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein 16993a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein if (orientation != 0) { 17093a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein // disable inBitmap-- bitmap reuse doesn't work with different decode regions due 17193a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein // to orientation 17293a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein if (mInBitmap != null) { 17393a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein mCache.offer(mInBitmap); 17493a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein mInBitmap = null; 17593a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein mOpts.inBitmap = null; 17693a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein } 17793a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein } 17893a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein 17993a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein if (isCancelled()) { 18093a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein return null; 18193a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein } 18293a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein 18393a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein if (fd == null) { 18493a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein in = reset(in); 18593a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein if (in == null) { 18693a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein return null; 18793a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein } 18893a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein } 18993a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein 19093a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein Trace.beginSection("decodeBounds"); 19193a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein mOpts.inJustDecodeBounds = true; 19293a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein if (fd != null) { 19393a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein BitmapFactory.decodeFileDescriptor(fd.getFileDescriptor(), null, mOpts); 19493a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein } else { 19593a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein BitmapFactory.decodeStream(in, null, mOpts); 19693a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein } 19793a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein Trace.endSection(); 19893a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein 19993a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein if (isCancelled()) { 20093a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein return null; 20193a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein } 20293a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein 20393a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein // We want to calculate the sample size "as if" the orientation has been corrected. 20493a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein final int srcW, srcH; // Orientation corrected. 20593a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein if (isNotRotatedOr180) { 20693a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein srcW = mOpts.outWidth; 20793a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein srcH = mOpts.outHeight; 20893a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein } else { 20993a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein srcW = mOpts.outHeight; 21093a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein srcH = mOpts.outWidth; 21193a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein } 21293a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein mOpts.inSampleSize = calculateSampleSize(srcW, srcH, mDestW, mDestH); 21393a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein mOpts.inJustDecodeBounds = false; 21493a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein mOpts.inMutable = true; 21593a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein if (isJellyBeanOrAbove && orientation == 0) { 21693a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein if (mInBitmap == null) { 21793a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein if (DEBUG) { 21893a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein Log.e(TAG, "decode thread wants a bitmap. cache dump:\n" 21993a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein + mCache.toDebugString()); 22093a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein } 22193a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein Trace.beginSection("create reusable bitmap"); 22293a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein mInBitmap = new ReusableBitmap(Bitmap.createBitmap(mDestW, mDestH, 22393a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein Bitmap.Config.ARGB_8888)); 22493a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein Trace.endSection(); 22593a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein 22693a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein if (isCancelled()) { 22793a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein return null; 22893a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein } 22993a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein 23093a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein if (DEBUG) { 23193a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein Log.e(TAG, "*** allocated new bitmap in decode thread: " 23293a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein + mInBitmap + " key=" + mKey); 23393a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein } 23493a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein } else { 23593a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein if (DEBUG) { 23693a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein Log.e(TAG, "*** reusing existing bitmap in decode thread: " 23793a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein + mInBitmap + " key=" + mKey); 23893a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein } 23993a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein 24093a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein } 24193a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein mOpts.inBitmap = mInBitmap.bmp; 24293a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein } 24393a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein 24493a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein if (isCancelled()) { 24593a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein return null; 24693a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein } 24793a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein 24893a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein if (fd == null) { 24993a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein in = reset(in); 25093a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein if (in == null) { 25193a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein return null; 25293a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein } 25393a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein } 25493a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein 25593a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein Bitmap decodeResult = null; 25693a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein final Rect srcRect = new Rect(); // Not orientation corrected. True coordinates. 25793a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein if (CROP_DURING_DECODE) { 25893a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein try { 25993a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein Trace.beginSection("decodeCropped" + mOpts.inSampleSize); 26093a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein decodeResult = decodeCropped(fd, in, orientation, srcRect); 26193a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein } catch (IOException e) { 26293a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein // fall through to below and try again with the non-cropping decoder 26393a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein e.printStackTrace(); 26493a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein } finally { 26593a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein Trace.endSection(); 26693a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein } 26793a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein 26893a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein if (isCancelled()) { 26993a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein return null; 27093a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein } 27193a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein } 27293a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein 27393a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein //noinspection PointlessBooleanExpression 27493a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein if (!CROP_DURING_DECODE || (decodeResult == null && !isCancelled())) { 27593a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein try { 27693a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein Trace.beginSection("decode" + mOpts.inSampleSize); 27793a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein // disable inBitmap-- bitmap reuse doesn't work well below K 27893a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein if (mInBitmap != null) { 27993a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein mCache.offer(mInBitmap); 28093a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein mInBitmap = null; 28193a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein mOpts.inBitmap = null; 28293a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein } 28393a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein decodeResult = decode(fd, in); 28493a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein } catch (IllegalArgumentException e) { 28593a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein Log.e(TAG, "decode failed: reason='" + e.getMessage() + "' ss=" 28693a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein + mOpts.inSampleSize); 28793a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein 28893a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein if (mOpts.inSampleSize > 1) { 28993a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein // try again with ss=1 29093a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein mOpts.inSampleSize = 1; 29193a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein decodeResult = decode(fd, in); 29293a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein } 29393a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein } finally { 29493a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein Trace.endSection(); 29593a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein } 29693a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein 29793a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein if (isCancelled()) { 29893a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein return null; 29993a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein } 30093a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein } 30193a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein 30293a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein if (decodeResult == null) { 30393a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein return null; 30493a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein } 30593a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein 30693a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein if (mInBitmap != null) { 30793a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein result = mInBitmap; 30893a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein // srcRect is non-empty when using the cropping BitmapRegionDecoder codepath 30993a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein if (!srcRect.isEmpty()) { 31093a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein result.setLogicalWidth((srcRect.right - srcRect.left) / mOpts.inSampleSize); 31193a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein result.setLogicalHeight( 31293a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein (srcRect.bottom - srcRect.top) / mOpts.inSampleSize); 31393a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein } else { 31493a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein result.setLogicalWidth(mOpts.outWidth); 31593a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein result.setLogicalHeight(mOpts.outHeight); 31693a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein } 31793a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein } else { 31893a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein // no mInBitmap means no pooling 31993a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein result = new ReusableBitmap(decodeResult, false /* reusable */); 32093a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein if (isNotRotatedOr180) { 32193a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein result.setLogicalWidth(decodeResult.getWidth()); 32293a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein result.setLogicalHeight(decodeResult.getHeight()); 32393a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein } else { 32493a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein result.setLogicalWidth(decodeResult.getHeight()); 32593a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein result.setLogicalHeight(decodeResult.getWidth()); 32693a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein } 32793a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein } 32893a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein result.setOrientation(orientation); 32993a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein } catch (Exception e) { 33093a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein e.printStackTrace(); 33193a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein } finally { 33293a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein if (fd != null) { 33393a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein try { 33493a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein fd.close(); 33593a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein } catch (IOException ignored) { 33693a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein } 33793a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein } 33893a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein if (in != null) { 33993a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein try { 34093a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein in.close(); 34193a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein } catch (IOException ignored) { 34293a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein } 34393a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein } 34493a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein if (result != null) { 34593a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein result.acquireReference(); 34693a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein mCache.put(mKey, result); 34793a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein if (DEBUG) { 34893a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein Log.d(TAG, "placed result in cache: key=" + mKey + " bmp=" 34993a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein + result + " cancelled=" + isCancelled()); 35093a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein } 35193a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein } else if (mInBitmap != null) { 35293a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein if (DEBUG) { 35393a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein Log.d(TAG, "placing failed/cancelled bitmap in pool: key=" 35493a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein + mKey + " bmp=" + mInBitmap); 35593a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein } 35693a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein mCache.offer(mInBitmap); 35793a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein } 35893a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein } 35993a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein return result; 36093a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein } 36193a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein 36293a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein private Bitmap decodeCropped(final AssetFileDescriptor fd, final InputStream in, 36393a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein final int orientation, final Rect outSrcRect) throws IOException { 36493a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein final BitmapRegionDecoder brd; 36593a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein if (fd != null) { 36693a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein brd = BitmapRegionDecoder.newInstance(fd.getFileDescriptor(), true /* shareable */); 36793a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein } else { 36893a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein brd = BitmapRegionDecoder.newInstance(in, true /* shareable */); 36993a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein } 37093a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein if (isCancelled()) { 37193a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein brd.recycle(); 37293a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein return null; 37393a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein } 37493a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein 37593a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein // We want to call calculateCroppedSrcRect() on the source rectangle "as if" the 37693a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein // orientation has been corrected. 37793a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein final int srcW, srcH; //Orientation corrected. 37893a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein final boolean isNotRotatedOr180 = orientation == 0 || orientation == 180; 37993a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein if (isNotRotatedOr180) { 38093a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein srcW = mOpts.outWidth; 38193a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein srcH = mOpts.outHeight; 38293a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein } else { 38393a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein srcW = mOpts.outHeight; 38493a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein srcH = mOpts.outWidth; 38593a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein } 38693a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein 38793a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein // Coordinates are orientation corrected. 38893a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein // Center the decode on the top 1/3. 38993a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein BitmapUtils.calculateCroppedSrcRect(srcW, srcH, mDestW, mDestH, mDestH, mOpts.inSampleSize, 39093a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein 1f / 3, true /* absoluteFraction */, 1f, outSrcRect); 39193a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein if (DEBUG) System.out.println("rect for this decode is: " + outSrcRect 39293a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein + " srcW/H=" + srcW + "/" + srcH 39393a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein + " dstW/H=" + mDestW + "/" + mDestH); 39493a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein 39593a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein // calculateCroppedSrcRect() gave us the source rectangle "as if" the orientation has 39693a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein // been corrected. We need to decode the uncorrected source rectangle. Calculate true 39793a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein // coordinates. 39893a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein RectUtils.rotateRectForOrientation(orientation, new Rect(0, 0, srcW, srcH), outSrcRect); 39993a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein 40093a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein final Bitmap result = brd.decodeRegion(outSrcRect, mOpts); 40193a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein brd.recycle(); 40293a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein return result; 40393a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein } 40493a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein 40593a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein /** 40693a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein * Return an input stream that can be read from the beginning using the most efficient way, 40793a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein * given an input stream that may or may not support reset(), or given null. 40893a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein * 40993a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein * The returned input stream may or may not be the same stream. 41093a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein */ 41193a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein private InputStream reset(InputStream in) throws IOException { 41293a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein Trace.beginSection("create stream"); 41393a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein if (in == null) { 41493a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein in = mKey.createInputStream(); 41593a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein } else if (in.markSupported()) { 41693a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein in.reset(); 41793a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein } else { 41893a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein try { 41993a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein in.close(); 42093a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein } catch (IOException ignored) { 42193a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein } 42293a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein in = mKey.createInputStream(); 42393a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein } 42493a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein Trace.endSection(); 42593a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein return in; 42693a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein } 42793a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein 42893a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein private Bitmap decode(AssetFileDescriptor fd, InputStream in) { 42993a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein final Bitmap result; 43093a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein if (fd != null) { 43193a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein result = BitmapFactory.decodeFileDescriptor(fd.getFileDescriptor(), null, mOpts); 43293a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein } else { 43393a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein result = BitmapFactory.decodeStream(in, null, mOpts); 43493a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein } 43593a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein return result; 43693a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein } 43793a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein 43893a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein private static int calculateSampleSize(int srcW, int srcH, int destW, int destH) { 43993a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein int result; 44093a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein 44193a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein final float sz = Math.min((float) srcW / destW, (float) srcH / destH); 44293a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein 44393a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein // round to the nearest power of two, or just truncate 44493a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein final boolean stricter = true; 44593a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein 44693a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein //noinspection ConstantConditions 44793a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein if (stricter) { 44893a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein result = (int) Math.pow(2, (int) (0.5 + (Math.log(sz) / Math.log(2)))); 44993a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein } else { 45093a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein result = (int) sz; 45193a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein } 45293a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein return Math.max(1, result); 45393a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein } 45493a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein 45593a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein public void cancel() { 45693a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein cancel(true); 45793a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein mOpts.requestCancelDecode(); 45893a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein } 45993a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein 46093a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein @Override 46193a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein protected void onProgressUpdate(Void... values) { 46293a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein mDecodeCallback.onDecodeBegin(mKey); 46393a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein } 46493a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein 46593a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein @Override 46693a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein public void onPostExecute(ReusableBitmap result) { 46793a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein mDecodeCallback.onDecodeComplete(mKey, result); 46893a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein } 46993a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein 47093a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein @Override 47193a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein protected void onCancelled(ReusableBitmap result) { 47293a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein mDecodeCallback.onDecodeCancel(mKey); 47393a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein if (result == null) { 47493a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein return; 47593a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein } 47693a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein 47793a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein result.releaseReference(); 47893a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein if (mInBitmap == null) { 47993a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein // not reusing bitmaps: can recycle immediately 48093a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein result.bmp.recycle(); 48193a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein } 48293a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein } 48393a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein 48493a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein} 485