ImageDecoder.java revision 671cce2605ed50c9aba73ab5bd530cb7741c53cd
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
19ed074fd70011cf804a14b5cf53ffd4b529c5f367Leon Scroggins IIIimport static android.system.OsConstants.SEEK_SET;
20ed074fd70011cf804a14b5cf53ffd4b529c5f367Leon Scroggins III
210c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins IIIimport android.annotation.IntDef;
220c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins IIIimport android.annotation.NonNull;
23b1cc8e64374832c8b296f609bebabff068ded460Leon Scroggins IIIimport android.annotation.Nullable;
240c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins IIIimport android.annotation.RawRes;
25ed074fd70011cf804a14b5cf53ffd4b529c5f367Leon Scroggins IIIimport android.content.ContentResolver;
26ed074fd70011cf804a14b5cf53ffd4b529c5f367Leon Scroggins IIIimport android.content.res.AssetFileDescriptor;
270c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins IIIimport android.content.res.AssetManager;
280c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins IIIimport android.content.res.Resources;
29671cce2605ed50c9aba73ab5bd530cb7741c53cdLeon Scroggins IIIimport android.graphics.drawable.AnimatedImageDrawable;
300c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins IIIimport android.graphics.drawable.Drawable;
310c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins IIIimport android.graphics.drawable.BitmapDrawable;
320c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins IIIimport android.graphics.drawable.NinePatchDrawable;
33ed074fd70011cf804a14b5cf53ffd4b529c5f367Leon Scroggins IIIimport android.net.Uri;
34ed074fd70011cf804a14b5cf53ffd4b529c5f367Leon Scroggins IIIimport android.system.ErrnoException;
35ed074fd70011cf804a14b5cf53ffd4b529c5f367Leon Scroggins IIIimport android.system.Os;
36ed074fd70011cf804a14b5cf53ffd4b529c5f367Leon Scroggins III
37ed074fd70011cf804a14b5cf53ffd4b529c5f367Leon Scroggins IIIimport libcore.io.IoUtils;
38ed074fd70011cf804a14b5cf53ffd4b529c5f367Leon Scroggins IIIimport dalvik.system.CloseGuard;
390c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III
400c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins IIIimport java.nio.ByteBuffer;
41ed074fd70011cf804a14b5cf53ffd4b529c5f367Leon Scroggins IIIimport java.io.FileDescriptor;
42ed074fd70011cf804a14b5cf53ffd4b529c5f367Leon Scroggins IIIimport java.io.FileInputStream;
43ed074fd70011cf804a14b5cf53ffd4b529c5f367Leon Scroggins IIIimport java.io.FileNotFoundException;
440c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins IIIimport java.io.IOException;
450c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins IIIimport java.io.InputStream;
460c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins IIIimport java.lang.ArrayIndexOutOfBoundsException;
47ed074fd70011cf804a14b5cf53ffd4b529c5f367Leon Scroggins IIIimport java.lang.AutoCloseable;
480c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins IIIimport java.lang.NullPointerException;
490c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins IIIimport java.lang.RuntimeException;
500c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins IIIimport java.lang.annotation.Retention;
510c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins IIIimport static java.lang.annotation.RetentionPolicy.SOURCE;
52ed074fd70011cf804a14b5cf53ffd4b529c5f367Leon Scroggins IIIimport java.util.concurrent.atomic.AtomicBoolean;
530c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III
540c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III/**
550c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III *  Class for decoding images as {@link Bitmap}s or {@link Drawable}s.
560c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III *  @hide
570c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III */
58ed074fd70011cf804a14b5cf53ffd4b529c5f367Leon Scroggins IIIpublic final class ImageDecoder implements AutoCloseable {
590c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III    /**
600c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III     *  Source of the encoded image data.
610c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III     */
620c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III    public static abstract class Source {
630c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III        /* @hide */
640c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III        Resources getResources() { return null; }
650c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III
660c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III        /* @hide */
67ed074fd70011cf804a14b5cf53ffd4b529c5f367Leon Scroggins III        abstract ImageDecoder createImageDecoder() throws IOException;
680c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III    };
690c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III
700c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III    private static class ByteArraySource extends Source {
710c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III        ByteArraySource(byte[] data, int offset, int length) {
720c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III            mData = data;
730c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III            mOffset = offset;
740c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III            mLength = length;
750c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III        };
760c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III        private final byte[] mData;
770c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III        private final int    mOffset;
780c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III        private final int    mLength;
790c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III
800c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III        @Override
81ed074fd70011cf804a14b5cf53ffd4b529c5f367Leon Scroggins III        public ImageDecoder createImageDecoder() throws IOException {
820c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III            return nCreate(mData, mOffset, mLength);
830c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III        }
840c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III    }
850c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III
860c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III    private static class ByteBufferSource extends Source {
870c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III        ByteBufferSource(ByteBuffer buffer) {
880c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III            mBuffer = buffer;
890c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III        }
900c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III        private final ByteBuffer mBuffer;
910c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III
920c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III        @Override
93ed074fd70011cf804a14b5cf53ffd4b529c5f367Leon Scroggins III        public ImageDecoder createImageDecoder() throws IOException {
940c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III            if (!mBuffer.isDirect() && mBuffer.hasArray()) {
950c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III                int offset = mBuffer.arrayOffset() + mBuffer.position();
960c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III                int length = mBuffer.limit() - mBuffer.position();
970c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III                return nCreate(mBuffer.array(), offset, length);
980c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III            }
990c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III            return nCreate(mBuffer, mBuffer.position(), mBuffer.limit());
1000c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III        }
1010c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III    }
1020c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III
103ed074fd70011cf804a14b5cf53ffd4b529c5f367Leon Scroggins III    private static class ContentResolverSource extends Source {
104ed074fd70011cf804a14b5cf53ffd4b529c5f367Leon Scroggins III        ContentResolverSource(ContentResolver resolver, Uri uri) {
105ed074fd70011cf804a14b5cf53ffd4b529c5f367Leon Scroggins III            mResolver = resolver;
106ed074fd70011cf804a14b5cf53ffd4b529c5f367Leon Scroggins III            mUri = uri;
107ed074fd70011cf804a14b5cf53ffd4b529c5f367Leon Scroggins III        }
108ed074fd70011cf804a14b5cf53ffd4b529c5f367Leon Scroggins III
109ed074fd70011cf804a14b5cf53ffd4b529c5f367Leon Scroggins III        private final ContentResolver mResolver;
110ed074fd70011cf804a14b5cf53ffd4b529c5f367Leon Scroggins III        private final Uri mUri;
111ed074fd70011cf804a14b5cf53ffd4b529c5f367Leon Scroggins III
112ed074fd70011cf804a14b5cf53ffd4b529c5f367Leon Scroggins III        @Override
113ed074fd70011cf804a14b5cf53ffd4b529c5f367Leon Scroggins III        public ImageDecoder createImageDecoder() throws IOException {
114ed074fd70011cf804a14b5cf53ffd4b529c5f367Leon Scroggins III            AssetFileDescriptor assetFd = null;
1150c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III            try {
116ed074fd70011cf804a14b5cf53ffd4b529c5f367Leon Scroggins III                if (mUri.getScheme() == ContentResolver.SCHEME_CONTENT) {
117ed074fd70011cf804a14b5cf53ffd4b529c5f367Leon Scroggins III                    assetFd = mResolver.openTypedAssetFileDescriptor(mUri,
118ed074fd70011cf804a14b5cf53ffd4b529c5f367Leon Scroggins III                            "image/*", null);
119ed074fd70011cf804a14b5cf53ffd4b529c5f367Leon Scroggins III                } else {
120ed074fd70011cf804a14b5cf53ffd4b529c5f367Leon Scroggins III                    assetFd = mResolver.openAssetFileDescriptor(mUri, "r");
121ed074fd70011cf804a14b5cf53ffd4b529c5f367Leon Scroggins III                }
122ed074fd70011cf804a14b5cf53ffd4b529c5f367Leon Scroggins III            } catch (FileNotFoundException e) {
123ed074fd70011cf804a14b5cf53ffd4b529c5f367Leon Scroggins III                // Some images cannot be opened as AssetFileDescriptors (e.g.
124ed074fd70011cf804a14b5cf53ffd4b529c5f367Leon Scroggins III                // bmp, ico). Open them as InputStreams.
125ed074fd70011cf804a14b5cf53ffd4b529c5f367Leon Scroggins III                InputStream is = mResolver.openInputStream(mUri);
126ed074fd70011cf804a14b5cf53ffd4b529c5f367Leon Scroggins III                if (is == null) {
127ed074fd70011cf804a14b5cf53ffd4b529c5f367Leon Scroggins III                    throw new FileNotFoundException(mUri.toString());
128ed074fd70011cf804a14b5cf53ffd4b529c5f367Leon Scroggins III                }
129ed074fd70011cf804a14b5cf53ffd4b529c5f367Leon Scroggins III
130ed074fd70011cf804a14b5cf53ffd4b529c5f367Leon Scroggins III                return createFromStream(is);
131ed074fd70011cf804a14b5cf53ffd4b529c5f367Leon Scroggins III            }
132ed074fd70011cf804a14b5cf53ffd4b529c5f367Leon Scroggins III
133ed074fd70011cf804a14b5cf53ffd4b529c5f367Leon Scroggins III            final FileDescriptor fd = assetFd.getFileDescriptor();
134ed074fd70011cf804a14b5cf53ffd4b529c5f367Leon Scroggins III            final long offset = assetFd.getStartOffset();
135ed074fd70011cf804a14b5cf53ffd4b529c5f367Leon Scroggins III
136ed074fd70011cf804a14b5cf53ffd4b529c5f367Leon Scroggins III            ImageDecoder decoder = null;
137ed074fd70011cf804a14b5cf53ffd4b529c5f367Leon Scroggins III            try {
138ed074fd70011cf804a14b5cf53ffd4b529c5f367Leon Scroggins III                try {
139ed074fd70011cf804a14b5cf53ffd4b529c5f367Leon Scroggins III                    Os.lseek(fd, offset, SEEK_SET);
140ed074fd70011cf804a14b5cf53ffd4b529c5f367Leon Scroggins III                    decoder = nCreate(fd);
141ed074fd70011cf804a14b5cf53ffd4b529c5f367Leon Scroggins III                } catch (ErrnoException e) {
142ed074fd70011cf804a14b5cf53ffd4b529c5f367Leon Scroggins III                    decoder = createFromStream(new FileInputStream(fd));
143ed074fd70011cf804a14b5cf53ffd4b529c5f367Leon Scroggins III                }
1440c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III            } finally {
145ed074fd70011cf804a14b5cf53ffd4b529c5f367Leon Scroggins III                if (decoder == null) {
146ed074fd70011cf804a14b5cf53ffd4b529c5f367Leon Scroggins III                    IoUtils.closeQuietly(assetFd);
147ed074fd70011cf804a14b5cf53ffd4b529c5f367Leon Scroggins III                } else {
148ed074fd70011cf804a14b5cf53ffd4b529c5f367Leon Scroggins III                    decoder.mAssetFd = assetFd;
1490c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III                }
1500c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III            }
151ed074fd70011cf804a14b5cf53ffd4b529c5f367Leon Scroggins III            return decoder;
152ed074fd70011cf804a14b5cf53ffd4b529c5f367Leon Scroggins III        }
153ed074fd70011cf804a14b5cf53ffd4b529c5f367Leon Scroggins III    }
154ed074fd70011cf804a14b5cf53ffd4b529c5f367Leon Scroggins III
155ed074fd70011cf804a14b5cf53ffd4b529c5f367Leon Scroggins III    private static ImageDecoder createFromStream(InputStream is) throws IOException {
156ed074fd70011cf804a14b5cf53ffd4b529c5f367Leon Scroggins III        // Arbitrary size matches BitmapFactory.
157ed074fd70011cf804a14b5cf53ffd4b529c5f367Leon Scroggins III        byte[] storage = new byte[16 * 1024];
158ed074fd70011cf804a14b5cf53ffd4b529c5f367Leon Scroggins III        ImageDecoder decoder = null;
159ed074fd70011cf804a14b5cf53ffd4b529c5f367Leon Scroggins III        try {
160ed074fd70011cf804a14b5cf53ffd4b529c5f367Leon Scroggins III            decoder = nCreate(is, storage);
161ed074fd70011cf804a14b5cf53ffd4b529c5f367Leon Scroggins III        } finally {
162ed074fd70011cf804a14b5cf53ffd4b529c5f367Leon Scroggins III            if (decoder == null) {
163ed074fd70011cf804a14b5cf53ffd4b529c5f367Leon Scroggins III                IoUtils.closeQuietly(is);
164ed074fd70011cf804a14b5cf53ffd4b529c5f367Leon Scroggins III            } else {
165ed074fd70011cf804a14b5cf53ffd4b529c5f367Leon Scroggins III                decoder.mInputStream = is;
166ed074fd70011cf804a14b5cf53ffd4b529c5f367Leon Scroggins III                decoder.mTempStorage = storage;
167ed074fd70011cf804a14b5cf53ffd4b529c5f367Leon Scroggins III            }
168ed074fd70011cf804a14b5cf53ffd4b529c5f367Leon Scroggins III        }
169ed074fd70011cf804a14b5cf53ffd4b529c5f367Leon Scroggins III
170ed074fd70011cf804a14b5cf53ffd4b529c5f367Leon Scroggins III        return decoder;
171ed074fd70011cf804a14b5cf53ffd4b529c5f367Leon Scroggins III    }
1720c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III
173ed074fd70011cf804a14b5cf53ffd4b529c5f367Leon Scroggins III    private static class ResourceSource extends Source {
174ed074fd70011cf804a14b5cf53ffd4b529c5f367Leon Scroggins III        ResourceSource(Resources res, int resId) {
1750c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III            mResources = res;
1760c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III            mResId = resId;
1770c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III        }
1780c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III
1790c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III        final Resources mResources;
1800c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III        final int       mResId;
1810c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III
1820c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III        @Override
1830c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III        public Resources getResources() { return mResources; }
1840c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III
1850c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III        @Override
186ed074fd70011cf804a14b5cf53ffd4b529c5f367Leon Scroggins III        public ImageDecoder createImageDecoder() throws IOException {
187ed074fd70011cf804a14b5cf53ffd4b529c5f367Leon Scroggins III            // This is just used in order to access the underlying Asset and
188ed074fd70011cf804a14b5cf53ffd4b529c5f367Leon Scroggins III            // keep it alive. FIXME: Can we skip creating this object?
189ed074fd70011cf804a14b5cf53ffd4b529c5f367Leon Scroggins III            InputStream is = null;
190ed074fd70011cf804a14b5cf53ffd4b529c5f367Leon Scroggins III            ImageDecoder decoder = null;
1910c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III            try {
192ed074fd70011cf804a14b5cf53ffd4b529c5f367Leon Scroggins III                is = mResources.openRawResource(mResId);
193ed074fd70011cf804a14b5cf53ffd4b529c5f367Leon Scroggins III                if (!(is instanceof AssetManager.AssetInputStream)) {
194ed074fd70011cf804a14b5cf53ffd4b529c5f367Leon Scroggins III                    // This should never happen.
195ed074fd70011cf804a14b5cf53ffd4b529c5f367Leon Scroggins III                    throw new RuntimeException("Resource is not an asset?");
196ed074fd70011cf804a14b5cf53ffd4b529c5f367Leon Scroggins III                }
197ed074fd70011cf804a14b5cf53ffd4b529c5f367Leon Scroggins III                long asset = ((AssetManager.AssetInputStream) is).getNativeAsset();
198ed074fd70011cf804a14b5cf53ffd4b529c5f367Leon Scroggins III                decoder = nCreate(asset);
1990c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III            } finally {
200ed074fd70011cf804a14b5cf53ffd4b529c5f367Leon Scroggins III                if (decoder == null) {
201ed074fd70011cf804a14b5cf53ffd4b529c5f367Leon Scroggins III                    IoUtils.closeQuietly(is);
202ed074fd70011cf804a14b5cf53ffd4b529c5f367Leon Scroggins III                } else {
203ed074fd70011cf804a14b5cf53ffd4b529c5f367Leon Scroggins III                    decoder.mInputStream = is;
204ed074fd70011cf804a14b5cf53ffd4b529c5f367Leon Scroggins III                }
2050c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III            }
206ed074fd70011cf804a14b5cf53ffd4b529c5f367Leon Scroggins III            return decoder;
2070c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III        }
2080c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III    }
2090c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III
2100c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III    /**
2110c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III     *  Contains information about the encoded image.
2120c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III     */
2130c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III    public static class ImageInfo {
2141fad09d4d3f43112abd842da4c94cf00fb1cb46dLeon Scroggins III        /**
2151fad09d4d3f43112abd842da4c94cf00fb1cb46dLeon Scroggins III         * Width of the image, without scaling or cropping.
2161fad09d4d3f43112abd842da4c94cf00fb1cb46dLeon Scroggins III         */
2170c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III        public final int width;
2181fad09d4d3f43112abd842da4c94cf00fb1cb46dLeon Scroggins III
2191fad09d4d3f43112abd842da4c94cf00fb1cb46dLeon Scroggins III        /**
2201fad09d4d3f43112abd842da4c94cf00fb1cb46dLeon Scroggins III         * Height of the image, without scaling or cropping.
2211fad09d4d3f43112abd842da4c94cf00fb1cb46dLeon Scroggins III         */
2220c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III        public final int height;
2230c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III
2241fad09d4d3f43112abd842da4c94cf00fb1cb46dLeon Scroggins III        /* @hide */
2251fad09d4d3f43112abd842da4c94cf00fb1cb46dLeon Scroggins III        ImageDecoder decoder;
2261fad09d4d3f43112abd842da4c94cf00fb1cb46dLeon Scroggins III
2271fad09d4d3f43112abd842da4c94cf00fb1cb46dLeon Scroggins III        /* @hide */
2281fad09d4d3f43112abd842da4c94cf00fb1cb46dLeon Scroggins III        ImageInfo(ImageDecoder decoder) {
2291fad09d4d3f43112abd842da4c94cf00fb1cb46dLeon Scroggins III            this.width   = decoder.mWidth;
2301fad09d4d3f43112abd842da4c94cf00fb1cb46dLeon Scroggins III            this.height  = decoder.mHeight;
2311fad09d4d3f43112abd842da4c94cf00fb1cb46dLeon Scroggins III            this.decoder = decoder;
2321fad09d4d3f43112abd842da4c94cf00fb1cb46dLeon Scroggins III        }
2331fad09d4d3f43112abd842da4c94cf00fb1cb46dLeon Scroggins III
2341fad09d4d3f43112abd842da4c94cf00fb1cb46dLeon Scroggins III        /**
2351fad09d4d3f43112abd842da4c94cf00fb1cb46dLeon Scroggins III         * The mimeType of the image, if known.
2361fad09d4d3f43112abd842da4c94cf00fb1cb46dLeon Scroggins III         */
2371fad09d4d3f43112abd842da4c94cf00fb1cb46dLeon Scroggins III        public String getMimeType() {
2381fad09d4d3f43112abd842da4c94cf00fb1cb46dLeon Scroggins III            return decoder.getMimeType();
2390c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III        }
2400c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III    };
2410c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III
2420c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III    /**
243c782ad886f957408d70e5c77ccf0928bb85f60daLeon Scroggins III     *  Used if the provided data is incomplete.
244ed074fd70011cf804a14b5cf53ffd4b529c5f367Leon Scroggins III     *
245c782ad886f957408d70e5c77ccf0928bb85f60daLeon Scroggins III     *  May be thrown if there is nothing to display.
2460c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III     *
247c782ad886f957408d70e5c77ccf0928bb85f60daLeon Scroggins III     *  If supplied to onPartialImage, there may be a correct partial image to
248c782ad886f957408d70e5c77ccf0928bb85f60daLeon Scroggins III     *  display.
2490c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III     */
250ed074fd70011cf804a14b5cf53ffd4b529c5f367Leon Scroggins III    public static class IncompleteException extends IOException {};
2510c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III
2520c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III    /**
2530c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III     *  Used if the provided data is corrupt.
2540c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III     *
255ed074fd70011cf804a14b5cf53ffd4b529c5f367Leon Scroggins III     *  May be thrown if there is nothing to display.
256ed074fd70011cf804a14b5cf53ffd4b529c5f367Leon Scroggins III     *
257edf26d6e40f0723e70d7dcd147a2a2ce07c7c1ccLeon Scroggins III     *  If supplied to onPartialImage, there may be a correct partial image to
258ed074fd70011cf804a14b5cf53ffd4b529c5f367Leon Scroggins III     *  display.
2590c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III     */
260ed074fd70011cf804a14b5cf53ffd4b529c5f367Leon Scroggins III    public static class CorruptException extends IOException {};
2610c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III
2620c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III    /**
2630c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III     *  Optional listener supplied to {@link #decodeDrawable} or
2640c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III     *  {@link #decodeBitmap}.
2650c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III     */
2660c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III    public static interface OnHeaderDecodedListener {
2670c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III        /**
2680c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III         *  Called when the header is decoded and the size is known.
2690c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III         *
2700c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III         *  @param info Information about the encoded image.
2710c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III         *  @param decoder allows changing the default settings of the decode.
2720c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III         */
2730c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III        public void onHeaderDecoded(ImageInfo info, ImageDecoder decoder);
2740c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III
2750c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III    };
2760c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III
2770c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III    /**
2780c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III     *  Optional listener supplied to the ImageDecoder.
2790c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III     */
280edf26d6e40f0723e70d7dcd147a2a2ce07c7c1ccLeon Scroggins III    public static interface OnPartialImageListener {
2810c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III        /**
282edf26d6e40f0723e70d7dcd147a2a2ce07c7c1ccLeon Scroggins III         *  Called when there is only a partial image to display.
2830c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III         *
284edf26d6e40f0723e70d7dcd147a2a2ce07c7c1ccLeon Scroggins III         *  If the input is incomplete or contains an error, this listener lets
285edf26d6e40f0723e70d7dcd147a2a2ce07c7c1ccLeon Scroggins III         *  the client know that and allows them to optionally bypass the rest
286edf26d6e40f0723e70d7dcd147a2a2ce07c7c1ccLeon Scroggins III         *  of the decode/creation process.
287edf26d6e40f0723e70d7dcd147a2a2ce07c7c1ccLeon Scroggins III         *
288edf26d6e40f0723e70d7dcd147a2a2ce07c7c1ccLeon Scroggins III         *  @param e IOException containing information about the error that
289edf26d6e40f0723e70d7dcd147a2a2ce07c7c1ccLeon Scroggins III         *      interrupted the decode.
290edf26d6e40f0723e70d7dcd147a2a2ce07c7c1ccLeon Scroggins III         *  @return True (which is the default) to create and return a
291edf26d6e40f0723e70d7dcd147a2a2ce07c7c1ccLeon Scroggins III         *      {@link Drawable}/{@link Bitmap} with partial data. False to
292edf26d6e40f0723e70d7dcd147a2a2ce07c7c1ccLeon Scroggins III         *      abort the decode and throw the {@link java.io.IOException}.
2930c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III         */
294edf26d6e40f0723e70d7dcd147a2a2ce07c7c1ccLeon Scroggins III        public boolean onPartialImage(IOException e);
2950c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III    };
2960c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III
2970c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III    // Fields
298671cce2605ed50c9aba73ab5bd530cb7741c53cdLeon Scroggins III    private long          mNativePtr;
299671cce2605ed50c9aba73ab5bd530cb7741c53cdLeon Scroggins III    private final int     mWidth;
300671cce2605ed50c9aba73ab5bd530cb7741c53cdLeon Scroggins III    private final int     mHeight;
301671cce2605ed50c9aba73ab5bd530cb7741c53cdLeon Scroggins III    private final boolean mAnimated;
3020c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III
3030c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III    private int     mDesiredWidth;
3040c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III    private int     mDesiredHeight;
3050c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III    private int     mAllocator = DEFAULT_ALLOCATOR;
3060c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III    private boolean mRequireUnpremultiplied = false;
3070c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III    private boolean mMutable = false;
3080c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III    private boolean mPreferRamOverQuality = false;
3090c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III    private boolean mAsAlphaMask = false;
3100c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III    private Rect    mCropRect;
3110c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III
312edf26d6e40f0723e70d7dcd147a2a2ce07c7c1ccLeon Scroggins III    private PostProcess            mPostProcess;
313edf26d6e40f0723e70d7dcd147a2a2ce07c7c1ccLeon Scroggins III    private OnPartialImageListener mOnPartialImageListener;
3140c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III
315ed074fd70011cf804a14b5cf53ffd4b529c5f367Leon Scroggins III    // Objects for interacting with the input.
316ed074fd70011cf804a14b5cf53ffd4b529c5f367Leon Scroggins III    private InputStream         mInputStream;
317ed074fd70011cf804a14b5cf53ffd4b529c5f367Leon Scroggins III    private byte[]              mTempStorage;
318ed074fd70011cf804a14b5cf53ffd4b529c5f367Leon Scroggins III    private AssetFileDescriptor mAssetFd;
319ed074fd70011cf804a14b5cf53ffd4b529c5f367Leon Scroggins III    private final AtomicBoolean mClosed = new AtomicBoolean();
320ed074fd70011cf804a14b5cf53ffd4b529c5f367Leon Scroggins III    private final CloseGuard    mCloseGuard = CloseGuard.get();
3210c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III
3220c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III    /**
323ed074fd70011cf804a14b5cf53ffd4b529c5f367Leon Scroggins III     * Private constructor called by JNI. {@link #close} must be
3240c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III     * called after decoding to delete native resources.
3250c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III     */
3260c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III    @SuppressWarnings("unused")
327671cce2605ed50c9aba73ab5bd530cb7741c53cdLeon Scroggins III    private ImageDecoder(long nativePtr, int width, int height,
328671cce2605ed50c9aba73ab5bd530cb7741c53cdLeon Scroggins III            boolean animated) {
3290c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III        mNativePtr = nativePtr;
3300c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III        mWidth = width;
3310c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III        mHeight = height;
3320c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III        mDesiredWidth = width;
3330c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III        mDesiredHeight = height;
334671cce2605ed50c9aba73ab5bd530cb7741c53cdLeon Scroggins III        mAnimated = animated;
335ed074fd70011cf804a14b5cf53ffd4b529c5f367Leon Scroggins III        mCloseGuard.open("close");
336ed074fd70011cf804a14b5cf53ffd4b529c5f367Leon Scroggins III    }
337ed074fd70011cf804a14b5cf53ffd4b529c5f367Leon Scroggins III
338ed074fd70011cf804a14b5cf53ffd4b529c5f367Leon Scroggins III    @Override
339ed074fd70011cf804a14b5cf53ffd4b529c5f367Leon Scroggins III    protected void finalize() throws Throwable {
340ed074fd70011cf804a14b5cf53ffd4b529c5f367Leon Scroggins III        try {
341ed074fd70011cf804a14b5cf53ffd4b529c5f367Leon Scroggins III            if (mCloseGuard != null) {
342ed074fd70011cf804a14b5cf53ffd4b529c5f367Leon Scroggins III                mCloseGuard.warnIfOpen();
343ed074fd70011cf804a14b5cf53ffd4b529c5f367Leon Scroggins III            }
344ed074fd70011cf804a14b5cf53ffd4b529c5f367Leon Scroggins III
345ed074fd70011cf804a14b5cf53ffd4b529c5f367Leon Scroggins III            close();
346ed074fd70011cf804a14b5cf53ffd4b529c5f367Leon Scroggins III        } finally {
347ed074fd70011cf804a14b5cf53ffd4b529c5f367Leon Scroggins III            super.finalize();
348ed074fd70011cf804a14b5cf53ffd4b529c5f367Leon Scroggins III        }
3490c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III    }
3500c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III
3510c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III    /**
3520c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III     * Create a new {@link Source} from an asset.
3530c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III     *
3540c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III     * @param res the {@link Resources} object containing the image data.
3550c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III     * @param resId resource ID of the image data.
3560c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III     *      // FIXME: Can be an @DrawableRes?
3570c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III     * @return a new Source object, which can be passed to
3580c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III     *      {@link #decodeDrawable} or {@link #decodeBitmap}.
3590c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III     */
360ed074fd70011cf804a14b5cf53ffd4b529c5f367Leon Scroggins III    @NonNull
3610c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III    public static Source createSource(@NonNull Resources res, @RawRes int resId)
362ed074fd70011cf804a14b5cf53ffd4b529c5f367Leon Scroggins III    {
3630c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III        return new ResourceSource(res, resId);
3640c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III    }
3650c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III
3660c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III    /**
367ed074fd70011cf804a14b5cf53ffd4b529c5f367Leon Scroggins III     * Create a new {@link Source} from a {@link android.net.Uri}.
368ed074fd70011cf804a14b5cf53ffd4b529c5f367Leon Scroggins III     *
369ed074fd70011cf804a14b5cf53ffd4b529c5f367Leon Scroggins III     * @param cr to retrieve from.
370ed074fd70011cf804a14b5cf53ffd4b529c5f367Leon Scroggins III     * @param uri of the image file.
371ed074fd70011cf804a14b5cf53ffd4b529c5f367Leon Scroggins III     * @return a new Source object, which can be passed to
372ed074fd70011cf804a14b5cf53ffd4b529c5f367Leon Scroggins III     *      {@link #decodeDrawable} or {@link #decodeBitmap}.
373ed074fd70011cf804a14b5cf53ffd4b529c5f367Leon Scroggins III     */
374ed074fd70011cf804a14b5cf53ffd4b529c5f367Leon Scroggins III    @NonNull
375ed074fd70011cf804a14b5cf53ffd4b529c5f367Leon Scroggins III    public static Source createSource(@NonNull ContentResolver cr,
376ed074fd70011cf804a14b5cf53ffd4b529c5f367Leon Scroggins III            @NonNull Uri uri) {
377ed074fd70011cf804a14b5cf53ffd4b529c5f367Leon Scroggins III        return new ContentResolverSource(cr, uri);
378ed074fd70011cf804a14b5cf53ffd4b529c5f367Leon Scroggins III    }
379ed074fd70011cf804a14b5cf53ffd4b529c5f367Leon Scroggins III
380ed074fd70011cf804a14b5cf53ffd4b529c5f367Leon Scroggins III    /**
3810c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III     * Create a new {@link Source} from a byte array.
3820c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III     * @param data byte array of compressed image data.
3830c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III     * @param offset offset into data for where the decoder should begin
3840c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III     *      parsing.
3850c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III     * @param length number of bytes, beginning at offset, to parse.
3860c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III     * @throws NullPointerException if data is null.
3870c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III     * @throws ArrayIndexOutOfBoundsException if offset and length are
3880c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III     *      not within data.
3890c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III     */
3900c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III    public static Source createSource(@NonNull byte[] data, int offset,
3910c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III            int length) throws ArrayIndexOutOfBoundsException {
3920c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III        if (data == null) {
3930c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III            throw new NullPointerException("null byte[] in createSource!");
3940c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III        }
3950c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III        if (offset < 0 || length < 0 || offset >= data.length ||
3960c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III                offset + length > data.length) {
3970c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III            throw new ArrayIndexOutOfBoundsException(
3980c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III                    "invalid offset/length!");
3990c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III        }
4000c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III        return new ByteArraySource(data, offset, length);
4010c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III    }
4020c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III
4030c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III    /**
404b1cc8e64374832c8b296f609bebabff068ded460Leon Scroggins III     * See {@link #createSource(byte[], int, int).
405b1cc8e64374832c8b296f609bebabff068ded460Leon Scroggins III     */
406b1cc8e64374832c8b296f609bebabff068ded460Leon Scroggins III    public static Source createSource(@NonNull byte[] data) {
407b1cc8e64374832c8b296f609bebabff068ded460Leon Scroggins III        return createSource(data, 0, data.length);
408b1cc8e64374832c8b296f609bebabff068ded460Leon Scroggins III    }
409b1cc8e64374832c8b296f609bebabff068ded460Leon Scroggins III
410b1cc8e64374832c8b296f609bebabff068ded460Leon Scroggins III    /**
4110c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III     * Create a new {@link Source} from a {@link java.nio.ByteBuffer}.
4120c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III     *
4130c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III     * The returned {@link Source} effectively takes ownership of the
4140c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III     * {@link java.nio.ByteBuffer}; i.e. no other code should modify it after
4150c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III     * this call.
4160c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III     *
4170c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III     * Decoding will start from {@link java.nio.ByteBuffer#position()}.
4180c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III     */
4190c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III    public static Source createSource(ByteBuffer buffer) {
4200c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III        return new ByteBufferSource(buffer);
4210c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III    }
4220c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III
4230c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III    /**
4240c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III     *  Return the width and height of a given sample size.
4250c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III     *
4260c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III     *  This takes an input that functions like
4270c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III     *  {@link BitmapFactory.Options#inSampleSize}. It returns a width and
4280c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III     *  height that can be acheived by sampling the encoded image. Other widths
4290c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III     *  and heights may be supported, but will require an additional (internal)
4300c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III     *  scaling step. Such internal scaling is *not* supported with
4310c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III     *  {@link #requireUnpremultiplied}.
4320c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III     *
4330c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III     *  @param sampleSize Sampling rate of the encoded image.
4340c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III     *  @return Point {@link Point#x} and {@link Point#y} correspond to the
4350c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III     *      width and height after sampling.
4360c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III     */
4370c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III    public Point getSampledSize(int sampleSize) {
4380c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III        if (sampleSize <= 0) {
4390c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III            throw new IllegalArgumentException("sampleSize must be positive! "
4400c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III                    + "provided " + sampleSize);
4410c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III        }
4420c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III        if (mNativePtr == 0) {
443ed074fd70011cf804a14b5cf53ffd4b529c5f367Leon Scroggins III            throw new IllegalStateException("ImageDecoder is closed!");
4440c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III        }
4450c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III
4460c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III        return nGetSampledSize(mNativePtr, sampleSize);
4470c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III    }
4480c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III
4490c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III    // Modifiers
4500c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III    /**
4510c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III     *  Resize the output to have the following size.
4520c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III     *
4530c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III     *  @param width must be greater than 0.
4540c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III     *  @param height must be greater than 0.
4550c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III     */
4560c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III    public void resize(int width, int height) {
4570c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III        if (width <= 0 || height <= 0) {
4580c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III            throw new IllegalArgumentException("Dimensions must be positive! "
4590c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III                    + "provided (" + width + ", " + height + ")");
4600c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III        }
4610c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III
4620c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III        mDesiredWidth = width;
4630c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III        mDesiredHeight = height;
4640c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III    }
4650c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III
4660c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III    /**
4670c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III     *  Resize based on a sample size.
4680c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III     *
4690c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III     *  This has the same effect as passing the result of
4700c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III     *  {@link #getSampledSize} to {@link #resize(int, int)}.
4710c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III     *
4720c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III     *  @param sampleSize Sampling rate of the encoded image.
4730c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III     */
4740c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III    public void resize(int sampleSize) {
4750c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III        Point dimensions = this.getSampledSize(sampleSize);
4760c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III        this.resize(dimensions.x, dimensions.y);
4770c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III    }
4780c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III
4790c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III    // These need to stay in sync with ImageDecoder.cpp's Allocator enum.
4800c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III    /**
4810c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III     *  Use the default allocation for the pixel memory.
4820c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III     *
4830c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III     *  Will typically result in a {@link Bitmap.Config#HARDWARE}
4840c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III     *  allocation, but may be software for small images. In addition, this will
4850c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III     *  switch to software when HARDWARE is incompatible, e.g.
4860c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III     *  {@link #setMutable}, {@link #setAsAlphaMask}.
4870c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III     */
4880c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III    public static final int DEFAULT_ALLOCATOR = 0;
4890c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III
4900c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III    /**
4910c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III     *  Use a software allocation for the pixel memory.
4920c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III     *
4930c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III     *  Useful for drawing to a software {@link Canvas} or for
4940c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III     *  accessing the pixels on the final output.
4950c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III     */
4960c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III    public static final int SOFTWARE_ALLOCATOR = 1;
4970c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III
4980c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III    /**
4990c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III     *  Use shared memory for the pixel memory.
5000c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III     *
5010c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III     *  Useful for sharing across processes.
5020c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III     */
5030c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III    public static final int SHARED_MEMORY_ALLOCATOR = 2;
5040c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III
5050c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III    /**
5060c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III     *  Require a {@link Bitmap.Config#HARDWARE} {@link Bitmap}.
5070c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III     *
5080c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III     *  This will throw an {@link java.lang.IllegalStateException} when combined
5090c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III     *  with incompatible options, like {@link #setMutable} or
5100c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III     *  {@link #setAsAlphaMask}.
5110c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III     */
5120c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III    public static final int HARDWARE_ALLOCATOR = 3;
5130c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III
5140c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III    /** @hide **/
5150c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III    @Retention(SOURCE)
5160c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III    @IntDef({ DEFAULT_ALLOCATOR, SOFTWARE_ALLOCATOR, SHARED_MEMORY_ALLOCATOR,
5170c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III              HARDWARE_ALLOCATOR })
5180c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III    public @interface Allocator {};
5190c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III
5200c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III    /**
5210c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III     *  Choose the backing for the pixel memory.
5220c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III     *
5230c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III     *  This is ignored for animated drawables.
5240c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III     *
5250c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III     *  TODO: Allow accessing the backing from the Bitmap.
5260c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III     *
5270c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III     *  @param allocator Type of allocator to use.
5280c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III     */
5290c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III    public void setAllocator(@Allocator int allocator) {
5300c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III        if (allocator < DEFAULT_ALLOCATOR || allocator > HARDWARE_ALLOCATOR) {
5310c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III            throw new IllegalArgumentException("invalid allocator " + allocator);
5320c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III        }
5330c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III        mAllocator = allocator;
5340c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III    }
5350c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III
5360c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III    /**
5370c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III     *  Create a {@link Bitmap} with unpremultiplied pixels.
5380c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III     *
5390c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III     *  By default, ImageDecoder will create a {@link Bitmap} with
5400c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III     *  premultiplied pixels, which is required for drawing with the
5410c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III     *  {@link android.view.View} system (i.e. to a {@link Canvas}). Calling
5420c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III     *  this method will result in {@link #decodeBitmap} returning a
5430c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III     *  {@link Bitmap} with unpremultiplied pixels. See
5440c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III     *  {@link Bitmap#isPremultiplied}. Incompatible with
5450c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III     *  {@link #decodeDrawable}; attempting to decode an unpremultiplied
5460c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III     *  {@link Drawable} will throw an {@link java.lang.IllegalStateException}.
5470c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III     */
5480c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III    public void requireUnpremultiplied() {
5490c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III        mRequireUnpremultiplied = true;
5500c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III    }
5510c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III
5520c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III    /**
5530c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III     *  Modify the image after decoding and scaling.
5540c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III     *
5550c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III     *  This allows adding effects prior to returning a {@link Drawable} or
5560c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III     *  {@link Bitmap}. For a {@code Drawable} or an immutable {@code Bitmap},
5570c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III     *  this is the only way to process the image after decoding.
5580c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III     *
5590c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III     *  If set on a nine-patch image, the nine-patch data is ignored.
5600c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III     *
5610c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III     *  For an animated image, the drawing commands drawn on the {@link Canvas}
5620c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III     *  will be recorded immediately and then applied to each frame.
5630c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III     */
5640c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III    public void setPostProcess(PostProcess p) {
5650c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III        mPostProcess = p;
5660c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III    }
5670c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III
5680c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III    /**
569edf26d6e40f0723e70d7dcd147a2a2ce07c7c1ccLeon Scroggins III     *  Set (replace) the {@link OnPartialImageListener} on this object.
5700c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III     *
5710c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III     *  Will be called if there is an error in the input. Without one, a
5720c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III     *  partial {@link Bitmap} will be created.
5730c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III     */
574edf26d6e40f0723e70d7dcd147a2a2ce07c7c1ccLeon Scroggins III    public void setOnPartialImageListener(OnPartialImageListener l) {
575edf26d6e40f0723e70d7dcd147a2a2ce07c7c1ccLeon Scroggins III        mOnPartialImageListener = l;
5760c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III    }
5770c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III
5780c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III    /**
5790c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III     *  Crop the output to {@code subset} of the (possibly) scaled image.
5800c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III     *
5810c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III     *  {@code subset} must be contained within the size set by {@link #resize}
5820c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III     *  or the bounds of the image if resize was not called. Otherwise an
5830c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III     *  {@link IllegalStateException} will be thrown.
5840c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III     *
5850c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III     *  NOT intended as a replacement for
5860c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III     *  {@link BitmapRegionDecoder#decodeRegion}. This supports all formats,
5870c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III     *  but merely crops the output.
5880c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III     */
5890c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III    public void crop(Rect subset) {
5900c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III        mCropRect = subset;
5910c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III    }
5920c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III
5930c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III    /**
5940c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III     *  Create a mutable {@link Bitmap}.
5950c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III     *
5960c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III     *  By default, a {@link Bitmap} created will be immutable, but that can be
5970c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III     *  changed with this call.
5980c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III     *
5990c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III     *  Incompatible with {@link #HARDWARE_ALLOCATOR}, because
6000c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III     *  {@link Bitmap.Config#HARDWARE} Bitmaps cannot be mutable. Attempting to
6010c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III     *  combine them will throw an {@link java.lang.IllegalStateException}.
6020c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III     *
6030c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III     *  Incompatible with {@link #decodeDrawable}, which would require
6040c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III     *  retrieving the Bitmap from the returned Drawable in order to modify.
6050c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III     *  Attempting to decode a mutable {@link Drawable} will throw an
6060c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III     *  {@link java.lang.IllegalStateException}
6070c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III     */
6080c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III    public void setMutable() {
6090c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III        mMutable = true;
6100c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III    }
6110c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III
6120c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III    /**
6130c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III     *  Potentially save RAM at the expense of quality.
6140c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III     *
6150c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III     *  This may result in a {@link Bitmap} with a denser {@link Bitmap.Config},
6160c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III     *  depending on the image. For example, for an opaque {@link Bitmap}, this
6170c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III     *  may result in a {@link Bitmap.Config} with no alpha information.
6180c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III     */
6190c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III    public void setPreferRamOverQuality() {
6200c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III        mPreferRamOverQuality = true;
6210c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III    }
6220c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III
6230c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III    /**
6240c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III     *  Potentially treat the output as an alpha mask.
6250c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III     *
6260c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III     *  If the image is encoded in a format with only one channel, treat that
6270c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III     *  channel as alpha. Otherwise this call has no effect.
6280c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III     *
6290c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III     *  Incompatible with {@link #HARDWARE_ALLOCATOR}. Trying to combine them
6300c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III     *  will throw an {@link java.lang.IllegalStateException}.
6310c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III     */
6320c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III    public void setAsAlphaMask() {
6330c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III        mAsAlphaMask = true;
6340c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III    }
6350c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III
636ed074fd70011cf804a14b5cf53ffd4b529c5f367Leon Scroggins III    @Override
637ed074fd70011cf804a14b5cf53ffd4b529c5f367Leon Scroggins III    public void close() {
638ed074fd70011cf804a14b5cf53ffd4b529c5f367Leon Scroggins III        mCloseGuard.close();
639ed074fd70011cf804a14b5cf53ffd4b529c5f367Leon Scroggins III        if (!mClosed.compareAndSet(false, true)) {
6400c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III            return;
6410c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III        }
642ed074fd70011cf804a14b5cf53ffd4b529c5f367Leon Scroggins III        nClose(mNativePtr);
6430c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III        mNativePtr = 0;
644ed074fd70011cf804a14b5cf53ffd4b529c5f367Leon Scroggins III
645ed074fd70011cf804a14b5cf53ffd4b529c5f367Leon Scroggins III        IoUtils.closeQuietly(mInputStream);
646ed074fd70011cf804a14b5cf53ffd4b529c5f367Leon Scroggins III        IoUtils.closeQuietly(mAssetFd);
647ed074fd70011cf804a14b5cf53ffd4b529c5f367Leon Scroggins III
648ed074fd70011cf804a14b5cf53ffd4b529c5f367Leon Scroggins III        mInputStream = null;
649ed074fd70011cf804a14b5cf53ffd4b529c5f367Leon Scroggins III        mAssetFd = null;
650ed074fd70011cf804a14b5cf53ffd4b529c5f367Leon Scroggins III        mTempStorage = null;
6510c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III    }
6520c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III
6530c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III    private void checkState() {
6540c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III        if (mNativePtr == 0) {
655ed074fd70011cf804a14b5cf53ffd4b529c5f367Leon Scroggins III            throw new IllegalStateException("Cannot use closed ImageDecoder!");
6560c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III        }
6570c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III
6580c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III        checkSubset(mDesiredWidth, mDesiredHeight, mCropRect);
6590c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III
6600c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III        if (mAllocator == HARDWARE_ALLOCATOR) {
6610c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III            if (mMutable) {
6620c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III                throw new IllegalStateException("Cannot make mutable HARDWARE Bitmap!");
6630c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III            }
6640c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III            if (mAsAlphaMask) {
6650c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III                throw new IllegalStateException("Cannot make HARDWARE Alpha mask Bitmap!");
6660c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III            }
6670c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III        }
6680c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III
6690c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III        if (mPostProcess != null && mRequireUnpremultiplied) {
6700c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III            throw new IllegalStateException("Cannot draw to unpremultiplied pixels!");
6710c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III        }
6720c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III    }
6730c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III
6740c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III    private static void checkSubset(int width, int height, Rect r) {
6750c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III        if (r == null) {
6760c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III            return;
6770c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III        }
6780c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III        if (r.left < 0 || r.top < 0 || r.right > width || r.bottom > height) {
6790c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III            throw new IllegalStateException("Subset " + r + " not contained by "
6800c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III                    + "scaled image bounds: (" + width + " x " + height + ")");
6810c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III        }
6820c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III    }
6830c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III
6848c9d8f2aec65e449005a4a69c54f691ebd514e52Leon Scroggins III    private Bitmap decodeBitmap() throws IOException {
6858c9d8f2aec65e449005a4a69c54f691ebd514e52Leon Scroggins III        checkState();
6868c9d8f2aec65e449005a4a69c54f691ebd514e52Leon Scroggins III        // nDecodeBitmap calls postProcessAndRelease only if mPostProcess
6878c9d8f2aec65e449005a4a69c54f691ebd514e52Leon Scroggins III        // exists.
6888c9d8f2aec65e449005a4a69c54f691ebd514e52Leon Scroggins III        ImageDecoder postProcessPtr = mPostProcess == null ? null : this;
6898c9d8f2aec65e449005a4a69c54f691ebd514e52Leon Scroggins III        return nDecodeBitmap(mNativePtr, mOnPartialImageListener,
6908c9d8f2aec65e449005a4a69c54f691ebd514e52Leon Scroggins III                postProcessPtr, mDesiredWidth, mDesiredHeight, mCropRect,
6918c9d8f2aec65e449005a4a69c54f691ebd514e52Leon Scroggins III                mMutable, mAllocator, mRequireUnpremultiplied,
6928c9d8f2aec65e449005a4a69c54f691ebd514e52Leon Scroggins III                mPreferRamOverQuality, mAsAlphaMask);
6938c9d8f2aec65e449005a4a69c54f691ebd514e52Leon Scroggins III
6948c9d8f2aec65e449005a4a69c54f691ebd514e52Leon Scroggins III    }
6958c9d8f2aec65e449005a4a69c54f691ebd514e52Leon Scroggins III
6960c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III    /**
697b1cc8e64374832c8b296f609bebabff068ded460Leon Scroggins III     *  Create a {@link Drawable} from a {@code Source}.
698b1cc8e64374832c8b296f609bebabff068ded460Leon Scroggins III     *
699b1cc8e64374832c8b296f609bebabff068ded460Leon Scroggins III     *  @param src representing the encoded image.
700b1cc8e64374832c8b296f609bebabff068ded460Leon Scroggins III     *  @param listener for learning the {@link ImageInfo} and changing any
701b1cc8e64374832c8b296f609bebabff068ded460Leon Scroggins III     *      default settings on the {@code ImageDecoder}. If not {@code null},
702b1cc8e64374832c8b296f609bebabff068ded460Leon Scroggins III     *      this will be called on the same thread as {@code decodeDrawable}
703b1cc8e64374832c8b296f609bebabff068ded460Leon Scroggins III     *      before that method returns.
704b1cc8e64374832c8b296f609bebabff068ded460Leon Scroggins III     *  @return Drawable for displaying the image.
705ed074fd70011cf804a14b5cf53ffd4b529c5f367Leon Scroggins III     *  @throws IOException if {@code src} is not found, is an unsupported
706ed074fd70011cf804a14b5cf53ffd4b529c5f367Leon Scroggins III     *      format, or cannot be decoded for any reason.
7070c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III     */
708ed074fd70011cf804a14b5cf53ffd4b529c5f367Leon Scroggins III    @NonNull
709b1cc8e64374832c8b296f609bebabff068ded460Leon Scroggins III    public static Drawable decodeDrawable(@NonNull Source src,
710b1cc8e64374832c8b296f609bebabff068ded460Leon Scroggins III            @Nullable OnHeaderDecodedListener listener) throws IOException {
711ed074fd70011cf804a14b5cf53ffd4b529c5f367Leon Scroggins III        try (ImageDecoder decoder = src.createImageDecoder()) {
712ed074fd70011cf804a14b5cf53ffd4b529c5f367Leon Scroggins III            if (listener != null) {
7131fad09d4d3f43112abd842da4c94cf00fb1cb46dLeon Scroggins III                ImageInfo info = new ImageInfo(decoder);
7141fad09d4d3f43112abd842da4c94cf00fb1cb46dLeon Scroggins III                try {
7151fad09d4d3f43112abd842da4c94cf00fb1cb46dLeon Scroggins III                    listener.onHeaderDecoded(info, decoder);
7161fad09d4d3f43112abd842da4c94cf00fb1cb46dLeon Scroggins III                } finally {
7171fad09d4d3f43112abd842da4c94cf00fb1cb46dLeon Scroggins III                    info.decoder = null;
7181fad09d4d3f43112abd842da4c94cf00fb1cb46dLeon Scroggins III                }
719ed074fd70011cf804a14b5cf53ffd4b529c5f367Leon Scroggins III            }
7200c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III
721ed074fd70011cf804a14b5cf53ffd4b529c5f367Leon Scroggins III            if (decoder.mRequireUnpremultiplied) {
722ed074fd70011cf804a14b5cf53ffd4b529c5f367Leon Scroggins III                // Though this could be supported (ignored) for opaque images,
723ed074fd70011cf804a14b5cf53ffd4b529c5f367Leon Scroggins III                // it seems better to always report this error.
724ed074fd70011cf804a14b5cf53ffd4b529c5f367Leon Scroggins III                throw new IllegalStateException("Cannot decode a Drawable " +
725ed074fd70011cf804a14b5cf53ffd4b529c5f367Leon Scroggins III                                                "with unpremultiplied pixels!");
726ed074fd70011cf804a14b5cf53ffd4b529c5f367Leon Scroggins III            }
7270c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III
728ed074fd70011cf804a14b5cf53ffd4b529c5f367Leon Scroggins III            if (decoder.mMutable) {
729ed074fd70011cf804a14b5cf53ffd4b529c5f367Leon Scroggins III                throw new IllegalStateException("Cannot decode a mutable " +
730ed074fd70011cf804a14b5cf53ffd4b529c5f367Leon Scroggins III                                                "Drawable!");
731ed074fd70011cf804a14b5cf53ffd4b529c5f367Leon Scroggins III            }
7320c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III
733671cce2605ed50c9aba73ab5bd530cb7741c53cdLeon Scroggins III            if (decoder.mAnimated) {
734671cce2605ed50c9aba73ab5bd530cb7741c53cdLeon Scroggins III                // AnimatedImageDrawable calls postProcessAndRelease only if
735671cce2605ed50c9aba73ab5bd530cb7741c53cdLeon Scroggins III                // mPostProcess exists.
736671cce2605ed50c9aba73ab5bd530cb7741c53cdLeon Scroggins III                ImageDecoder postProcessPtr = decoder.mPostProcess == null ?
737671cce2605ed50c9aba73ab5bd530cb7741c53cdLeon Scroggins III                        null : decoder;
738671cce2605ed50c9aba73ab5bd530cb7741c53cdLeon Scroggins III                Drawable d = new AnimatedImageDrawable(decoder.mNativePtr,
739671cce2605ed50c9aba73ab5bd530cb7741c53cdLeon Scroggins III                        postProcessPtr, decoder.mDesiredWidth,
740671cce2605ed50c9aba73ab5bd530cb7741c53cdLeon Scroggins III                        decoder.mDesiredHeight, decoder.mCropRect,
741671cce2605ed50c9aba73ab5bd530cb7741c53cdLeon Scroggins III                        decoder.mInputStream, decoder.mAssetFd);
742671cce2605ed50c9aba73ab5bd530cb7741c53cdLeon Scroggins III                // d has taken ownership of these objects.
743671cce2605ed50c9aba73ab5bd530cb7741c53cdLeon Scroggins III                decoder.mInputStream = null;
744671cce2605ed50c9aba73ab5bd530cb7741c53cdLeon Scroggins III                decoder.mAssetFd = null;
745671cce2605ed50c9aba73ab5bd530cb7741c53cdLeon Scroggins III                return d;
746671cce2605ed50c9aba73ab5bd530cb7741c53cdLeon Scroggins III            }
747671cce2605ed50c9aba73ab5bd530cb7741c53cdLeon Scroggins III
7488c9d8f2aec65e449005a4a69c54f691ebd514e52Leon Scroggins III            Bitmap bm = decoder.decodeBitmap();
7490c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III            Resources res = src.getResources();
7500c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III            if (res == null) {
7510c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III                bm.setDensity(Bitmap.DENSITY_NONE);
7520c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III            }
7530c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III
7540c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III            byte[] np = bm.getNinePatchChunk();
7550c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III            if (np != null && NinePatch.isNinePatchChunk(np)) {
7560c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III                Rect opticalInsets = new Rect();
7570c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III                bm.getOpticalInsets(opticalInsets);
7580c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III                Rect padding = new Rect();
7590c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III                nGetPadding(decoder.mNativePtr, padding);
7600c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III                return new NinePatchDrawable(res, bm, np, padding,
7610c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III                        opticalInsets, null);
7620c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III            }
7630c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III
7640c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III            return new BitmapDrawable(res, bm);
7650c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III        }
7660c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III    }
7670c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III
7680c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III    /**
769b1cc8e64374832c8b296f609bebabff068ded460Leon Scroggins III     * See {@link #decodeDrawable(Source, OnHeaderDecodedListener)}.
770b1cc8e64374832c8b296f609bebabff068ded460Leon Scroggins III     */
771b1cc8e64374832c8b296f609bebabff068ded460Leon Scroggins III    @NonNull
772b1cc8e64374832c8b296f609bebabff068ded460Leon Scroggins III    public static Drawable decodeDrawable(@NonNull Source src)
773b1cc8e64374832c8b296f609bebabff068ded460Leon Scroggins III            throws IOException {
774b1cc8e64374832c8b296f609bebabff068ded460Leon Scroggins III        return decodeDrawable(src, null);
775b1cc8e64374832c8b296f609bebabff068ded460Leon Scroggins III    }
776b1cc8e64374832c8b296f609bebabff068ded460Leon Scroggins III
777b1cc8e64374832c8b296f609bebabff068ded460Leon Scroggins III    /**
778b1cc8e64374832c8b296f609bebabff068ded460Leon Scroggins III     *  Create a {@link Bitmap} from a {@code Source}.
779b1cc8e64374832c8b296f609bebabff068ded460Leon Scroggins III     *
780b1cc8e64374832c8b296f609bebabff068ded460Leon Scroggins III     *  @param src representing the encoded image.
781b1cc8e64374832c8b296f609bebabff068ded460Leon Scroggins III     *  @param listener for learning the {@link ImageInfo} and changing any
782b1cc8e64374832c8b296f609bebabff068ded460Leon Scroggins III     *      default settings on the {@code ImageDecoder}. If not {@code null},
783b1cc8e64374832c8b296f609bebabff068ded460Leon Scroggins III     *      this will be called on the same thread as {@code decodeBitmap}
784b1cc8e64374832c8b296f609bebabff068ded460Leon Scroggins III     *      before that method returns.
785b1cc8e64374832c8b296f609bebabff068ded460Leon Scroggins III     *  @return Bitmap containing the image.
786ed074fd70011cf804a14b5cf53ffd4b529c5f367Leon Scroggins III     *  @throws IOException if {@code src} is not found, is an unsupported
787ed074fd70011cf804a14b5cf53ffd4b529c5f367Leon Scroggins III     *      format, or cannot be decoded for any reason.
7880c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III     */
789ed074fd70011cf804a14b5cf53ffd4b529c5f367Leon Scroggins III    @NonNull
790b1cc8e64374832c8b296f609bebabff068ded460Leon Scroggins III    public static Bitmap decodeBitmap(@NonNull Source src,
791b1cc8e64374832c8b296f609bebabff068ded460Leon Scroggins III            @Nullable OnHeaderDecodedListener listener) throws IOException {
792ed074fd70011cf804a14b5cf53ffd4b529c5f367Leon Scroggins III        try (ImageDecoder decoder = src.createImageDecoder()) {
793ed074fd70011cf804a14b5cf53ffd4b529c5f367Leon Scroggins III            if (listener != null) {
7941fad09d4d3f43112abd842da4c94cf00fb1cb46dLeon Scroggins III                ImageInfo info = new ImageInfo(decoder);
7951fad09d4d3f43112abd842da4c94cf00fb1cb46dLeon Scroggins III                try {
7961fad09d4d3f43112abd842da4c94cf00fb1cb46dLeon Scroggins III                    listener.onHeaderDecoded(info, decoder);
7971fad09d4d3f43112abd842da4c94cf00fb1cb46dLeon Scroggins III                } finally {
7981fad09d4d3f43112abd842da4c94cf00fb1cb46dLeon Scroggins III                    info.decoder = null;
7991fad09d4d3f43112abd842da4c94cf00fb1cb46dLeon Scroggins III                }
800ed074fd70011cf804a14b5cf53ffd4b529c5f367Leon Scroggins III            }
8010c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III
8028c9d8f2aec65e449005a4a69c54f691ebd514e52Leon Scroggins III            return decoder.decodeBitmap();
8030c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III        }
8040c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III    }
8050c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III
8061fad09d4d3f43112abd842da4c94cf00fb1cb46dLeon Scroggins III    private String getMimeType() {
8071fad09d4d3f43112abd842da4c94cf00fb1cb46dLeon Scroggins III        return nGetMimeType(mNativePtr);
8081fad09d4d3f43112abd842da4c94cf00fb1cb46dLeon Scroggins III    }
8091fad09d4d3f43112abd842da4c94cf00fb1cb46dLeon Scroggins III
810b1cc8e64374832c8b296f609bebabff068ded460Leon Scroggins III    /**
811b1cc8e64374832c8b296f609bebabff068ded460Leon Scroggins III     *  See {@link #decodeBitmap(Source, OnHeaderDecodedListener)}.
812b1cc8e64374832c8b296f609bebabff068ded460Leon Scroggins III     */
813b1cc8e64374832c8b296f609bebabff068ded460Leon Scroggins III    @NonNull
814b1cc8e64374832c8b296f609bebabff068ded460Leon Scroggins III    public static Bitmap decodeBitmap(@NonNull Source src) throws IOException {
815b1cc8e64374832c8b296f609bebabff068ded460Leon Scroggins III        return decodeBitmap(src, null);
816b1cc8e64374832c8b296f609bebabff068ded460Leon Scroggins III    }
817b1cc8e64374832c8b296f609bebabff068ded460Leon Scroggins III
8188c9d8f2aec65e449005a4a69c54f691ebd514e52Leon Scroggins III    /**
8198c9d8f2aec65e449005a4a69c54f691ebd514e52Leon Scroggins III     * Private method called by JNI.
8208c9d8f2aec65e449005a4a69c54f691ebd514e52Leon Scroggins III     */
8218c9d8f2aec65e449005a4a69c54f691ebd514e52Leon Scroggins III    @SuppressWarnings("unused")
8228c9d8f2aec65e449005a4a69c54f691ebd514e52Leon Scroggins III    private int postProcessAndRelease(@NonNull Canvas canvas, int width, int height) {
8238c9d8f2aec65e449005a4a69c54f691ebd514e52Leon Scroggins III        try {
8248c9d8f2aec65e449005a4a69c54f691ebd514e52Leon Scroggins III            return mPostProcess.postProcess(canvas, width, height);
8258c9d8f2aec65e449005a4a69c54f691ebd514e52Leon Scroggins III        } finally {
8268c9d8f2aec65e449005a4a69c54f691ebd514e52Leon Scroggins III            canvas.release();
8278c9d8f2aec65e449005a4a69c54f691ebd514e52Leon Scroggins III        }
8288c9d8f2aec65e449005a4a69c54f691ebd514e52Leon Scroggins III    }
8298c9d8f2aec65e449005a4a69c54f691ebd514e52Leon Scroggins III
830ed074fd70011cf804a14b5cf53ffd4b529c5f367Leon Scroggins III    private static native ImageDecoder nCreate(long asset) throws IOException;
8310c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III    private static native ImageDecoder nCreate(ByteBuffer buffer,
8320c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III                                               int position,
833ed074fd70011cf804a14b5cf53ffd4b529c5f367Leon Scroggins III                                               int limit) throws IOException;
8340c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III    private static native ImageDecoder nCreate(byte[] data, int offset,
835ed074fd70011cf804a14b5cf53ffd4b529c5f367Leon Scroggins III                                               int length) throws IOException;
836ed074fd70011cf804a14b5cf53ffd4b529c5f367Leon Scroggins III    private static native ImageDecoder nCreate(InputStream is, byte[] storage);
837ed074fd70011cf804a14b5cf53ffd4b529c5f367Leon Scroggins III    private static native ImageDecoder nCreate(FileDescriptor fd) throws IOException;
838ed074fd70011cf804a14b5cf53ffd4b529c5f367Leon Scroggins III    @NonNull
8390c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III    private static native Bitmap nDecodeBitmap(long nativePtr,
840edf26d6e40f0723e70d7dcd147a2a2ce07c7c1ccLeon Scroggins III            OnPartialImageListener listener,
8418c9d8f2aec65e449005a4a69c54f691ebd514e52Leon Scroggins III            @Nullable ImageDecoder decoder,     // Only used if mPostProcess != null
8420c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III            int width, int height,
8430c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III            Rect cropRect, boolean mutable,
8440c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III            int allocator, boolean requireUnpremul,
845ed074fd70011cf804a14b5cf53ffd4b529c5f367Leon Scroggins III            boolean preferRamOverQuality, boolean asAlphaMask)
846ed074fd70011cf804a14b5cf53ffd4b529c5f367Leon Scroggins III        throws IOException;
8470c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III    private static native Point nGetSampledSize(long nativePtr,
8480c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III                                                int sampleSize);
8490c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III    private static native void nGetPadding(long nativePtr, Rect outRect);
850ed074fd70011cf804a14b5cf53ffd4b529c5f367Leon Scroggins III    private static native void nClose(long nativePtr);
8511fad09d4d3f43112abd842da4c94cf00fb1cb46dLeon Scroggins III    private static native String nGetMimeType(long nativePtr);
8520c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III}
853