1f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin/* 2f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin * Copyright (C) 2010 The Android Open Source Project 3f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin * 4f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin * Licensed under the Apache License, Version 2.0 (the "License"); 5f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin * you may not use this file except in compliance with the License. 6f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin * You may obtain a copy of the License at 7f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin * 8f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin * http://www.apache.org/licenses/LICENSE-2.0 9f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin * 10f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin * Unless required by applicable law or agreed to in writing, software 11f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin * distributed under the License is distributed on an "AS IS" BASIS, 12f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin * See the License for the specific language governing permissions and 14f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin * limitations under the License. 15f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin */ 16f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 17f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Linpackage com.android.gallery3d.data; 18f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 19df4763cf8752fb1babc7244fc2be33ed87d3b072Owen Linimport android.annotation.TargetApi; 20f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Linimport android.graphics.Bitmap; 21f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Linimport android.graphics.Bitmap.Config; 22f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Linimport android.graphics.BitmapFactory; 23f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Linimport android.graphics.BitmapFactory.Options; 24f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Linimport android.graphics.BitmapRegionDecoder; 25df4763cf8752fb1babc7244fc2be33ed87d3b072Owen Linimport android.os.Build; 264bb5912e85f6d1bd8a6b78d6d52b4c4da7aeb740Owen Linimport android.util.FloatMath; 274bb5912e85f6d1bd8a6b78d6d52b4c4da7aeb740Owen Lin 28a625b6562d3bfc86465778b336c96fb42064be21Owen Linimport com.android.gallery3d.common.ApiHelper; 294bb5912e85f6d1bd8a6b78d6d52b4c4da7aeb740Owen Linimport com.android.gallery3d.common.BitmapUtils; 304bb5912e85f6d1bd8a6b78d6d52b4c4da7aeb740Owen Linimport com.android.gallery3d.common.Utils; 31f52ceba89962829aa12f5caba131580e8da85880Bobby Georgescuimport com.android.photos.data.GalleryBitmapPool; 32df4763cf8752fb1babc7244fc2be33ed87d3b072Owen Linimport com.android.gallery3d.ui.Log; 334bb5912e85f6d1bd8a6b78d6d52b4c4da7aeb740Owen Linimport com.android.gallery3d.util.ThreadPool.CancelListener; 344bb5912e85f6d1bd8a6b78d6d52b4c4da7aeb740Owen Linimport com.android.gallery3d.util.ThreadPool.JobContext; 35f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 36f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Linimport java.io.FileDescriptor; 37f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Linimport java.io.FileInputStream; 38b289d441eb5af97ac8716479831b1a2c5fe2e878Chih-Chung Changimport java.io.InputStream; 39f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 40f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Linpublic class DecodeUtils { 41df4763cf8752fb1babc7244fc2be33ed87d3b072Owen Lin private static final String TAG = "DecodeUtils"; 42f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 43f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin private static class DecodeCanceller implements CancelListener { 44f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin Options mOptions; 454bb5912e85f6d1bd8a6b78d6d52b4c4da7aeb740Owen Lin 46f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin public DecodeCanceller(Options options) { 47f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin mOptions = options; 48f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 494bb5912e85f6d1bd8a6b78d6d52b4c4da7aeb740Owen Lin 504bb5912e85f6d1bd8a6b78d6d52b4c4da7aeb740Owen Lin @Override 51f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin public void onCancel() { 52f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin mOptions.requestCancelDecode(); 53f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 54f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 55f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 56a625b6562d3bfc86465778b336c96fb42064be21Owen Lin @TargetApi(ApiHelper.VERSION_CODES.HONEYCOMB) 57a625b6562d3bfc86465778b336c96fb42064be21Owen Lin public static void setOptionsMutable(Options options) { 58a625b6562d3bfc86465778b336c96fb42064be21Owen Lin if (ApiHelper.HAS_OPTIONS_IN_MUTABLE) options.inMutable = true; 59a625b6562d3bfc86465778b336c96fb42064be21Owen Lin } 60a625b6562d3bfc86465778b336c96fb42064be21Owen Lin 614bb5912e85f6d1bd8a6b78d6d52b4c4da7aeb740Owen Lin public static Bitmap decode(JobContext jc, FileDescriptor fd, Options options) { 62c060a99d0d0f6a0bbcf3cd6bbc6ee9d91e15814dOwen Lin if (options == null) options = new Options(); 63c060a99d0d0f6a0bbcf3cd6bbc6ee9d91e15814dOwen Lin jc.setCancelListener(new DecodeCanceller(options)); 64a625b6562d3bfc86465778b336c96fb42064be21Owen Lin setOptionsMutable(options); 65c060a99d0d0f6a0bbcf3cd6bbc6ee9d91e15814dOwen Lin return ensureGLCompatibleBitmap( 66c060a99d0d0f6a0bbcf3cd6bbc6ee9d91e15814dOwen Lin BitmapFactory.decodeFileDescriptor(fd, null, options)); 67c060a99d0d0f6a0bbcf3cd6bbc6ee9d91e15814dOwen Lin } 68c060a99d0d0f6a0bbcf3cd6bbc6ee9d91e15814dOwen Lin 69b8be1e0ad76b6abc0da7ead39f7a9811195d001eChih-Chung Chang public static void decodeBounds(JobContext jc, FileDescriptor fd, 70b8be1e0ad76b6abc0da7ead39f7a9811195d001eChih-Chung Chang Options options) { 71b8be1e0ad76b6abc0da7ead39f7a9811195d001eChih-Chung Chang Utils.assertTrue(options != null); 72b8be1e0ad76b6abc0da7ead39f7a9811195d001eChih-Chung Chang options.inJustDecodeBounds = true; 73b8be1e0ad76b6abc0da7ead39f7a9811195d001eChih-Chung Chang jc.setCancelListener(new DecodeCanceller(options)); 74b8be1e0ad76b6abc0da7ead39f7a9811195d001eChih-Chung Chang BitmapFactory.decodeFileDescriptor(fd, null, options); 75b8be1e0ad76b6abc0da7ead39f7a9811195d001eChih-Chung Chang options.inJustDecodeBounds = false; 76b8be1e0ad76b6abc0da7ead39f7a9811195d001eChih-Chung Chang } 77b8be1e0ad76b6abc0da7ead39f7a9811195d001eChih-Chung Chang 784bb5912e85f6d1bd8a6b78d6d52b4c4da7aeb740Owen Lin public static Bitmap decode(JobContext jc, byte[] bytes, Options options) { 794bb5912e85f6d1bd8a6b78d6d52b4c4da7aeb740Owen Lin return decode(jc, bytes, 0, bytes.length, options); 80f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 81f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 824bb5912e85f6d1bd8a6b78d6d52b4c4da7aeb740Owen Lin public static Bitmap decode(JobContext jc, byte[] bytes, int offset, 83f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin int length, Options options) { 84f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin if (options == null) options = new Options(); 85f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin jc.setCancelListener(new DecodeCanceller(options)); 86a625b6562d3bfc86465778b336c96fb42064be21Owen Lin setOptionsMutable(options); 87f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin return ensureGLCompatibleBitmap( 88f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin BitmapFactory.decodeByteArray(bytes, offset, length, options)); 89f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 90f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 91b8be1e0ad76b6abc0da7ead39f7a9811195d001eChih-Chung Chang public static void decodeBounds(JobContext jc, byte[] bytes, int offset, 92b8be1e0ad76b6abc0da7ead39f7a9811195d001eChih-Chung Chang int length, Options options) { 93b8be1e0ad76b6abc0da7ead39f7a9811195d001eChih-Chung Chang Utils.assertTrue(options != null); 94b8be1e0ad76b6abc0da7ead39f7a9811195d001eChih-Chung Chang options.inJustDecodeBounds = true; 95b8be1e0ad76b6abc0da7ead39f7a9811195d001eChih-Chung Chang jc.setCancelListener(new DecodeCanceller(options)); 96b8be1e0ad76b6abc0da7ead39f7a9811195d001eChih-Chung Chang BitmapFactory.decodeByteArray(bytes, offset, length, options); 97b8be1e0ad76b6abc0da7ead39f7a9811195d001eChih-Chung Chang options.inJustDecodeBounds = false; 98b8be1e0ad76b6abc0da7ead39f7a9811195d001eChih-Chung Chang } 99b8be1e0ad76b6abc0da7ead39f7a9811195d001eChih-Chung Chang 1004bb5912e85f6d1bd8a6b78d6d52b4c4da7aeb740Owen Lin public static Bitmap decodeThumbnail( 1014bb5912e85f6d1bd8a6b78d6d52b4c4da7aeb740Owen Lin JobContext jc, String filePath, Options options, int targetSize, int type) { 102f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin FileInputStream fis = null; 103f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin try { 104f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin fis = new FileInputStream(filePath); 105f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin FileDescriptor fd = fis.getFD(); 1064bb5912e85f6d1bd8a6b78d6d52b4c4da7aeb740Owen Lin return decodeThumbnail(jc, fd, options, targetSize, type); 107f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } catch (Exception ex) { 108f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin Log.w(TAG, ex); 109f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin return null; 110f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } finally { 111f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin Utils.closeSilently(fis); 112f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 113f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 114f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 1154bb5912e85f6d1bd8a6b78d6d52b4c4da7aeb740Owen Lin public static Bitmap decodeThumbnail( 1164bb5912e85f6d1bd8a6b78d6d52b4c4da7aeb740Owen Lin JobContext jc, FileDescriptor fd, Options options, int targetSize, int type) { 117f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin if (options == null) options = new Options(); 118f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin jc.setCancelListener(new DecodeCanceller(options)); 119f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 120f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin options.inJustDecodeBounds = true; 121f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin BitmapFactory.decodeFileDescriptor(fd, null, options); 122f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin if (jc.isCancelled()) return null; 123f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 1244bb5912e85f6d1bd8a6b78d6d52b4c4da7aeb740Owen Lin int w = options.outWidth; 1254bb5912e85f6d1bd8a6b78d6d52b4c4da7aeb740Owen Lin int h = options.outHeight; 1264bb5912e85f6d1bd8a6b78d6d52b4c4da7aeb740Owen Lin 1274bb5912e85f6d1bd8a6b78d6d52b4c4da7aeb740Owen Lin if (type == MediaItem.TYPE_MICROTHUMBNAIL) { 1284bb5912e85f6d1bd8a6b78d6d52b4c4da7aeb740Owen Lin // We center-crop the original image as it's micro thumbnail. In this case, 1294bb5912e85f6d1bd8a6b78d6d52b4c4da7aeb740Owen Lin // we want to make sure the shorter side >= "targetSize". 1304bb5912e85f6d1bd8a6b78d6d52b4c4da7aeb740Owen Lin float scale = (float) targetSize / Math.min(w, h); 1314bb5912e85f6d1bd8a6b78d6d52b4c4da7aeb740Owen Lin options.inSampleSize = BitmapUtils.computeSampleSizeLarger(scale); 1324bb5912e85f6d1bd8a6b78d6d52b4c4da7aeb740Owen Lin 1334bb5912e85f6d1bd8a6b78d6d52b4c4da7aeb740Owen Lin // For an extremely wide image, e.g. 300x30000, we may got OOM when decoding 1344bb5912e85f6d1bd8a6b78d6d52b4c4da7aeb740Owen Lin // it for TYPE_MICROTHUMBNAIL. So we add a max number of pixels limit here. 1354bb5912e85f6d1bd8a6b78d6d52b4c4da7aeb740Owen Lin final int MAX_PIXEL_COUNT = 640000; // 400 x 1600 1364bb5912e85f6d1bd8a6b78d6d52b4c4da7aeb740Owen Lin if ((w / options.inSampleSize) * (h / options.inSampleSize) > MAX_PIXEL_COUNT) { 1374bb5912e85f6d1bd8a6b78d6d52b4c4da7aeb740Owen Lin options.inSampleSize = BitmapUtils.computeSampleSize( 1384bb5912e85f6d1bd8a6b78d6d52b4c4da7aeb740Owen Lin FloatMath.sqrt((float) MAX_PIXEL_COUNT / (w * h))); 1394bb5912e85f6d1bd8a6b78d6d52b4c4da7aeb740Owen Lin } 1404bb5912e85f6d1bd8a6b78d6d52b4c4da7aeb740Owen Lin } else { 1414bb5912e85f6d1bd8a6b78d6d52b4c4da7aeb740Owen Lin // For screen nail, we only want to keep the longer side >= targetSize. 1424bb5912e85f6d1bd8a6b78d6d52b4c4da7aeb740Owen Lin float scale = (float) targetSize / Math.max(w, h); 1434bb5912e85f6d1bd8a6b78d6d52b4c4da7aeb740Owen Lin options.inSampleSize = BitmapUtils.computeSampleSizeLarger(scale); 1444bb5912e85f6d1bd8a6b78d6d52b4c4da7aeb740Owen Lin } 1454bb5912e85f6d1bd8a6b78d6d52b4c4da7aeb740Owen Lin 146f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin options.inJustDecodeBounds = false; 147a625b6562d3bfc86465778b336c96fb42064be21Owen Lin setOptionsMutable(options); 1486c8d0fd879242f78a0c1a7daf4c037043663a49fChih-Chung Chang 1496c8d0fd879242f78a0c1a7daf4c037043663a49fChih-Chung Chang Bitmap result = BitmapFactory.decodeFileDescriptor(fd, null, options); 1504bb5912e85f6d1bd8a6b78d6d52b4c4da7aeb740Owen Lin if (result == null) return null; 1514bb5912e85f6d1bd8a6b78d6d52b4c4da7aeb740Owen Lin 1524bb5912e85f6d1bd8a6b78d6d52b4c4da7aeb740Owen Lin // We need to resize down if the decoder does not support inSampleSize 1534bb5912e85f6d1bd8a6b78d6d52b4c4da7aeb740Owen Lin // (For example, GIF images) 1544bb5912e85f6d1bd8a6b78d6d52b4c4da7aeb740Owen Lin float scale = (float) targetSize / (type == MediaItem.TYPE_MICROTHUMBNAIL 1554bb5912e85f6d1bd8a6b78d6d52b4c4da7aeb740Owen Lin ? Math.min(result.getWidth(), result.getHeight()) 1564bb5912e85f6d1bd8a6b78d6d52b4c4da7aeb740Owen Lin : Math.max(result.getWidth(), result.getHeight())); 1574bb5912e85f6d1bd8a6b78d6d52b4c4da7aeb740Owen Lin 1584bb5912e85f6d1bd8a6b78d6d52b4c4da7aeb740Owen Lin if (scale <= 0.5) result = BitmapUtils.resizeBitmapByScale(result, scale, true); 1596c8d0fd879242f78a0c1a7daf4c037043663a49fChih-Chung Chang return ensureGLCompatibleBitmap(result); 160f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 161f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 162113bfc77c4468411da9ae1290553c3be89f8df9aOwen Lin /** 163113bfc77c4468411da9ae1290553c3be89f8df9aOwen Lin * Decodes the bitmap from the given byte array if the image size is larger than the given 164113bfc77c4468411da9ae1290553c3be89f8df9aOwen Lin * requirement. 165113bfc77c4468411da9ae1290553c3be89f8df9aOwen Lin * 1665da31f8fd85d7c1e33133473bd1fbc5e3a240f2dOwen Lin * Note: The returned image may be resized down. However, both width and height must be 167113bfc77c4468411da9ae1290553c3be89f8df9aOwen Lin * larger than the <code>targetSize</code>. 168113bfc77c4468411da9ae1290553c3be89f8df9aOwen Lin */ 1694bb5912e85f6d1bd8a6b78d6d52b4c4da7aeb740Owen Lin public static Bitmap decodeIfBigEnough(JobContext jc, byte[] data, 170113bfc77c4468411da9ae1290553c3be89f8df9aOwen Lin Options options, int targetSize) { 171113bfc77c4468411da9ae1290553c3be89f8df9aOwen Lin if (options == null) options = new Options(); 172113bfc77c4468411da9ae1290553c3be89f8df9aOwen Lin jc.setCancelListener(new DecodeCanceller(options)); 173113bfc77c4468411da9ae1290553c3be89f8df9aOwen Lin 174113bfc77c4468411da9ae1290553c3be89f8df9aOwen Lin options.inJustDecodeBounds = true; 175113bfc77c4468411da9ae1290553c3be89f8df9aOwen Lin BitmapFactory.decodeByteArray(data, 0, data.length, options); 176113bfc77c4468411da9ae1290553c3be89f8df9aOwen Lin if (jc.isCancelled()) return null; 177113bfc77c4468411da9ae1290553c3be89f8df9aOwen Lin if (options.outWidth < targetSize || options.outHeight < targetSize) { 178113bfc77c4468411da9ae1290553c3be89f8df9aOwen Lin return null; 179113bfc77c4468411da9ae1290553c3be89f8df9aOwen Lin } 180113bfc77c4468411da9ae1290553c3be89f8df9aOwen Lin options.inSampleSize = BitmapUtils.computeSampleSizeLarger( 181113bfc77c4468411da9ae1290553c3be89f8df9aOwen Lin options.outWidth, options.outHeight, targetSize); 182113bfc77c4468411da9ae1290553c3be89f8df9aOwen Lin options.inJustDecodeBounds = false; 183a625b6562d3bfc86465778b336c96fb42064be21Owen Lin setOptionsMutable(options); 184a625b6562d3bfc86465778b336c96fb42064be21Owen Lin 185113bfc77c4468411da9ae1290553c3be89f8df9aOwen Lin return ensureGLCompatibleBitmap( 186113bfc77c4468411da9ae1290553c3be89f8df9aOwen Lin BitmapFactory.decodeByteArray(data, 0, data.length, options)); 187113bfc77c4468411da9ae1290553c3be89f8df9aOwen Lin } 188113bfc77c4468411da9ae1290553c3be89f8df9aOwen Lin 189f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin // TODO: This function should not be called directly from 190f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin // DecodeUtils.requestDecode(...), since we don't have the knowledge 191f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin // if the bitmap will be uploaded to GL. 192f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin public static Bitmap ensureGLCompatibleBitmap(Bitmap bitmap) { 193f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin if (bitmap == null || bitmap.getConfig() != null) return bitmap; 194f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin Bitmap newBitmap = bitmap.copy(Config.ARGB_8888, false); 195f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin bitmap.recycle(); 196f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin return newBitmap; 197f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 198f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 1994bb5912e85f6d1bd8a6b78d6d52b4c4da7aeb740Owen Lin public static BitmapRegionDecoder createBitmapRegionDecoder( 200f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin JobContext jc, byte[] bytes, int offset, int length, 201f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin boolean shareable) { 202f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin if (offset < 0 || length <= 0 || offset + length > bytes.length) { 203f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin throw new IllegalArgumentException(String.format( 204f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin "offset = %s, length = %s, bytes = %s", 205f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin offset, length, bytes.length)); 206f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 207f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 208f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin try { 209f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin return BitmapRegionDecoder.newInstance( 210f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin bytes, offset, length, shareable); 211f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } catch (Throwable t) { 212f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin Log.w(TAG, t); 213f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin return null; 214f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 215f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 216f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 2174bb5912e85f6d1bd8a6b78d6d52b4c4da7aeb740Owen Lin public static BitmapRegionDecoder createBitmapRegionDecoder( 218f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin JobContext jc, String filePath, boolean shareable) { 219f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin try { 220f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin return BitmapRegionDecoder.newInstance(filePath, shareable); 221f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } catch (Throwable t) { 222f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin Log.w(TAG, t); 223f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin return null; 224f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 225f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 226f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 2274bb5912e85f6d1bd8a6b78d6d52b4c4da7aeb740Owen Lin public static BitmapRegionDecoder createBitmapRegionDecoder( 228f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin JobContext jc, FileDescriptor fd, boolean shareable) { 229f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin try { 230f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin return BitmapRegionDecoder.newInstance(fd, shareable); 231f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } catch (Throwable t) { 232f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin Log.w(TAG, t); 233f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin return null; 234f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 235f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 236f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 2374bb5912e85f6d1bd8a6b78d6d52b4c4da7aeb740Owen Lin public static BitmapRegionDecoder createBitmapRegionDecoder( 238b289d441eb5af97ac8716479831b1a2c5fe2e878Chih-Chung Chang JobContext jc, InputStream is, boolean shareable) { 239b289d441eb5af97ac8716479831b1a2c5fe2e878Chih-Chung Chang try { 240b289d441eb5af97ac8716479831b1a2c5fe2e878Chih-Chung Chang return BitmapRegionDecoder.newInstance(is, shareable); 241b289d441eb5af97ac8716479831b1a2c5fe2e878Chih-Chung Chang } catch (Throwable t) { 242b289d441eb5af97ac8716479831b1a2c5fe2e878Chih-Chung Chang // We often cancel the creating of bitmap region decoder, 243b289d441eb5af97ac8716479831b1a2c5fe2e878Chih-Chung Chang // so just log one line. 244b289d441eb5af97ac8716479831b1a2c5fe2e878Chih-Chung Chang Log.w(TAG, "requestCreateBitmapRegionDecoder: " + t); 245b289d441eb5af97ac8716479831b1a2c5fe2e878Chih-Chung Chang return null; 246b289d441eb5af97ac8716479831b1a2c5fe2e878Chih-Chung Chang } 247b289d441eb5af97ac8716479831b1a2c5fe2e878Chih-Chung Chang } 248df4763cf8752fb1babc7244fc2be33ed87d3b072Owen Lin 249df4763cf8752fb1babc7244fc2be33ed87d3b072Owen Lin @TargetApi(Build.VERSION_CODES.HONEYCOMB) 250f52ceba89962829aa12f5caba131580e8da85880Bobby Georgescu public static Bitmap decodeUsingPool(JobContext jc, byte[] data, int offset, 251f52ceba89962829aa12f5caba131580e8da85880Bobby Georgescu int length, BitmapFactory.Options options) { 252df4763cf8752fb1babc7244fc2be33ed87d3b072Owen Lin if (options == null) options = new BitmapFactory.Options(); 253df4763cf8752fb1babc7244fc2be33ed87d3b072Owen Lin if (options.inSampleSize < 1) options.inSampleSize = 1; 254df4763cf8752fb1babc7244fc2be33ed87d3b072Owen Lin options.inPreferredConfig = Bitmap.Config.ARGB_8888; 255df4763cf8752fb1babc7244fc2be33ed87d3b072Owen Lin options.inBitmap = (options.inSampleSize == 1) 256f52ceba89962829aa12f5caba131580e8da85880Bobby Georgescu ? findCachedBitmap(jc, data, offset, length, options) : null; 257df4763cf8752fb1babc7244fc2be33ed87d3b072Owen Lin try { 258df4763cf8752fb1babc7244fc2be33ed87d3b072Owen Lin Bitmap bitmap = decode(jc, data, offset, length, options); 259df4763cf8752fb1babc7244fc2be33ed87d3b072Owen Lin if (options.inBitmap != null && options.inBitmap != bitmap) { 260f52ceba89962829aa12f5caba131580e8da85880Bobby Georgescu GalleryBitmapPool.getInstance().put(options.inBitmap); 261df4763cf8752fb1babc7244fc2be33ed87d3b072Owen Lin options.inBitmap = null; 262df4763cf8752fb1babc7244fc2be33ed87d3b072Owen Lin } 263df4763cf8752fb1babc7244fc2be33ed87d3b072Owen Lin return bitmap; 264df4763cf8752fb1babc7244fc2be33ed87d3b072Owen Lin } catch (IllegalArgumentException e) { 265df4763cf8752fb1babc7244fc2be33ed87d3b072Owen Lin if (options.inBitmap == null) throw e; 266df4763cf8752fb1babc7244fc2be33ed87d3b072Owen Lin 267df4763cf8752fb1babc7244fc2be33ed87d3b072Owen Lin Log.w(TAG, "decode fail with a given bitmap, try decode to a new bitmap"); 268f52ceba89962829aa12f5caba131580e8da85880Bobby Georgescu GalleryBitmapPool.getInstance().put(options.inBitmap); 269df4763cf8752fb1babc7244fc2be33ed87d3b072Owen Lin options.inBitmap = null; 270df4763cf8752fb1babc7244fc2be33ed87d3b072Owen Lin return decode(jc, data, offset, length, options); 271df4763cf8752fb1babc7244fc2be33ed87d3b072Owen Lin } 272df4763cf8752fb1babc7244fc2be33ed87d3b072Owen Lin } 273df4763cf8752fb1babc7244fc2be33ed87d3b072Owen Lin 274df4763cf8752fb1babc7244fc2be33ed87d3b072Owen Lin // This is the same as the method above except the source data comes 275df4763cf8752fb1babc7244fc2be33ed87d3b072Owen Lin // from a file descriptor instead of a byte array. 276df4763cf8752fb1babc7244fc2be33ed87d3b072Owen Lin @TargetApi(Build.VERSION_CODES.HONEYCOMB) 277f52ceba89962829aa12f5caba131580e8da85880Bobby Georgescu public static Bitmap decodeUsingPool(JobContext jc, 278f52ceba89962829aa12f5caba131580e8da85880Bobby Georgescu FileDescriptor fileDescriptor, Options options) { 279df4763cf8752fb1babc7244fc2be33ed87d3b072Owen Lin if (options == null) options = new BitmapFactory.Options(); 280df4763cf8752fb1babc7244fc2be33ed87d3b072Owen Lin if (options.inSampleSize < 1) options.inSampleSize = 1; 281df4763cf8752fb1babc7244fc2be33ed87d3b072Owen Lin options.inPreferredConfig = Bitmap.Config.ARGB_8888; 282df4763cf8752fb1babc7244fc2be33ed87d3b072Owen Lin options.inBitmap = (options.inSampleSize == 1) 283f52ceba89962829aa12f5caba131580e8da85880Bobby Georgescu ? findCachedBitmap(jc, fileDescriptor, options) : null; 284df4763cf8752fb1babc7244fc2be33ed87d3b072Owen Lin try { 285df4763cf8752fb1babc7244fc2be33ed87d3b072Owen Lin Bitmap bitmap = DecodeUtils.decode(jc, fileDescriptor, options); 286df4763cf8752fb1babc7244fc2be33ed87d3b072Owen Lin if (options.inBitmap != null && options.inBitmap != bitmap) { 287f52ceba89962829aa12f5caba131580e8da85880Bobby Georgescu GalleryBitmapPool.getInstance().put(options.inBitmap); 288df4763cf8752fb1babc7244fc2be33ed87d3b072Owen Lin options.inBitmap = null; 289df4763cf8752fb1babc7244fc2be33ed87d3b072Owen Lin } 290df4763cf8752fb1babc7244fc2be33ed87d3b072Owen Lin return bitmap; 291df4763cf8752fb1babc7244fc2be33ed87d3b072Owen Lin } catch (IllegalArgumentException e) { 292df4763cf8752fb1babc7244fc2be33ed87d3b072Owen Lin if (options.inBitmap == null) throw e; 293df4763cf8752fb1babc7244fc2be33ed87d3b072Owen Lin 294df4763cf8752fb1babc7244fc2be33ed87d3b072Owen Lin Log.w(TAG, "decode fail with a given bitmap, try decode to a new bitmap"); 295f52ceba89962829aa12f5caba131580e8da85880Bobby Georgescu GalleryBitmapPool.getInstance().put(options.inBitmap); 296df4763cf8752fb1babc7244fc2be33ed87d3b072Owen Lin options.inBitmap = null; 297df4763cf8752fb1babc7244fc2be33ed87d3b072Owen Lin return decode(jc, fileDescriptor, options); 298df4763cf8752fb1babc7244fc2be33ed87d3b072Owen Lin } 299df4763cf8752fb1babc7244fc2be33ed87d3b072Owen Lin } 300df4763cf8752fb1babc7244fc2be33ed87d3b072Owen Lin 301f52ceba89962829aa12f5caba131580e8da85880Bobby Georgescu private static Bitmap findCachedBitmap(JobContext jc, byte[] data, 302f52ceba89962829aa12f5caba131580e8da85880Bobby Georgescu int offset, int length, Options options) { 303df4763cf8752fb1babc7244fc2be33ed87d3b072Owen Lin decodeBounds(jc, data, offset, length, options); 304f52ceba89962829aa12f5caba131580e8da85880Bobby Georgescu return GalleryBitmapPool.getInstance().get(options.outWidth, options.outHeight); 305df4763cf8752fb1babc7244fc2be33ed87d3b072Owen Lin } 306df4763cf8752fb1babc7244fc2be33ed87d3b072Owen Lin 307f52ceba89962829aa12f5caba131580e8da85880Bobby Georgescu private static Bitmap findCachedBitmap(JobContext jc, FileDescriptor fileDescriptor, 308f52ceba89962829aa12f5caba131580e8da85880Bobby Georgescu Options options) { 309df4763cf8752fb1babc7244fc2be33ed87d3b072Owen Lin decodeBounds(jc, fileDescriptor, options); 310f52ceba89962829aa12f5caba131580e8da85880Bobby Georgescu return GalleryBitmapPool.getInstance().get(options.outWidth, options.outHeight); 311df4763cf8752fb1babc7244fc2be33ed87d3b072Owen Lin } 312f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin} 313