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 Lin 27a625b6562d3bfc86465778b336c96fb42064be21Owen Linimport com.android.gallery3d.common.ApiHelper; 284bb5912e85f6d1bd8a6b78d6d52b4c4da7aeb740Owen Linimport com.android.gallery3d.common.BitmapUtils; 294bb5912e85f6d1bd8a6b78d6d52b4c4da7aeb740Owen Linimport com.android.gallery3d.common.Utils; 30f52ceba89962829aa12f5caba131580e8da85880Bobby Georgescuimport com.android.photos.data.GalleryBitmapPool; 31df4763cf8752fb1babc7244fc2be33ed87d3b072Owen Linimport com.android.gallery3d.ui.Log; 324bb5912e85f6d1bd8a6b78d6d52b4c4da7aeb740Owen Linimport com.android.gallery3d.util.ThreadPool.CancelListener; 334bb5912e85f6d1bd8a6b78d6d52b4c4da7aeb740Owen Linimport com.android.gallery3d.util.ThreadPool.JobContext; 34f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 35f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Linimport java.io.FileDescriptor; 36f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Linimport java.io.FileInputStream; 37b289d441eb5af97ac8716479831b1a2c5fe2e878Chih-Chung Changimport java.io.InputStream; 38f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 39f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Linpublic class DecodeUtils { 40df4763cf8752fb1babc7244fc2be33ed87d3b072Owen Lin private static final String TAG = "DecodeUtils"; 41f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 42f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin private static class DecodeCanceller implements CancelListener { 43f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin Options mOptions; 444bb5912e85f6d1bd8a6b78d6d52b4c4da7aeb740Owen Lin 45f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin public DecodeCanceller(Options options) { 46f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin mOptions = options; 47f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 484bb5912e85f6d1bd8a6b78d6d52b4c4da7aeb740Owen Lin 494bb5912e85f6d1bd8a6b78d6d52b4c4da7aeb740Owen Lin @Override 50f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin public void onCancel() { 51f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin mOptions.requestCancelDecode(); 52f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 53f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 54f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 55a625b6562d3bfc86465778b336c96fb42064be21Owen Lin @TargetApi(ApiHelper.VERSION_CODES.HONEYCOMB) 56a625b6562d3bfc86465778b336c96fb42064be21Owen Lin public static void setOptionsMutable(Options options) { 57a625b6562d3bfc86465778b336c96fb42064be21Owen Lin if (ApiHelper.HAS_OPTIONS_IN_MUTABLE) options.inMutable = true; 58a625b6562d3bfc86465778b336c96fb42064be21Owen Lin } 59a625b6562d3bfc86465778b336c96fb42064be21Owen Lin 604bb5912e85f6d1bd8a6b78d6d52b4c4da7aeb740Owen Lin public static Bitmap decode(JobContext jc, FileDescriptor fd, Options options) { 61c060a99d0d0f6a0bbcf3cd6bbc6ee9d91e15814dOwen Lin if (options == null) options = new Options(); 62c060a99d0d0f6a0bbcf3cd6bbc6ee9d91e15814dOwen Lin jc.setCancelListener(new DecodeCanceller(options)); 63a625b6562d3bfc86465778b336c96fb42064be21Owen Lin setOptionsMutable(options); 64c060a99d0d0f6a0bbcf3cd6bbc6ee9d91e15814dOwen Lin return ensureGLCompatibleBitmap( 65c060a99d0d0f6a0bbcf3cd6bbc6ee9d91e15814dOwen Lin BitmapFactory.decodeFileDescriptor(fd, null, options)); 66c060a99d0d0f6a0bbcf3cd6bbc6ee9d91e15814dOwen Lin } 67c060a99d0d0f6a0bbcf3cd6bbc6ee9d91e15814dOwen Lin 68b8be1e0ad76b6abc0da7ead39f7a9811195d001eChih-Chung Chang public static void decodeBounds(JobContext jc, FileDescriptor fd, 69b8be1e0ad76b6abc0da7ead39f7a9811195d001eChih-Chung Chang Options options) { 70b8be1e0ad76b6abc0da7ead39f7a9811195d001eChih-Chung Chang Utils.assertTrue(options != null); 71b8be1e0ad76b6abc0da7ead39f7a9811195d001eChih-Chung Chang options.inJustDecodeBounds = true; 72b8be1e0ad76b6abc0da7ead39f7a9811195d001eChih-Chung Chang jc.setCancelListener(new DecodeCanceller(options)); 73b8be1e0ad76b6abc0da7ead39f7a9811195d001eChih-Chung Chang BitmapFactory.decodeFileDescriptor(fd, null, options); 74b8be1e0ad76b6abc0da7ead39f7a9811195d001eChih-Chung Chang options.inJustDecodeBounds = false; 75b8be1e0ad76b6abc0da7ead39f7a9811195d001eChih-Chung Chang } 76b8be1e0ad76b6abc0da7ead39f7a9811195d001eChih-Chung Chang 774bb5912e85f6d1bd8a6b78d6d52b4c4da7aeb740Owen Lin public static Bitmap decode(JobContext jc, byte[] bytes, Options options) { 784bb5912e85f6d1bd8a6b78d6d52b4c4da7aeb740Owen Lin return decode(jc, bytes, 0, bytes.length, options); 79f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 80f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 814bb5912e85f6d1bd8a6b78d6d52b4c4da7aeb740Owen Lin public static Bitmap decode(JobContext jc, byte[] bytes, int offset, 82f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin int length, Options options) { 83f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin if (options == null) options = new Options(); 84f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin jc.setCancelListener(new DecodeCanceller(options)); 85a625b6562d3bfc86465778b336c96fb42064be21Owen Lin setOptionsMutable(options); 86f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin return ensureGLCompatibleBitmap( 87f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin BitmapFactory.decodeByteArray(bytes, offset, length, options)); 88f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 89f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 90b8be1e0ad76b6abc0da7ead39f7a9811195d001eChih-Chung Chang public static void decodeBounds(JobContext jc, byte[] bytes, int offset, 91b8be1e0ad76b6abc0da7ead39f7a9811195d001eChih-Chung Chang int length, Options options) { 92b8be1e0ad76b6abc0da7ead39f7a9811195d001eChih-Chung Chang Utils.assertTrue(options != null); 93b8be1e0ad76b6abc0da7ead39f7a9811195d001eChih-Chung Chang options.inJustDecodeBounds = true; 94b8be1e0ad76b6abc0da7ead39f7a9811195d001eChih-Chung Chang jc.setCancelListener(new DecodeCanceller(options)); 95b8be1e0ad76b6abc0da7ead39f7a9811195d001eChih-Chung Chang BitmapFactory.decodeByteArray(bytes, offset, length, options); 96b8be1e0ad76b6abc0da7ead39f7a9811195d001eChih-Chung Chang options.inJustDecodeBounds = false; 97b8be1e0ad76b6abc0da7ead39f7a9811195d001eChih-Chung Chang } 98b8be1e0ad76b6abc0da7ead39f7a9811195d001eChih-Chung Chang 994bb5912e85f6d1bd8a6b78d6d52b4c4da7aeb740Owen Lin public static Bitmap decodeThumbnail( 1004bb5912e85f6d1bd8a6b78d6d52b4c4da7aeb740Owen Lin JobContext jc, String filePath, Options options, int targetSize, int type) { 101f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin FileInputStream fis = null; 102f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin try { 103f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin fis = new FileInputStream(filePath); 104f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin FileDescriptor fd = fis.getFD(); 1054bb5912e85f6d1bd8a6b78d6d52b4c4da7aeb740Owen Lin return decodeThumbnail(jc, fd, options, targetSize, type); 106f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } catch (Exception ex) { 107f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin Log.w(TAG, ex); 108f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin return null; 109f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } finally { 110f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin Utils.closeSilently(fis); 111f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 112f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 113f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 1144bb5912e85f6d1bd8a6b78d6d52b4c4da7aeb740Owen Lin public static Bitmap decodeThumbnail( 1154bb5912e85f6d1bd8a6b78d6d52b4c4da7aeb740Owen Lin JobContext jc, FileDescriptor fd, Options options, int targetSize, int type) { 116f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin if (options == null) options = new Options(); 117f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin jc.setCancelListener(new DecodeCanceller(options)); 118f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 119f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin options.inJustDecodeBounds = true; 120f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin BitmapFactory.decodeFileDescriptor(fd, null, options); 121f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin if (jc.isCancelled()) return null; 122f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 1234bb5912e85f6d1bd8a6b78d6d52b4c4da7aeb740Owen Lin int w = options.outWidth; 1244bb5912e85f6d1bd8a6b78d6d52b4c4da7aeb740Owen Lin int h = options.outHeight; 1254bb5912e85f6d1bd8a6b78d6d52b4c4da7aeb740Owen Lin 1264bb5912e85f6d1bd8a6b78d6d52b4c4da7aeb740Owen Lin if (type == MediaItem.TYPE_MICROTHUMBNAIL) { 1274bb5912e85f6d1bd8a6b78d6d52b4c4da7aeb740Owen Lin // We center-crop the original image as it's micro thumbnail. In this case, 1284bb5912e85f6d1bd8a6b78d6d52b4c4da7aeb740Owen Lin // we want to make sure the shorter side >= "targetSize". 1294bb5912e85f6d1bd8a6b78d6d52b4c4da7aeb740Owen Lin float scale = (float) targetSize / Math.min(w, h); 1304bb5912e85f6d1bd8a6b78d6d52b4c4da7aeb740Owen Lin options.inSampleSize = BitmapUtils.computeSampleSizeLarger(scale); 1314bb5912e85f6d1bd8a6b78d6d52b4c4da7aeb740Owen Lin 1324bb5912e85f6d1bd8a6b78d6d52b4c4da7aeb740Owen Lin // For an extremely wide image, e.g. 300x30000, we may got OOM when decoding 1334bb5912e85f6d1bd8a6b78d6d52b4c4da7aeb740Owen Lin // it for TYPE_MICROTHUMBNAIL. So we add a max number of pixels limit here. 1344bb5912e85f6d1bd8a6b78d6d52b4c4da7aeb740Owen Lin final int MAX_PIXEL_COUNT = 640000; // 400 x 1600 1354bb5912e85f6d1bd8a6b78d6d52b4c4da7aeb740Owen Lin if ((w / options.inSampleSize) * (h / options.inSampleSize) > MAX_PIXEL_COUNT) { 1364bb5912e85f6d1bd8a6b78d6d52b4c4da7aeb740Owen Lin options.inSampleSize = BitmapUtils.computeSampleSize( 1378a55d3ae7486b798e4c26eeb91993916145f3cefNeil Fuller (float) Math.sqrt((double) MAX_PIXEL_COUNT / (w * h))); 1384bb5912e85f6d1bd8a6b78d6d52b4c4da7aeb740Owen Lin } 1394bb5912e85f6d1bd8a6b78d6d52b4c4da7aeb740Owen Lin } else { 1404bb5912e85f6d1bd8a6b78d6d52b4c4da7aeb740Owen Lin // For screen nail, we only want to keep the longer side >= targetSize. 1414bb5912e85f6d1bd8a6b78d6d52b4c4da7aeb740Owen Lin float scale = (float) targetSize / Math.max(w, h); 1424bb5912e85f6d1bd8a6b78d6d52b4c4da7aeb740Owen Lin options.inSampleSize = BitmapUtils.computeSampleSizeLarger(scale); 1434bb5912e85f6d1bd8a6b78d6d52b4c4da7aeb740Owen Lin } 1444bb5912e85f6d1bd8a6b78d6d52b4c4da7aeb740Owen Lin 145f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin options.inJustDecodeBounds = false; 146a625b6562d3bfc86465778b336c96fb42064be21Owen Lin setOptionsMutable(options); 1476c8d0fd879242f78a0c1a7daf4c037043663a49fChih-Chung Chang 1486c8d0fd879242f78a0c1a7daf4c037043663a49fChih-Chung Chang Bitmap result = BitmapFactory.decodeFileDescriptor(fd, null, options); 1494bb5912e85f6d1bd8a6b78d6d52b4c4da7aeb740Owen Lin if (result == null) return null; 1504bb5912e85f6d1bd8a6b78d6d52b4c4da7aeb740Owen Lin 1514bb5912e85f6d1bd8a6b78d6d52b4c4da7aeb740Owen Lin // We need to resize down if the decoder does not support inSampleSize 1524bb5912e85f6d1bd8a6b78d6d52b4c4da7aeb740Owen Lin // (For example, GIF images) 1534bb5912e85f6d1bd8a6b78d6d52b4c4da7aeb740Owen Lin float scale = (float) targetSize / (type == MediaItem.TYPE_MICROTHUMBNAIL 1544bb5912e85f6d1bd8a6b78d6d52b4c4da7aeb740Owen Lin ? Math.min(result.getWidth(), result.getHeight()) 1554bb5912e85f6d1bd8a6b78d6d52b4c4da7aeb740Owen Lin : Math.max(result.getWidth(), result.getHeight())); 1564bb5912e85f6d1bd8a6b78d6d52b4c4da7aeb740Owen Lin 1574bb5912e85f6d1bd8a6b78d6d52b4c4da7aeb740Owen Lin if (scale <= 0.5) result = BitmapUtils.resizeBitmapByScale(result, scale, true); 1586c8d0fd879242f78a0c1a7daf4c037043663a49fChih-Chung Chang return ensureGLCompatibleBitmap(result); 159f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 160f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 161113bfc77c4468411da9ae1290553c3be89f8df9aOwen Lin /** 162113bfc77c4468411da9ae1290553c3be89f8df9aOwen Lin * Decodes the bitmap from the given byte array if the image size is larger than the given 163113bfc77c4468411da9ae1290553c3be89f8df9aOwen Lin * requirement. 164113bfc77c4468411da9ae1290553c3be89f8df9aOwen Lin * 1655da31f8fd85d7c1e33133473bd1fbc5e3a240f2dOwen Lin * Note: The returned image may be resized down. However, both width and height must be 166113bfc77c4468411da9ae1290553c3be89f8df9aOwen Lin * larger than the <code>targetSize</code>. 167113bfc77c4468411da9ae1290553c3be89f8df9aOwen Lin */ 1684bb5912e85f6d1bd8a6b78d6d52b4c4da7aeb740Owen Lin public static Bitmap decodeIfBigEnough(JobContext jc, byte[] data, 169113bfc77c4468411da9ae1290553c3be89f8df9aOwen Lin Options options, int targetSize) { 170113bfc77c4468411da9ae1290553c3be89f8df9aOwen Lin if (options == null) options = new Options(); 171113bfc77c4468411da9ae1290553c3be89f8df9aOwen Lin jc.setCancelListener(new DecodeCanceller(options)); 172113bfc77c4468411da9ae1290553c3be89f8df9aOwen Lin 173113bfc77c4468411da9ae1290553c3be89f8df9aOwen Lin options.inJustDecodeBounds = true; 174113bfc77c4468411da9ae1290553c3be89f8df9aOwen Lin BitmapFactory.decodeByteArray(data, 0, data.length, options); 175113bfc77c4468411da9ae1290553c3be89f8df9aOwen Lin if (jc.isCancelled()) return null; 176113bfc77c4468411da9ae1290553c3be89f8df9aOwen Lin if (options.outWidth < targetSize || options.outHeight < targetSize) { 177113bfc77c4468411da9ae1290553c3be89f8df9aOwen Lin return null; 178113bfc77c4468411da9ae1290553c3be89f8df9aOwen Lin } 179113bfc77c4468411da9ae1290553c3be89f8df9aOwen Lin options.inSampleSize = BitmapUtils.computeSampleSizeLarger( 180113bfc77c4468411da9ae1290553c3be89f8df9aOwen Lin options.outWidth, options.outHeight, targetSize); 181113bfc77c4468411da9ae1290553c3be89f8df9aOwen Lin options.inJustDecodeBounds = false; 182a625b6562d3bfc86465778b336c96fb42064be21Owen Lin setOptionsMutable(options); 183a625b6562d3bfc86465778b336c96fb42064be21Owen Lin 184113bfc77c4468411da9ae1290553c3be89f8df9aOwen Lin return ensureGLCompatibleBitmap( 185113bfc77c4468411da9ae1290553c3be89f8df9aOwen Lin BitmapFactory.decodeByteArray(data, 0, data.length, options)); 186113bfc77c4468411da9ae1290553c3be89f8df9aOwen Lin } 187113bfc77c4468411da9ae1290553c3be89f8df9aOwen Lin 188f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin // TODO: This function should not be called directly from 189f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin // DecodeUtils.requestDecode(...), since we don't have the knowledge 190f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin // if the bitmap will be uploaded to GL. 191f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin public static Bitmap ensureGLCompatibleBitmap(Bitmap bitmap) { 192f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin if (bitmap == null || bitmap.getConfig() != null) return bitmap; 193f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin Bitmap newBitmap = bitmap.copy(Config.ARGB_8888, false); 194f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin bitmap.recycle(); 195f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin return newBitmap; 196f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 197f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 1984bb5912e85f6d1bd8a6b78d6d52b4c4da7aeb740Owen Lin public static BitmapRegionDecoder createBitmapRegionDecoder( 199f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin JobContext jc, byte[] bytes, int offset, int length, 200f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin boolean shareable) { 201f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin if (offset < 0 || length <= 0 || offset + length > bytes.length) { 202f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin throw new IllegalArgumentException(String.format( 203f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin "offset = %s, length = %s, bytes = %s", 204f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin offset, length, bytes.length)); 205f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 206f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 207f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin try { 208f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin return BitmapRegionDecoder.newInstance( 209f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin bytes, offset, length, shareable); 210f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } catch (Throwable t) { 211f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin Log.w(TAG, t); 212f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin return null; 213f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 214f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 215f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 2164bb5912e85f6d1bd8a6b78d6d52b4c4da7aeb740Owen Lin public static BitmapRegionDecoder createBitmapRegionDecoder( 217f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin JobContext jc, String filePath, boolean shareable) { 218f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin try { 219f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin return BitmapRegionDecoder.newInstance(filePath, shareable); 220f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } catch (Throwable t) { 221f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin Log.w(TAG, t); 222f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin return null; 223f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 224f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 225f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 2264bb5912e85f6d1bd8a6b78d6d52b4c4da7aeb740Owen Lin public static BitmapRegionDecoder createBitmapRegionDecoder( 227f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin JobContext jc, FileDescriptor fd, boolean shareable) { 228f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin try { 229f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin return BitmapRegionDecoder.newInstance(fd, shareable); 230f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } catch (Throwable t) { 231f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin Log.w(TAG, t); 232f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin return null; 233f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 234f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 235f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 2364bb5912e85f6d1bd8a6b78d6d52b4c4da7aeb740Owen Lin public static BitmapRegionDecoder createBitmapRegionDecoder( 237b289d441eb5af97ac8716479831b1a2c5fe2e878Chih-Chung Chang JobContext jc, InputStream is, boolean shareable) { 238b289d441eb5af97ac8716479831b1a2c5fe2e878Chih-Chung Chang try { 239b289d441eb5af97ac8716479831b1a2c5fe2e878Chih-Chung Chang return BitmapRegionDecoder.newInstance(is, shareable); 240b289d441eb5af97ac8716479831b1a2c5fe2e878Chih-Chung Chang } catch (Throwable t) { 241b289d441eb5af97ac8716479831b1a2c5fe2e878Chih-Chung Chang // We often cancel the creating of bitmap region decoder, 242b289d441eb5af97ac8716479831b1a2c5fe2e878Chih-Chung Chang // so just log one line. 243b289d441eb5af97ac8716479831b1a2c5fe2e878Chih-Chung Chang Log.w(TAG, "requestCreateBitmapRegionDecoder: " + t); 244b289d441eb5af97ac8716479831b1a2c5fe2e878Chih-Chung Chang return null; 245b289d441eb5af97ac8716479831b1a2c5fe2e878Chih-Chung Chang } 246b289d441eb5af97ac8716479831b1a2c5fe2e878Chih-Chung Chang } 247df4763cf8752fb1babc7244fc2be33ed87d3b072Owen Lin 248df4763cf8752fb1babc7244fc2be33ed87d3b072Owen Lin @TargetApi(Build.VERSION_CODES.HONEYCOMB) 249f52ceba89962829aa12f5caba131580e8da85880Bobby Georgescu public static Bitmap decodeUsingPool(JobContext jc, byte[] data, int offset, 250f52ceba89962829aa12f5caba131580e8da85880Bobby Georgescu int length, BitmapFactory.Options options) { 251df4763cf8752fb1babc7244fc2be33ed87d3b072Owen Lin if (options == null) options = new BitmapFactory.Options(); 252df4763cf8752fb1babc7244fc2be33ed87d3b072Owen Lin if (options.inSampleSize < 1) options.inSampleSize = 1; 253df4763cf8752fb1babc7244fc2be33ed87d3b072Owen Lin options.inPreferredConfig = Bitmap.Config.ARGB_8888; 254df4763cf8752fb1babc7244fc2be33ed87d3b072Owen Lin options.inBitmap = (options.inSampleSize == 1) 255f52ceba89962829aa12f5caba131580e8da85880Bobby Georgescu ? findCachedBitmap(jc, data, offset, length, options) : null; 256df4763cf8752fb1babc7244fc2be33ed87d3b072Owen Lin try { 257df4763cf8752fb1babc7244fc2be33ed87d3b072Owen Lin Bitmap bitmap = decode(jc, data, offset, length, options); 258df4763cf8752fb1babc7244fc2be33ed87d3b072Owen Lin if (options.inBitmap != null && options.inBitmap != bitmap) { 259f52ceba89962829aa12f5caba131580e8da85880Bobby Georgescu GalleryBitmapPool.getInstance().put(options.inBitmap); 260df4763cf8752fb1babc7244fc2be33ed87d3b072Owen Lin options.inBitmap = null; 261df4763cf8752fb1babc7244fc2be33ed87d3b072Owen Lin } 262df4763cf8752fb1babc7244fc2be33ed87d3b072Owen Lin return bitmap; 263df4763cf8752fb1babc7244fc2be33ed87d3b072Owen Lin } catch (IllegalArgumentException e) { 264df4763cf8752fb1babc7244fc2be33ed87d3b072Owen Lin if (options.inBitmap == null) throw e; 265df4763cf8752fb1babc7244fc2be33ed87d3b072Owen Lin 266df4763cf8752fb1babc7244fc2be33ed87d3b072Owen Lin Log.w(TAG, "decode fail with a given bitmap, try decode to a new bitmap"); 267f52ceba89962829aa12f5caba131580e8da85880Bobby Georgescu GalleryBitmapPool.getInstance().put(options.inBitmap); 268df4763cf8752fb1babc7244fc2be33ed87d3b072Owen Lin options.inBitmap = null; 269df4763cf8752fb1babc7244fc2be33ed87d3b072Owen Lin return decode(jc, data, offset, length, options); 270df4763cf8752fb1babc7244fc2be33ed87d3b072Owen Lin } 271df4763cf8752fb1babc7244fc2be33ed87d3b072Owen Lin } 272df4763cf8752fb1babc7244fc2be33ed87d3b072Owen Lin 273df4763cf8752fb1babc7244fc2be33ed87d3b072Owen Lin // This is the same as the method above except the source data comes 274df4763cf8752fb1babc7244fc2be33ed87d3b072Owen Lin // from a file descriptor instead of a byte array. 275df4763cf8752fb1babc7244fc2be33ed87d3b072Owen Lin @TargetApi(Build.VERSION_CODES.HONEYCOMB) 276f52ceba89962829aa12f5caba131580e8da85880Bobby Georgescu public static Bitmap decodeUsingPool(JobContext jc, 277f52ceba89962829aa12f5caba131580e8da85880Bobby Georgescu FileDescriptor fileDescriptor, Options options) { 278df4763cf8752fb1babc7244fc2be33ed87d3b072Owen Lin if (options == null) options = new BitmapFactory.Options(); 279df4763cf8752fb1babc7244fc2be33ed87d3b072Owen Lin if (options.inSampleSize < 1) options.inSampleSize = 1; 280df4763cf8752fb1babc7244fc2be33ed87d3b072Owen Lin options.inPreferredConfig = Bitmap.Config.ARGB_8888; 281df4763cf8752fb1babc7244fc2be33ed87d3b072Owen Lin options.inBitmap = (options.inSampleSize == 1) 282f52ceba89962829aa12f5caba131580e8da85880Bobby Georgescu ? findCachedBitmap(jc, fileDescriptor, options) : null; 283df4763cf8752fb1babc7244fc2be33ed87d3b072Owen Lin try { 284df4763cf8752fb1babc7244fc2be33ed87d3b072Owen Lin Bitmap bitmap = DecodeUtils.decode(jc, fileDescriptor, options); 285df4763cf8752fb1babc7244fc2be33ed87d3b072Owen Lin if (options.inBitmap != null && options.inBitmap != bitmap) { 286f52ceba89962829aa12f5caba131580e8da85880Bobby Georgescu GalleryBitmapPool.getInstance().put(options.inBitmap); 287df4763cf8752fb1babc7244fc2be33ed87d3b072Owen Lin options.inBitmap = null; 288df4763cf8752fb1babc7244fc2be33ed87d3b072Owen Lin } 289df4763cf8752fb1babc7244fc2be33ed87d3b072Owen Lin return bitmap; 290df4763cf8752fb1babc7244fc2be33ed87d3b072Owen Lin } catch (IllegalArgumentException e) { 291df4763cf8752fb1babc7244fc2be33ed87d3b072Owen Lin if (options.inBitmap == null) throw e; 292df4763cf8752fb1babc7244fc2be33ed87d3b072Owen Lin 293df4763cf8752fb1babc7244fc2be33ed87d3b072Owen Lin Log.w(TAG, "decode fail with a given bitmap, try decode to a new bitmap"); 294f52ceba89962829aa12f5caba131580e8da85880Bobby Georgescu GalleryBitmapPool.getInstance().put(options.inBitmap); 295df4763cf8752fb1babc7244fc2be33ed87d3b072Owen Lin options.inBitmap = null; 296df4763cf8752fb1babc7244fc2be33ed87d3b072Owen Lin return decode(jc, fileDescriptor, options); 297df4763cf8752fb1babc7244fc2be33ed87d3b072Owen Lin } 298df4763cf8752fb1babc7244fc2be33ed87d3b072Owen Lin } 299df4763cf8752fb1babc7244fc2be33ed87d3b072Owen Lin 300f52ceba89962829aa12f5caba131580e8da85880Bobby Georgescu private static Bitmap findCachedBitmap(JobContext jc, byte[] data, 301f52ceba89962829aa12f5caba131580e8da85880Bobby Georgescu int offset, int length, Options options) { 302df4763cf8752fb1babc7244fc2be33ed87d3b072Owen Lin decodeBounds(jc, data, offset, length, options); 303f52ceba89962829aa12f5caba131580e8da85880Bobby Georgescu return GalleryBitmapPool.getInstance().get(options.outWidth, options.outHeight); 304df4763cf8752fb1babc7244fc2be33ed87d3b072Owen Lin } 305df4763cf8752fb1babc7244fc2be33ed87d3b072Owen Lin 306f52ceba89962829aa12f5caba131580e8da85880Bobby Georgescu private static Bitmap findCachedBitmap(JobContext jc, FileDescriptor fileDescriptor, 307f52ceba89962829aa12f5caba131580e8da85880Bobby Georgescu Options options) { 308df4763cf8752fb1babc7244fc2be33ed87d3b072Owen Lin decodeBounds(jc, fileDescriptor, options); 309f52ceba89962829aa12f5caba131580e8da85880Bobby Georgescu return GalleryBitmapPool.getInstance().get(options.outWidth, options.outHeight); 310df4763cf8752fb1babc7244fc2be33ed87d3b072Owen Lin } 311f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin} 312