ImageDecoder.java revision 1a69f4598faef083d0123bb9b6bfcd6acfdec4e0
10c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III/* 20c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III * Copyright (C) 2017 The Android Open Source Project 30c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III * 40c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III * Licensed under the Apache License, Version 2.0 (the "License"); 50c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III * you may not use this file except in compliance with the License. 60c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III * You may obtain a copy of the License at 70c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III * 80c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III * http://www.apache.org/licenses/LICENSE-2.0 90c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III * 100c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III * Unless required by applicable law or agreed to in writing, software 110c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III * distributed under the License is distributed on an "AS IS" BASIS, 120c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 130c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III * See the License for the specific language governing permissions and 140c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III * limitations under the License. 150c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III */ 160c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III 170c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins IIIpackage android.graphics; 180c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III 19e5de9aa4a9bab9c4d8288212d6352a65e9808737Leon Scroggins IIIimport static android.system.OsConstants.SEEK_CUR; 20ed074fd70011cf804a14b5cf53ffd4b529c5f367Leon Scroggins IIIimport static android.system.OsConstants.SEEK_SET; 21ed074fd70011cf804a14b5cf53ffd4b529c5f367Leon Scroggins III 225f7e948ad808d3f9c84482594e0da45b4181a6e5Leon Scroggins IIIimport static java.lang.annotation.RetentionPolicy.SOURCE; 235f7e948ad808d3f9c84482594e0da45b4181a6e5Leon Scroggins III 240c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins IIIimport android.annotation.IntDef; 250c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins IIIimport android.annotation.NonNull; 26b1cc8e64374832c8b296f609bebabff068ded460Leon Scroggins IIIimport android.annotation.Nullable; 271d2bf2b846f0a98f7403bbc791adb2969685d87aLeon Scroggins IIIimport android.annotation.TestApi; 28ed074fd70011cf804a14b5cf53ffd4b529c5f367Leon Scroggins IIIimport android.content.ContentResolver; 29ed074fd70011cf804a14b5cf53ffd4b529c5f367Leon Scroggins IIIimport android.content.res.AssetFileDescriptor; 30121ef98bfb0e34a2726dd0fb9112915017bfcde4Leon Scroggins IIIimport android.content.res.AssetManager; 31513031d15b78579e39d59b71ab5a1b0afabc5544Leon Scroggins IIIimport android.content.res.AssetManager.AssetInputStream; 320c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins IIIimport android.content.res.Resources; 33671cce2605ed50c9aba73ab5bd530cb7741c53cdLeon Scroggins IIIimport android.graphics.drawable.AnimatedImageDrawable; 340c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins IIIimport android.graphics.drawable.BitmapDrawable; 35a38b2135a4bf4368734567a73d2e56f1c318fee9Leon Scroggins IIIimport android.graphics.drawable.Drawable; 360c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins IIIimport android.graphics.drawable.NinePatchDrawable; 37ed074fd70011cf804a14b5cf53ffd4b529c5f367Leon Scroggins IIIimport android.net.Uri; 388290eaba47b99398fbe0bd59138f902bde558ecbLeon Scroggins IIIimport android.os.Build; 39ed074fd70011cf804a14b5cf53ffd4b529c5f367Leon Scroggins IIIimport android.system.ErrnoException; 40ed074fd70011cf804a14b5cf53ffd4b529c5f367Leon Scroggins IIIimport android.system.Os; 4166c6d78908e0203a497c2e97398c824b2591ea19Derek Sollenbergerimport android.util.DisplayMetrics; 42a38b2135a4bf4368734567a73d2e56f1c318fee9Leon Scroggins IIIimport android.util.Size; 4366c6d78908e0203a497c2e97398c824b2591ea19Derek Sollenbergerimport android.util.TypedValue; 44ed074fd70011cf804a14b5cf53ffd4b529c5f367Leon Scroggins III 45ed074fd70011cf804a14b5cf53ffd4b529c5f367Leon Scroggins IIIimport dalvik.system.CloseGuard; 460c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III 47a38b2135a4bf4368734567a73d2e56f1c318fee9Leon Scroggins IIIimport libcore.io.IoUtils; 48a38b2135a4bf4368734567a73d2e56f1c318fee9Leon Scroggins III 49e5de9aa4a9bab9c4d8288212d6352a65e9808737Leon Scroggins IIIimport java.io.File; 50ed074fd70011cf804a14b5cf53ffd4b529c5f367Leon Scroggins IIIimport java.io.FileDescriptor; 51ed074fd70011cf804a14b5cf53ffd4b529c5f367Leon Scroggins IIIimport java.io.FileInputStream; 52ed074fd70011cf804a14b5cf53ffd4b529c5f367Leon Scroggins IIIimport java.io.FileNotFoundException; 530c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins IIIimport java.io.IOException; 540c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins IIIimport java.io.InputStream; 550c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins IIIimport java.lang.annotation.Retention; 56a38b2135a4bf4368734567a73d2e56f1c318fee9Leon Scroggins IIIimport java.nio.ByteBuffer; 57ed074fd70011cf804a14b5cf53ffd4b529c5f367Leon Scroggins IIIimport java.util.concurrent.atomic.AtomicBoolean; 580c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III 590c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III/** 600c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III * Class for decoding images as {@link Bitmap}s or {@link Drawable}s. 610c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III */ 62ed074fd70011cf804a14b5cf53ffd4b529c5f367Leon Scroggins IIIpublic final class ImageDecoder implements AutoCloseable { 638290eaba47b99398fbe0bd59138f902bde558ecbLeon Scroggins III /** @hide **/ 648290eaba47b99398fbe0bd59138f902bde558ecbLeon Scroggins III public static int sApiLevel; 658290eaba47b99398fbe0bd59138f902bde558ecbLeon Scroggins III 660c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III /** 670c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III * Source of the encoded image data. 680c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III */ 690c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III public static abstract class Source { 70e5de9aa4a9bab9c4d8288212d6352a65e9808737Leon Scroggins III private Source() {} 71e5de9aa4a9bab9c4d8288212d6352a65e9808737Leon Scroggins III 720c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III /* @hide */ 73e5de9aa4a9bab9c4d8288212d6352a65e9808737Leon Scroggins III @Nullable 740c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III Resources getResources() { return null; } 750c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III 760c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III /* @hide */ 7766c6d78908e0203a497c2e97398c824b2591ea19Derek Sollenberger int getDensity() { return Bitmap.DENSITY_NONE; } 7866c6d78908e0203a497c2e97398c824b2591ea19Derek Sollenberger 7966c6d78908e0203a497c2e97398c824b2591ea19Derek Sollenberger /* @hide */ 80046a99ebbb90f9ecdead7b057ef99764a1d295b9Leon Scroggins III final int computeDstDensity() { 8166c6d78908e0203a497c2e97398c824b2591ea19Derek Sollenberger Resources res = getResources(); 8266c6d78908e0203a497c2e97398c824b2591ea19Derek Sollenberger if (res == null) { 8366c6d78908e0203a497c2e97398c824b2591ea19Derek Sollenberger return Bitmap.getDefaultDensity(); 8466c6d78908e0203a497c2e97398c824b2591ea19Derek Sollenberger } 8566c6d78908e0203a497c2e97398c824b2591ea19Derek Sollenberger 8666c6d78908e0203a497c2e97398c824b2591ea19Derek Sollenberger return res.getDisplayMetrics().densityDpi; 8766c6d78908e0203a497c2e97398c824b2591ea19Derek Sollenberger } 8866c6d78908e0203a497c2e97398c824b2591ea19Derek Sollenberger 8966c6d78908e0203a497c2e97398c824b2591ea19Derek Sollenberger /* @hide */ 90e5de9aa4a9bab9c4d8288212d6352a65e9808737Leon Scroggins III @NonNull 91ed074fd70011cf804a14b5cf53ffd4b529c5f367Leon Scroggins III abstract ImageDecoder createImageDecoder() throws IOException; 920c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III }; 930c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III 940c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III private static class ByteArraySource extends Source { 95e5de9aa4a9bab9c4d8288212d6352a65e9808737Leon Scroggins III ByteArraySource(@NonNull byte[] data, int offset, int length) { 960c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III mData = data; 970c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III mOffset = offset; 980c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III mLength = length; 990c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III }; 1000c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III private final byte[] mData; 1010c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III private final int mOffset; 1020c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III private final int mLength; 1030c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III 1040c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III @Override 105ed074fd70011cf804a14b5cf53ffd4b529c5f367Leon Scroggins III public ImageDecoder createImageDecoder() throws IOException { 1061d2bf2b846f0a98f7403bbc791adb2969685d87aLeon Scroggins III return nCreate(mData, mOffset, mLength, this); 1070c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III } 1080c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III } 1090c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III 1100c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III private static class ByteBufferSource extends Source { 111e5de9aa4a9bab9c4d8288212d6352a65e9808737Leon Scroggins III ByteBufferSource(@NonNull ByteBuffer buffer) { 1120c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III mBuffer = buffer; 1130c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III } 1140c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III private final ByteBuffer mBuffer; 1150c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III 1160c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III @Override 117ed074fd70011cf804a14b5cf53ffd4b529c5f367Leon Scroggins III public ImageDecoder createImageDecoder() throws IOException { 1180c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III if (!mBuffer.isDirect() && mBuffer.hasArray()) { 1190c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III int offset = mBuffer.arrayOffset() + mBuffer.position(); 1200c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III int length = mBuffer.limit() - mBuffer.position(); 1211d2bf2b846f0a98f7403bbc791adb2969685d87aLeon Scroggins III return nCreate(mBuffer.array(), offset, length, this); 1220c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III } 1231d2bf2b846f0a98f7403bbc791adb2969685d87aLeon Scroggins III return nCreate(mBuffer, mBuffer.position(), mBuffer.limit(), this); 1240c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III } 1250c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III } 1260c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III 127ed074fd70011cf804a14b5cf53ffd4b529c5f367Leon Scroggins III private static class ContentResolverSource extends Source { 128046a99ebbb90f9ecdead7b057ef99764a1d295b9Leon Scroggins III ContentResolverSource(@NonNull ContentResolver resolver, @NonNull Uri uri, 129046a99ebbb90f9ecdead7b057ef99764a1d295b9Leon Scroggins III @Nullable Resources res) { 130ed074fd70011cf804a14b5cf53ffd4b529c5f367Leon Scroggins III mResolver = resolver; 131ed074fd70011cf804a14b5cf53ffd4b529c5f367Leon Scroggins III mUri = uri; 132046a99ebbb90f9ecdead7b057ef99764a1d295b9Leon Scroggins III mResources = res; 133ed074fd70011cf804a14b5cf53ffd4b529c5f367Leon Scroggins III } 134ed074fd70011cf804a14b5cf53ffd4b529c5f367Leon Scroggins III 135ed074fd70011cf804a14b5cf53ffd4b529c5f367Leon Scroggins III private final ContentResolver mResolver; 136ed074fd70011cf804a14b5cf53ffd4b529c5f367Leon Scroggins III private final Uri mUri; 137046a99ebbb90f9ecdead7b057ef99764a1d295b9Leon Scroggins III private final Resources mResources; 138046a99ebbb90f9ecdead7b057ef99764a1d295b9Leon Scroggins III 139046a99ebbb90f9ecdead7b057ef99764a1d295b9Leon Scroggins III @Nullable 140046a99ebbb90f9ecdead7b057ef99764a1d295b9Leon Scroggins III Resources getResources() { return mResources; } 141ed074fd70011cf804a14b5cf53ffd4b529c5f367Leon Scroggins III 142ed074fd70011cf804a14b5cf53ffd4b529c5f367Leon Scroggins III @Override 143ed074fd70011cf804a14b5cf53ffd4b529c5f367Leon Scroggins III public ImageDecoder createImageDecoder() throws IOException { 144ed074fd70011cf804a14b5cf53ffd4b529c5f367Leon Scroggins III AssetFileDescriptor assetFd = null; 1450c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III try { 146ed074fd70011cf804a14b5cf53ffd4b529c5f367Leon Scroggins III if (mUri.getScheme() == ContentResolver.SCHEME_CONTENT) { 147ed074fd70011cf804a14b5cf53ffd4b529c5f367Leon Scroggins III assetFd = mResolver.openTypedAssetFileDescriptor(mUri, 148ed074fd70011cf804a14b5cf53ffd4b529c5f367Leon Scroggins III "image/*", null); 149ed074fd70011cf804a14b5cf53ffd4b529c5f367Leon Scroggins III } else { 150ed074fd70011cf804a14b5cf53ffd4b529c5f367Leon Scroggins III assetFd = mResolver.openAssetFileDescriptor(mUri, "r"); 151ed074fd70011cf804a14b5cf53ffd4b529c5f367Leon Scroggins III } 152ed074fd70011cf804a14b5cf53ffd4b529c5f367Leon Scroggins III } catch (FileNotFoundException e) { 153ed074fd70011cf804a14b5cf53ffd4b529c5f367Leon Scroggins III // Some images cannot be opened as AssetFileDescriptors (e.g. 154ed074fd70011cf804a14b5cf53ffd4b529c5f367Leon Scroggins III // bmp, ico). Open them as InputStreams. 155ed074fd70011cf804a14b5cf53ffd4b529c5f367Leon Scroggins III InputStream is = mResolver.openInputStream(mUri); 156ed074fd70011cf804a14b5cf53ffd4b529c5f367Leon Scroggins III if (is == null) { 157ed074fd70011cf804a14b5cf53ffd4b529c5f367Leon Scroggins III throw new FileNotFoundException(mUri.toString()); 158ed074fd70011cf804a14b5cf53ffd4b529c5f367Leon Scroggins III } 159ed074fd70011cf804a14b5cf53ffd4b529c5f367Leon Scroggins III 1601d2bf2b846f0a98f7403bbc791adb2969685d87aLeon Scroggins III return createFromStream(is, true, this); 161ed074fd70011cf804a14b5cf53ffd4b529c5f367Leon Scroggins III } 162ed074fd70011cf804a14b5cf53ffd4b529c5f367Leon Scroggins III 163ed074fd70011cf804a14b5cf53ffd4b529c5f367Leon Scroggins III final FileDescriptor fd = assetFd.getFileDescriptor(); 164ed074fd70011cf804a14b5cf53ffd4b529c5f367Leon Scroggins III final long offset = assetFd.getStartOffset(); 165ed074fd70011cf804a14b5cf53ffd4b529c5f367Leon Scroggins III 166ed074fd70011cf804a14b5cf53ffd4b529c5f367Leon Scroggins III ImageDecoder decoder = null; 167ed074fd70011cf804a14b5cf53ffd4b529c5f367Leon Scroggins III try { 168ed074fd70011cf804a14b5cf53ffd4b529c5f367Leon Scroggins III try { 169ed074fd70011cf804a14b5cf53ffd4b529c5f367Leon Scroggins III Os.lseek(fd, offset, SEEK_SET); 1701d2bf2b846f0a98f7403bbc791adb2969685d87aLeon Scroggins III decoder = nCreate(fd, this); 171ed074fd70011cf804a14b5cf53ffd4b529c5f367Leon Scroggins III } catch (ErrnoException e) { 1721d2bf2b846f0a98f7403bbc791adb2969685d87aLeon Scroggins III decoder = createFromStream(new FileInputStream(fd), true, this); 173ed074fd70011cf804a14b5cf53ffd4b529c5f367Leon Scroggins III } 1740c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III } finally { 175ed074fd70011cf804a14b5cf53ffd4b529c5f367Leon Scroggins III if (decoder == null) { 176ed074fd70011cf804a14b5cf53ffd4b529c5f367Leon Scroggins III IoUtils.closeQuietly(assetFd); 177ed074fd70011cf804a14b5cf53ffd4b529c5f367Leon Scroggins III } else { 178ed074fd70011cf804a14b5cf53ffd4b529c5f367Leon Scroggins III decoder.mAssetFd = assetFd; 1790c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III } 1800c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III } 181ed074fd70011cf804a14b5cf53ffd4b529c5f367Leon Scroggins III return decoder; 182ed074fd70011cf804a14b5cf53ffd4b529c5f367Leon Scroggins III } 183ed074fd70011cf804a14b5cf53ffd4b529c5f367Leon Scroggins III } 184ed074fd70011cf804a14b5cf53ffd4b529c5f367Leon Scroggins III 185e5de9aa4a9bab9c4d8288212d6352a65e9808737Leon Scroggins III @NonNull 1861d2bf2b846f0a98f7403bbc791adb2969685d87aLeon Scroggins III private static ImageDecoder createFromFile(@NonNull File file, 1871d2bf2b846f0a98f7403bbc791adb2969685d87aLeon Scroggins III @NonNull Source source) throws IOException { 188e5de9aa4a9bab9c4d8288212d6352a65e9808737Leon Scroggins III FileInputStream stream = new FileInputStream(file); 189e5de9aa4a9bab9c4d8288212d6352a65e9808737Leon Scroggins III FileDescriptor fd = stream.getFD(); 190e5de9aa4a9bab9c4d8288212d6352a65e9808737Leon Scroggins III try { 191e5de9aa4a9bab9c4d8288212d6352a65e9808737Leon Scroggins III Os.lseek(fd, 0, SEEK_CUR); 192e5de9aa4a9bab9c4d8288212d6352a65e9808737Leon Scroggins III } catch (ErrnoException e) { 1931d2bf2b846f0a98f7403bbc791adb2969685d87aLeon Scroggins III return createFromStream(stream, true, source); 194e5de9aa4a9bab9c4d8288212d6352a65e9808737Leon Scroggins III } 195e5de9aa4a9bab9c4d8288212d6352a65e9808737Leon Scroggins III 196e5de9aa4a9bab9c4d8288212d6352a65e9808737Leon Scroggins III ImageDecoder decoder = null; 197e5de9aa4a9bab9c4d8288212d6352a65e9808737Leon Scroggins III try { 1981d2bf2b846f0a98f7403bbc791adb2969685d87aLeon Scroggins III decoder = nCreate(fd, source); 199e5de9aa4a9bab9c4d8288212d6352a65e9808737Leon Scroggins III } finally { 200e5de9aa4a9bab9c4d8288212d6352a65e9808737Leon Scroggins III if (decoder == null) { 201e5de9aa4a9bab9c4d8288212d6352a65e9808737Leon Scroggins III IoUtils.closeQuietly(stream); 202e5de9aa4a9bab9c4d8288212d6352a65e9808737Leon Scroggins III } else { 203e5de9aa4a9bab9c4d8288212d6352a65e9808737Leon Scroggins III decoder.mInputStream = stream; 2040b49f5725cabd64d27960b1b017e5c009f701cf8Leon Scroggins III decoder.mOwnsInputStream = true; 205e5de9aa4a9bab9c4d8288212d6352a65e9808737Leon Scroggins III } 206e5de9aa4a9bab9c4d8288212d6352a65e9808737Leon Scroggins III } 207e5de9aa4a9bab9c4d8288212d6352a65e9808737Leon Scroggins III return decoder; 208e5de9aa4a9bab9c4d8288212d6352a65e9808737Leon Scroggins III } 209e5de9aa4a9bab9c4d8288212d6352a65e9808737Leon Scroggins III 210e5de9aa4a9bab9c4d8288212d6352a65e9808737Leon Scroggins III @NonNull 2110b49f5725cabd64d27960b1b017e5c009f701cf8Leon Scroggins III private static ImageDecoder createFromStream(@NonNull InputStream is, 2121d2bf2b846f0a98f7403bbc791adb2969685d87aLeon Scroggins III boolean closeInputStream, Source source) throws IOException { 213ed074fd70011cf804a14b5cf53ffd4b529c5f367Leon Scroggins III // Arbitrary size matches BitmapFactory. 214ed074fd70011cf804a14b5cf53ffd4b529c5f367Leon Scroggins III byte[] storage = new byte[16 * 1024]; 215ed074fd70011cf804a14b5cf53ffd4b529c5f367Leon Scroggins III ImageDecoder decoder = null; 216ed074fd70011cf804a14b5cf53ffd4b529c5f367Leon Scroggins III try { 2171d2bf2b846f0a98f7403bbc791adb2969685d87aLeon Scroggins III decoder = nCreate(is, storage, source); 218ed074fd70011cf804a14b5cf53ffd4b529c5f367Leon Scroggins III } finally { 219ed074fd70011cf804a14b5cf53ffd4b529c5f367Leon Scroggins III if (decoder == null) { 2200b49f5725cabd64d27960b1b017e5c009f701cf8Leon Scroggins III if (closeInputStream) { 2210b49f5725cabd64d27960b1b017e5c009f701cf8Leon Scroggins III IoUtils.closeQuietly(is); 2220b49f5725cabd64d27960b1b017e5c009f701cf8Leon Scroggins III } 223ed074fd70011cf804a14b5cf53ffd4b529c5f367Leon Scroggins III } else { 224ed074fd70011cf804a14b5cf53ffd4b529c5f367Leon Scroggins III decoder.mInputStream = is; 2250b49f5725cabd64d27960b1b017e5c009f701cf8Leon Scroggins III decoder.mOwnsInputStream = closeInputStream; 226ed074fd70011cf804a14b5cf53ffd4b529c5f367Leon Scroggins III decoder.mTempStorage = storage; 227ed074fd70011cf804a14b5cf53ffd4b529c5f367Leon Scroggins III } 228ed074fd70011cf804a14b5cf53ffd4b529c5f367Leon Scroggins III } 229ed074fd70011cf804a14b5cf53ffd4b529c5f367Leon Scroggins III 230ed074fd70011cf804a14b5cf53ffd4b529c5f367Leon Scroggins III return decoder; 231ed074fd70011cf804a14b5cf53ffd4b529c5f367Leon Scroggins III } 2320c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III 2330b49f5725cabd64d27960b1b017e5c009f701cf8Leon Scroggins III /** 2340b49f5725cabd64d27960b1b017e5c009f701cf8Leon Scroggins III * For backwards compatibility, this does *not* close the InputStream. 2350b49f5725cabd64d27960b1b017e5c009f701cf8Leon Scroggins III */ 23666c6d78908e0203a497c2e97398c824b2591ea19Derek Sollenberger private static class InputStreamSource extends Source { 23766c6d78908e0203a497c2e97398c824b2591ea19Derek Sollenberger InputStreamSource(Resources res, InputStream is, int inputDensity) { 23866c6d78908e0203a497c2e97398c824b2591ea19Derek Sollenberger if (is == null) { 23966c6d78908e0203a497c2e97398c824b2591ea19Derek Sollenberger throw new IllegalArgumentException("The InputStream cannot be null"); 24066c6d78908e0203a497c2e97398c824b2591ea19Derek Sollenberger } 24166c6d78908e0203a497c2e97398c824b2591ea19Derek Sollenberger mResources = res; 24266c6d78908e0203a497c2e97398c824b2591ea19Derek Sollenberger mInputStream = is; 24366c6d78908e0203a497c2e97398c824b2591ea19Derek Sollenberger mInputDensity = res != null ? inputDensity : Bitmap.DENSITY_NONE; 24466c6d78908e0203a497c2e97398c824b2591ea19Derek Sollenberger } 24566c6d78908e0203a497c2e97398c824b2591ea19Derek Sollenberger 24666c6d78908e0203a497c2e97398c824b2591ea19Derek Sollenberger final Resources mResources; 24766c6d78908e0203a497c2e97398c824b2591ea19Derek Sollenberger InputStream mInputStream; 24866c6d78908e0203a497c2e97398c824b2591ea19Derek Sollenberger final int mInputDensity; 24966c6d78908e0203a497c2e97398c824b2591ea19Derek Sollenberger 25066c6d78908e0203a497c2e97398c824b2591ea19Derek Sollenberger @Override 25166c6d78908e0203a497c2e97398c824b2591ea19Derek Sollenberger public Resources getResources() { return mResources; } 25266c6d78908e0203a497c2e97398c824b2591ea19Derek Sollenberger 25366c6d78908e0203a497c2e97398c824b2591ea19Derek Sollenberger @Override 25466c6d78908e0203a497c2e97398c824b2591ea19Derek Sollenberger public int getDensity() { return mInputDensity; } 25566c6d78908e0203a497c2e97398c824b2591ea19Derek Sollenberger 25666c6d78908e0203a497c2e97398c824b2591ea19Derek Sollenberger @Override 25766c6d78908e0203a497c2e97398c824b2591ea19Derek Sollenberger public ImageDecoder createImageDecoder() throws IOException { 25866c6d78908e0203a497c2e97398c824b2591ea19Derek Sollenberger 25966c6d78908e0203a497c2e97398c824b2591ea19Derek Sollenberger synchronized (this) { 26066c6d78908e0203a497c2e97398c824b2591ea19Derek Sollenberger if (mInputStream == null) { 26166c6d78908e0203a497c2e97398c824b2591ea19Derek Sollenberger throw new IOException("Cannot reuse InputStreamSource"); 26266c6d78908e0203a497c2e97398c824b2591ea19Derek Sollenberger } 26366c6d78908e0203a497c2e97398c824b2591ea19Derek Sollenberger InputStream is = mInputStream; 26466c6d78908e0203a497c2e97398c824b2591ea19Derek Sollenberger mInputStream = null; 2651d2bf2b846f0a98f7403bbc791adb2969685d87aLeon Scroggins III return createFromStream(is, false, this); 26666c6d78908e0203a497c2e97398c824b2591ea19Derek Sollenberger } 26766c6d78908e0203a497c2e97398c824b2591ea19Derek Sollenberger } 26866c6d78908e0203a497c2e97398c824b2591ea19Derek Sollenberger } 26966c6d78908e0203a497c2e97398c824b2591ea19Derek Sollenberger 270513031d15b78579e39d59b71ab5a1b0afabc5544Leon Scroggins III /** 271513031d15b78579e39d59b71ab5a1b0afabc5544Leon Scroggins III * Takes ownership of the AssetInputStream. 272513031d15b78579e39d59b71ab5a1b0afabc5544Leon Scroggins III * 273513031d15b78579e39d59b71ab5a1b0afabc5544Leon Scroggins III * @hide 274513031d15b78579e39d59b71ab5a1b0afabc5544Leon Scroggins III */ 275513031d15b78579e39d59b71ab5a1b0afabc5544Leon Scroggins III public static class AssetInputStreamSource extends Source { 276513031d15b78579e39d59b71ab5a1b0afabc5544Leon Scroggins III public AssetInputStreamSource(@NonNull AssetInputStream ais, 277513031d15b78579e39d59b71ab5a1b0afabc5544Leon Scroggins III @NonNull Resources res, @NonNull TypedValue value) { 278513031d15b78579e39d59b71ab5a1b0afabc5544Leon Scroggins III mAssetInputStream = ais; 279513031d15b78579e39d59b71ab5a1b0afabc5544Leon Scroggins III mResources = res; 280513031d15b78579e39d59b71ab5a1b0afabc5544Leon Scroggins III 281513031d15b78579e39d59b71ab5a1b0afabc5544Leon Scroggins III if (value.density == TypedValue.DENSITY_DEFAULT) { 282513031d15b78579e39d59b71ab5a1b0afabc5544Leon Scroggins III mDensity = DisplayMetrics.DENSITY_DEFAULT; 283513031d15b78579e39d59b71ab5a1b0afabc5544Leon Scroggins III } else if (value.density != TypedValue.DENSITY_NONE) { 284513031d15b78579e39d59b71ab5a1b0afabc5544Leon Scroggins III mDensity = value.density; 285513031d15b78579e39d59b71ab5a1b0afabc5544Leon Scroggins III } else { 286513031d15b78579e39d59b71ab5a1b0afabc5544Leon Scroggins III mDensity = Bitmap.DENSITY_NONE; 287513031d15b78579e39d59b71ab5a1b0afabc5544Leon Scroggins III } 288513031d15b78579e39d59b71ab5a1b0afabc5544Leon Scroggins III } 289513031d15b78579e39d59b71ab5a1b0afabc5544Leon Scroggins III 290513031d15b78579e39d59b71ab5a1b0afabc5544Leon Scroggins III private AssetInputStream mAssetInputStream; 291513031d15b78579e39d59b71ab5a1b0afabc5544Leon Scroggins III private final Resources mResources; 292513031d15b78579e39d59b71ab5a1b0afabc5544Leon Scroggins III private final int mDensity; 293513031d15b78579e39d59b71ab5a1b0afabc5544Leon Scroggins III 294513031d15b78579e39d59b71ab5a1b0afabc5544Leon Scroggins III @Override 295513031d15b78579e39d59b71ab5a1b0afabc5544Leon Scroggins III public Resources getResources() { return mResources; } 296513031d15b78579e39d59b71ab5a1b0afabc5544Leon Scroggins III 297513031d15b78579e39d59b71ab5a1b0afabc5544Leon Scroggins III @Override 298513031d15b78579e39d59b71ab5a1b0afabc5544Leon Scroggins III public int getDensity() { 299513031d15b78579e39d59b71ab5a1b0afabc5544Leon Scroggins III return mDensity; 300513031d15b78579e39d59b71ab5a1b0afabc5544Leon Scroggins III } 301513031d15b78579e39d59b71ab5a1b0afabc5544Leon Scroggins III 302513031d15b78579e39d59b71ab5a1b0afabc5544Leon Scroggins III @Override 303513031d15b78579e39d59b71ab5a1b0afabc5544Leon Scroggins III public ImageDecoder createImageDecoder() throws IOException { 304513031d15b78579e39d59b71ab5a1b0afabc5544Leon Scroggins III synchronized (this) { 305513031d15b78579e39d59b71ab5a1b0afabc5544Leon Scroggins III if (mAssetInputStream == null) { 306513031d15b78579e39d59b71ab5a1b0afabc5544Leon Scroggins III throw new IOException("Cannot reuse AssetInputStreamSource"); 307513031d15b78579e39d59b71ab5a1b0afabc5544Leon Scroggins III } 308513031d15b78579e39d59b71ab5a1b0afabc5544Leon Scroggins III AssetInputStream ais = mAssetInputStream; 309513031d15b78579e39d59b71ab5a1b0afabc5544Leon Scroggins III mAssetInputStream = null; 3101d2bf2b846f0a98f7403bbc791adb2969685d87aLeon Scroggins III return createFromAsset(ais, this); 311513031d15b78579e39d59b71ab5a1b0afabc5544Leon Scroggins III } 312513031d15b78579e39d59b71ab5a1b0afabc5544Leon Scroggins III } 313513031d15b78579e39d59b71ab5a1b0afabc5544Leon Scroggins III } 314513031d15b78579e39d59b71ab5a1b0afabc5544Leon Scroggins III 315ed074fd70011cf804a14b5cf53ffd4b529c5f367Leon Scroggins III private static class ResourceSource extends Source { 316e5de9aa4a9bab9c4d8288212d6352a65e9808737Leon Scroggins III ResourceSource(@NonNull Resources res, int resId) { 3170c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III mResources = res; 3180c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III mResId = resId; 31966c6d78908e0203a497c2e97398c824b2591ea19Derek Sollenberger mResDensity = Bitmap.DENSITY_NONE; 3200c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III } 3210c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III 3220c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III final Resources mResources; 3230c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III final int mResId; 32466c6d78908e0203a497c2e97398c824b2591ea19Derek Sollenberger int mResDensity; 3250c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III 3260c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III @Override 3270c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III public Resources getResources() { return mResources; } 3280c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III 3290c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III @Override 33066c6d78908e0203a497c2e97398c824b2591ea19Derek Sollenberger public int getDensity() { return mResDensity; } 33166c6d78908e0203a497c2e97398c824b2591ea19Derek Sollenberger 33266c6d78908e0203a497c2e97398c824b2591ea19Derek Sollenberger @Override 333ed074fd70011cf804a14b5cf53ffd4b529c5f367Leon Scroggins III public ImageDecoder createImageDecoder() throws IOException { 33466c6d78908e0203a497c2e97398c824b2591ea19Derek Sollenberger TypedValue value = new TypedValue(); 335121ef98bfb0e34a2726dd0fb9112915017bfcde4Leon Scroggins III // This is just used in order to access the underlying Asset and 336121ef98bfb0e34a2726dd0fb9112915017bfcde4Leon Scroggins III // keep it alive. 337121ef98bfb0e34a2726dd0fb9112915017bfcde4Leon Scroggins III InputStream is = mResources.openRawResource(mResId, value); 33866c6d78908e0203a497c2e97398c824b2591ea19Derek Sollenberger 339121ef98bfb0e34a2726dd0fb9112915017bfcde4Leon Scroggins III if (value.density == TypedValue.DENSITY_DEFAULT) { 340121ef98bfb0e34a2726dd0fb9112915017bfcde4Leon Scroggins III mResDensity = DisplayMetrics.DENSITY_DEFAULT; 341121ef98bfb0e34a2726dd0fb9112915017bfcde4Leon Scroggins III } else if (value.density != TypedValue.DENSITY_NONE) { 342121ef98bfb0e34a2726dd0fb9112915017bfcde4Leon Scroggins III mResDensity = value.density; 343121ef98bfb0e34a2726dd0fb9112915017bfcde4Leon Scroggins III } 34466c6d78908e0203a497c2e97398c824b2591ea19Derek Sollenberger 3451d2bf2b846f0a98f7403bbc791adb2969685d87aLeon Scroggins III return createFromAsset((AssetInputStream) is, this); 346121ef98bfb0e34a2726dd0fb9112915017bfcde4Leon Scroggins III } 347121ef98bfb0e34a2726dd0fb9112915017bfcde4Leon Scroggins III } 348121ef98bfb0e34a2726dd0fb9112915017bfcde4Leon Scroggins III 349121ef98bfb0e34a2726dd0fb9112915017bfcde4Leon Scroggins III /** 350121ef98bfb0e34a2726dd0fb9112915017bfcde4Leon Scroggins III * ImageDecoder will own the AssetInputStream. 351121ef98bfb0e34a2726dd0fb9112915017bfcde4Leon Scroggins III */ 3521d2bf2b846f0a98f7403bbc791adb2969685d87aLeon Scroggins III private static ImageDecoder createFromAsset(AssetInputStream ais, 3531d2bf2b846f0a98f7403bbc791adb2969685d87aLeon Scroggins III Source source) throws IOException { 354121ef98bfb0e34a2726dd0fb9112915017bfcde4Leon Scroggins III ImageDecoder decoder = null; 355121ef98bfb0e34a2726dd0fb9112915017bfcde4Leon Scroggins III try { 356121ef98bfb0e34a2726dd0fb9112915017bfcde4Leon Scroggins III long asset = ais.getNativeAsset(); 3571d2bf2b846f0a98f7403bbc791adb2969685d87aLeon Scroggins III decoder = nCreate(asset, source); 358121ef98bfb0e34a2726dd0fb9112915017bfcde4Leon Scroggins III } finally { 359121ef98bfb0e34a2726dd0fb9112915017bfcde4Leon Scroggins III if (decoder == null) { 360121ef98bfb0e34a2726dd0fb9112915017bfcde4Leon Scroggins III IoUtils.closeQuietly(ais); 361121ef98bfb0e34a2726dd0fb9112915017bfcde4Leon Scroggins III } else { 362121ef98bfb0e34a2726dd0fb9112915017bfcde4Leon Scroggins III decoder.mInputStream = ais; 363121ef98bfb0e34a2726dd0fb9112915017bfcde4Leon Scroggins III decoder.mOwnsInputStream = true; 3640c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III } 365121ef98bfb0e34a2726dd0fb9112915017bfcde4Leon Scroggins III } 366121ef98bfb0e34a2726dd0fb9112915017bfcde4Leon Scroggins III return decoder; 367121ef98bfb0e34a2726dd0fb9112915017bfcde4Leon Scroggins III } 368121ef98bfb0e34a2726dd0fb9112915017bfcde4Leon Scroggins III 369121ef98bfb0e34a2726dd0fb9112915017bfcde4Leon Scroggins III private static class AssetSource extends Source { 370121ef98bfb0e34a2726dd0fb9112915017bfcde4Leon Scroggins III AssetSource(@NonNull AssetManager assets, @NonNull String fileName) { 371121ef98bfb0e34a2726dd0fb9112915017bfcde4Leon Scroggins III mAssets = assets; 372121ef98bfb0e34a2726dd0fb9112915017bfcde4Leon Scroggins III mFileName = fileName; 373121ef98bfb0e34a2726dd0fb9112915017bfcde4Leon Scroggins III } 374121ef98bfb0e34a2726dd0fb9112915017bfcde4Leon Scroggins III 375121ef98bfb0e34a2726dd0fb9112915017bfcde4Leon Scroggins III private final AssetManager mAssets; 376121ef98bfb0e34a2726dd0fb9112915017bfcde4Leon Scroggins III private final String mFileName; 377121ef98bfb0e34a2726dd0fb9112915017bfcde4Leon Scroggins III 378121ef98bfb0e34a2726dd0fb9112915017bfcde4Leon Scroggins III @Override 379121ef98bfb0e34a2726dd0fb9112915017bfcde4Leon Scroggins III public ImageDecoder createImageDecoder() throws IOException { 380121ef98bfb0e34a2726dd0fb9112915017bfcde4Leon Scroggins III InputStream is = mAssets.open(mFileName); 3811d2bf2b846f0a98f7403bbc791adb2969685d87aLeon Scroggins III return createFromAsset((AssetInputStream) is, this); 3820c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III } 3830c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III } 3840c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III 385e5de9aa4a9bab9c4d8288212d6352a65e9808737Leon Scroggins III private static class FileSource extends Source { 386e5de9aa4a9bab9c4d8288212d6352a65e9808737Leon Scroggins III FileSource(@NonNull File file) { 387e5de9aa4a9bab9c4d8288212d6352a65e9808737Leon Scroggins III mFile = file; 388e5de9aa4a9bab9c4d8288212d6352a65e9808737Leon Scroggins III } 389e5de9aa4a9bab9c4d8288212d6352a65e9808737Leon Scroggins III 390e5de9aa4a9bab9c4d8288212d6352a65e9808737Leon Scroggins III private final File mFile; 391e5de9aa4a9bab9c4d8288212d6352a65e9808737Leon Scroggins III 392e5de9aa4a9bab9c4d8288212d6352a65e9808737Leon Scroggins III @Override 393e5de9aa4a9bab9c4d8288212d6352a65e9808737Leon Scroggins III public ImageDecoder createImageDecoder() throws IOException { 3941d2bf2b846f0a98f7403bbc791adb2969685d87aLeon Scroggins III return createFromFile(mFile, this); 395e5de9aa4a9bab9c4d8288212d6352a65e9808737Leon Scroggins III } 396e5de9aa4a9bab9c4d8288212d6352a65e9808737Leon Scroggins III } 397e5de9aa4a9bab9c4d8288212d6352a65e9808737Leon Scroggins III 3980c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III /** 3990c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III * Contains information about the encoded image. 4000c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III */ 4010c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III public static class ImageInfo { 402e5de9aa4a9bab9c4d8288212d6352a65e9808737Leon Scroggins III private final Size mSize; 403e5de9aa4a9bab9c4d8288212d6352a65e9808737Leon Scroggins III private ImageDecoder mDecoder; 404e5de9aa4a9bab9c4d8288212d6352a65e9808737Leon Scroggins III 405e5de9aa4a9bab9c4d8288212d6352a65e9808737Leon Scroggins III private ImageInfo(@NonNull ImageDecoder decoder) { 406e5de9aa4a9bab9c4d8288212d6352a65e9808737Leon Scroggins III mSize = new Size(decoder.mWidth, decoder.mHeight); 407e5de9aa4a9bab9c4d8288212d6352a65e9808737Leon Scroggins III mDecoder = decoder; 408e5de9aa4a9bab9c4d8288212d6352a65e9808737Leon Scroggins III } 4091fad09d4d3f43112abd842da4c94cf00fb1cb46dLeon Scroggins III 4101fad09d4d3f43112abd842da4c94cf00fb1cb46dLeon Scroggins III /** 411e5de9aa4a9bab9c4d8288212d6352a65e9808737Leon Scroggins III * Size of the image, without scaling or cropping. 4121fad09d4d3f43112abd842da4c94cf00fb1cb46dLeon Scroggins III */ 413e5de9aa4a9bab9c4d8288212d6352a65e9808737Leon Scroggins III @NonNull 414e5de9aa4a9bab9c4d8288212d6352a65e9808737Leon Scroggins III public Size getSize() { 415e5de9aa4a9bab9c4d8288212d6352a65e9808737Leon Scroggins III return mSize; 4161fad09d4d3f43112abd842da4c94cf00fb1cb46dLeon Scroggins III } 4171fad09d4d3f43112abd842da4c94cf00fb1cb46dLeon Scroggins III 4181fad09d4d3f43112abd842da4c94cf00fb1cb46dLeon Scroggins III /** 419e5de9aa4a9bab9c4d8288212d6352a65e9808737Leon Scroggins III * The mimeType of the image. 4201fad09d4d3f43112abd842da4c94cf00fb1cb46dLeon Scroggins III */ 421e5de9aa4a9bab9c4d8288212d6352a65e9808737Leon Scroggins III @NonNull 4221fad09d4d3f43112abd842da4c94cf00fb1cb46dLeon Scroggins III public String getMimeType() { 423e5de9aa4a9bab9c4d8288212d6352a65e9808737Leon Scroggins III return mDecoder.getMimeType(); 4240c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III } 425127d31a6842b6cca49885c3607e7ea35b1885b6fLeon Scroggins III 426127d31a6842b6cca49885c3607e7ea35b1885b6fLeon Scroggins III /** 427127d31a6842b6cca49885c3607e7ea35b1885b6fLeon Scroggins III * Whether the image is animated. 428127d31a6842b6cca49885c3607e7ea35b1885b6fLeon Scroggins III * 429127d31a6842b6cca49885c3607e7ea35b1885b6fLeon Scroggins III * <p>Calling {@link #decodeDrawable} will return an 430127d31a6842b6cca49885c3607e7ea35b1885b6fLeon Scroggins III * {@link AnimatedImageDrawable}.</p> 431127d31a6842b6cca49885c3607e7ea35b1885b6fLeon Scroggins III */ 432127d31a6842b6cca49885c3607e7ea35b1885b6fLeon Scroggins III public boolean isAnimated() { 433127d31a6842b6cca49885c3607e7ea35b1885b6fLeon Scroggins III return mDecoder.mAnimated; 434127d31a6842b6cca49885c3607e7ea35b1885b6fLeon Scroggins III } 4351a69f4598faef083d0123bb9b6bfcd6acfdec4e0Leon Scroggins III 4361a69f4598faef083d0123bb9b6bfcd6acfdec4e0Leon Scroggins III /** 4371a69f4598faef083d0123bb9b6bfcd6acfdec4e0Leon Scroggins III * If known, the color space the decoded bitmap will have. Note that the 4381a69f4598faef083d0123bb9b6bfcd6acfdec4e0Leon Scroggins III * output color space is not guaranteed to be the color space the bitmap 4391a69f4598faef083d0123bb9b6bfcd6acfdec4e0Leon Scroggins III * is encoded with. If not known (when the config is 4401a69f4598faef083d0123bb9b6bfcd6acfdec4e0Leon Scroggins III * {@link Bitmap.Config#ALPHA_8} for instance), or there is an error, 4411a69f4598faef083d0123bb9b6bfcd6acfdec4e0Leon Scroggins III * it is set to null. 4421a69f4598faef083d0123bb9b6bfcd6acfdec4e0Leon Scroggins III */ 4431a69f4598faef083d0123bb9b6bfcd6acfdec4e0Leon Scroggins III @Nullable 4441a69f4598faef083d0123bb9b6bfcd6acfdec4e0Leon Scroggins III public ColorSpace getColorSpace() { 4451a69f4598faef083d0123bb9b6bfcd6acfdec4e0Leon Scroggins III return mDecoder.getColorSpace(); 4461a69f4598faef083d0123bb9b6bfcd6acfdec4e0Leon Scroggins III } 4470c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III }; 4480c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III 4491d2bf2b846f0a98f7403bbc791adb2969685d87aLeon Scroggins III /** @removed 4501d2bf2b846f0a98f7403bbc791adb2969685d87aLeon Scroggins III * @deprecated Subsumed by {@link #DecodeException}. 4510c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III */ 4521d2bf2b846f0a98f7403bbc791adb2969685d87aLeon Scroggins III @java.lang.Deprecated 453ed074fd70011cf804a14b5cf53ffd4b529c5f367Leon Scroggins III public static class IncompleteException extends IOException {}; 4540c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III 4550c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III /** 4560c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III * Optional listener supplied to {@link #decodeDrawable} or 4570c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III * {@link #decodeBitmap}. 4580c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III */ 4590c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III public static interface OnHeaderDecodedListener { 4600c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III /** 4610c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III * Called when the header is decoded and the size is known. 4620c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III * 4630c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III * @param decoder allows changing the default settings of the decode. 464e5de9aa4a9bab9c4d8288212d6352a65e9808737Leon Scroggins III * @param info Information about the encoded image. 465e5de9aa4a9bab9c4d8288212d6352a65e9808737Leon Scroggins III * @param source that created the decoder. 4660c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III */ 467e5de9aa4a9bab9c4d8288212d6352a65e9808737Leon Scroggins III public void onHeaderDecoded(@NonNull ImageDecoder decoder, 468e5de9aa4a9bab9c4d8288212d6352a65e9808737Leon Scroggins III @NonNull ImageInfo info, @NonNull Source source); 4690c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III 4700c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III }; 4710c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III 472cf7294fda671a39e6aa21da30be0dac261d71638Leon Scroggins III /** @removed 473cf7294fda671a39e6aa21da30be0dac261d71638Leon Scroggins III * @deprecated Replaced by {@link #DecodeException#SOURCE_EXCEPTION}. 474e5de9aa4a9bab9c4d8288212d6352a65e9808737Leon Scroggins III */ 475cf7294fda671a39e6aa21da30be0dac261d71638Leon Scroggins III @java.lang.Deprecated 476e5de9aa4a9bab9c4d8288212d6352a65e9808737Leon Scroggins III public static final int ERROR_SOURCE_EXCEPTION = 1; 477e5de9aa4a9bab9c4d8288212d6352a65e9808737Leon Scroggins III 478cf7294fda671a39e6aa21da30be0dac261d71638Leon Scroggins III /** @removed 479cf7294fda671a39e6aa21da30be0dac261d71638Leon Scroggins III * @deprecated Replaced by {@link #DecodeException#SOURCE_INCOMPLETE}. 480e5de9aa4a9bab9c4d8288212d6352a65e9808737Leon Scroggins III */ 481cf7294fda671a39e6aa21da30be0dac261d71638Leon Scroggins III @java.lang.Deprecated 482e5de9aa4a9bab9c4d8288212d6352a65e9808737Leon Scroggins III public static final int ERROR_SOURCE_INCOMPLETE = 2; 483e5de9aa4a9bab9c4d8288212d6352a65e9808737Leon Scroggins III 484cf7294fda671a39e6aa21da30be0dac261d71638Leon Scroggins III /** @removed 485cf7294fda671a39e6aa21da30be0dac261d71638Leon Scroggins III * @deprecated Replaced by {@link #DecodeException#SOURCE_MALFORMED_DATA}. 486e5de9aa4a9bab9c4d8288212d6352a65e9808737Leon Scroggins III */ 487cf7294fda671a39e6aa21da30be0dac261d71638Leon Scroggins III @java.lang.Deprecated 488e5de9aa4a9bab9c4d8288212d6352a65e9808737Leon Scroggins III public static final int ERROR_SOURCE_ERROR = 3; 489e5de9aa4a9bab9c4d8288212d6352a65e9808737Leon Scroggins III 490e5de9aa4a9bab9c4d8288212d6352a65e9808737Leon Scroggins III /** 4911d2bf2b846f0a98f7403bbc791adb2969685d87aLeon Scroggins III * Information about an interrupted decode. 4921d2bf2b846f0a98f7403bbc791adb2969685d87aLeon Scroggins III */ 4931d2bf2b846f0a98f7403bbc791adb2969685d87aLeon Scroggins III public static final class DecodeException extends IOException { 494cf7294fda671a39e6aa21da30be0dac261d71638Leon Scroggins III /** 495cf7294fda671a39e6aa21da30be0dac261d71638Leon Scroggins III * An Exception was thrown reading the {@link Source}. 496cf7294fda671a39e6aa21da30be0dac261d71638Leon Scroggins III */ 497cf7294fda671a39e6aa21da30be0dac261d71638Leon Scroggins III public static final int SOURCE_EXCEPTION = 1; 498cf7294fda671a39e6aa21da30be0dac261d71638Leon Scroggins III 499cf7294fda671a39e6aa21da30be0dac261d71638Leon Scroggins III /** 500cf7294fda671a39e6aa21da30be0dac261d71638Leon Scroggins III * The encoded data was incomplete. 501cf7294fda671a39e6aa21da30be0dac261d71638Leon Scroggins III */ 502cf7294fda671a39e6aa21da30be0dac261d71638Leon Scroggins III public static final int SOURCE_INCOMPLETE = 2; 503cf7294fda671a39e6aa21da30be0dac261d71638Leon Scroggins III 504cf7294fda671a39e6aa21da30be0dac261d71638Leon Scroggins III /** 505cf7294fda671a39e6aa21da30be0dac261d71638Leon Scroggins III * The encoded data contained an error. 506cf7294fda671a39e6aa21da30be0dac261d71638Leon Scroggins III */ 507cf7294fda671a39e6aa21da30be0dac261d71638Leon Scroggins III public static final int SOURCE_MALFORMED_DATA = 3; 508cf7294fda671a39e6aa21da30be0dac261d71638Leon Scroggins III 509cf7294fda671a39e6aa21da30be0dac261d71638Leon Scroggins III /** @hide **/ 510cf7294fda671a39e6aa21da30be0dac261d71638Leon Scroggins III @Retention(SOURCE) 511cf7294fda671a39e6aa21da30be0dac261d71638Leon Scroggins III @IntDef(value = { SOURCE_EXCEPTION, SOURCE_INCOMPLETE, SOURCE_MALFORMED_DATA }, 512cf7294fda671a39e6aa21da30be0dac261d71638Leon Scroggins III prefix = {"SOURCE_"}) 513cf7294fda671a39e6aa21da30be0dac261d71638Leon Scroggins III public @interface Error {}; 514cf7294fda671a39e6aa21da30be0dac261d71638Leon Scroggins III 5151d2bf2b846f0a98f7403bbc791adb2969685d87aLeon Scroggins III @Error final int mError; 5161d2bf2b846f0a98f7403bbc791adb2969685d87aLeon Scroggins III @NonNull final Source mSource; 5171d2bf2b846f0a98f7403bbc791adb2969685d87aLeon Scroggins III 5181d2bf2b846f0a98f7403bbc791adb2969685d87aLeon Scroggins III DecodeException(@Error int error, @Nullable Throwable cause, @NonNull Source source) { 5191d2bf2b846f0a98f7403bbc791adb2969685d87aLeon Scroggins III super(errorMessage(error, cause), cause); 5201d2bf2b846f0a98f7403bbc791adb2969685d87aLeon Scroggins III mError = error; 5211d2bf2b846f0a98f7403bbc791adb2969685d87aLeon Scroggins III mSource = source; 5221d2bf2b846f0a98f7403bbc791adb2969685d87aLeon Scroggins III } 5231d2bf2b846f0a98f7403bbc791adb2969685d87aLeon Scroggins III 5241d2bf2b846f0a98f7403bbc791adb2969685d87aLeon Scroggins III /** 5251d2bf2b846f0a98f7403bbc791adb2969685d87aLeon Scroggins III * Private method called by JNI. 5261d2bf2b846f0a98f7403bbc791adb2969685d87aLeon Scroggins III */ 5271d2bf2b846f0a98f7403bbc791adb2969685d87aLeon Scroggins III @SuppressWarnings("unused") 5281d2bf2b846f0a98f7403bbc791adb2969685d87aLeon Scroggins III DecodeException(@Error int error, @Nullable String msg, @Nullable Throwable cause, 5291d2bf2b846f0a98f7403bbc791adb2969685d87aLeon Scroggins III @NonNull Source source) { 5301d2bf2b846f0a98f7403bbc791adb2969685d87aLeon Scroggins III super(msg + errorMessage(error, cause), cause); 5311d2bf2b846f0a98f7403bbc791adb2969685d87aLeon Scroggins III mError = error; 5321d2bf2b846f0a98f7403bbc791adb2969685d87aLeon Scroggins III mSource = source; 5331d2bf2b846f0a98f7403bbc791adb2969685d87aLeon Scroggins III } 5341d2bf2b846f0a98f7403bbc791adb2969685d87aLeon Scroggins III 5351d2bf2b846f0a98f7403bbc791adb2969685d87aLeon Scroggins III /** 5361d2bf2b846f0a98f7403bbc791adb2969685d87aLeon Scroggins III * Retrieve the reason that decoding was interrupted. 5371d2bf2b846f0a98f7403bbc791adb2969685d87aLeon Scroggins III * 538cf7294fda671a39e6aa21da30be0dac261d71638Leon Scroggins III * <p>If the error is {@link #SOURCE_EXCEPTION}, the underlying 5391d2bf2b846f0a98f7403bbc791adb2969685d87aLeon Scroggins III * {@link java.lang.Throwable} can be retrieved with 5401d2bf2b846f0a98f7403bbc791adb2969685d87aLeon Scroggins III * {@link java.lang.Throwable#getCause}.</p> 5411d2bf2b846f0a98f7403bbc791adb2969685d87aLeon Scroggins III */ 5421d2bf2b846f0a98f7403bbc791adb2969685d87aLeon Scroggins III @Error 5431d2bf2b846f0a98f7403bbc791adb2969685d87aLeon Scroggins III public int getError() { 5441d2bf2b846f0a98f7403bbc791adb2969685d87aLeon Scroggins III return mError; 5451d2bf2b846f0a98f7403bbc791adb2969685d87aLeon Scroggins III } 5461d2bf2b846f0a98f7403bbc791adb2969685d87aLeon Scroggins III 5471d2bf2b846f0a98f7403bbc791adb2969685d87aLeon Scroggins III /** 5481d2bf2b846f0a98f7403bbc791adb2969685d87aLeon Scroggins III * Retrieve the {@link Source} that was interrupted. 5491d2bf2b846f0a98f7403bbc791adb2969685d87aLeon Scroggins III */ 5501d2bf2b846f0a98f7403bbc791adb2969685d87aLeon Scroggins III @NonNull 5511d2bf2b846f0a98f7403bbc791adb2969685d87aLeon Scroggins III public Source getSource() { 5521d2bf2b846f0a98f7403bbc791adb2969685d87aLeon Scroggins III return mSource; 5531d2bf2b846f0a98f7403bbc791adb2969685d87aLeon Scroggins III } 5541d2bf2b846f0a98f7403bbc791adb2969685d87aLeon Scroggins III 5551d2bf2b846f0a98f7403bbc791adb2969685d87aLeon Scroggins III private static String errorMessage(@Error int error, @Nullable Throwable cause) { 5561d2bf2b846f0a98f7403bbc791adb2969685d87aLeon Scroggins III switch (error) { 557cf7294fda671a39e6aa21da30be0dac261d71638Leon Scroggins III case SOURCE_EXCEPTION: 5581d2bf2b846f0a98f7403bbc791adb2969685d87aLeon Scroggins III return "Exception in input: " + cause; 559cf7294fda671a39e6aa21da30be0dac261d71638Leon Scroggins III case SOURCE_INCOMPLETE: 5601d2bf2b846f0a98f7403bbc791adb2969685d87aLeon Scroggins III return "Input was incomplete."; 561cf7294fda671a39e6aa21da30be0dac261d71638Leon Scroggins III case SOURCE_MALFORMED_DATA: 5621d2bf2b846f0a98f7403bbc791adb2969685d87aLeon Scroggins III return "Input contained an error."; 5631d2bf2b846f0a98f7403bbc791adb2969685d87aLeon Scroggins III default: 5641d2bf2b846f0a98f7403bbc791adb2969685d87aLeon Scroggins III return ""; 5651d2bf2b846f0a98f7403bbc791adb2969685d87aLeon Scroggins III } 5661d2bf2b846f0a98f7403bbc791adb2969685d87aLeon Scroggins III } 5671d2bf2b846f0a98f7403bbc791adb2969685d87aLeon Scroggins III } 5681d2bf2b846f0a98f7403bbc791adb2969685d87aLeon Scroggins III 5691d2bf2b846f0a98f7403bbc791adb2969685d87aLeon Scroggins III /** 5700c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III * Optional listener supplied to the ImageDecoder. 571e5de9aa4a9bab9c4d8288212d6352a65e9808737Leon Scroggins III * 572e5de9aa4a9bab9c4d8288212d6352a65e9808737Leon Scroggins III * Without this listener, errors will throw {@link java.io.IOException}. 5730c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III */ 574edf26d6e40f0723e70d7dcd147a2a2ce07c7c1ccLeon Scroggins III public static interface OnPartialImageListener { 5750c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III /** 576edf26d6e40f0723e70d7dcd147a2a2ce07c7c1ccLeon Scroggins III * Called when there is only a partial image to display. 5770c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III * 578e5de9aa4a9bab9c4d8288212d6352a65e9808737Leon Scroggins III * If decoding is interrupted after having decoded a partial image, 579e5de9aa4a9bab9c4d8288212d6352a65e9808737Leon Scroggins III * this listener lets the client know that and allows them to 580e5de9aa4a9bab9c4d8288212d6352a65e9808737Leon Scroggins III * optionally finish the rest of the decode/creation process to create 581e5de9aa4a9bab9c4d8288212d6352a65e9808737Leon Scroggins III * a partial {@link Drawable}/{@link Bitmap}. 582edf26d6e40f0723e70d7dcd147a2a2ce07c7c1ccLeon Scroggins III * 5831d2bf2b846f0a98f7403bbc791adb2969685d87aLeon Scroggins III * @param e containing information about the decode interruption. 584e5de9aa4a9bab9c4d8288212d6352a65e9808737Leon Scroggins III * @return True to create and return a {@link Drawable}/{@link Bitmap} 585e5de9aa4a9bab9c4d8288212d6352a65e9808737Leon Scroggins III * with partial data. False (which is the default) to abort the 5861d2bf2b846f0a98f7403bbc791adb2969685d87aLeon Scroggins III * decode and throw {@code e}. 5870c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III */ 5881d2bf2b846f0a98f7403bbc791adb2969685d87aLeon Scroggins III boolean onPartialImage(@NonNull DecodeException e); 5890c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III }; 5900c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III 5910c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III // Fields 592671cce2605ed50c9aba73ab5bd530cb7741c53cdLeon Scroggins III private long mNativePtr; 593671cce2605ed50c9aba73ab5bd530cb7741c53cdLeon Scroggins III private final int mWidth; 594671cce2605ed50c9aba73ab5bd530cb7741c53cdLeon Scroggins III private final int mHeight; 595671cce2605ed50c9aba73ab5bd530cb7741c53cdLeon Scroggins III private final boolean mAnimated; 5960c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III 5971a69f4598faef083d0123bb9b6bfcd6acfdec4e0Leon Scroggins III private int mDesiredWidth; 5981a69f4598faef083d0123bb9b6bfcd6acfdec4e0Leon Scroggins III private int mDesiredHeight; 5991a69f4598faef083d0123bb9b6bfcd6acfdec4e0Leon Scroggins III private int mAllocator = ALLOCATOR_DEFAULT; 6001a69f4598faef083d0123bb9b6bfcd6acfdec4e0Leon Scroggins III private boolean mRequireUnpremultiplied = false; 6011a69f4598faef083d0123bb9b6bfcd6acfdec4e0Leon Scroggins III private boolean mMutable = false; 6021a69f4598faef083d0123bb9b6bfcd6acfdec4e0Leon Scroggins III private boolean mConserveMemory = false; 6031a69f4598faef083d0123bb9b6bfcd6acfdec4e0Leon Scroggins III private boolean mDecodeAsAlphaMask = false; 6041a69f4598faef083d0123bb9b6bfcd6acfdec4e0Leon Scroggins III private ColorSpace mDesiredColorSpace = null; 6051a69f4598faef083d0123bb9b6bfcd6acfdec4e0Leon Scroggins III private Rect mCropRect; 6061a69f4598faef083d0123bb9b6bfcd6acfdec4e0Leon Scroggins III private Rect mOutPaddingRect; 6071a69f4598faef083d0123bb9b6bfcd6acfdec4e0Leon Scroggins III private Source mSource; 6080c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III 609e5de9aa4a9bab9c4d8288212d6352a65e9808737Leon Scroggins III private PostProcessor mPostProcessor; 610edf26d6e40f0723e70d7dcd147a2a2ce07c7c1ccLeon Scroggins III private OnPartialImageListener mOnPartialImageListener; 6110c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III 612ed074fd70011cf804a14b5cf53ffd4b529c5f367Leon Scroggins III // Objects for interacting with the input. 613ed074fd70011cf804a14b5cf53ffd4b529c5f367Leon Scroggins III private InputStream mInputStream; 6140b49f5725cabd64d27960b1b017e5c009f701cf8Leon Scroggins III private boolean mOwnsInputStream; 615ed074fd70011cf804a14b5cf53ffd4b529c5f367Leon Scroggins III private byte[] mTempStorage; 616ed074fd70011cf804a14b5cf53ffd4b529c5f367Leon Scroggins III private AssetFileDescriptor mAssetFd; 617ed074fd70011cf804a14b5cf53ffd4b529c5f367Leon Scroggins III private final AtomicBoolean mClosed = new AtomicBoolean(); 618ed074fd70011cf804a14b5cf53ffd4b529c5f367Leon Scroggins III private final CloseGuard mCloseGuard = CloseGuard.get(); 6190c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III 6200c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III /** 621ed074fd70011cf804a14b5cf53ffd4b529c5f367Leon Scroggins III * Private constructor called by JNI. {@link #close} must be 6220c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III * called after decoding to delete native resources. 6230c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III */ 6240c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III @SuppressWarnings("unused") 625671cce2605ed50c9aba73ab5bd530cb7741c53cdLeon Scroggins III private ImageDecoder(long nativePtr, int width, int height, 626671cce2605ed50c9aba73ab5bd530cb7741c53cdLeon Scroggins III boolean animated) { 6270c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III mNativePtr = nativePtr; 6280c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III mWidth = width; 6290c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III mHeight = height; 6300c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III mDesiredWidth = width; 6310c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III mDesiredHeight = height; 632671cce2605ed50c9aba73ab5bd530cb7741c53cdLeon Scroggins III mAnimated = animated; 633ed074fd70011cf804a14b5cf53ffd4b529c5f367Leon Scroggins III mCloseGuard.open("close"); 634ed074fd70011cf804a14b5cf53ffd4b529c5f367Leon Scroggins III } 635ed074fd70011cf804a14b5cf53ffd4b529c5f367Leon Scroggins III 636ed074fd70011cf804a14b5cf53ffd4b529c5f367Leon Scroggins III @Override 637ed074fd70011cf804a14b5cf53ffd4b529c5f367Leon Scroggins III protected void finalize() throws Throwable { 638ed074fd70011cf804a14b5cf53ffd4b529c5f367Leon Scroggins III try { 639ed074fd70011cf804a14b5cf53ffd4b529c5f367Leon Scroggins III if (mCloseGuard != null) { 640ed074fd70011cf804a14b5cf53ffd4b529c5f367Leon Scroggins III mCloseGuard.warnIfOpen(); 641ed074fd70011cf804a14b5cf53ffd4b529c5f367Leon Scroggins III } 642ed074fd70011cf804a14b5cf53ffd4b529c5f367Leon Scroggins III 643127d31a6842b6cca49885c3607e7ea35b1885b6fLeon Scroggins III // Avoid closing these in finalizer. 644127d31a6842b6cca49885c3607e7ea35b1885b6fLeon Scroggins III mInputStream = null; 645127d31a6842b6cca49885c3607e7ea35b1885b6fLeon Scroggins III mAssetFd = null; 646127d31a6842b6cca49885c3607e7ea35b1885b6fLeon Scroggins III 647ed074fd70011cf804a14b5cf53ffd4b529c5f367Leon Scroggins III close(); 648ed074fd70011cf804a14b5cf53ffd4b529c5f367Leon Scroggins III } finally { 649ed074fd70011cf804a14b5cf53ffd4b529c5f367Leon Scroggins III super.finalize(); 650ed074fd70011cf804a14b5cf53ffd4b529c5f367Leon Scroggins III } 6510c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III } 6520c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III 6530c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III /** 6541eccac89c13a79671e04cfce359a9506b284d5feLeon Scroggins III * Create a new {@link Source} from a resource. 6550c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III * 6560c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III * @param res the {@link Resources} object containing the image data. 6570c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III * @param resId resource ID of the image data. 6580c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III * @return a new Source object, which can be passed to 6590c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III * {@link #decodeDrawable} or {@link #decodeBitmap}. 6600c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III */ 661ed074fd70011cf804a14b5cf53ffd4b529c5f367Leon Scroggins III @NonNull 6621eccac89c13a79671e04cfce359a9506b284d5feLeon Scroggins III public static Source createSource(@NonNull Resources res, int resId) 663ed074fd70011cf804a14b5cf53ffd4b529c5f367Leon Scroggins III { 6640c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III return new ResourceSource(res, resId); 6650c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III } 6660c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III 6670c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III /** 668ed074fd70011cf804a14b5cf53ffd4b529c5f367Leon Scroggins III * Create a new {@link Source} from a {@link android.net.Uri}. 669ed074fd70011cf804a14b5cf53ffd4b529c5f367Leon Scroggins III * 670ed074fd70011cf804a14b5cf53ffd4b529c5f367Leon Scroggins III * @param cr to retrieve from. 671ed074fd70011cf804a14b5cf53ffd4b529c5f367Leon Scroggins III * @param uri of the image file. 672ed074fd70011cf804a14b5cf53ffd4b529c5f367Leon Scroggins III * @return a new Source object, which can be passed to 673ed074fd70011cf804a14b5cf53ffd4b529c5f367Leon Scroggins III * {@link #decodeDrawable} or {@link #decodeBitmap}. 674ed074fd70011cf804a14b5cf53ffd4b529c5f367Leon Scroggins III */ 675ed074fd70011cf804a14b5cf53ffd4b529c5f367Leon Scroggins III @NonNull 676ed074fd70011cf804a14b5cf53ffd4b529c5f367Leon Scroggins III public static Source createSource(@NonNull ContentResolver cr, 677ed074fd70011cf804a14b5cf53ffd4b529c5f367Leon Scroggins III @NonNull Uri uri) { 678046a99ebbb90f9ecdead7b057ef99764a1d295b9Leon Scroggins III return new ContentResolverSource(cr, uri, null); 679046a99ebbb90f9ecdead7b057ef99764a1d295b9Leon Scroggins III } 680046a99ebbb90f9ecdead7b057ef99764a1d295b9Leon Scroggins III 681046a99ebbb90f9ecdead7b057ef99764a1d295b9Leon Scroggins III /** 682046a99ebbb90f9ecdead7b057ef99764a1d295b9Leon Scroggins III * Provide Resources for density scaling. 683046a99ebbb90f9ecdead7b057ef99764a1d295b9Leon Scroggins III * 684046a99ebbb90f9ecdead7b057ef99764a1d295b9Leon Scroggins III * @hide 685046a99ebbb90f9ecdead7b057ef99764a1d295b9Leon Scroggins III */ 686046a99ebbb90f9ecdead7b057ef99764a1d295b9Leon Scroggins III @NonNull 687046a99ebbb90f9ecdead7b057ef99764a1d295b9Leon Scroggins III public static Source createSource(@NonNull ContentResolver cr, 688046a99ebbb90f9ecdead7b057ef99764a1d295b9Leon Scroggins III @NonNull Uri uri, @Nullable Resources res) { 689046a99ebbb90f9ecdead7b057ef99764a1d295b9Leon Scroggins III return new ContentResolverSource(cr, uri, res); 690ed074fd70011cf804a14b5cf53ffd4b529c5f367Leon Scroggins III } 691ed074fd70011cf804a14b5cf53ffd4b529c5f367Leon Scroggins III 692ed074fd70011cf804a14b5cf53ffd4b529c5f367Leon Scroggins III /** 693121ef98bfb0e34a2726dd0fb9112915017bfcde4Leon Scroggins III * Create a new {@link Source} from a file in the "assets" directory. 694121ef98bfb0e34a2726dd0fb9112915017bfcde4Leon Scroggins III */ 695121ef98bfb0e34a2726dd0fb9112915017bfcde4Leon Scroggins III @NonNull 696121ef98bfb0e34a2726dd0fb9112915017bfcde4Leon Scroggins III public static Source createSource(@NonNull AssetManager assets, @NonNull String fileName) { 697121ef98bfb0e34a2726dd0fb9112915017bfcde4Leon Scroggins III return new AssetSource(assets, fileName); 698121ef98bfb0e34a2726dd0fb9112915017bfcde4Leon Scroggins III } 699121ef98bfb0e34a2726dd0fb9112915017bfcde4Leon Scroggins III 700121ef98bfb0e34a2726dd0fb9112915017bfcde4Leon Scroggins III /** 7010c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III * Create a new {@link Source} from a byte array. 702e5de9aa4a9bab9c4d8288212d6352a65e9808737Leon Scroggins III * 7030c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III * @param data byte array of compressed image data. 7040c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III * @param offset offset into data for where the decoder should begin 7050c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III * parsing. 7060c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III * @param length number of bytes, beginning at offset, to parse. 7070c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III * @throws NullPointerException if data is null. 7080c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III * @throws ArrayIndexOutOfBoundsException if offset and length are 7090c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III * not within data. 710e5de9aa4a9bab9c4d8288212d6352a65e9808737Leon Scroggins III * @hide 7110c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III */ 712e5de9aa4a9bab9c4d8288212d6352a65e9808737Leon Scroggins III @NonNull 7130c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III public static Source createSource(@NonNull byte[] data, int offset, 7140c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III int length) throws ArrayIndexOutOfBoundsException { 7150c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III if (data == null) { 7160c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III throw new NullPointerException("null byte[] in createSource!"); 7170c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III } 7180c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III if (offset < 0 || length < 0 || offset >= data.length || 7190c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III offset + length > data.length) { 7200c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III throw new ArrayIndexOutOfBoundsException( 7210c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III "invalid offset/length!"); 7220c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III } 7230c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III return new ByteArraySource(data, offset, length); 7240c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III } 7250c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III 7260c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III /** 727b1cc8e64374832c8b296f609bebabff068ded460Leon Scroggins III * See {@link #createSource(byte[], int, int). 728e5de9aa4a9bab9c4d8288212d6352a65e9808737Leon Scroggins III * @hide 729b1cc8e64374832c8b296f609bebabff068ded460Leon Scroggins III */ 730e5de9aa4a9bab9c4d8288212d6352a65e9808737Leon Scroggins III @NonNull 731b1cc8e64374832c8b296f609bebabff068ded460Leon Scroggins III public static Source createSource(@NonNull byte[] data) { 732b1cc8e64374832c8b296f609bebabff068ded460Leon Scroggins III return createSource(data, 0, data.length); 733b1cc8e64374832c8b296f609bebabff068ded460Leon Scroggins III } 734b1cc8e64374832c8b296f609bebabff068ded460Leon Scroggins III 735b1cc8e64374832c8b296f609bebabff068ded460Leon Scroggins III /** 7360c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III * Create a new {@link Source} from a {@link java.nio.ByteBuffer}. 7370c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III * 7384367534058a07fd79ef1bbfec4e27f34275ab5c7Leon Scroggins III * <p>Decoding will start from {@link java.nio.ByteBuffer#position()}. The 7394367534058a07fd79ef1bbfec4e27f34275ab5c7Leon Scroggins III * position of {@code buffer} will not be affected.</p> 7400c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III * 7414367534058a07fd79ef1bbfec4e27f34275ab5c7Leon Scroggins III * <p>Note: If this {@code Source} is passed to {@link #decodeDrawable}, and 7424367534058a07fd79ef1bbfec4e27f34275ab5c7Leon Scroggins III * the encoded image is animated, the returned {@link AnimatedImageDrawable} 7434367534058a07fd79ef1bbfec4e27f34275ab5c7Leon Scroggins III * will continue reading from the {@code buffer}, so its contents must not 7444367534058a07fd79ef1bbfec4e27f34275ab5c7Leon Scroggins III * be modified, even after the {@code AnimatedImageDrawable} is returned. 7454367534058a07fd79ef1bbfec4e27f34275ab5c7Leon Scroggins III * {@code buffer}'s contents should never be modified during decode.</p> 7460c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III */ 747e5de9aa4a9bab9c4d8288212d6352a65e9808737Leon Scroggins III @NonNull 748e5de9aa4a9bab9c4d8288212d6352a65e9808737Leon Scroggins III public static Source createSource(@NonNull ByteBuffer buffer) { 7494367534058a07fd79ef1bbfec4e27f34275ab5c7Leon Scroggins III return new ByteBufferSource(buffer.slice()); 7500c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III } 7510c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III 7520c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III /** 75366c6d78908e0203a497c2e97398c824b2591ea19Derek Sollenberger * Internal API used to generate bitmaps for use by Drawables (i.e. BitmapDrawable) 75466c6d78908e0203a497c2e97398c824b2591ea19Derek Sollenberger * @hide 75566c6d78908e0203a497c2e97398c824b2591ea19Derek Sollenberger */ 75666c6d78908e0203a497c2e97398c824b2591ea19Derek Sollenberger public static Source createSource(Resources res, InputStream is) { 75766c6d78908e0203a497c2e97398c824b2591ea19Derek Sollenberger return new InputStreamSource(res, is, Bitmap.getDefaultDensity()); 75866c6d78908e0203a497c2e97398c824b2591ea19Derek Sollenberger } 75966c6d78908e0203a497c2e97398c824b2591ea19Derek Sollenberger 76066c6d78908e0203a497c2e97398c824b2591ea19Derek Sollenberger /** 76166c6d78908e0203a497c2e97398c824b2591ea19Derek Sollenberger * Internal API used to generate bitmaps for use by Drawables (i.e. BitmapDrawable) 76266c6d78908e0203a497c2e97398c824b2591ea19Derek Sollenberger * @hide 76366c6d78908e0203a497c2e97398c824b2591ea19Derek Sollenberger */ 7641d2bf2b846f0a98f7403bbc791adb2969685d87aLeon Scroggins III @TestApi 76566c6d78908e0203a497c2e97398c824b2591ea19Derek Sollenberger public static Source createSource(Resources res, InputStream is, int density) { 76666c6d78908e0203a497c2e97398c824b2591ea19Derek Sollenberger return new InputStreamSource(res, is, density); 76766c6d78908e0203a497c2e97398c824b2591ea19Derek Sollenberger } 76866c6d78908e0203a497c2e97398c824b2591ea19Derek Sollenberger 76966c6d78908e0203a497c2e97398c824b2591ea19Derek Sollenberger /** 770e5de9aa4a9bab9c4d8288212d6352a65e9808737Leon Scroggins III * Create a new {@link Source} from a {@link java.io.File}. 771e5de9aa4a9bab9c4d8288212d6352a65e9808737Leon Scroggins III */ 772e5de9aa4a9bab9c4d8288212d6352a65e9808737Leon Scroggins III @NonNull 773e5de9aa4a9bab9c4d8288212d6352a65e9808737Leon Scroggins III public static Source createSource(@NonNull File file) { 774e5de9aa4a9bab9c4d8288212d6352a65e9808737Leon Scroggins III return new FileSource(file); 775e5de9aa4a9bab9c4d8288212d6352a65e9808737Leon Scroggins III } 776e5de9aa4a9bab9c4d8288212d6352a65e9808737Leon Scroggins III 777e5de9aa4a9bab9c4d8288212d6352a65e9808737Leon Scroggins III /** 7780c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III * Return the width and height of a given sample size. 7790c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III * 780e5de9aa4a9bab9c4d8288212d6352a65e9808737Leon Scroggins III * <p>This takes an input that functions like 7810c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III * {@link BitmapFactory.Options#inSampleSize}. It returns a width and 78264481195e13e2dd7197fff569344e5a263b7871aLeon Scroggins III * height that can be achieved by sampling the encoded image. Other widths 7830c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III * and heights may be supported, but will require an additional (internal) 7840c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III * scaling step. Such internal scaling is *not* supported with 785e5de9aa4a9bab9c4d8288212d6352a65e9808737Leon Scroggins III * {@link #setRequireUnpremultiplied} set to {@code true}.</p> 7860c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III * 7870c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III * @param sampleSize Sampling rate of the encoded image. 788e5de9aa4a9bab9c4d8288212d6352a65e9808737Leon Scroggins III * @return {@link android.util.Size} of the width and height after 789e5de9aa4a9bab9c4d8288212d6352a65e9808737Leon Scroggins III * sampling. 79064481195e13e2dd7197fff569344e5a263b7871aLeon Scroggins III * 79164481195e13e2dd7197fff569344e5a263b7871aLeon Scroggins III * @hide 7920c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III */ 793e5de9aa4a9bab9c4d8288212d6352a65e9808737Leon Scroggins III @NonNull 794e5de9aa4a9bab9c4d8288212d6352a65e9808737Leon Scroggins III public Size getSampledSize(int sampleSize) { 7950c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III if (sampleSize <= 0) { 7960c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III throw new IllegalArgumentException("sampleSize must be positive! " 7970c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III + "provided " + sampleSize); 7980c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III } 7990c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III if (mNativePtr == 0) { 800ed074fd70011cf804a14b5cf53ffd4b529c5f367Leon Scroggins III throw new IllegalStateException("ImageDecoder is closed!"); 8010c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III } 8020c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III 8030c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III return nGetSampledSize(mNativePtr, sampleSize); 8040c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III } 8050c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III 8060c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III // Modifiers 80764481195e13e2dd7197fff569344e5a263b7871aLeon Scroggins III /** @removed 80864481195e13e2dd7197fff569344e5a263b7871aLeon Scroggins III * @deprecated Renamed to {@link #setTargetSize}. 80964481195e13e2dd7197fff569344e5a263b7871aLeon Scroggins III */ 81064481195e13e2dd7197fff569344e5a263b7871aLeon Scroggins III @java.lang.Deprecated 81164481195e13e2dd7197fff569344e5a263b7871aLeon Scroggins III public ImageDecoder setResize(int width, int height) { 81264481195e13e2dd7197fff569344e5a263b7871aLeon Scroggins III return this.setTargetSize(width, height); 81364481195e13e2dd7197fff569344e5a263b7871aLeon Scroggins III } 81464481195e13e2dd7197fff569344e5a263b7871aLeon Scroggins III 8150c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III /** 81664481195e13e2dd7197fff569344e5a263b7871aLeon Scroggins III * Specify the size of the output {@link Drawable} or {@link Bitmap}. 81764481195e13e2dd7197fff569344e5a263b7871aLeon Scroggins III * 81864481195e13e2dd7197fff569344e5a263b7871aLeon Scroggins III * <p>By default, the output size will match the size of the encoded 81964481195e13e2dd7197fff569344e5a263b7871aLeon Scroggins III * image, which can be retrieved from the {@link ImageInfo} in 82064481195e13e2dd7197fff569344e5a263b7871aLeon Scroggins III * {@link OnHeaderDecodedListener#onHeaderDecoded}.</p> 82164481195e13e2dd7197fff569344e5a263b7871aLeon Scroggins III * 8221a69f4598faef083d0123bb9b6bfcd6acfdec4e0Leon Scroggins III * <p>Only the last call to this or {@link #setTargetSampleSize} is 8231a69f4598faef083d0123bb9b6bfcd6acfdec4e0Leon Scroggins III * respected.</p> 8240c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III * 8250c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III * @param width must be greater than 0. 8260c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III * @param height must be greater than 0. 8275f7e948ad808d3f9c84482594e0da45b4181a6e5Leon Scroggins III * @return this object for chaining. 8280c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III */ 82964481195e13e2dd7197fff569344e5a263b7871aLeon Scroggins III public ImageDecoder setTargetSize(int width, int height) { 8300c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III if (width <= 0 || height <= 0) { 8310c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III throw new IllegalArgumentException("Dimensions must be positive! " 8320c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III + "provided (" + width + ", " + height + ")"); 8330c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III } 8340c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III 8350c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III mDesiredWidth = width; 8360c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III mDesiredHeight = height; 8375f7e948ad808d3f9c84482594e0da45b4181a6e5Leon Scroggins III return this; 8380c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III } 8390c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III 84064481195e13e2dd7197fff569344e5a263b7871aLeon Scroggins III /** @removed 8411a69f4598faef083d0123bb9b6bfcd6acfdec4e0Leon Scroggins III * @deprecated Renamed to {@link #setTargetSampleSize}. 84264481195e13e2dd7197fff569344e5a263b7871aLeon Scroggins III */ 84364481195e13e2dd7197fff569344e5a263b7871aLeon Scroggins III @java.lang.Deprecated 84464481195e13e2dd7197fff569344e5a263b7871aLeon Scroggins III public ImageDecoder setResize(int sampleSize) { 8451a69f4598faef083d0123bb9b6bfcd6acfdec4e0Leon Scroggins III return this.setTargetSampleSize(sampleSize); 84664481195e13e2dd7197fff569344e5a263b7871aLeon Scroggins III } 84764481195e13e2dd7197fff569344e5a263b7871aLeon Scroggins III 84864481195e13e2dd7197fff569344e5a263b7871aLeon Scroggins III private int getTargetDimension(int original, int sampleSize, int computed) { 84964481195e13e2dd7197fff569344e5a263b7871aLeon Scroggins III // Sampling will never result in a smaller size than 1. 85064481195e13e2dd7197fff569344e5a263b7871aLeon Scroggins III if (sampleSize >= original) { 85164481195e13e2dd7197fff569344e5a263b7871aLeon Scroggins III return 1; 85264481195e13e2dd7197fff569344e5a263b7871aLeon Scroggins III } 85364481195e13e2dd7197fff569344e5a263b7871aLeon Scroggins III 85464481195e13e2dd7197fff569344e5a263b7871aLeon Scroggins III // Use integer divide to find the desired size. If that is what 85564481195e13e2dd7197fff569344e5a263b7871aLeon Scroggins III // getSampledSize computed, that is the size to use. 85664481195e13e2dd7197fff569344e5a263b7871aLeon Scroggins III int target = original / sampleSize; 85764481195e13e2dd7197fff569344e5a263b7871aLeon Scroggins III if (computed == target) { 85864481195e13e2dd7197fff569344e5a263b7871aLeon Scroggins III return computed; 85964481195e13e2dd7197fff569344e5a263b7871aLeon Scroggins III } 86064481195e13e2dd7197fff569344e5a263b7871aLeon Scroggins III 86164481195e13e2dd7197fff569344e5a263b7871aLeon Scroggins III // If sampleSize does not divide evenly into original, the decoder 86264481195e13e2dd7197fff569344e5a263b7871aLeon Scroggins III // may round in either direction. It just needs to get a result that 86364481195e13e2dd7197fff569344e5a263b7871aLeon Scroggins III // is close. 86464481195e13e2dd7197fff569344e5a263b7871aLeon Scroggins III int reverse = computed * sampleSize; 86564481195e13e2dd7197fff569344e5a263b7871aLeon Scroggins III if (Math.abs(reverse - original) < sampleSize) { 86664481195e13e2dd7197fff569344e5a263b7871aLeon Scroggins III // This is the size that can be decoded most efficiently. 86764481195e13e2dd7197fff569344e5a263b7871aLeon Scroggins III return computed; 86864481195e13e2dd7197fff569344e5a263b7871aLeon Scroggins III } 86964481195e13e2dd7197fff569344e5a263b7871aLeon Scroggins III 87064481195e13e2dd7197fff569344e5a263b7871aLeon Scroggins III // The decoder could not get close (e.g. it is a DNG image). 87164481195e13e2dd7197fff569344e5a263b7871aLeon Scroggins III return target; 87264481195e13e2dd7197fff569344e5a263b7871aLeon Scroggins III } 87364481195e13e2dd7197fff569344e5a263b7871aLeon Scroggins III 8740c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III /** 87564481195e13e2dd7197fff569344e5a263b7871aLeon Scroggins III * Set the target size with a sampleSize. 87664481195e13e2dd7197fff569344e5a263b7871aLeon Scroggins III * 87764481195e13e2dd7197fff569344e5a263b7871aLeon Scroggins III * <p>By default, the output size will match the size of the encoded 87864481195e13e2dd7197fff569344e5a263b7871aLeon Scroggins III * image, which can be retrieved from the {@link ImageInfo} in 87964481195e13e2dd7197fff569344e5a263b7871aLeon Scroggins III * {@link OnHeaderDecodedListener#onHeaderDecoded}.</p> 8800c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III * 88164481195e13e2dd7197fff569344e5a263b7871aLeon Scroggins III * <p>Requests the decoder to subsample the original image, returning a 88264481195e13e2dd7197fff569344e5a263b7871aLeon Scroggins III * smaller image to save memory. The sample size is the number of pixels 88364481195e13e2dd7197fff569344e5a263b7871aLeon Scroggins III * in either dimension that correspond to a single pixel in the output. 88464481195e13e2dd7197fff569344e5a263b7871aLeon Scroggins III * For example, sampleSize == 4 returns an image that is 1/4 the 88564481195e13e2dd7197fff569344e5a263b7871aLeon Scroggins III * width/height of the original, and 1/16 the number of pixels.</p> 88664481195e13e2dd7197fff569344e5a263b7871aLeon Scroggins III * 88764481195e13e2dd7197fff569344e5a263b7871aLeon Scroggins III * <p>Must be greater than or equal to 1.</p> 88864481195e13e2dd7197fff569344e5a263b7871aLeon Scroggins III * 88964481195e13e2dd7197fff569344e5a263b7871aLeon Scroggins III * <p>Only the last call to this or {@link #setTargetSize} is respected.</p> 8900c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III * 8910c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III * @param sampleSize Sampling rate of the encoded image. 8925f7e948ad808d3f9c84482594e0da45b4181a6e5Leon Scroggins III * @return this object for chaining. 8930c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III */ 8941a69f4598faef083d0123bb9b6bfcd6acfdec4e0Leon Scroggins III public ImageDecoder setTargetSampleSize(int sampleSize) { 895e5de9aa4a9bab9c4d8288212d6352a65e9808737Leon Scroggins III Size size = this.getSampledSize(sampleSize); 89664481195e13e2dd7197fff569344e5a263b7871aLeon Scroggins III int targetWidth = getTargetDimension(mWidth, sampleSize, size.getWidth()); 89764481195e13e2dd7197fff569344e5a263b7871aLeon Scroggins III int targetHeight = getTargetDimension(mHeight, sampleSize, size.getHeight()); 89864481195e13e2dd7197fff569344e5a263b7871aLeon Scroggins III return this.setTargetSize(targetWidth, targetHeight); 8990c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III } 9000c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III 90166c6d78908e0203a497c2e97398c824b2591ea19Derek Sollenberger private boolean requestedResize() { 90266c6d78908e0203a497c2e97398c824b2591ea19Derek Sollenberger return mWidth != mDesiredWidth || mHeight != mDesiredHeight; 90366c6d78908e0203a497c2e97398c824b2591ea19Derek Sollenberger } 90466c6d78908e0203a497c2e97398c824b2591ea19Derek Sollenberger 9050c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III // These need to stay in sync with ImageDecoder.cpp's Allocator enum. 9060c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III /** 9070c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III * Use the default allocation for the pixel memory. 9080c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III * 9090c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III * Will typically result in a {@link Bitmap.Config#HARDWARE} 9100c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III * allocation, but may be software for small images. In addition, this will 9110c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III * switch to software when HARDWARE is incompatible, e.g. 912746a9fee937969af9be7e060335e26e098971615Leon Scroggins III * {@link #setMutable}, {@link #setDecodeAsAlphaMask}. 9130c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III */ 914e5de9aa4a9bab9c4d8288212d6352a65e9808737Leon Scroggins III public static final int ALLOCATOR_DEFAULT = 0; 9150c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III 9160c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III /** 9170c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III * Use a software allocation for the pixel memory. 9180c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III * 9190c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III * Useful for drawing to a software {@link Canvas} or for 9200c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III * accessing the pixels on the final output. 9210c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III */ 922e5de9aa4a9bab9c4d8288212d6352a65e9808737Leon Scroggins III public static final int ALLOCATOR_SOFTWARE = 1; 9230c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III 9240c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III /** 9250c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III * Use shared memory for the pixel memory. 9260c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III * 9270c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III * Useful for sharing across processes. 9280c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III */ 929e5de9aa4a9bab9c4d8288212d6352a65e9808737Leon Scroggins III public static final int ALLOCATOR_SHARED_MEMORY = 2; 9300c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III 9310c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III /** 9320c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III * Require a {@link Bitmap.Config#HARDWARE} {@link Bitmap}. 9330c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III * 934e5de9aa4a9bab9c4d8288212d6352a65e9808737Leon Scroggins III * When this is combined with incompatible options, like 935746a9fee937969af9be7e060335e26e098971615Leon Scroggins III * {@link #setMutable} or {@link #setDecodeAsAlphaMask}, {@link #decodeDrawable} 936e5de9aa4a9bab9c4d8288212d6352a65e9808737Leon Scroggins III * / {@link #decodeBitmap} will throw an 937e5de9aa4a9bab9c4d8288212d6352a65e9808737Leon Scroggins III * {@link java.lang.IllegalStateException}. 9380c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III */ 939e5de9aa4a9bab9c4d8288212d6352a65e9808737Leon Scroggins III public static final int ALLOCATOR_HARDWARE = 3; 9400c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III 9410c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III /** @hide **/ 9420c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III @Retention(SOURCE) 94362f0800ef4f41f97ddb18b755a63c01fea67b9faLeon Scroggins III @IntDef(value = { ALLOCATOR_DEFAULT, ALLOCATOR_SOFTWARE, 94462f0800ef4f41f97ddb18b755a63c01fea67b9faLeon Scroggins III ALLOCATOR_SHARED_MEMORY, ALLOCATOR_HARDWARE }, 94562f0800ef4f41f97ddb18b755a63c01fea67b9faLeon Scroggins III prefix = {"ALLOCATOR_"}) 9460c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III public @interface Allocator {}; 9470c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III 9480c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III /** 9490c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III * Choose the backing for the pixel memory. 9500c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III * 9510c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III * This is ignored for animated drawables. 9520c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III * 9530c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III * @param allocator Type of allocator to use. 9545f7e948ad808d3f9c84482594e0da45b4181a6e5Leon Scroggins III * @return this object for chaining. 9550c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III */ 9565f7e948ad808d3f9c84482594e0da45b4181a6e5Leon Scroggins III public ImageDecoder setAllocator(@Allocator int allocator) { 957e5de9aa4a9bab9c4d8288212d6352a65e9808737Leon Scroggins III if (allocator < ALLOCATOR_DEFAULT || allocator > ALLOCATOR_HARDWARE) { 9580c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III throw new IllegalArgumentException("invalid allocator " + allocator); 9590c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III } 9600c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III mAllocator = allocator; 9615f7e948ad808d3f9c84482594e0da45b4181a6e5Leon Scroggins III return this; 9620c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III } 9630c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III 9640c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III /** 965746a9fee937969af9be7e060335e26e098971615Leon Scroggins III * Return the allocator for the pixel memory. 966746a9fee937969af9be7e060335e26e098971615Leon Scroggins III */ 967746a9fee937969af9be7e060335e26e098971615Leon Scroggins III @Allocator 968746a9fee937969af9be7e060335e26e098971615Leon Scroggins III public int getAllocator() { 969746a9fee937969af9be7e060335e26e098971615Leon Scroggins III return mAllocator; 970746a9fee937969af9be7e060335e26e098971615Leon Scroggins III } 971746a9fee937969af9be7e060335e26e098971615Leon Scroggins III 972746a9fee937969af9be7e060335e26e098971615Leon Scroggins III /** 973e5de9aa4a9bab9c4d8288212d6352a65e9808737Leon Scroggins III * Specify whether the {@link Bitmap} should have unpremultiplied pixels. 9740c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III * 9755f7e948ad808d3f9c84482594e0da45b4181a6e5Leon Scroggins III * <p>By default, ImageDecoder will create a {@link Bitmap} with 9760c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III * premultiplied pixels, which is required for drawing with the 9770c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III * {@link android.view.View} system (i.e. to a {@link Canvas}). Calling 978e5de9aa4a9bab9c4d8288212d6352a65e9808737Leon Scroggins III * this method with a value of {@code true} will result in 979e5de9aa4a9bab9c4d8288212d6352a65e9808737Leon Scroggins III * {@link #decodeBitmap} returning a {@link Bitmap} with unpremultiplied 980e5de9aa4a9bab9c4d8288212d6352a65e9808737Leon Scroggins III * pixels. See {@link Bitmap#isPremultiplied}. This is incompatible with 9810c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III * {@link #decodeDrawable}; attempting to decode an unpremultiplied 9820c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III * {@link Drawable} will throw an {@link java.lang.IllegalStateException}. 9835f7e948ad808d3f9c84482594e0da45b4181a6e5Leon Scroggins III * </p> 9845f7e948ad808d3f9c84482594e0da45b4181a6e5Leon Scroggins III * 9855f7e948ad808d3f9c84482594e0da45b4181a6e5Leon Scroggins III * @return this object for chaining. 9860c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III */ 9875f7e948ad808d3f9c84482594e0da45b4181a6e5Leon Scroggins III public ImageDecoder setRequireUnpremultiplied(boolean requireUnpremultiplied) { 988e5de9aa4a9bab9c4d8288212d6352a65e9808737Leon Scroggins III mRequireUnpremultiplied = requireUnpremultiplied; 9895f7e948ad808d3f9c84482594e0da45b4181a6e5Leon Scroggins III return this; 9900c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III } 9910c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III 9920c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III /** 993746a9fee937969af9be7e060335e26e098971615Leon Scroggins III * Return whether the {@link Bitmap} will have unpremultiplied pixels. 994746a9fee937969af9be7e060335e26e098971615Leon Scroggins III */ 995746a9fee937969af9be7e060335e26e098971615Leon Scroggins III public boolean getRequireUnpremultiplied() { 996746a9fee937969af9be7e060335e26e098971615Leon Scroggins III return mRequireUnpremultiplied; 997746a9fee937969af9be7e060335e26e098971615Leon Scroggins III } 998746a9fee937969af9be7e060335e26e098971615Leon Scroggins III 999746a9fee937969af9be7e060335e26e098971615Leon Scroggins III /** 10000c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III * Modify the image after decoding and scaling. 10010c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III * 1002e5de9aa4a9bab9c4d8288212d6352a65e9808737Leon Scroggins III * <p>This allows adding effects prior to returning a {@link Drawable} or 10030c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III * {@link Bitmap}. For a {@code Drawable} or an immutable {@code Bitmap}, 1004e5de9aa4a9bab9c4d8288212d6352a65e9808737Leon Scroggins III * this is the only way to process the image after decoding.</p> 10050c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III * 1006e5de9aa4a9bab9c4d8288212d6352a65e9808737Leon Scroggins III * <p>If set on a nine-patch image, the nine-patch data is ignored.</p> 10070c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III * 1008e5de9aa4a9bab9c4d8288212d6352a65e9808737Leon Scroggins III * <p>For an animated image, the drawing commands drawn on the 1009e5de9aa4a9bab9c4d8288212d6352a65e9808737Leon Scroggins III * {@link Canvas} will be recorded immediately and then applied to each 1010e5de9aa4a9bab9c4d8288212d6352a65e9808737Leon Scroggins III * frame.</p> 10115f7e948ad808d3f9c84482594e0da45b4181a6e5Leon Scroggins III * 10125f7e948ad808d3f9c84482594e0da45b4181a6e5Leon Scroggins III * @return this object for chaining. 10130c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III */ 10145f7e948ad808d3f9c84482594e0da45b4181a6e5Leon Scroggins III public ImageDecoder setPostProcessor(@Nullable PostProcessor p) { 1015e5de9aa4a9bab9c4d8288212d6352a65e9808737Leon Scroggins III mPostProcessor = p; 10165f7e948ad808d3f9c84482594e0da45b4181a6e5Leon Scroggins III return this; 10170c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III } 10180c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III 10190c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III /** 1020746a9fee937969af9be7e060335e26e098971615Leon Scroggins III * Return the {@link PostProcessor} currently set. 1021746a9fee937969af9be7e060335e26e098971615Leon Scroggins III */ 1022746a9fee937969af9be7e060335e26e098971615Leon Scroggins III @Nullable 1023746a9fee937969af9be7e060335e26e098971615Leon Scroggins III public PostProcessor getPostProcessor() { 1024746a9fee937969af9be7e060335e26e098971615Leon Scroggins III return mPostProcessor; 1025746a9fee937969af9be7e060335e26e098971615Leon Scroggins III } 1026746a9fee937969af9be7e060335e26e098971615Leon Scroggins III 1027746a9fee937969af9be7e060335e26e098971615Leon Scroggins III /** 1028edf26d6e40f0723e70d7dcd147a2a2ce07c7c1ccLeon Scroggins III * Set (replace) the {@link OnPartialImageListener} on this object. 10290c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III * 10305f7e948ad808d3f9c84482594e0da45b4181a6e5Leon Scroggins III * <p>Will be called if there is an error in the input. Without one, an 10315f7e948ad808d3f9c84482594e0da45b4181a6e5Leon Scroggins III * error will result in an Exception being thrown.</p> 10325f7e948ad808d3f9c84482594e0da45b4181a6e5Leon Scroggins III * 10335f7e948ad808d3f9c84482594e0da45b4181a6e5Leon Scroggins III * @return this object for chaining. 10340c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III */ 10355f7e948ad808d3f9c84482594e0da45b4181a6e5Leon Scroggins III public ImageDecoder setOnPartialImageListener(@Nullable OnPartialImageListener l) { 1036edf26d6e40f0723e70d7dcd147a2a2ce07c7c1ccLeon Scroggins III mOnPartialImageListener = l; 10375f7e948ad808d3f9c84482594e0da45b4181a6e5Leon Scroggins III return this; 10380c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III } 10390c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III 10400c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III /** 1041746a9fee937969af9be7e060335e26e098971615Leon Scroggins III * Return the {@link OnPartialImageListener} currently set. 1042746a9fee937969af9be7e060335e26e098971615Leon Scroggins III */ 1043746a9fee937969af9be7e060335e26e098971615Leon Scroggins III @Nullable 1044746a9fee937969af9be7e060335e26e098971615Leon Scroggins III public OnPartialImageListener getOnPartialImageListener() { 1045746a9fee937969af9be7e060335e26e098971615Leon Scroggins III return mOnPartialImageListener; 1046746a9fee937969af9be7e060335e26e098971615Leon Scroggins III } 1047746a9fee937969af9be7e060335e26e098971615Leon Scroggins III 1048746a9fee937969af9be7e060335e26e098971615Leon Scroggins III /** 10490c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III * Crop the output to {@code subset} of the (possibly) scaled image. 10500c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III * 1051e5de9aa4a9bab9c4d8288212d6352a65e9808737Leon Scroggins III * <p>{@code subset} must be contained within the size set by 105264481195e13e2dd7197fff569344e5a263b7871aLeon Scroggins III * {@link #setTargetSize} or the bounds of the image if setTargetSize was 105364481195e13e2dd7197fff569344e5a263b7871aLeon Scroggins III * not called. Otherwise an {@link IllegalStateException} will be thrown by 1054e5de9aa4a9bab9c4d8288212d6352a65e9808737Leon Scroggins III * {@link #decodeDrawable}/{@link #decodeBitmap}.</p> 10550c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III * 1056e5de9aa4a9bab9c4d8288212d6352a65e9808737Leon Scroggins III * <p>NOT intended as a replacement for 10570c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III * {@link BitmapRegionDecoder#decodeRegion}. This supports all formats, 1058e5de9aa4a9bab9c4d8288212d6352a65e9808737Leon Scroggins III * but merely crops the output.</p> 10595f7e948ad808d3f9c84482594e0da45b4181a6e5Leon Scroggins III * 10605f7e948ad808d3f9c84482594e0da45b4181a6e5Leon Scroggins III * @return this object for chaining. 10610c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III */ 10625f7e948ad808d3f9c84482594e0da45b4181a6e5Leon Scroggins III public ImageDecoder setCrop(@Nullable Rect subset) { 10630c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III mCropRect = subset; 10645f7e948ad808d3f9c84482594e0da45b4181a6e5Leon Scroggins III return this; 10650c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III } 10660c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III 10670c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III /** 1068746a9fee937969af9be7e060335e26e098971615Leon Scroggins III * Return the cropping rectangle, if set. 1069746a9fee937969af9be7e060335e26e098971615Leon Scroggins III */ 1070746a9fee937969af9be7e060335e26e098971615Leon Scroggins III @Nullable 1071746a9fee937969af9be7e060335e26e098971615Leon Scroggins III public Rect getCrop() { 1072746a9fee937969af9be7e060335e26e098971615Leon Scroggins III return mCropRect; 1073746a9fee937969af9be7e060335e26e098971615Leon Scroggins III } 1074746a9fee937969af9be7e060335e26e098971615Leon Scroggins III 1075746a9fee937969af9be7e060335e26e098971615Leon Scroggins III /** 10762f1b06b58fc3c496832afc9b6ceeb2a36ef4bfa6Leon Scroggins III * Set a Rect for retrieving nine patch padding. 10772f1b06b58fc3c496832afc9b6ceeb2a36ef4bfa6Leon Scroggins III * 10782f1b06b58fc3c496832afc9b6ceeb2a36ef4bfa6Leon Scroggins III * If the image is a nine patch, this Rect will be set to the padding 10792f1b06b58fc3c496832afc9b6ceeb2a36ef4bfa6Leon Scroggins III * rectangle during decode. Otherwise it will not be modified. 10802f1b06b58fc3c496832afc9b6ceeb2a36ef4bfa6Leon Scroggins III * 10815f7e948ad808d3f9c84482594e0da45b4181a6e5Leon Scroggins III * @return this object for chaining. 10825f7e948ad808d3f9c84482594e0da45b4181a6e5Leon Scroggins III * 10832f1b06b58fc3c496832afc9b6ceeb2a36ef4bfa6Leon Scroggins III * @hide 10842f1b06b58fc3c496832afc9b6ceeb2a36ef4bfa6Leon Scroggins III */ 10855f7e948ad808d3f9c84482594e0da45b4181a6e5Leon Scroggins III public ImageDecoder setOutPaddingRect(@NonNull Rect outPadding) { 10862f1b06b58fc3c496832afc9b6ceeb2a36ef4bfa6Leon Scroggins III mOutPaddingRect = outPadding; 10875f7e948ad808d3f9c84482594e0da45b4181a6e5Leon Scroggins III return this; 10882f1b06b58fc3c496832afc9b6ceeb2a36ef4bfa6Leon Scroggins III } 10892f1b06b58fc3c496832afc9b6ceeb2a36ef4bfa6Leon Scroggins III 10902f1b06b58fc3c496832afc9b6ceeb2a36ef4bfa6Leon Scroggins III /** 1091e5de9aa4a9bab9c4d8288212d6352a65e9808737Leon Scroggins III * Specify whether the {@link Bitmap} should be mutable. 10920c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III * 1093e5de9aa4a9bab9c4d8288212d6352a65e9808737Leon Scroggins III * <p>By default, a {@link Bitmap} created will be immutable, but that can 1094e5de9aa4a9bab9c4d8288212d6352a65e9808737Leon Scroggins III * be changed with this call.</p> 10950c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III * 1096e5de9aa4a9bab9c4d8288212d6352a65e9808737Leon Scroggins III * <p>Mutable Bitmaps are incompatible with {@link #ALLOCATOR_HARDWARE}, 1097e5de9aa4a9bab9c4d8288212d6352a65e9808737Leon Scroggins III * because {@link Bitmap.Config#HARDWARE} Bitmaps cannot be mutable. 1098e5de9aa4a9bab9c4d8288212d6352a65e9808737Leon Scroggins III * Attempting to combine them will throw an 1099e5de9aa4a9bab9c4d8288212d6352a65e9808737Leon Scroggins III * {@link java.lang.IllegalStateException}.</p> 11000c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III * 1101e5de9aa4a9bab9c4d8288212d6352a65e9808737Leon Scroggins III * <p>Mutable Bitmaps are also incompatible with {@link #decodeDrawable}, 1102e5de9aa4a9bab9c4d8288212d6352a65e9808737Leon Scroggins III * which would require retrieving the Bitmap from the returned Drawable in 1103e5de9aa4a9bab9c4d8288212d6352a65e9808737Leon Scroggins III * order to modify. Attempting to decode a mutable {@link Drawable} will 1104e5de9aa4a9bab9c4d8288212d6352a65e9808737Leon Scroggins III * throw an {@link java.lang.IllegalStateException}.</p> 11055f7e948ad808d3f9c84482594e0da45b4181a6e5Leon Scroggins III * 11065f7e948ad808d3f9c84482594e0da45b4181a6e5Leon Scroggins III * @return this object for chaining. 11070c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III */ 11085f7e948ad808d3f9c84482594e0da45b4181a6e5Leon Scroggins III public ImageDecoder setMutable(boolean mutable) { 1109e5de9aa4a9bab9c4d8288212d6352a65e9808737Leon Scroggins III mMutable = mutable; 11105f7e948ad808d3f9c84482594e0da45b4181a6e5Leon Scroggins III return this; 11110c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III } 11120c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III 11130c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III /** 1114746a9fee937969af9be7e060335e26e098971615Leon Scroggins III * Return whether the {@link Bitmap} will be mutable. 1115746a9fee937969af9be7e060335e26e098971615Leon Scroggins III */ 1116746a9fee937969af9be7e060335e26e098971615Leon Scroggins III public boolean getMutable() { 1117746a9fee937969af9be7e060335e26e098971615Leon Scroggins III return mMutable; 1118746a9fee937969af9be7e060335e26e098971615Leon Scroggins III } 1119746a9fee937969af9be7e060335e26e098971615Leon Scroggins III 1120746a9fee937969af9be7e060335e26e098971615Leon Scroggins III /** 1121e5de9aa4a9bab9c4d8288212d6352a65e9808737Leon Scroggins III * Specify whether to potentially save RAM at the expense of quality. 11220c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III * 11235f7e948ad808d3f9c84482594e0da45b4181a6e5Leon Scroggins III * <p>Setting this to {@code true} may result in a {@link Bitmap} with a 1124a38b2135a4bf4368734567a73d2e56f1c318fee9Leon Scroggins III * denser {@link Bitmap.Config}, depending on the image. For example, an 1125a38b2135a4bf4368734567a73d2e56f1c318fee9Leon Scroggins III * opaque {@link Bitmap} with 8 bits or precision for each of its red, 1126a38b2135a4bf4368734567a73d2e56f1c318fee9Leon Scroggins III * green and blue components would decode to 1127a38b2135a4bf4368734567a73d2e56f1c318fee9Leon Scroggins III * {@link Bitmap.Config#ARGB_8888} by default, but setting this to 1128a38b2135a4bf4368734567a73d2e56f1c318fee9Leon Scroggins III * {@code true} will result in decoding to {@link Bitmap.Config#RGB_565}. 1129a38b2135a4bf4368734567a73d2e56f1c318fee9Leon Scroggins III * This necessarily lowers the quality of the output, but saves half 11305f7e948ad808d3f9c84482594e0da45b4181a6e5Leon Scroggins III * the memory used.</p> 11315f7e948ad808d3f9c84482594e0da45b4181a6e5Leon Scroggins III * 11325f7e948ad808d3f9c84482594e0da45b4181a6e5Leon Scroggins III * @return this object for chaining. 11330c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III */ 11345f7e948ad808d3f9c84482594e0da45b4181a6e5Leon Scroggins III public ImageDecoder setConserveMemory(boolean conserveMemory) { 1135a38b2135a4bf4368734567a73d2e56f1c318fee9Leon Scroggins III mConserveMemory = conserveMemory; 11365f7e948ad808d3f9c84482594e0da45b4181a6e5Leon Scroggins III return this; 11370c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III } 11380c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III 11390c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III /** 1140746a9fee937969af9be7e060335e26e098971615Leon Scroggins III * Return whether this object will try to save RAM at the expense of quality. 1141746a9fee937969af9be7e060335e26e098971615Leon Scroggins III * 1142746a9fee937969af9be7e060335e26e098971615Leon Scroggins III * <p>This returns whether {@link #setConserveMemory} was set to {@code true}. 1143746a9fee937969af9be7e060335e26e098971615Leon Scroggins III * It may still return {@code true} even if the {@code ImageDecoder} does not 1144746a9fee937969af9be7e060335e26e098971615Leon Scroggins III * have a way to save RAM at the expense of quality for this image.</p> 1145746a9fee937969af9be7e060335e26e098971615Leon Scroggins III */ 1146746a9fee937969af9be7e060335e26e098971615Leon Scroggins III public boolean getConserveMemory() { 1147746a9fee937969af9be7e060335e26e098971615Leon Scroggins III return mConserveMemory; 1148746a9fee937969af9be7e060335e26e098971615Leon Scroggins III } 1149746a9fee937969af9be7e060335e26e098971615Leon Scroggins III 1150746a9fee937969af9be7e060335e26e098971615Leon Scroggins III /** 1151e5de9aa4a9bab9c4d8288212d6352a65e9808737Leon Scroggins III * Specify whether to potentially treat the output as an alpha mask. 11520c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III * 1153e5de9aa4a9bab9c4d8288212d6352a65e9808737Leon Scroggins III * <p>If this is set to {@code true} and the image is encoded in a format 1154e5de9aa4a9bab9c4d8288212d6352a65e9808737Leon Scroggins III * with only one channel, treat that channel as alpha. Otherwise this call has 1155e5de9aa4a9bab9c4d8288212d6352a65e9808737Leon Scroggins III * no effect.</p> 11560c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III * 1157746a9fee937969af9be7e060335e26e098971615Leon Scroggins III * <p>setDecodeAsAlphaMask is incompatible with {@link #ALLOCATOR_HARDWARE}. Trying to 1158e5de9aa4a9bab9c4d8288212d6352a65e9808737Leon Scroggins III * combine them will result in {@link #decodeDrawable}/ 1159e5de9aa4a9bab9c4d8288212d6352a65e9808737Leon Scroggins III * {@link #decodeBitmap} throwing an 1160e5de9aa4a9bab9c4d8288212d6352a65e9808737Leon Scroggins III * {@link java.lang.IllegalStateException}.</p> 11615f7e948ad808d3f9c84482594e0da45b4181a6e5Leon Scroggins III * 11625f7e948ad808d3f9c84482594e0da45b4181a6e5Leon Scroggins III * @return this object for chaining. 11630c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III */ 1164746a9fee937969af9be7e060335e26e098971615Leon Scroggins III public ImageDecoder setDecodeAsAlphaMask(boolean decodeAsAlphaMask) { 1165746a9fee937969af9be7e060335e26e098971615Leon Scroggins III mDecodeAsAlphaMask = decodeAsAlphaMask; 11665f7e948ad808d3f9c84482594e0da45b4181a6e5Leon Scroggins III return this; 11670c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III } 11680c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III 1169746a9fee937969af9be7e060335e26e098971615Leon Scroggins III /** @removed 1170746a9fee937969af9be7e060335e26e098971615Leon Scroggins III * @deprecated Call {@link #setDecodeAsAlphaMask} instead. 1171746a9fee937969af9be7e060335e26e098971615Leon Scroggins III */ 1172746a9fee937969af9be7e060335e26e098971615Leon Scroggins III @java.lang.Deprecated 1173746a9fee937969af9be7e060335e26e098971615Leon Scroggins III public ImageDecoder setAsAlphaMask(boolean asAlphaMask) { 1174746a9fee937969af9be7e060335e26e098971615Leon Scroggins III return this.setDecodeAsAlphaMask(asAlphaMask); 1175746a9fee937969af9be7e060335e26e098971615Leon Scroggins III } 1176746a9fee937969af9be7e060335e26e098971615Leon Scroggins III 1177746a9fee937969af9be7e060335e26e098971615Leon Scroggins III /** 1178746a9fee937969af9be7e060335e26e098971615Leon Scroggins III * Return whether to treat single channel input as alpha. 1179746a9fee937969af9be7e060335e26e098971615Leon Scroggins III * 1180746a9fee937969af9be7e060335e26e098971615Leon Scroggins III * <p>This returns whether {@link #setDecodeAsAlphaMask} was set to {@code true}. 1181746a9fee937969af9be7e060335e26e098971615Leon Scroggins III * It may still return {@code true} even if the image has more than one 1182746a9fee937969af9be7e060335e26e098971615Leon Scroggins III * channel and therefore will not be treated as an alpha mask.</p> 1183746a9fee937969af9be7e060335e26e098971615Leon Scroggins III */ 1184746a9fee937969af9be7e060335e26e098971615Leon Scroggins III public boolean getDecodeAsAlphaMask() { 1185746a9fee937969af9be7e060335e26e098971615Leon Scroggins III return mDecodeAsAlphaMask; 1186746a9fee937969af9be7e060335e26e098971615Leon Scroggins III } 1187746a9fee937969af9be7e060335e26e098971615Leon Scroggins III 1188746a9fee937969af9be7e060335e26e098971615Leon Scroggins III /** @removed 1189746a9fee937969af9be7e060335e26e098971615Leon Scroggins III * @deprecated Call {@link #getDecodeAsAlphaMask} instead. 1190746a9fee937969af9be7e060335e26e098971615Leon Scroggins III */ 1191746a9fee937969af9be7e060335e26e098971615Leon Scroggins III @java.lang.Deprecated 1192746a9fee937969af9be7e060335e26e098971615Leon Scroggins III public boolean getAsAlphaMask() { 1193746a9fee937969af9be7e060335e26e098971615Leon Scroggins III return this.getDecodeAsAlphaMask(); 1194746a9fee937969af9be7e060335e26e098971615Leon Scroggins III } 1195746a9fee937969af9be7e060335e26e098971615Leon Scroggins III 11961a69f4598faef083d0123bb9b6bfcd6acfdec4e0Leon Scroggins III /** 11971a69f4598faef083d0123bb9b6bfcd6acfdec4e0Leon Scroggins III * Specify the desired {@link ColorSpace} for the output. 11981a69f4598faef083d0123bb9b6bfcd6acfdec4e0Leon Scroggins III * 11991a69f4598faef083d0123bb9b6bfcd6acfdec4e0Leon Scroggins III * <p>If non-null, the decoder will try to decode into this 12001a69f4598faef083d0123bb9b6bfcd6acfdec4e0Leon Scroggins III * color space. If it is null, which is the default, or the request cannot 12011a69f4598faef083d0123bb9b6bfcd6acfdec4e0Leon Scroggins III * be met, the decoder will pick either the color space embedded in the 12021a69f4598faef083d0123bb9b6bfcd6acfdec4e0Leon Scroggins III * image or the color space best suited for the requested image 12031a69f4598faef083d0123bb9b6bfcd6acfdec4e0Leon Scroggins III * configuration (for instance {@link ColorSpace.Named#SRGB sRGB} for 12041a69f4598faef083d0123bb9b6bfcd6acfdec4e0Leon Scroggins III * the {@link Bitmap.Config#ARGB_8888} configuration).</p> 12051a69f4598faef083d0123bb9b6bfcd6acfdec4e0Leon Scroggins III * 12061a69f4598faef083d0123bb9b6bfcd6acfdec4e0Leon Scroggins III * <p>{@link Bitmap.Config#RGBA_F16} always uses the 12071a69f4598faef083d0123bb9b6bfcd6acfdec4e0Leon Scroggins III * {@link ColorSpace.Named#LINEAR_EXTENDED_SRGB scRGB} color space). 12081a69f4598faef083d0123bb9b6bfcd6acfdec4e0Leon Scroggins III * Bitmaps in other configurations without an embedded color space are 12091a69f4598faef083d0123bb9b6bfcd6acfdec4e0Leon Scroggins III * assumed to be in the {@link ColorSpace.Named#SRGB sRGB} color space.</p> 12101a69f4598faef083d0123bb9b6bfcd6acfdec4e0Leon Scroggins III * 12111a69f4598faef083d0123bb9b6bfcd6acfdec4e0Leon Scroggins III * <p class="note">Only {@link ColorSpace.Model#RGB} color spaces are 12121a69f4598faef083d0123bb9b6bfcd6acfdec4e0Leon Scroggins III * currently supported. An <code>IllegalArgumentException</code> will 12131a69f4598faef083d0123bb9b6bfcd6acfdec4e0Leon Scroggins III * be thrown by the decode methods when setting a non-RGB color space 12141a69f4598faef083d0123bb9b6bfcd6acfdec4e0Leon Scroggins III * such as {@link ColorSpace.Named#CIE_LAB Lab}.</p> 12151a69f4598faef083d0123bb9b6bfcd6acfdec4e0Leon Scroggins III * 12161a69f4598faef083d0123bb9b6bfcd6acfdec4e0Leon Scroggins III * <p class="note">The specified color space's transfer function must be 12171a69f4598faef083d0123bb9b6bfcd6acfdec4e0Leon Scroggins III * an {@link ColorSpace.Rgb.TransferParameters ICC parametric curve}. An 12181a69f4598faef083d0123bb9b6bfcd6acfdec4e0Leon Scroggins III * <code>IllegalArgumentException</code> will be thrown by the decode methods 12191a69f4598faef083d0123bb9b6bfcd6acfdec4e0Leon Scroggins III * if calling {@link ColorSpace.Rgb#getTransferParameters()} on the 12201a69f4598faef083d0123bb9b6bfcd6acfdec4e0Leon Scroggins III * specified color space returns null.</p> 12211a69f4598faef083d0123bb9b6bfcd6acfdec4e0Leon Scroggins III */ 12221a69f4598faef083d0123bb9b6bfcd6acfdec4e0Leon Scroggins III public ImageDecoder setTargetColorSpace(ColorSpace colorSpace) { 12231a69f4598faef083d0123bb9b6bfcd6acfdec4e0Leon Scroggins III mDesiredColorSpace = colorSpace; 12241a69f4598faef083d0123bb9b6bfcd6acfdec4e0Leon Scroggins III return this; 12251a69f4598faef083d0123bb9b6bfcd6acfdec4e0Leon Scroggins III } 12261a69f4598faef083d0123bb9b6bfcd6acfdec4e0Leon Scroggins III 1227ed074fd70011cf804a14b5cf53ffd4b529c5f367Leon Scroggins III @Override 1228ed074fd70011cf804a14b5cf53ffd4b529c5f367Leon Scroggins III public void close() { 1229ed074fd70011cf804a14b5cf53ffd4b529c5f367Leon Scroggins III mCloseGuard.close(); 1230ed074fd70011cf804a14b5cf53ffd4b529c5f367Leon Scroggins III if (!mClosed.compareAndSet(false, true)) { 12310c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III return; 12320c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III } 1233ed074fd70011cf804a14b5cf53ffd4b529c5f367Leon Scroggins III nClose(mNativePtr); 12340c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III mNativePtr = 0; 1235ed074fd70011cf804a14b5cf53ffd4b529c5f367Leon Scroggins III 12360b49f5725cabd64d27960b1b017e5c009f701cf8Leon Scroggins III if (mOwnsInputStream) { 12370b49f5725cabd64d27960b1b017e5c009f701cf8Leon Scroggins III IoUtils.closeQuietly(mInputStream); 12380b49f5725cabd64d27960b1b017e5c009f701cf8Leon Scroggins III } 1239ed074fd70011cf804a14b5cf53ffd4b529c5f367Leon Scroggins III IoUtils.closeQuietly(mAssetFd); 1240ed074fd70011cf804a14b5cf53ffd4b529c5f367Leon Scroggins III 1241ed074fd70011cf804a14b5cf53ffd4b529c5f367Leon Scroggins III mInputStream = null; 1242ed074fd70011cf804a14b5cf53ffd4b529c5f367Leon Scroggins III mAssetFd = null; 1243ed074fd70011cf804a14b5cf53ffd4b529c5f367Leon Scroggins III mTempStorage = null; 12440c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III } 12450c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III 12460c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III private void checkState() { 12470c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III if (mNativePtr == 0) { 1248ed074fd70011cf804a14b5cf53ffd4b529c5f367Leon Scroggins III throw new IllegalStateException("Cannot use closed ImageDecoder!"); 12490c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III } 12500c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III 12510c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III checkSubset(mDesiredWidth, mDesiredHeight, mCropRect); 12520c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III 1253e5de9aa4a9bab9c4d8288212d6352a65e9808737Leon Scroggins III if (mAllocator == ALLOCATOR_HARDWARE) { 12540c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III if (mMutable) { 12550c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III throw new IllegalStateException("Cannot make mutable HARDWARE Bitmap!"); 12560c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III } 1257746a9fee937969af9be7e060335e26e098971615Leon Scroggins III if (mDecodeAsAlphaMask) { 12580c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III throw new IllegalStateException("Cannot make HARDWARE Alpha mask Bitmap!"); 12590c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III } 12600c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III } 12610c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III 1262e5de9aa4a9bab9c4d8288212d6352a65e9808737Leon Scroggins III if (mPostProcessor != null && mRequireUnpremultiplied) { 12630c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III throw new IllegalStateException("Cannot draw to unpremultiplied pixels!"); 12640c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III } 12651a69f4598faef083d0123bb9b6bfcd6acfdec4e0Leon Scroggins III 12661a69f4598faef083d0123bb9b6bfcd6acfdec4e0Leon Scroggins III if (mDesiredColorSpace != null) { 12671a69f4598faef083d0123bb9b6bfcd6acfdec4e0Leon Scroggins III if (!(mDesiredColorSpace instanceof ColorSpace.Rgb)) { 12681a69f4598faef083d0123bb9b6bfcd6acfdec4e0Leon Scroggins III throw new IllegalArgumentException("The target color space must use the " 12691a69f4598faef083d0123bb9b6bfcd6acfdec4e0Leon Scroggins III + "RGB color model - provided: " + mDesiredColorSpace); 12701a69f4598faef083d0123bb9b6bfcd6acfdec4e0Leon Scroggins III } 12711a69f4598faef083d0123bb9b6bfcd6acfdec4e0Leon Scroggins III if (((ColorSpace.Rgb) mDesiredColorSpace).getTransferParameters() == null) { 12721a69f4598faef083d0123bb9b6bfcd6acfdec4e0Leon Scroggins III throw new IllegalArgumentException("The target color space must use an " 12731a69f4598faef083d0123bb9b6bfcd6acfdec4e0Leon Scroggins III + "ICC parametric transfer function - provided: " + mDesiredColorSpace); 12741a69f4598faef083d0123bb9b6bfcd6acfdec4e0Leon Scroggins III } 12751a69f4598faef083d0123bb9b6bfcd6acfdec4e0Leon Scroggins III } 12760c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III } 12770c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III 12780c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III private static void checkSubset(int width, int height, Rect r) { 12790c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III if (r == null) { 12800c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III return; 12810c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III } 12820c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III if (r.left < 0 || r.top < 0 || r.right > width || r.bottom > height) { 12830c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III throw new IllegalStateException("Subset " + r + " not contained by " 12840c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III + "scaled image bounds: (" + width + " x " + height + ")"); 12850c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III } 12860c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III } 12870c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III 1288e5de9aa4a9bab9c4d8288212d6352a65e9808737Leon Scroggins III @NonNull 1289c9aa856559ca3b08c9409164b2f86c218c71505fLeon Scroggins III private Bitmap decodeBitmapInternal() throws IOException { 12908c9d8f2aec65e449005a4a69c54f691ebd514e52Leon Scroggins III checkState(); 12911d2bf2b846f0a98f7403bbc791adb2969685d87aLeon Scroggins III return nDecodeBitmap(mNativePtr, this, mPostProcessor != null, 12921d2bf2b846f0a98f7403bbc791adb2969685d87aLeon Scroggins III mDesiredWidth, mDesiredHeight, mCropRect, 12938c9d8f2aec65e449005a4a69c54f691ebd514e52Leon Scroggins III mMutable, mAllocator, mRequireUnpremultiplied, 12941a69f4598faef083d0123bb9b6bfcd6acfdec4e0Leon Scroggins III mConserveMemory, mDecodeAsAlphaMask, mDesiredColorSpace); 12958c9d8f2aec65e449005a4a69c54f691ebd514e52Leon Scroggins III } 12968c9d8f2aec65e449005a4a69c54f691ebd514e52Leon Scroggins III 1297e5de9aa4a9bab9c4d8288212d6352a65e9808737Leon Scroggins III private void callHeaderDecoded(@Nullable OnHeaderDecodedListener listener, 1298e5de9aa4a9bab9c4d8288212d6352a65e9808737Leon Scroggins III @NonNull Source src) { 1299e5de9aa4a9bab9c4d8288212d6352a65e9808737Leon Scroggins III if (listener != null) { 1300e5de9aa4a9bab9c4d8288212d6352a65e9808737Leon Scroggins III ImageInfo info = new ImageInfo(this); 1301e5de9aa4a9bab9c4d8288212d6352a65e9808737Leon Scroggins III try { 1302e5de9aa4a9bab9c4d8288212d6352a65e9808737Leon Scroggins III listener.onHeaderDecoded(this, info, src); 1303e5de9aa4a9bab9c4d8288212d6352a65e9808737Leon Scroggins III } finally { 1304e5de9aa4a9bab9c4d8288212d6352a65e9808737Leon Scroggins III info.mDecoder = null; 1305e5de9aa4a9bab9c4d8288212d6352a65e9808737Leon Scroggins III } 1306e5de9aa4a9bab9c4d8288212d6352a65e9808737Leon Scroggins III } 1307e5de9aa4a9bab9c4d8288212d6352a65e9808737Leon Scroggins III } 1308e5de9aa4a9bab9c4d8288212d6352a65e9808737Leon Scroggins III 13090c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III /** 1310b1cc8e64374832c8b296f609bebabff068ded460Leon Scroggins III * Create a {@link Drawable} from a {@code Source}. 1311b1cc8e64374832c8b296f609bebabff068ded460Leon Scroggins III * 1312b1cc8e64374832c8b296f609bebabff068ded460Leon Scroggins III * @param src representing the encoded image. 1313b1cc8e64374832c8b296f609bebabff068ded460Leon Scroggins III * @param listener for learning the {@link ImageInfo} and changing any 1314c9aa856559ca3b08c9409164b2f86c218c71505fLeon Scroggins III * default settings on the {@code ImageDecoder}. This will be called on 1315c9aa856559ca3b08c9409164b2f86c218c71505fLeon Scroggins III * the same thread as {@code decodeDrawable} before that method returns. 1316b1cc8e64374832c8b296f609bebabff068ded460Leon Scroggins III * @return Drawable for displaying the image. 1317ed074fd70011cf804a14b5cf53ffd4b529c5f367Leon Scroggins III * @throws IOException if {@code src} is not found, is an unsupported 1318ed074fd70011cf804a14b5cf53ffd4b529c5f367Leon Scroggins III * format, or cannot be decoded for any reason. 13190c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III */ 1320ed074fd70011cf804a14b5cf53ffd4b529c5f367Leon Scroggins III @NonNull 1321b1cc8e64374832c8b296f609bebabff068ded460Leon Scroggins III public static Drawable decodeDrawable(@NonNull Source src, 1322c9aa856559ca3b08c9409164b2f86c218c71505fLeon Scroggins III @NonNull OnHeaderDecodedListener listener) throws IOException { 1323c9aa856559ca3b08c9409164b2f86c218c71505fLeon Scroggins III if (listener == null) { 1324c9aa856559ca3b08c9409164b2f86c218c71505fLeon Scroggins III throw new IllegalArgumentException("listener cannot be null! " 1325c9aa856559ca3b08c9409164b2f86c218c71505fLeon Scroggins III + "Use decodeDrawable(Source) to not have a listener"); 1326c9aa856559ca3b08c9409164b2f86c218c71505fLeon Scroggins III } 1327c9aa856559ca3b08c9409164b2f86c218c71505fLeon Scroggins III return decodeDrawableImpl(src, listener); 1328c9aa856559ca3b08c9409164b2f86c218c71505fLeon Scroggins III } 1329c9aa856559ca3b08c9409164b2f86c218c71505fLeon Scroggins III 1330c9aa856559ca3b08c9409164b2f86c218c71505fLeon Scroggins III @NonNull 1331c9aa856559ca3b08c9409164b2f86c218c71505fLeon Scroggins III private static Drawable decodeDrawableImpl(@NonNull Source src, 1332b1cc8e64374832c8b296f609bebabff068ded460Leon Scroggins III @Nullable OnHeaderDecodedListener listener) throws IOException { 1333ed074fd70011cf804a14b5cf53ffd4b529c5f367Leon Scroggins III try (ImageDecoder decoder = src.createImageDecoder()) { 1334e5de9aa4a9bab9c4d8288212d6352a65e9808737Leon Scroggins III decoder.mSource = src; 1335e5de9aa4a9bab9c4d8288212d6352a65e9808737Leon Scroggins III decoder.callHeaderDecoded(listener, src); 13360c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III 1337ed074fd70011cf804a14b5cf53ffd4b529c5f367Leon Scroggins III if (decoder.mRequireUnpremultiplied) { 1338ed074fd70011cf804a14b5cf53ffd4b529c5f367Leon Scroggins III // Though this could be supported (ignored) for opaque images, 1339ed074fd70011cf804a14b5cf53ffd4b529c5f367Leon Scroggins III // it seems better to always report this error. 1340ed074fd70011cf804a14b5cf53ffd4b529c5f367Leon Scroggins III throw new IllegalStateException("Cannot decode a Drawable " + 1341ed074fd70011cf804a14b5cf53ffd4b529c5f367Leon Scroggins III "with unpremultiplied pixels!"); 1342ed074fd70011cf804a14b5cf53ffd4b529c5f367Leon Scroggins III } 13430c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III 1344ed074fd70011cf804a14b5cf53ffd4b529c5f367Leon Scroggins III if (decoder.mMutable) { 1345ed074fd70011cf804a14b5cf53ffd4b529c5f367Leon Scroggins III throw new IllegalStateException("Cannot decode a mutable " + 1346ed074fd70011cf804a14b5cf53ffd4b529c5f367Leon Scroggins III "Drawable!"); 1347ed074fd70011cf804a14b5cf53ffd4b529c5f367Leon Scroggins III } 13480c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III 134966c6d78908e0203a497c2e97398c824b2591ea19Derek Sollenberger // this call potentially manipulates the decoder so it must be performed prior to 135066c6d78908e0203a497c2e97398c824b2591ea19Derek Sollenberger // decoding the bitmap and after decode set the density on the resulting bitmap 135166c6d78908e0203a497c2e97398c824b2591ea19Derek Sollenberger final int srcDensity = computeDensity(src, decoder); 1352671cce2605ed50c9aba73ab5bd530cb7741c53cdLeon Scroggins III if (decoder.mAnimated) { 1353671cce2605ed50c9aba73ab5bd530cb7741c53cdLeon Scroggins III // AnimatedImageDrawable calls postProcessAndRelease only if 1354e5de9aa4a9bab9c4d8288212d6352a65e9808737Leon Scroggins III // mPostProcessor exists. 1355e5de9aa4a9bab9c4d8288212d6352a65e9808737Leon Scroggins III ImageDecoder postProcessPtr = decoder.mPostProcessor == null ? 1356671cce2605ed50c9aba73ab5bd530cb7741c53cdLeon Scroggins III null : decoder; 1357671cce2605ed50c9aba73ab5bd530cb7741c53cdLeon Scroggins III Drawable d = new AnimatedImageDrawable(decoder.mNativePtr, 1358671cce2605ed50c9aba73ab5bd530cb7741c53cdLeon Scroggins III postProcessPtr, decoder.mDesiredWidth, 135966c6d78908e0203a497c2e97398c824b2591ea19Derek Sollenberger decoder.mDesiredHeight, srcDensity, 136066c6d78908e0203a497c2e97398c824b2591ea19Derek Sollenberger src.computeDstDensity(), decoder.mCropRect, 1361671cce2605ed50c9aba73ab5bd530cb7741c53cdLeon Scroggins III decoder.mInputStream, decoder.mAssetFd); 1362671cce2605ed50c9aba73ab5bd530cb7741c53cdLeon Scroggins III // d has taken ownership of these objects. 1363671cce2605ed50c9aba73ab5bd530cb7741c53cdLeon Scroggins III decoder.mInputStream = null; 1364671cce2605ed50c9aba73ab5bd530cb7741c53cdLeon Scroggins III decoder.mAssetFd = null; 1365671cce2605ed50c9aba73ab5bd530cb7741c53cdLeon Scroggins III return d; 1366671cce2605ed50c9aba73ab5bd530cb7741c53cdLeon Scroggins III } 1367671cce2605ed50c9aba73ab5bd530cb7741c53cdLeon Scroggins III 1368c9aa856559ca3b08c9409164b2f86c218c71505fLeon Scroggins III Bitmap bm = decoder.decodeBitmapInternal(); 136966c6d78908e0203a497c2e97398c824b2591ea19Derek Sollenberger bm.setDensity(srcDensity); 13700c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III 137166c6d78908e0203a497c2e97398c824b2591ea19Derek Sollenberger Resources res = src.getResources(); 13720c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III byte[] np = bm.getNinePatchChunk(); 13730c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III if (np != null && NinePatch.isNinePatchChunk(np)) { 13740c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III Rect opticalInsets = new Rect(); 13750c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III bm.getOpticalInsets(opticalInsets); 13762f1b06b58fc3c496832afc9b6ceeb2a36ef4bfa6Leon Scroggins III Rect padding = decoder.mOutPaddingRect; 13772f1b06b58fc3c496832afc9b6ceeb2a36ef4bfa6Leon Scroggins III if (padding == null) { 13782f1b06b58fc3c496832afc9b6ceeb2a36ef4bfa6Leon Scroggins III padding = new Rect(); 13792f1b06b58fc3c496832afc9b6ceeb2a36ef4bfa6Leon Scroggins III } 13800c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III nGetPadding(decoder.mNativePtr, padding); 13810c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III return new NinePatchDrawable(res, bm, np, padding, 13820c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III opticalInsets, null); 13830c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III } 13840c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III 13850c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III return new BitmapDrawable(res, bm); 13860c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III } 13870c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III } 13880c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III 13890c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III /** 1390b1cc8e64374832c8b296f609bebabff068ded460Leon Scroggins III * See {@link #decodeDrawable(Source, OnHeaderDecodedListener)}. 1391b1cc8e64374832c8b296f609bebabff068ded460Leon Scroggins III */ 1392b1cc8e64374832c8b296f609bebabff068ded460Leon Scroggins III @NonNull 1393b1cc8e64374832c8b296f609bebabff068ded460Leon Scroggins III public static Drawable decodeDrawable(@NonNull Source src) 1394b1cc8e64374832c8b296f609bebabff068ded460Leon Scroggins III throws IOException { 1395c9aa856559ca3b08c9409164b2f86c218c71505fLeon Scroggins III return decodeDrawableImpl(src, null); 1396b1cc8e64374832c8b296f609bebabff068ded460Leon Scroggins III } 1397b1cc8e64374832c8b296f609bebabff068ded460Leon Scroggins III 1398b1cc8e64374832c8b296f609bebabff068ded460Leon Scroggins III /** 1399b1cc8e64374832c8b296f609bebabff068ded460Leon Scroggins III * Create a {@link Bitmap} from a {@code Source}. 1400b1cc8e64374832c8b296f609bebabff068ded460Leon Scroggins III * 1401b1cc8e64374832c8b296f609bebabff068ded460Leon Scroggins III * @param src representing the encoded image. 1402b1cc8e64374832c8b296f609bebabff068ded460Leon Scroggins III * @param listener for learning the {@link ImageInfo} and changing any 1403c9aa856559ca3b08c9409164b2f86c218c71505fLeon Scroggins III * default settings on the {@code ImageDecoder}. This will be called on 1404c9aa856559ca3b08c9409164b2f86c218c71505fLeon Scroggins III * the same thread as {@code decodeBitmap} before that method returns. 1405b1cc8e64374832c8b296f609bebabff068ded460Leon Scroggins III * @return Bitmap containing the image. 1406ed074fd70011cf804a14b5cf53ffd4b529c5f367Leon Scroggins III * @throws IOException if {@code src} is not found, is an unsupported 1407ed074fd70011cf804a14b5cf53ffd4b529c5f367Leon Scroggins III * format, or cannot be decoded for any reason. 14080c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III */ 1409ed074fd70011cf804a14b5cf53ffd4b529c5f367Leon Scroggins III @NonNull 1410b1cc8e64374832c8b296f609bebabff068ded460Leon Scroggins III public static Bitmap decodeBitmap(@NonNull Source src, 1411c9aa856559ca3b08c9409164b2f86c218c71505fLeon Scroggins III @NonNull OnHeaderDecodedListener listener) throws IOException { 1412c9aa856559ca3b08c9409164b2f86c218c71505fLeon Scroggins III if (listener == null) { 1413c9aa856559ca3b08c9409164b2f86c218c71505fLeon Scroggins III throw new IllegalArgumentException("listener cannot be null! " 1414c9aa856559ca3b08c9409164b2f86c218c71505fLeon Scroggins III + "Use decodeBitmap(Source) to not have a listener"); 1415c9aa856559ca3b08c9409164b2f86c218c71505fLeon Scroggins III } 1416c9aa856559ca3b08c9409164b2f86c218c71505fLeon Scroggins III return decodeBitmapImpl(src, listener); 1417c9aa856559ca3b08c9409164b2f86c218c71505fLeon Scroggins III } 1418c9aa856559ca3b08c9409164b2f86c218c71505fLeon Scroggins III 1419c9aa856559ca3b08c9409164b2f86c218c71505fLeon Scroggins III @NonNull 1420c9aa856559ca3b08c9409164b2f86c218c71505fLeon Scroggins III private static Bitmap decodeBitmapImpl(@NonNull Source src, 1421b1cc8e64374832c8b296f609bebabff068ded460Leon Scroggins III @Nullable OnHeaderDecodedListener listener) throws IOException { 1422ed074fd70011cf804a14b5cf53ffd4b529c5f367Leon Scroggins III try (ImageDecoder decoder = src.createImageDecoder()) { 1423e5de9aa4a9bab9c4d8288212d6352a65e9808737Leon Scroggins III decoder.mSource = src; 1424e5de9aa4a9bab9c4d8288212d6352a65e9808737Leon Scroggins III decoder.callHeaderDecoded(listener, src); 14250c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III 142666c6d78908e0203a497c2e97398c824b2591ea19Derek Sollenberger // this call potentially manipulates the decoder so it must be performed prior to 142766c6d78908e0203a497c2e97398c824b2591ea19Derek Sollenberger // decoding the bitmap 142866c6d78908e0203a497c2e97398c824b2591ea19Derek Sollenberger final int srcDensity = computeDensity(src, decoder); 1429c9aa856559ca3b08c9409164b2f86c218c71505fLeon Scroggins III Bitmap bm = decoder.decodeBitmapInternal(); 143066c6d78908e0203a497c2e97398c824b2591ea19Derek Sollenberger bm.setDensity(srcDensity); 14312f1b06b58fc3c496832afc9b6ceeb2a36ef4bfa6Leon Scroggins III 14322f1b06b58fc3c496832afc9b6ceeb2a36ef4bfa6Leon Scroggins III Rect padding = decoder.mOutPaddingRect; 14332f1b06b58fc3c496832afc9b6ceeb2a36ef4bfa6Leon Scroggins III if (padding != null) { 14342f1b06b58fc3c496832afc9b6ceeb2a36ef4bfa6Leon Scroggins III byte[] np = bm.getNinePatchChunk(); 14352f1b06b58fc3c496832afc9b6ceeb2a36ef4bfa6Leon Scroggins III if (np != null && NinePatch.isNinePatchChunk(np)) { 14362f1b06b58fc3c496832afc9b6ceeb2a36ef4bfa6Leon Scroggins III nGetPadding(decoder.mNativePtr, padding); 14372f1b06b58fc3c496832afc9b6ceeb2a36ef4bfa6Leon Scroggins III } 14382f1b06b58fc3c496832afc9b6ceeb2a36ef4bfa6Leon Scroggins III } 14392f1b06b58fc3c496832afc9b6ceeb2a36ef4bfa6Leon Scroggins III 144066c6d78908e0203a497c2e97398c824b2591ea19Derek Sollenberger return bm; 144166c6d78908e0203a497c2e97398c824b2591ea19Derek Sollenberger } 144266c6d78908e0203a497c2e97398c824b2591ea19Derek Sollenberger } 144366c6d78908e0203a497c2e97398c824b2591ea19Derek Sollenberger 144466c6d78908e0203a497c2e97398c824b2591ea19Derek Sollenberger // This method may modify the decoder so it must be called prior to performing the decode 144566c6d78908e0203a497c2e97398c824b2591ea19Derek Sollenberger private static int computeDensity(@NonNull Source src, @NonNull ImageDecoder decoder) { 144666c6d78908e0203a497c2e97398c824b2591ea19Derek Sollenberger // if the caller changed the size then we treat the density as unknown 144766c6d78908e0203a497c2e97398c824b2591ea19Derek Sollenberger if (decoder.requestedResize()) { 144866c6d78908e0203a497c2e97398c824b2591ea19Derek Sollenberger return Bitmap.DENSITY_NONE; 144966c6d78908e0203a497c2e97398c824b2591ea19Derek Sollenberger } 145066c6d78908e0203a497c2e97398c824b2591ea19Derek Sollenberger 145166c6d78908e0203a497c2e97398c824b2591ea19Derek Sollenberger // Special stuff for compatibility mode: if the target density is not 145266c6d78908e0203a497c2e97398c824b2591ea19Derek Sollenberger // the same as the display density, but the resource -is- the same as 145366c6d78908e0203a497c2e97398c824b2591ea19Derek Sollenberger // the display density, then don't scale it down to the target density. 145466c6d78908e0203a497c2e97398c824b2591ea19Derek Sollenberger // This allows us to load the system's density-correct resources into 145566c6d78908e0203a497c2e97398c824b2591ea19Derek Sollenberger // an application in compatibility mode, without scaling those down 145666c6d78908e0203a497c2e97398c824b2591ea19Derek Sollenberger // to the compatibility density only to have them scaled back up when 145766c6d78908e0203a497c2e97398c824b2591ea19Derek Sollenberger // drawn to the screen. 145866c6d78908e0203a497c2e97398c824b2591ea19Derek Sollenberger Resources res = src.getResources(); 145966c6d78908e0203a497c2e97398c824b2591ea19Derek Sollenberger final int srcDensity = src.getDensity(); 146066c6d78908e0203a497c2e97398c824b2591ea19Derek Sollenberger if (res != null && res.getDisplayMetrics().noncompatDensityDpi == srcDensity) { 146166c6d78908e0203a497c2e97398c824b2591ea19Derek Sollenberger return srcDensity; 14620c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III } 146366c6d78908e0203a497c2e97398c824b2591ea19Derek Sollenberger 14648290eaba47b99398fbe0bd59138f902bde558ecbLeon Scroggins III // For P and above, only resize if it would be a downscale. Scale up prior 14658290eaba47b99398fbe0bd59138f902bde558ecbLeon Scroggins III // to P in case the app relies on the Bitmap's size without considering density. 146666c6d78908e0203a497c2e97398c824b2591ea19Derek Sollenberger final int dstDensity = src.computeDstDensity(); 14678290eaba47b99398fbe0bd59138f902bde558ecbLeon Scroggins III if (srcDensity == Bitmap.DENSITY_NONE || srcDensity == dstDensity 14688290eaba47b99398fbe0bd59138f902bde558ecbLeon Scroggins III || (srcDensity < dstDensity && sApiLevel >= Build.VERSION_CODES.P)) { 14698290eaba47b99398fbe0bd59138f902bde558ecbLeon Scroggins III return srcDensity; 147066c6d78908e0203a497c2e97398c824b2591ea19Derek Sollenberger } 147166c6d78908e0203a497c2e97398c824b2591ea19Derek Sollenberger 14728290eaba47b99398fbe0bd59138f902bde558ecbLeon Scroggins III float scale = (float) dstDensity / srcDensity; 14738290eaba47b99398fbe0bd59138f902bde558ecbLeon Scroggins III int scaledWidth = (int) (decoder.mWidth * scale + 0.5f); 14748290eaba47b99398fbe0bd59138f902bde558ecbLeon Scroggins III int scaledHeight = (int) (decoder.mHeight * scale + 0.5f); 147564481195e13e2dd7197fff569344e5a263b7871aLeon Scroggins III decoder.setTargetSize(scaledWidth, scaledHeight); 14768290eaba47b99398fbe0bd59138f902bde558ecbLeon Scroggins III return dstDensity; 14770c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III } 14780c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III 1479e5de9aa4a9bab9c4d8288212d6352a65e9808737Leon Scroggins III @NonNull 14801fad09d4d3f43112abd842da4c94cf00fb1cb46dLeon Scroggins III private String getMimeType() { 14811fad09d4d3f43112abd842da4c94cf00fb1cb46dLeon Scroggins III return nGetMimeType(mNativePtr); 14821fad09d4d3f43112abd842da4c94cf00fb1cb46dLeon Scroggins III } 14831fad09d4d3f43112abd842da4c94cf00fb1cb46dLeon Scroggins III 14841a69f4598faef083d0123bb9b6bfcd6acfdec4e0Leon Scroggins III @Nullable 14851a69f4598faef083d0123bb9b6bfcd6acfdec4e0Leon Scroggins III private ColorSpace getColorSpace() { 14861a69f4598faef083d0123bb9b6bfcd6acfdec4e0Leon Scroggins III return nGetColorSpace(mNativePtr); 14871a69f4598faef083d0123bb9b6bfcd6acfdec4e0Leon Scroggins III } 14881a69f4598faef083d0123bb9b6bfcd6acfdec4e0Leon Scroggins III 1489b1cc8e64374832c8b296f609bebabff068ded460Leon Scroggins III /** 1490b1cc8e64374832c8b296f609bebabff068ded460Leon Scroggins III * See {@link #decodeBitmap(Source, OnHeaderDecodedListener)}. 1491b1cc8e64374832c8b296f609bebabff068ded460Leon Scroggins III */ 1492b1cc8e64374832c8b296f609bebabff068ded460Leon Scroggins III @NonNull 1493b1cc8e64374832c8b296f609bebabff068ded460Leon Scroggins III public static Bitmap decodeBitmap(@NonNull Source src) throws IOException { 1494c9aa856559ca3b08c9409164b2f86c218c71505fLeon Scroggins III return decodeBitmapImpl(src, null); 1495b1cc8e64374832c8b296f609bebabff068ded460Leon Scroggins III } 1496b1cc8e64374832c8b296f609bebabff068ded460Leon Scroggins III 14978c9d8f2aec65e449005a4a69c54f691ebd514e52Leon Scroggins III /** 14988c9d8f2aec65e449005a4a69c54f691ebd514e52Leon Scroggins III * Private method called by JNI. 14998c9d8f2aec65e449005a4a69c54f691ebd514e52Leon Scroggins III */ 15008c9d8f2aec65e449005a4a69c54f691ebd514e52Leon Scroggins III @SuppressWarnings("unused") 1501e5de9aa4a9bab9c4d8288212d6352a65e9808737Leon Scroggins III private int postProcessAndRelease(@NonNull Canvas canvas) { 15028c9d8f2aec65e449005a4a69c54f691ebd514e52Leon Scroggins III try { 1503e5de9aa4a9bab9c4d8288212d6352a65e9808737Leon Scroggins III return mPostProcessor.onPostProcess(canvas); 15048c9d8f2aec65e449005a4a69c54f691ebd514e52Leon Scroggins III } finally { 15058c9d8f2aec65e449005a4a69c54f691ebd514e52Leon Scroggins III canvas.release(); 15068c9d8f2aec65e449005a4a69c54f691ebd514e52Leon Scroggins III } 15078c9d8f2aec65e449005a4a69c54f691ebd514e52Leon Scroggins III } 15088c9d8f2aec65e449005a4a69c54f691ebd514e52Leon Scroggins III 1509e5de9aa4a9bab9c4d8288212d6352a65e9808737Leon Scroggins III /** 1510e5de9aa4a9bab9c4d8288212d6352a65e9808737Leon Scroggins III * Private method called by JNI. 1511e5de9aa4a9bab9c4d8288212d6352a65e9808737Leon Scroggins III */ 1512e5de9aa4a9bab9c4d8288212d6352a65e9808737Leon Scroggins III @SuppressWarnings("unused") 1513cf7294fda671a39e6aa21da30be0dac261d71638Leon Scroggins III private void onPartialImage(@DecodeException.Error int error, @Nullable Throwable cause) 15141d2bf2b846f0a98f7403bbc791adb2969685d87aLeon Scroggins III throws DecodeException { 15151d2bf2b846f0a98f7403bbc791adb2969685d87aLeon Scroggins III DecodeException exception = new DecodeException(error, cause, mSource); 15161d2bf2b846f0a98f7403bbc791adb2969685d87aLeon Scroggins III if (mOnPartialImageListener == null 15171d2bf2b846f0a98f7403bbc791adb2969685d87aLeon Scroggins III || !mOnPartialImageListener.onPartialImage(exception)) { 15181d2bf2b846f0a98f7403bbc791adb2969685d87aLeon Scroggins III throw exception; 15191d2bf2b846f0a98f7403bbc791adb2969685d87aLeon Scroggins III } 1520e5de9aa4a9bab9c4d8288212d6352a65e9808737Leon Scroggins III } 1521e5de9aa4a9bab9c4d8288212d6352a65e9808737Leon Scroggins III 15221d2bf2b846f0a98f7403bbc791adb2969685d87aLeon Scroggins III private static native ImageDecoder nCreate(long asset, Source src) throws IOException; 15231d2bf2b846f0a98f7403bbc791adb2969685d87aLeon Scroggins III private static native ImageDecoder nCreate(ByteBuffer buffer, int position, 15241d2bf2b846f0a98f7403bbc791adb2969685d87aLeon Scroggins III int limit, Source src) throws IOException; 15251d2bf2b846f0a98f7403bbc791adb2969685d87aLeon Scroggins III private static native ImageDecoder nCreate(byte[] data, int offset, int length, 15261d2bf2b846f0a98f7403bbc791adb2969685d87aLeon Scroggins III Source src) throws IOException; 15271d2bf2b846f0a98f7403bbc791adb2969685d87aLeon Scroggins III private static native ImageDecoder nCreate(InputStream is, byte[] storage, 15281d2bf2b846f0a98f7403bbc791adb2969685d87aLeon Scroggins III Source src) throws IOException; 1529e5de9aa4a9bab9c4d8288212d6352a65e9808737Leon Scroggins III // The fd must be seekable. 15301d2bf2b846f0a98f7403bbc791adb2969685d87aLeon Scroggins III private static native ImageDecoder nCreate(FileDescriptor fd, Source src) throws IOException; 1531ed074fd70011cf804a14b5cf53ffd4b529c5f367Leon Scroggins III @NonNull 15320c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III private static native Bitmap nDecodeBitmap(long nativePtr, 15331d2bf2b846f0a98f7403bbc791adb2969685d87aLeon Scroggins III @NonNull ImageDecoder decoder, 15341d2bf2b846f0a98f7403bbc791adb2969685d87aLeon Scroggins III boolean doPostProcess, 15350c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III int width, int height, 1536e5de9aa4a9bab9c4d8288212d6352a65e9808737Leon Scroggins III @Nullable Rect cropRect, boolean mutable, 15370c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III int allocator, boolean requireUnpremul, 15381a69f4598faef083d0123bb9b6bfcd6acfdec4e0Leon Scroggins III boolean conserveMemory, boolean decodeAsAlphaMask, 15391a69f4598faef083d0123bb9b6bfcd6acfdec4e0Leon Scroggins III @Nullable ColorSpace desiredColorSpace) 1540ed074fd70011cf804a14b5cf53ffd4b529c5f367Leon Scroggins III throws IOException; 1541e5de9aa4a9bab9c4d8288212d6352a65e9808737Leon Scroggins III private static native Size nGetSampledSize(long nativePtr, 1542e5de9aa4a9bab9c4d8288212d6352a65e9808737Leon Scroggins III int sampleSize); 1543e5de9aa4a9bab9c4d8288212d6352a65e9808737Leon Scroggins III private static native void nGetPadding(long nativePtr, @NonNull Rect outRect); 1544ed074fd70011cf804a14b5cf53ffd4b529c5f367Leon Scroggins III private static native void nClose(long nativePtr); 15451fad09d4d3f43112abd842da4c94cf00fb1cb46dLeon Scroggins III private static native String nGetMimeType(long nativePtr); 15461a69f4598faef083d0123bb9b6bfcd6acfdec4e0Leon Scroggins III private static native ColorSpace nGetColorSpace(long nativePtr); 15470c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III} 1548