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
240a87cb3128a7fe8a999544ec1187159d82aa09ddLeon Scroggins IIIimport android.annotation.AnyThread;
250c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins IIIimport android.annotation.IntDef;
26d97e26428d1c61759910a1b983d5e316c9b893a1Leon Scroggins IIIimport android.annotation.IntRange;
270c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins IIIimport android.annotation.NonNull;
28b1cc8e64374832c8b296f609bebabff068ded460Leon Scroggins IIIimport android.annotation.Nullable;
29d97e26428d1c61759910a1b983d5e316c9b893a1Leon Scroggins IIIimport android.annotation.Px;
301d2bf2b846f0a98f7403bbc791adb2969685d87aLeon Scroggins IIIimport android.annotation.TestApi;
310a87cb3128a7fe8a999544ec1187159d82aa09ddLeon Scroggins IIIimport android.annotation.WorkerThread;
32ed074fd70011cf804a14b5cf53ffd4b529c5f367Leon Scroggins IIIimport android.content.ContentResolver;
33ed074fd70011cf804a14b5cf53ffd4b529c5f367Leon Scroggins IIIimport android.content.res.AssetFileDescriptor;
34121ef98bfb0e34a2726dd0fb9112915017bfcde4Leon Scroggins IIIimport android.content.res.AssetManager;
35513031d15b78579e39d59b71ab5a1b0afabc5544Leon Scroggins IIIimport android.content.res.AssetManager.AssetInputStream;
360c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins IIIimport android.content.res.Resources;
37671cce2605ed50c9aba73ab5bd530cb7741c53cdLeon Scroggins IIIimport android.graphics.drawable.AnimatedImageDrawable;
380c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins IIIimport android.graphics.drawable.BitmapDrawable;
39a38b2135a4bf4368734567a73d2e56f1c318fee9Leon Scroggins IIIimport android.graphics.drawable.Drawable;
400c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins IIIimport android.graphics.drawable.NinePatchDrawable;
41ed074fd70011cf804a14b5cf53ffd4b529c5f367Leon Scroggins IIIimport android.net.Uri;
428290eaba47b99398fbe0bd59138f902bde558ecbLeon Scroggins IIIimport android.os.Build;
43ed074fd70011cf804a14b5cf53ffd4b529c5f367Leon Scroggins IIIimport android.system.ErrnoException;
44ed074fd70011cf804a14b5cf53ffd4b529c5f367Leon Scroggins IIIimport android.system.Os;
4566c6d78908e0203a497c2e97398c824b2591ea19Derek Sollenbergerimport android.util.DisplayMetrics;
46a38b2135a4bf4368734567a73d2e56f1c318fee9Leon Scroggins IIIimport android.util.Size;
4766c6d78908e0203a497c2e97398c824b2591ea19Derek Sollenbergerimport android.util.TypedValue;
48ed074fd70011cf804a14b5cf53ffd4b529c5f367Leon Scroggins III
49ed074fd70011cf804a14b5cf53ffd4b529c5f367Leon Scroggins IIIimport dalvik.system.CloseGuard;
500c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III
51a38b2135a4bf4368734567a73d2e56f1c318fee9Leon Scroggins IIIimport libcore.io.IoUtils;
52a38b2135a4bf4368734567a73d2e56f1c318fee9Leon Scroggins III
53e5de9aa4a9bab9c4d8288212d6352a65e9808737Leon Scroggins IIIimport java.io.File;
54ed074fd70011cf804a14b5cf53ffd4b529c5f367Leon Scroggins IIIimport java.io.FileDescriptor;
55ed074fd70011cf804a14b5cf53ffd4b529c5f367Leon Scroggins IIIimport java.io.FileInputStream;
56ed074fd70011cf804a14b5cf53ffd4b529c5f367Leon Scroggins IIIimport java.io.FileNotFoundException;
570c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins IIIimport java.io.IOException;
580c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins IIIimport java.io.InputStream;
590c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins IIIimport java.lang.annotation.Retention;
60a38b2135a4bf4368734567a73d2e56f1c318fee9Leon Scroggins IIIimport java.nio.ByteBuffer;
61ed074fd70011cf804a14b5cf53ffd4b529c5f367Leon Scroggins IIIimport java.util.concurrent.atomic.AtomicBoolean;
620c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III
630c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III/**
64d84c652a4ebbdd8a42d09e28e2d3d83962a0350dLeon Scroggins III *  <p>A class for converting encoded images (like {@code PNG}, {@code JPEG},
65d84c652a4ebbdd8a42d09e28e2d3d83962a0350dLeon Scroggins III *  {@code WEBP}, {@code GIF}, or {@code HEIF}) into {@link Drawable} or
66d84c652a4ebbdd8a42d09e28e2d3d83962a0350dLeon Scroggins III *  {@link Bitmap} objects.
67d84c652a4ebbdd8a42d09e28e2d3d83962a0350dLeon Scroggins III *
68d84c652a4ebbdd8a42d09e28e2d3d83962a0350dLeon Scroggins III *  <p>To use it, first create a {@link Source Source} using one of the
69d84c652a4ebbdd8a42d09e28e2d3d83962a0350dLeon Scroggins III *  {@code createSource} overloads. For example, to decode from a {@link File}, call
70d84c652a4ebbdd8a42d09e28e2d3d83962a0350dLeon Scroggins III *  {@link #createSource(File)} and pass the result to {@link #decodeDrawable(Source)}
71d84c652a4ebbdd8a42d09e28e2d3d83962a0350dLeon Scroggins III *  or {@link #decodeBitmap(Source)}:
72d84c652a4ebbdd8a42d09e28e2d3d83962a0350dLeon Scroggins III *
73d84c652a4ebbdd8a42d09e28e2d3d83962a0350dLeon Scroggins III *  <pre class="prettyprint">
74d84c652a4ebbdd8a42d09e28e2d3d83962a0350dLeon Scroggins III *  File file = new File(...);
75d84c652a4ebbdd8a42d09e28e2d3d83962a0350dLeon Scroggins III *  ImageDecoder.Source source = ImageDecoder.createSource(file);
76d84c652a4ebbdd8a42d09e28e2d3d83962a0350dLeon Scroggins III *  Drawable drawable = ImageDecoder.decodeDrawable(source);
77d84c652a4ebbdd8a42d09e28e2d3d83962a0350dLeon Scroggins III *  </pre>
78d84c652a4ebbdd8a42d09e28e2d3d83962a0350dLeon Scroggins III *
79d84c652a4ebbdd8a42d09e28e2d3d83962a0350dLeon Scroggins III *  <p>To change the default settings, pass the {@link Source Source} and an
80d84c652a4ebbdd8a42d09e28e2d3d83962a0350dLeon Scroggins III *  {@link OnHeaderDecodedListener OnHeaderDecodedListener} to
81d84c652a4ebbdd8a42d09e28e2d3d83962a0350dLeon Scroggins III *  {@link #decodeDrawable(Source, OnHeaderDecodedListener)} or
82d84c652a4ebbdd8a42d09e28e2d3d83962a0350dLeon Scroggins III *  {@link #decodeBitmap(Source, OnHeaderDecodedListener)}. For example, to
83d84c652a4ebbdd8a42d09e28e2d3d83962a0350dLeon Scroggins III *  create a sampled image with half the width and height of the original image,
84d84c652a4ebbdd8a42d09e28e2d3d83962a0350dLeon Scroggins III *  call {@link #setTargetSampleSize setTargetSampleSize(2)} inside
85d84c652a4ebbdd8a42d09e28e2d3d83962a0350dLeon Scroggins III *  {@link OnHeaderDecodedListener#onHeaderDecoded onHeaderDecoded}:
86d84c652a4ebbdd8a42d09e28e2d3d83962a0350dLeon Scroggins III *
87d84c652a4ebbdd8a42d09e28e2d3d83962a0350dLeon Scroggins III *  <pre class="prettyprint">
88d84c652a4ebbdd8a42d09e28e2d3d83962a0350dLeon Scroggins III *  OnHeaderDecodedListener listener = new OnHeaderDecodedListener() {
89d84c652a4ebbdd8a42d09e28e2d3d83962a0350dLeon Scroggins III *      public void onHeaderDecoded(ImageDecoder decoder, ImageInfo info, Source source) {
90d84c652a4ebbdd8a42d09e28e2d3d83962a0350dLeon Scroggins III *          decoder.setTargetSampleSize(2);
91d84c652a4ebbdd8a42d09e28e2d3d83962a0350dLeon Scroggins III *      }
92d84c652a4ebbdd8a42d09e28e2d3d83962a0350dLeon Scroggins III *  };
93d84c652a4ebbdd8a42d09e28e2d3d83962a0350dLeon Scroggins III *  Drawable drawable = ImageDecoder.decodeDrawable(source, listener);
94d84c652a4ebbdd8a42d09e28e2d3d83962a0350dLeon Scroggins III *  </pre>
95d84c652a4ebbdd8a42d09e28e2d3d83962a0350dLeon Scroggins III *
96d84c652a4ebbdd8a42d09e28e2d3d83962a0350dLeon Scroggins III *  <p>The {@link ImageInfo ImageInfo} contains information about the encoded image, like
97d84c652a4ebbdd8a42d09e28e2d3d83962a0350dLeon Scroggins III *  its width and height, and the {@link Source Source} can be used to match to a particular
98d84c652a4ebbdd8a42d09e28e2d3d83962a0350dLeon Scroggins III *  {@link Source Source} if a single {@link OnHeaderDecodedListener OnHeaderDecodedListener}
99d84c652a4ebbdd8a42d09e28e2d3d83962a0350dLeon Scroggins III *  is used with multiple {@link Source Source} objects.
100d84c652a4ebbdd8a42d09e28e2d3d83962a0350dLeon Scroggins III *
101d84c652a4ebbdd8a42d09e28e2d3d83962a0350dLeon Scroggins III *  <p>The {@link OnHeaderDecodedListener OnHeaderDecodedListener} can also be implemented
102d84c652a4ebbdd8a42d09e28e2d3d83962a0350dLeon Scroggins III *  as a lambda:
103d84c652a4ebbdd8a42d09e28e2d3d83962a0350dLeon Scroggins III *
104d84c652a4ebbdd8a42d09e28e2d3d83962a0350dLeon Scroggins III *  <pre class="prettyprint">
105d84c652a4ebbdd8a42d09e28e2d3d83962a0350dLeon Scroggins III *  Drawable drawable = ImageDecoder.decodeDrawable(source, (decoder, info, src) -&gt; {
106d84c652a4ebbdd8a42d09e28e2d3d83962a0350dLeon Scroggins III *      decoder.setTargetSampleSize(2);
107d84c652a4ebbdd8a42d09e28e2d3d83962a0350dLeon Scroggins III *  });
108d84c652a4ebbdd8a42d09e28e2d3d83962a0350dLeon Scroggins III *  </pre>
109d84c652a4ebbdd8a42d09e28e2d3d83962a0350dLeon Scroggins III *
110d84c652a4ebbdd8a42d09e28e2d3d83962a0350dLeon Scroggins III *  <p>If the encoded image is an animated {@code GIF} or {@code WEBP},
111d84c652a4ebbdd8a42d09e28e2d3d83962a0350dLeon Scroggins III *  {@link #decodeDrawable decodeDrawable} will return an {@link AnimatedImageDrawable}. To
112d84c652a4ebbdd8a42d09e28e2d3d83962a0350dLeon Scroggins III *  start its animation, call {@link AnimatedImageDrawable#start AnimatedImageDrawable.start()}:
113d84c652a4ebbdd8a42d09e28e2d3d83962a0350dLeon Scroggins III *
114d84c652a4ebbdd8a42d09e28e2d3d83962a0350dLeon Scroggins III *  <pre class="prettyprint">
115d84c652a4ebbdd8a42d09e28e2d3d83962a0350dLeon Scroggins III *  Drawable drawable = ImageDecoder.decodeDrawable(source);
116d84c652a4ebbdd8a42d09e28e2d3d83962a0350dLeon Scroggins III *  if (drawable instanceof AnimatedImageDrawable) {
117d84c652a4ebbdd8a42d09e28e2d3d83962a0350dLeon Scroggins III *      ((AnimatedImageDrawable) drawable).start();
118d84c652a4ebbdd8a42d09e28e2d3d83962a0350dLeon Scroggins III *  }
119d84c652a4ebbdd8a42d09e28e2d3d83962a0350dLeon Scroggins III *  </pre>
120d84c652a4ebbdd8a42d09e28e2d3d83962a0350dLeon Scroggins III *
121d84c652a4ebbdd8a42d09e28e2d3d83962a0350dLeon Scroggins III *  <p>By default, a {@link Bitmap} created by {@link ImageDecoder} (including
122d84c652a4ebbdd8a42d09e28e2d3d83962a0350dLeon Scroggins III *  one that is inside a {@link Drawable}) will be immutable (i.e.
123d84c652a4ebbdd8a42d09e28e2d3d83962a0350dLeon Scroggins III *  {@link Bitmap#isMutable Bitmap.isMutable()} returns {@code false}), and it
124d84c652a4ebbdd8a42d09e28e2d3d83962a0350dLeon Scroggins III *  will typically have {@code Config} {@link Bitmap.Config#HARDWARE}. Although
125d84c652a4ebbdd8a42d09e28e2d3d83962a0350dLeon Scroggins III *  these properties can be changed with {@link #setMutableRequired setMutableRequired(true)}
126d84c652a4ebbdd8a42d09e28e2d3d83962a0350dLeon Scroggins III *  (which is only compatible with {@link #decodeBitmap(Source)} and
127d84c652a4ebbdd8a42d09e28e2d3d83962a0350dLeon Scroggins III *  {@link #decodeBitmap(Source, OnHeaderDecodedListener)}) and {@link #setAllocator},
128d84c652a4ebbdd8a42d09e28e2d3d83962a0350dLeon Scroggins III *  it is also possible to apply custom effects regardless of the mutability of
129d84c652a4ebbdd8a42d09e28e2d3d83962a0350dLeon Scroggins III *  the final returned object by passing a {@link PostProcessor} to
130d84c652a4ebbdd8a42d09e28e2d3d83962a0350dLeon Scroggins III *  {@link #setPostProcessor setPostProcessor}. A {@link PostProcessor} can also be a lambda:
131d84c652a4ebbdd8a42d09e28e2d3d83962a0350dLeon Scroggins III *
132d84c652a4ebbdd8a42d09e28e2d3d83962a0350dLeon Scroggins III *  <pre class="prettyprint">
133d84c652a4ebbdd8a42d09e28e2d3d83962a0350dLeon Scroggins III *  Drawable drawable = ImageDecoder.decodeDrawable(source, (decoder, info, src) -&gt; {
134d84c652a4ebbdd8a42d09e28e2d3d83962a0350dLeon Scroggins III *      decoder.setPostProcessor((canvas) -&gt; {
135d84c652a4ebbdd8a42d09e28e2d3d83962a0350dLeon Scroggins III *              // This will create rounded corners.
136d84c652a4ebbdd8a42d09e28e2d3d83962a0350dLeon Scroggins III *              Path path = new Path();
137d84c652a4ebbdd8a42d09e28e2d3d83962a0350dLeon Scroggins III *              path.setFillType(Path.FillType.INVERSE_EVEN_ODD);
138d84c652a4ebbdd8a42d09e28e2d3d83962a0350dLeon Scroggins III *              int width = canvas.getWidth();
139d84c652a4ebbdd8a42d09e28e2d3d83962a0350dLeon Scroggins III *              int height = canvas.getHeight();
140d84c652a4ebbdd8a42d09e28e2d3d83962a0350dLeon Scroggins III *              path.addRoundRect(0, 0, width, height, 20, 20, Path.Direction.CW);
141d84c652a4ebbdd8a42d09e28e2d3d83962a0350dLeon Scroggins III *              Paint paint = new Paint();
142d84c652a4ebbdd8a42d09e28e2d3d83962a0350dLeon Scroggins III *              paint.setAntiAlias(true);
143d84c652a4ebbdd8a42d09e28e2d3d83962a0350dLeon Scroggins III *              paint.setColor(Color.TRANSPARENT);
144d84c652a4ebbdd8a42d09e28e2d3d83962a0350dLeon Scroggins III *              paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC));
145d84c652a4ebbdd8a42d09e28e2d3d83962a0350dLeon Scroggins III *              canvas.drawPath(path, paint);
146d84c652a4ebbdd8a42d09e28e2d3d83962a0350dLeon Scroggins III *              return PixelFormat.TRANSLUCENT;
147d84c652a4ebbdd8a42d09e28e2d3d83962a0350dLeon Scroggins III *      });
148d84c652a4ebbdd8a42d09e28e2d3d83962a0350dLeon Scroggins III *  });
149d84c652a4ebbdd8a42d09e28e2d3d83962a0350dLeon Scroggins III *  </pre>
150d84c652a4ebbdd8a42d09e28e2d3d83962a0350dLeon Scroggins III *
151d84c652a4ebbdd8a42d09e28e2d3d83962a0350dLeon Scroggins III *  <p>If the encoded image is incomplete or contains an error, or if an
152d84c652a4ebbdd8a42d09e28e2d3d83962a0350dLeon Scroggins III *  {@link Exception} occurs during decoding, a {@link DecodeException DecodeException}
153d84c652a4ebbdd8a42d09e28e2d3d83962a0350dLeon Scroggins III *  will be thrown. In some cases, the {@link ImageDecoder} may have decoded part of
154d84c652a4ebbdd8a42d09e28e2d3d83962a0350dLeon Scroggins III *  the image. In order to display the partial image, an
155d84c652a4ebbdd8a42d09e28e2d3d83962a0350dLeon Scroggins III *  {@link OnPartialImageListener OnPartialImageListener} must be passed to
156d84c652a4ebbdd8a42d09e28e2d3d83962a0350dLeon Scroggins III *  {@link #setOnPartialImageListener setOnPartialImageListener}. For example:
157d84c652a4ebbdd8a42d09e28e2d3d83962a0350dLeon Scroggins III *
158d84c652a4ebbdd8a42d09e28e2d3d83962a0350dLeon Scroggins III *  <pre class="prettyprint">
159d84c652a4ebbdd8a42d09e28e2d3d83962a0350dLeon Scroggins III *  Drawable drawable = ImageDecoder.decodeDrawable(source, (decoder, info, src) -&gt; {
160d84c652a4ebbdd8a42d09e28e2d3d83962a0350dLeon Scroggins III *      decoder.setOnPartialImageListener((DecodeException e) -&gt; {
161d84c652a4ebbdd8a42d09e28e2d3d83962a0350dLeon Scroggins III *              // Returning true indicates to create a Drawable or Bitmap even
162d84c652a4ebbdd8a42d09e28e2d3d83962a0350dLeon Scroggins III *              // if the whole image could not be decoded. Any remaining lines
163d84c652a4ebbdd8a42d09e28e2d3d83962a0350dLeon Scroggins III *              // will be blank.
164d84c652a4ebbdd8a42d09e28e2d3d83962a0350dLeon Scroggins III *              return true;
165d84c652a4ebbdd8a42d09e28e2d3d83962a0350dLeon Scroggins III *      });
166d84c652a4ebbdd8a42d09e28e2d3d83962a0350dLeon Scroggins III *  });
167d84c652a4ebbdd8a42d09e28e2d3d83962a0350dLeon Scroggins III *  </pre>
1680c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III */
169ed074fd70011cf804a14b5cf53ffd4b529c5f367Leon Scroggins IIIpublic final class ImageDecoder implements AutoCloseable {
1708290eaba47b99398fbe0bd59138f902bde558ecbLeon Scroggins III    /** @hide **/
1718290eaba47b99398fbe0bd59138f902bde558ecbLeon Scroggins III    public static int sApiLevel;
1728290eaba47b99398fbe0bd59138f902bde558ecbLeon Scroggins III
1730c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III    /**
174d84c652a4ebbdd8a42d09e28e2d3d83962a0350dLeon Scroggins III     *  Source of encoded image data.
175d84c652a4ebbdd8a42d09e28e2d3d83962a0350dLeon Scroggins III     *
176d84c652a4ebbdd8a42d09e28e2d3d83962a0350dLeon Scroggins III     *  <p>References the data that will be used to decode a {@link Drawable}
177d84c652a4ebbdd8a42d09e28e2d3d83962a0350dLeon Scroggins III     *  or {@link Bitmap} in {@link #decodeDrawable decodeDrawable} or
178d84c652a4ebbdd8a42d09e28e2d3d83962a0350dLeon Scroggins III     *  {@link #decodeBitmap decodeBitmap}. Constructing a {@code Source} (with
179d84c652a4ebbdd8a42d09e28e2d3d83962a0350dLeon Scroggins III     *  one of the overloads of {@code createSource}) can be done on any thread
180d84c652a4ebbdd8a42d09e28e2d3d83962a0350dLeon Scroggins III     *  because the construction simply captures values. The real work is done
181d84c652a4ebbdd8a42d09e28e2d3d83962a0350dLeon Scroggins III     *  in {@link #decodeDrawable decodeDrawable} or {@link #decodeBitmap decodeBitmap}.
182d84c652a4ebbdd8a42d09e28e2d3d83962a0350dLeon Scroggins III     *
183d84c652a4ebbdd8a42d09e28e2d3d83962a0350dLeon Scroggins III     *  <p>A {@code Source} object can be reused to create multiple versions of the
184d84c652a4ebbdd8a42d09e28e2d3d83962a0350dLeon Scroggins III     *  same image. For example, to decode a full size image and its thumbnail,
185d84c652a4ebbdd8a42d09e28e2d3d83962a0350dLeon Scroggins III     *  the same {@code Source} can be used once with no
186d84c652a4ebbdd8a42d09e28e2d3d83962a0350dLeon Scroggins III     *  {@link OnHeaderDecodedListener OnHeaderDecodedListener} and once with an
187d84c652a4ebbdd8a42d09e28e2d3d83962a0350dLeon Scroggins III     *  implementation of {@link OnHeaderDecodedListener#onHeaderDecoded onHeaderDecoded}
188d84c652a4ebbdd8a42d09e28e2d3d83962a0350dLeon Scroggins III     *  that calls {@link #setTargetSize} with smaller dimensions. One {@code Source}
1890a87cb3128a7fe8a999544ec1187159d82aa09ddLeon Scroggins III     *  even used simultaneously in multiple threads.</p>
1900c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III     */
1910c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III    public static abstract class Source {
192e5de9aa4a9bab9c4d8288212d6352a65e9808737Leon Scroggins III        private Source() {}
193e5de9aa4a9bab9c4d8288212d6352a65e9808737Leon Scroggins III
1940c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III        /* @hide */
195e5de9aa4a9bab9c4d8288212d6352a65e9808737Leon Scroggins III        @Nullable
1960c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III        Resources getResources() { return null; }
1970c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III
1980c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III        /* @hide */
19966c6d78908e0203a497c2e97398c824b2591ea19Derek Sollenberger        int getDensity() { return Bitmap.DENSITY_NONE; }
20066c6d78908e0203a497c2e97398c824b2591ea19Derek Sollenberger
20166c6d78908e0203a497c2e97398c824b2591ea19Derek Sollenberger        /* @hide */
202046a99ebbb90f9ecdead7b057ef99764a1d295b9Leon Scroggins III        final int computeDstDensity() {
20366c6d78908e0203a497c2e97398c824b2591ea19Derek Sollenberger            Resources res = getResources();
20466c6d78908e0203a497c2e97398c824b2591ea19Derek Sollenberger            if (res == null) {
20566c6d78908e0203a497c2e97398c824b2591ea19Derek Sollenberger                return Bitmap.getDefaultDensity();
20666c6d78908e0203a497c2e97398c824b2591ea19Derek Sollenberger            }
20766c6d78908e0203a497c2e97398c824b2591ea19Derek Sollenberger
20866c6d78908e0203a497c2e97398c824b2591ea19Derek Sollenberger            return res.getDisplayMetrics().densityDpi;
20966c6d78908e0203a497c2e97398c824b2591ea19Derek Sollenberger        }
21066c6d78908e0203a497c2e97398c824b2591ea19Derek Sollenberger
21166c6d78908e0203a497c2e97398c824b2591ea19Derek Sollenberger        /* @hide */
212e5de9aa4a9bab9c4d8288212d6352a65e9808737Leon Scroggins III        @NonNull
213ed074fd70011cf804a14b5cf53ffd4b529c5f367Leon Scroggins III        abstract ImageDecoder createImageDecoder() throws IOException;
2140c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III    };
2150c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III
2160c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III    private static class ByteArraySource extends Source {
217e5de9aa4a9bab9c4d8288212d6352a65e9808737Leon Scroggins III        ByteArraySource(@NonNull byte[] data, int offset, int length) {
2180c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III            mData = data;
2190c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III            mOffset = offset;
2200c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III            mLength = length;
2210c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III        };
2220c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III        private final byte[] mData;
2230c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III        private final int    mOffset;
2240c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III        private final int    mLength;
2250c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III
2260c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III        @Override
227ed074fd70011cf804a14b5cf53ffd4b529c5f367Leon Scroggins III        public ImageDecoder createImageDecoder() throws IOException {
2281d2bf2b846f0a98f7403bbc791adb2969685d87aLeon Scroggins III            return nCreate(mData, mOffset, mLength, this);
2290c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III        }
2300c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III    }
2310c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III
2320c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III    private static class ByteBufferSource extends Source {
233e5de9aa4a9bab9c4d8288212d6352a65e9808737Leon Scroggins III        ByteBufferSource(@NonNull ByteBuffer buffer) {
2340c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III            mBuffer = buffer;
2350c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III        }
2360c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III        private final ByteBuffer mBuffer;
2370c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III
2380c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III        @Override
239ed074fd70011cf804a14b5cf53ffd4b529c5f367Leon Scroggins III        public ImageDecoder createImageDecoder() throws IOException {
2400c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III            if (!mBuffer.isDirect() && mBuffer.hasArray()) {
2410c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III                int offset = mBuffer.arrayOffset() + mBuffer.position();
2420c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III                int length = mBuffer.limit() - mBuffer.position();
2431d2bf2b846f0a98f7403bbc791adb2969685d87aLeon Scroggins III                return nCreate(mBuffer.array(), offset, length, this);
2440c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III            }
2450a87cb3128a7fe8a999544ec1187159d82aa09ddLeon Scroggins III            ByteBuffer buffer = mBuffer.slice();
2460a87cb3128a7fe8a999544ec1187159d82aa09ddLeon Scroggins III            return nCreate(buffer, buffer.position(), buffer.limit(), this);
2470c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III        }
2480c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III    }
2490c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III
250ed074fd70011cf804a14b5cf53ffd4b529c5f367Leon Scroggins III    private static class ContentResolverSource extends Source {
251046a99ebbb90f9ecdead7b057ef99764a1d295b9Leon Scroggins III        ContentResolverSource(@NonNull ContentResolver resolver, @NonNull Uri uri,
252046a99ebbb90f9ecdead7b057ef99764a1d295b9Leon Scroggins III                @Nullable Resources res) {
253ed074fd70011cf804a14b5cf53ffd4b529c5f367Leon Scroggins III            mResolver = resolver;
254ed074fd70011cf804a14b5cf53ffd4b529c5f367Leon Scroggins III            mUri = uri;
255046a99ebbb90f9ecdead7b057ef99764a1d295b9Leon Scroggins III            mResources = res;
256ed074fd70011cf804a14b5cf53ffd4b529c5f367Leon Scroggins III        }
257ed074fd70011cf804a14b5cf53ffd4b529c5f367Leon Scroggins III
258ed074fd70011cf804a14b5cf53ffd4b529c5f367Leon Scroggins III        private final ContentResolver mResolver;
259ed074fd70011cf804a14b5cf53ffd4b529c5f367Leon Scroggins III        private final Uri mUri;
260046a99ebbb90f9ecdead7b057ef99764a1d295b9Leon Scroggins III        private final Resources mResources;
261046a99ebbb90f9ecdead7b057ef99764a1d295b9Leon Scroggins III
262046a99ebbb90f9ecdead7b057ef99764a1d295b9Leon Scroggins III        @Nullable
263046a99ebbb90f9ecdead7b057ef99764a1d295b9Leon Scroggins III        Resources getResources() { return mResources; }
264ed074fd70011cf804a14b5cf53ffd4b529c5f367Leon Scroggins III
265ed074fd70011cf804a14b5cf53ffd4b529c5f367Leon Scroggins III        @Override
266ed074fd70011cf804a14b5cf53ffd4b529c5f367Leon Scroggins III        public ImageDecoder createImageDecoder() throws IOException {
267ed074fd70011cf804a14b5cf53ffd4b529c5f367Leon Scroggins III            AssetFileDescriptor assetFd = null;
2680c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III            try {
269ed074fd70011cf804a14b5cf53ffd4b529c5f367Leon Scroggins III                if (mUri.getScheme() == ContentResolver.SCHEME_CONTENT) {
270ed074fd70011cf804a14b5cf53ffd4b529c5f367Leon Scroggins III                    assetFd = mResolver.openTypedAssetFileDescriptor(mUri,
271ed074fd70011cf804a14b5cf53ffd4b529c5f367Leon Scroggins III                            "image/*", null);
272ed074fd70011cf804a14b5cf53ffd4b529c5f367Leon Scroggins III                } else {
273ed074fd70011cf804a14b5cf53ffd4b529c5f367Leon Scroggins III                    assetFd = mResolver.openAssetFileDescriptor(mUri, "r");
274ed074fd70011cf804a14b5cf53ffd4b529c5f367Leon Scroggins III                }
275ed074fd70011cf804a14b5cf53ffd4b529c5f367Leon Scroggins III            } catch (FileNotFoundException e) {
276ed074fd70011cf804a14b5cf53ffd4b529c5f367Leon Scroggins III                // Some images cannot be opened as AssetFileDescriptors (e.g.
277ed074fd70011cf804a14b5cf53ffd4b529c5f367Leon Scroggins III                // bmp, ico). Open them as InputStreams.
278ed074fd70011cf804a14b5cf53ffd4b529c5f367Leon Scroggins III                InputStream is = mResolver.openInputStream(mUri);
279ed074fd70011cf804a14b5cf53ffd4b529c5f367Leon Scroggins III                if (is == null) {
280ed074fd70011cf804a14b5cf53ffd4b529c5f367Leon Scroggins III                    throw new FileNotFoundException(mUri.toString());
281ed074fd70011cf804a14b5cf53ffd4b529c5f367Leon Scroggins III                }
282ed074fd70011cf804a14b5cf53ffd4b529c5f367Leon Scroggins III
2831d2bf2b846f0a98f7403bbc791adb2969685d87aLeon Scroggins III                return createFromStream(is, true, this);
284ed074fd70011cf804a14b5cf53ffd4b529c5f367Leon Scroggins III            }
285ed074fd70011cf804a14b5cf53ffd4b529c5f367Leon Scroggins III
286ed074fd70011cf804a14b5cf53ffd4b529c5f367Leon Scroggins III            final FileDescriptor fd = assetFd.getFileDescriptor();
287ed074fd70011cf804a14b5cf53ffd4b529c5f367Leon Scroggins III            final long offset = assetFd.getStartOffset();
288ed074fd70011cf804a14b5cf53ffd4b529c5f367Leon Scroggins III
289ed074fd70011cf804a14b5cf53ffd4b529c5f367Leon Scroggins III            ImageDecoder decoder = null;
290ed074fd70011cf804a14b5cf53ffd4b529c5f367Leon Scroggins III            try {
291ed074fd70011cf804a14b5cf53ffd4b529c5f367Leon Scroggins III                try {
292ed074fd70011cf804a14b5cf53ffd4b529c5f367Leon Scroggins III                    Os.lseek(fd, offset, SEEK_SET);
2931d2bf2b846f0a98f7403bbc791adb2969685d87aLeon Scroggins III                    decoder = nCreate(fd, this);
294ed074fd70011cf804a14b5cf53ffd4b529c5f367Leon Scroggins III                } catch (ErrnoException e) {
2951d2bf2b846f0a98f7403bbc791adb2969685d87aLeon Scroggins III                    decoder = createFromStream(new FileInputStream(fd), true, this);
296ed074fd70011cf804a14b5cf53ffd4b529c5f367Leon Scroggins III                }
2970c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III            } finally {
298ed074fd70011cf804a14b5cf53ffd4b529c5f367Leon Scroggins III                if (decoder == null) {
299ed074fd70011cf804a14b5cf53ffd4b529c5f367Leon Scroggins III                    IoUtils.closeQuietly(assetFd);
300ed074fd70011cf804a14b5cf53ffd4b529c5f367Leon Scroggins III                } else {
301ed074fd70011cf804a14b5cf53ffd4b529c5f367Leon Scroggins III                    decoder.mAssetFd = assetFd;
3020c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III                }
3030c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III            }
304ed074fd70011cf804a14b5cf53ffd4b529c5f367Leon Scroggins III            return decoder;
305ed074fd70011cf804a14b5cf53ffd4b529c5f367Leon Scroggins III        }
306ed074fd70011cf804a14b5cf53ffd4b529c5f367Leon Scroggins III    }
307ed074fd70011cf804a14b5cf53ffd4b529c5f367Leon Scroggins III
308e5de9aa4a9bab9c4d8288212d6352a65e9808737Leon Scroggins III    @NonNull
3091d2bf2b846f0a98f7403bbc791adb2969685d87aLeon Scroggins III    private static ImageDecoder createFromFile(@NonNull File file,
3101d2bf2b846f0a98f7403bbc791adb2969685d87aLeon Scroggins III            @NonNull Source source) throws IOException {
311e5de9aa4a9bab9c4d8288212d6352a65e9808737Leon Scroggins III        FileInputStream stream = new FileInputStream(file);
312e5de9aa4a9bab9c4d8288212d6352a65e9808737Leon Scroggins III        FileDescriptor fd = stream.getFD();
313e5de9aa4a9bab9c4d8288212d6352a65e9808737Leon Scroggins III        try {
314e5de9aa4a9bab9c4d8288212d6352a65e9808737Leon Scroggins III            Os.lseek(fd, 0, SEEK_CUR);
315e5de9aa4a9bab9c4d8288212d6352a65e9808737Leon Scroggins III        } catch (ErrnoException e) {
3161d2bf2b846f0a98f7403bbc791adb2969685d87aLeon Scroggins III            return createFromStream(stream, true, source);
317e5de9aa4a9bab9c4d8288212d6352a65e9808737Leon Scroggins III        }
318e5de9aa4a9bab9c4d8288212d6352a65e9808737Leon Scroggins III
319e5de9aa4a9bab9c4d8288212d6352a65e9808737Leon Scroggins III        ImageDecoder decoder = null;
320e5de9aa4a9bab9c4d8288212d6352a65e9808737Leon Scroggins III        try {
3211d2bf2b846f0a98f7403bbc791adb2969685d87aLeon Scroggins III            decoder = nCreate(fd, source);
322e5de9aa4a9bab9c4d8288212d6352a65e9808737Leon Scroggins III        } finally {
323e5de9aa4a9bab9c4d8288212d6352a65e9808737Leon Scroggins III            if (decoder == null) {
324e5de9aa4a9bab9c4d8288212d6352a65e9808737Leon Scroggins III                IoUtils.closeQuietly(stream);
325e5de9aa4a9bab9c4d8288212d6352a65e9808737Leon Scroggins III            } else {
326e5de9aa4a9bab9c4d8288212d6352a65e9808737Leon Scroggins III                decoder.mInputStream = stream;
3270b49f5725cabd64d27960b1b017e5c009f701cf8Leon Scroggins III                decoder.mOwnsInputStream = true;
328e5de9aa4a9bab9c4d8288212d6352a65e9808737Leon Scroggins III            }
329e5de9aa4a9bab9c4d8288212d6352a65e9808737Leon Scroggins III        }
330e5de9aa4a9bab9c4d8288212d6352a65e9808737Leon Scroggins III        return decoder;
331e5de9aa4a9bab9c4d8288212d6352a65e9808737Leon Scroggins III    }
332e5de9aa4a9bab9c4d8288212d6352a65e9808737Leon Scroggins III
333e5de9aa4a9bab9c4d8288212d6352a65e9808737Leon Scroggins III    @NonNull
3340b49f5725cabd64d27960b1b017e5c009f701cf8Leon Scroggins III    private static ImageDecoder createFromStream(@NonNull InputStream is,
3351d2bf2b846f0a98f7403bbc791adb2969685d87aLeon Scroggins III            boolean closeInputStream, Source source) throws IOException {
336ed074fd70011cf804a14b5cf53ffd4b529c5f367Leon Scroggins III        // Arbitrary size matches BitmapFactory.
337ed074fd70011cf804a14b5cf53ffd4b529c5f367Leon Scroggins III        byte[] storage = new byte[16 * 1024];
338ed074fd70011cf804a14b5cf53ffd4b529c5f367Leon Scroggins III        ImageDecoder decoder = null;
339ed074fd70011cf804a14b5cf53ffd4b529c5f367Leon Scroggins III        try {
3401d2bf2b846f0a98f7403bbc791adb2969685d87aLeon Scroggins III            decoder = nCreate(is, storage, source);
341ed074fd70011cf804a14b5cf53ffd4b529c5f367Leon Scroggins III        } finally {
342ed074fd70011cf804a14b5cf53ffd4b529c5f367Leon Scroggins III            if (decoder == null) {
3430b49f5725cabd64d27960b1b017e5c009f701cf8Leon Scroggins III                if (closeInputStream) {
3440b49f5725cabd64d27960b1b017e5c009f701cf8Leon Scroggins III                    IoUtils.closeQuietly(is);
3450b49f5725cabd64d27960b1b017e5c009f701cf8Leon Scroggins III                }
346ed074fd70011cf804a14b5cf53ffd4b529c5f367Leon Scroggins III            } else {
347ed074fd70011cf804a14b5cf53ffd4b529c5f367Leon Scroggins III                decoder.mInputStream = is;
3480b49f5725cabd64d27960b1b017e5c009f701cf8Leon Scroggins III                decoder.mOwnsInputStream = closeInputStream;
349ed074fd70011cf804a14b5cf53ffd4b529c5f367Leon Scroggins III                decoder.mTempStorage = storage;
350ed074fd70011cf804a14b5cf53ffd4b529c5f367Leon Scroggins III            }
351ed074fd70011cf804a14b5cf53ffd4b529c5f367Leon Scroggins III        }
352ed074fd70011cf804a14b5cf53ffd4b529c5f367Leon Scroggins III
353ed074fd70011cf804a14b5cf53ffd4b529c5f367Leon Scroggins III        return decoder;
354ed074fd70011cf804a14b5cf53ffd4b529c5f367Leon Scroggins III    }
3550c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III
3560b49f5725cabd64d27960b1b017e5c009f701cf8Leon Scroggins III    /**
3570b49f5725cabd64d27960b1b017e5c009f701cf8Leon Scroggins III     * For backwards compatibility, this does *not* close the InputStream.
3580a87cb3128a7fe8a999544ec1187159d82aa09ddLeon Scroggins III     *
3590a87cb3128a7fe8a999544ec1187159d82aa09ddLeon Scroggins III     * Further, unlike other Sources, this one is not reusable.
3600b49f5725cabd64d27960b1b017e5c009f701cf8Leon Scroggins III     */
36166c6d78908e0203a497c2e97398c824b2591ea19Derek Sollenberger    private static class InputStreamSource extends Source {
36266c6d78908e0203a497c2e97398c824b2591ea19Derek Sollenberger        InputStreamSource(Resources res, InputStream is, int inputDensity) {
36366c6d78908e0203a497c2e97398c824b2591ea19Derek Sollenberger            if (is == null) {
36466c6d78908e0203a497c2e97398c824b2591ea19Derek Sollenberger                throw new IllegalArgumentException("The InputStream cannot be null");
36566c6d78908e0203a497c2e97398c824b2591ea19Derek Sollenberger            }
36666c6d78908e0203a497c2e97398c824b2591ea19Derek Sollenberger            mResources = res;
36766c6d78908e0203a497c2e97398c824b2591ea19Derek Sollenberger            mInputStream = is;
36866c6d78908e0203a497c2e97398c824b2591ea19Derek Sollenberger            mInputDensity = res != null ? inputDensity : Bitmap.DENSITY_NONE;
36966c6d78908e0203a497c2e97398c824b2591ea19Derek Sollenberger        }
37066c6d78908e0203a497c2e97398c824b2591ea19Derek Sollenberger
37166c6d78908e0203a497c2e97398c824b2591ea19Derek Sollenberger        final Resources mResources;
37266c6d78908e0203a497c2e97398c824b2591ea19Derek Sollenberger        InputStream mInputStream;
37366c6d78908e0203a497c2e97398c824b2591ea19Derek Sollenberger        final int mInputDensity;
37466c6d78908e0203a497c2e97398c824b2591ea19Derek Sollenberger
37566c6d78908e0203a497c2e97398c824b2591ea19Derek Sollenberger        @Override
37666c6d78908e0203a497c2e97398c824b2591ea19Derek Sollenberger        public Resources getResources() { return mResources; }
37766c6d78908e0203a497c2e97398c824b2591ea19Derek Sollenberger
37866c6d78908e0203a497c2e97398c824b2591ea19Derek Sollenberger        @Override
37966c6d78908e0203a497c2e97398c824b2591ea19Derek Sollenberger        public int getDensity() { return mInputDensity; }
38066c6d78908e0203a497c2e97398c824b2591ea19Derek Sollenberger
38166c6d78908e0203a497c2e97398c824b2591ea19Derek Sollenberger        @Override
38266c6d78908e0203a497c2e97398c824b2591ea19Derek Sollenberger        public ImageDecoder createImageDecoder() throws IOException {
38366c6d78908e0203a497c2e97398c824b2591ea19Derek Sollenberger
38466c6d78908e0203a497c2e97398c824b2591ea19Derek Sollenberger            synchronized (this) {
38566c6d78908e0203a497c2e97398c824b2591ea19Derek Sollenberger                if (mInputStream == null) {
38666c6d78908e0203a497c2e97398c824b2591ea19Derek Sollenberger                    throw new IOException("Cannot reuse InputStreamSource");
38766c6d78908e0203a497c2e97398c824b2591ea19Derek Sollenberger                }
38866c6d78908e0203a497c2e97398c824b2591ea19Derek Sollenberger                InputStream is = mInputStream;
38966c6d78908e0203a497c2e97398c824b2591ea19Derek Sollenberger                mInputStream = null;
3901d2bf2b846f0a98f7403bbc791adb2969685d87aLeon Scroggins III                return createFromStream(is, false, this);
39166c6d78908e0203a497c2e97398c824b2591ea19Derek Sollenberger            }
39266c6d78908e0203a497c2e97398c824b2591ea19Derek Sollenberger        }
39366c6d78908e0203a497c2e97398c824b2591ea19Derek Sollenberger    }
39466c6d78908e0203a497c2e97398c824b2591ea19Derek Sollenberger
395513031d15b78579e39d59b71ab5a1b0afabc5544Leon Scroggins III    /**
396513031d15b78579e39d59b71ab5a1b0afabc5544Leon Scroggins III     * Takes ownership of the AssetInputStream.
397513031d15b78579e39d59b71ab5a1b0afabc5544Leon Scroggins III     *
398513031d15b78579e39d59b71ab5a1b0afabc5544Leon Scroggins III     * @hide
399513031d15b78579e39d59b71ab5a1b0afabc5544Leon Scroggins III     */
400513031d15b78579e39d59b71ab5a1b0afabc5544Leon Scroggins III    public static class AssetInputStreamSource extends Source {
401513031d15b78579e39d59b71ab5a1b0afabc5544Leon Scroggins III        public AssetInputStreamSource(@NonNull AssetInputStream ais,
402513031d15b78579e39d59b71ab5a1b0afabc5544Leon Scroggins III                @NonNull Resources res, @NonNull TypedValue value) {
403513031d15b78579e39d59b71ab5a1b0afabc5544Leon Scroggins III            mAssetInputStream = ais;
404513031d15b78579e39d59b71ab5a1b0afabc5544Leon Scroggins III            mResources = res;
405513031d15b78579e39d59b71ab5a1b0afabc5544Leon Scroggins III
406513031d15b78579e39d59b71ab5a1b0afabc5544Leon Scroggins III            if (value.density == TypedValue.DENSITY_DEFAULT) {
407513031d15b78579e39d59b71ab5a1b0afabc5544Leon Scroggins III                mDensity = DisplayMetrics.DENSITY_DEFAULT;
408513031d15b78579e39d59b71ab5a1b0afabc5544Leon Scroggins III            } else if (value.density != TypedValue.DENSITY_NONE) {
409513031d15b78579e39d59b71ab5a1b0afabc5544Leon Scroggins III                mDensity = value.density;
410513031d15b78579e39d59b71ab5a1b0afabc5544Leon Scroggins III            } else {
411513031d15b78579e39d59b71ab5a1b0afabc5544Leon Scroggins III                mDensity = Bitmap.DENSITY_NONE;
412513031d15b78579e39d59b71ab5a1b0afabc5544Leon Scroggins III            }
413513031d15b78579e39d59b71ab5a1b0afabc5544Leon Scroggins III        }
414513031d15b78579e39d59b71ab5a1b0afabc5544Leon Scroggins III
415513031d15b78579e39d59b71ab5a1b0afabc5544Leon Scroggins III        private AssetInputStream mAssetInputStream;
416513031d15b78579e39d59b71ab5a1b0afabc5544Leon Scroggins III        private final Resources  mResources;
417513031d15b78579e39d59b71ab5a1b0afabc5544Leon Scroggins III        private final int        mDensity;
418513031d15b78579e39d59b71ab5a1b0afabc5544Leon Scroggins III
419513031d15b78579e39d59b71ab5a1b0afabc5544Leon Scroggins III        @Override
420513031d15b78579e39d59b71ab5a1b0afabc5544Leon Scroggins III        public Resources getResources() { return mResources; }
421513031d15b78579e39d59b71ab5a1b0afabc5544Leon Scroggins III
422513031d15b78579e39d59b71ab5a1b0afabc5544Leon Scroggins III        @Override
423513031d15b78579e39d59b71ab5a1b0afabc5544Leon Scroggins III        public int getDensity() {
424513031d15b78579e39d59b71ab5a1b0afabc5544Leon Scroggins III            return mDensity;
425513031d15b78579e39d59b71ab5a1b0afabc5544Leon Scroggins III        }
426513031d15b78579e39d59b71ab5a1b0afabc5544Leon Scroggins III
427513031d15b78579e39d59b71ab5a1b0afabc5544Leon Scroggins III        @Override
428513031d15b78579e39d59b71ab5a1b0afabc5544Leon Scroggins III        public ImageDecoder createImageDecoder() throws IOException {
429513031d15b78579e39d59b71ab5a1b0afabc5544Leon Scroggins III            synchronized (this) {
430513031d15b78579e39d59b71ab5a1b0afabc5544Leon Scroggins III                if (mAssetInputStream == null) {
431513031d15b78579e39d59b71ab5a1b0afabc5544Leon Scroggins III                    throw new IOException("Cannot reuse AssetInputStreamSource");
432513031d15b78579e39d59b71ab5a1b0afabc5544Leon Scroggins III                }
433513031d15b78579e39d59b71ab5a1b0afabc5544Leon Scroggins III                AssetInputStream ais = mAssetInputStream;
434513031d15b78579e39d59b71ab5a1b0afabc5544Leon Scroggins III                mAssetInputStream = null;
4351d2bf2b846f0a98f7403bbc791adb2969685d87aLeon Scroggins III                return createFromAsset(ais, this);
436513031d15b78579e39d59b71ab5a1b0afabc5544Leon Scroggins III            }
437513031d15b78579e39d59b71ab5a1b0afabc5544Leon Scroggins III        }
438513031d15b78579e39d59b71ab5a1b0afabc5544Leon Scroggins III    }
439513031d15b78579e39d59b71ab5a1b0afabc5544Leon Scroggins III
440ed074fd70011cf804a14b5cf53ffd4b529c5f367Leon Scroggins III    private static class ResourceSource extends Source {
441e5de9aa4a9bab9c4d8288212d6352a65e9808737Leon Scroggins III        ResourceSource(@NonNull Resources res, int resId) {
4420c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III            mResources = res;
4430c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III            mResId = resId;
44466c6d78908e0203a497c2e97398c824b2591ea19Derek Sollenberger            mResDensity = Bitmap.DENSITY_NONE;
4450c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III        }
4460c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III
4470c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III        final Resources mResources;
4480c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III        final int       mResId;
44966c6d78908e0203a497c2e97398c824b2591ea19Derek Sollenberger        int             mResDensity;
4500a87cb3128a7fe8a999544ec1187159d82aa09ddLeon Scroggins III        private Object  mLock = new Object();
4510c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III
4520c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III        @Override
4530c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III        public Resources getResources() { return mResources; }
4540c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III
4550c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III        @Override
4560a87cb3128a7fe8a999544ec1187159d82aa09ddLeon Scroggins III        public int getDensity() {
4570a87cb3128a7fe8a999544ec1187159d82aa09ddLeon Scroggins III            synchronized (mLock) {
4580a87cb3128a7fe8a999544ec1187159d82aa09ddLeon Scroggins III                return mResDensity;
4590a87cb3128a7fe8a999544ec1187159d82aa09ddLeon Scroggins III            }
4600a87cb3128a7fe8a999544ec1187159d82aa09ddLeon Scroggins III        }
46166c6d78908e0203a497c2e97398c824b2591ea19Derek Sollenberger
46266c6d78908e0203a497c2e97398c824b2591ea19Derek Sollenberger        @Override
463ed074fd70011cf804a14b5cf53ffd4b529c5f367Leon Scroggins III        public ImageDecoder createImageDecoder() throws IOException {
46466c6d78908e0203a497c2e97398c824b2591ea19Derek Sollenberger            TypedValue value = new TypedValue();
465121ef98bfb0e34a2726dd0fb9112915017bfcde4Leon Scroggins III            // This is just used in order to access the underlying Asset and
466121ef98bfb0e34a2726dd0fb9112915017bfcde4Leon Scroggins III            // keep it alive.
467121ef98bfb0e34a2726dd0fb9112915017bfcde4Leon Scroggins III            InputStream is = mResources.openRawResource(mResId, value);
46866c6d78908e0203a497c2e97398c824b2591ea19Derek Sollenberger
4690a87cb3128a7fe8a999544ec1187159d82aa09ddLeon Scroggins III            synchronized (mLock) {
4700a87cb3128a7fe8a999544ec1187159d82aa09ddLeon Scroggins III                if (value.density == TypedValue.DENSITY_DEFAULT) {
4710a87cb3128a7fe8a999544ec1187159d82aa09ddLeon Scroggins III                    mResDensity = DisplayMetrics.DENSITY_DEFAULT;
4720a87cb3128a7fe8a999544ec1187159d82aa09ddLeon Scroggins III                } else if (value.density != TypedValue.DENSITY_NONE) {
4730a87cb3128a7fe8a999544ec1187159d82aa09ddLeon Scroggins III                    mResDensity = value.density;
4740a87cb3128a7fe8a999544ec1187159d82aa09ddLeon Scroggins III                }
475121ef98bfb0e34a2726dd0fb9112915017bfcde4Leon Scroggins III            }
47666c6d78908e0203a497c2e97398c824b2591ea19Derek Sollenberger
4771d2bf2b846f0a98f7403bbc791adb2969685d87aLeon Scroggins III            return createFromAsset((AssetInputStream) is, this);
478121ef98bfb0e34a2726dd0fb9112915017bfcde4Leon Scroggins III        }
479121ef98bfb0e34a2726dd0fb9112915017bfcde4Leon Scroggins III    }
480121ef98bfb0e34a2726dd0fb9112915017bfcde4Leon Scroggins III
481121ef98bfb0e34a2726dd0fb9112915017bfcde4Leon Scroggins III    /**
482121ef98bfb0e34a2726dd0fb9112915017bfcde4Leon Scroggins III     *  ImageDecoder will own the AssetInputStream.
483121ef98bfb0e34a2726dd0fb9112915017bfcde4Leon Scroggins III     */
4841d2bf2b846f0a98f7403bbc791adb2969685d87aLeon Scroggins III    private static ImageDecoder createFromAsset(AssetInputStream ais,
4851d2bf2b846f0a98f7403bbc791adb2969685d87aLeon Scroggins III            Source source) throws IOException {
486121ef98bfb0e34a2726dd0fb9112915017bfcde4Leon Scroggins III        ImageDecoder decoder = null;
487121ef98bfb0e34a2726dd0fb9112915017bfcde4Leon Scroggins III        try {
488121ef98bfb0e34a2726dd0fb9112915017bfcde4Leon Scroggins III            long asset = ais.getNativeAsset();
4891d2bf2b846f0a98f7403bbc791adb2969685d87aLeon Scroggins III            decoder = nCreate(asset, source);
490121ef98bfb0e34a2726dd0fb9112915017bfcde4Leon Scroggins III        } finally {
491121ef98bfb0e34a2726dd0fb9112915017bfcde4Leon Scroggins III            if (decoder == null) {
492121ef98bfb0e34a2726dd0fb9112915017bfcde4Leon Scroggins III                IoUtils.closeQuietly(ais);
493121ef98bfb0e34a2726dd0fb9112915017bfcde4Leon Scroggins III            } else {
494121ef98bfb0e34a2726dd0fb9112915017bfcde4Leon Scroggins III                decoder.mInputStream = ais;
495121ef98bfb0e34a2726dd0fb9112915017bfcde4Leon Scroggins III                decoder.mOwnsInputStream = true;
4960c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III            }
497121ef98bfb0e34a2726dd0fb9112915017bfcde4Leon Scroggins III        }
498121ef98bfb0e34a2726dd0fb9112915017bfcde4Leon Scroggins III        return decoder;
499121ef98bfb0e34a2726dd0fb9112915017bfcde4Leon Scroggins III    }
500121ef98bfb0e34a2726dd0fb9112915017bfcde4Leon Scroggins III
501121ef98bfb0e34a2726dd0fb9112915017bfcde4Leon Scroggins III    private static class AssetSource extends Source {
502121ef98bfb0e34a2726dd0fb9112915017bfcde4Leon Scroggins III        AssetSource(@NonNull AssetManager assets, @NonNull String fileName) {
503121ef98bfb0e34a2726dd0fb9112915017bfcde4Leon Scroggins III            mAssets = assets;
504121ef98bfb0e34a2726dd0fb9112915017bfcde4Leon Scroggins III            mFileName = fileName;
505121ef98bfb0e34a2726dd0fb9112915017bfcde4Leon Scroggins III        }
506121ef98bfb0e34a2726dd0fb9112915017bfcde4Leon Scroggins III
507121ef98bfb0e34a2726dd0fb9112915017bfcde4Leon Scroggins III        private final AssetManager mAssets;
508121ef98bfb0e34a2726dd0fb9112915017bfcde4Leon Scroggins III        private final String mFileName;
509121ef98bfb0e34a2726dd0fb9112915017bfcde4Leon Scroggins III
510121ef98bfb0e34a2726dd0fb9112915017bfcde4Leon Scroggins III        @Override
511121ef98bfb0e34a2726dd0fb9112915017bfcde4Leon Scroggins III        public ImageDecoder createImageDecoder() throws IOException {
512121ef98bfb0e34a2726dd0fb9112915017bfcde4Leon Scroggins III            InputStream is = mAssets.open(mFileName);
5131d2bf2b846f0a98f7403bbc791adb2969685d87aLeon Scroggins III            return createFromAsset((AssetInputStream) is, this);
5140c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III        }
5150c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III    }
5160c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III
517e5de9aa4a9bab9c4d8288212d6352a65e9808737Leon Scroggins III    private static class FileSource extends Source {
518e5de9aa4a9bab9c4d8288212d6352a65e9808737Leon Scroggins III        FileSource(@NonNull File file) {
519e5de9aa4a9bab9c4d8288212d6352a65e9808737Leon Scroggins III            mFile = file;
520e5de9aa4a9bab9c4d8288212d6352a65e9808737Leon Scroggins III        }
521e5de9aa4a9bab9c4d8288212d6352a65e9808737Leon Scroggins III
522e5de9aa4a9bab9c4d8288212d6352a65e9808737Leon Scroggins III        private final File mFile;
523e5de9aa4a9bab9c4d8288212d6352a65e9808737Leon Scroggins III
524e5de9aa4a9bab9c4d8288212d6352a65e9808737Leon Scroggins III        @Override
525e5de9aa4a9bab9c4d8288212d6352a65e9808737Leon Scroggins III        public ImageDecoder createImageDecoder() throws IOException {
5261d2bf2b846f0a98f7403bbc791adb2969685d87aLeon Scroggins III            return createFromFile(mFile, this);
527e5de9aa4a9bab9c4d8288212d6352a65e9808737Leon Scroggins III        }
528e5de9aa4a9bab9c4d8288212d6352a65e9808737Leon Scroggins III    }
529e5de9aa4a9bab9c4d8288212d6352a65e9808737Leon Scroggins III
5300c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III    /**
531d84c652a4ebbdd8a42d09e28e2d3d83962a0350dLeon Scroggins III     *  Information about an encoded image.
5320c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III     */
5330c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III    public static class ImageInfo {
534e5de9aa4a9bab9c4d8288212d6352a65e9808737Leon Scroggins III        private final Size mSize;
535e5de9aa4a9bab9c4d8288212d6352a65e9808737Leon Scroggins III        private ImageDecoder mDecoder;
536e5de9aa4a9bab9c4d8288212d6352a65e9808737Leon Scroggins III
537e5de9aa4a9bab9c4d8288212d6352a65e9808737Leon Scroggins III        private ImageInfo(@NonNull ImageDecoder decoder) {
538e5de9aa4a9bab9c4d8288212d6352a65e9808737Leon Scroggins III            mSize = new Size(decoder.mWidth, decoder.mHeight);
539e5de9aa4a9bab9c4d8288212d6352a65e9808737Leon Scroggins III            mDecoder = decoder;
540e5de9aa4a9bab9c4d8288212d6352a65e9808737Leon Scroggins III        }
5411fad09d4d3f43112abd842da4c94cf00fb1cb46dLeon Scroggins III
5421fad09d4d3f43112abd842da4c94cf00fb1cb46dLeon Scroggins III        /**
543e5de9aa4a9bab9c4d8288212d6352a65e9808737Leon Scroggins III         * Size of the image, without scaling or cropping.
5441fad09d4d3f43112abd842da4c94cf00fb1cb46dLeon Scroggins III         */
545e5de9aa4a9bab9c4d8288212d6352a65e9808737Leon Scroggins III        @NonNull
546e5de9aa4a9bab9c4d8288212d6352a65e9808737Leon Scroggins III        public Size getSize() {
547e5de9aa4a9bab9c4d8288212d6352a65e9808737Leon Scroggins III            return mSize;
5481fad09d4d3f43112abd842da4c94cf00fb1cb46dLeon Scroggins III        }
5491fad09d4d3f43112abd842da4c94cf00fb1cb46dLeon Scroggins III
5501fad09d4d3f43112abd842da4c94cf00fb1cb46dLeon Scroggins III        /**
551e5de9aa4a9bab9c4d8288212d6352a65e9808737Leon Scroggins III         * The mimeType of the image.
5521fad09d4d3f43112abd842da4c94cf00fb1cb46dLeon Scroggins III         */
553e5de9aa4a9bab9c4d8288212d6352a65e9808737Leon Scroggins III        @NonNull
5541fad09d4d3f43112abd842da4c94cf00fb1cb46dLeon Scroggins III        public String getMimeType() {
555e5de9aa4a9bab9c4d8288212d6352a65e9808737Leon Scroggins III            return mDecoder.getMimeType();
5560c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III        }
557127d31a6842b6cca49885c3607e7ea35b1885b6fLeon Scroggins III
558127d31a6842b6cca49885c3607e7ea35b1885b6fLeon Scroggins III        /**
559127d31a6842b6cca49885c3607e7ea35b1885b6fLeon Scroggins III         * Whether the image is animated.
560127d31a6842b6cca49885c3607e7ea35b1885b6fLeon Scroggins III         *
561d84c652a4ebbdd8a42d09e28e2d3d83962a0350dLeon Scroggins III         * <p>If {@code true}, {@link #decodeDrawable decodeDrawable} will
562d84c652a4ebbdd8a42d09e28e2d3d83962a0350dLeon Scroggins III         * return an {@link AnimatedImageDrawable}.</p>
563127d31a6842b6cca49885c3607e7ea35b1885b6fLeon Scroggins III         */
564127d31a6842b6cca49885c3607e7ea35b1885b6fLeon Scroggins III        public boolean isAnimated() {
565127d31a6842b6cca49885c3607e7ea35b1885b6fLeon Scroggins III            return mDecoder.mAnimated;
566127d31a6842b6cca49885c3607e7ea35b1885b6fLeon Scroggins III        }
5671a69f4598faef083d0123bb9b6bfcd6acfdec4e0Leon Scroggins III
5681a69f4598faef083d0123bb9b6bfcd6acfdec4e0Leon Scroggins III        /**
5691a69f4598faef083d0123bb9b6bfcd6acfdec4e0Leon Scroggins III         * If known, the color space the decoded bitmap will have. Note that the
5701a69f4598faef083d0123bb9b6bfcd6acfdec4e0Leon Scroggins III         * output color space is not guaranteed to be the color space the bitmap
5711a69f4598faef083d0123bb9b6bfcd6acfdec4e0Leon Scroggins III         * is encoded with. If not known (when the config is
5721a69f4598faef083d0123bb9b6bfcd6acfdec4e0Leon Scroggins III         * {@link Bitmap.Config#ALPHA_8} for instance), or there is an error,
5731a69f4598faef083d0123bb9b6bfcd6acfdec4e0Leon Scroggins III         * it is set to null.
5741a69f4598faef083d0123bb9b6bfcd6acfdec4e0Leon Scroggins III         */
5751a69f4598faef083d0123bb9b6bfcd6acfdec4e0Leon Scroggins III        @Nullable
5761a69f4598faef083d0123bb9b6bfcd6acfdec4e0Leon Scroggins III        public ColorSpace getColorSpace() {
5771a69f4598faef083d0123bb9b6bfcd6acfdec4e0Leon Scroggins III            return mDecoder.getColorSpace();
5781a69f4598faef083d0123bb9b6bfcd6acfdec4e0Leon Scroggins III        }
5790c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III    };
5800c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III
5811d2bf2b846f0a98f7403bbc791adb2969685d87aLeon Scroggins III    /** @removed
5821d2bf2b846f0a98f7403bbc791adb2969685d87aLeon Scroggins III     * @deprecated Subsumed by {@link #DecodeException}.
5830c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III     */
584ac959199e5cf553a1b42a486e91918ead4394ff5Leon Scroggins III    @Deprecated
585ed074fd70011cf804a14b5cf53ffd4b529c5f367Leon Scroggins III    public static class IncompleteException extends IOException {};
5860c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III
5870c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III    /**
588d84c652a4ebbdd8a42d09e28e2d3d83962a0350dLeon Scroggins III     *  Interface for changing the default settings of a decode.
589d84c652a4ebbdd8a42d09e28e2d3d83962a0350dLeon Scroggins III     *
590d84c652a4ebbdd8a42d09e28e2d3d83962a0350dLeon Scroggins III     *  <p>Supply an instance to
591d84c652a4ebbdd8a42d09e28e2d3d83962a0350dLeon Scroggins III     *  {@link #decodeDrawable(Source, OnHeaderDecodedListener) decodeDrawable}
592d84c652a4ebbdd8a42d09e28e2d3d83962a0350dLeon Scroggins III     *  or {@link #decodeBitmap(Source, OnHeaderDecodedListener) decodeBitmap},
593d84c652a4ebbdd8a42d09e28e2d3d83962a0350dLeon Scroggins III     *  which will call {@link OnHeaderDecodedListener#onHeaderDecoded onHeaderDecoded}
594d84c652a4ebbdd8a42d09e28e2d3d83962a0350dLeon Scroggins III     *  (in the same thread) once the size is known. The implementation of
595d84c652a4ebbdd8a42d09e28e2d3d83962a0350dLeon Scroggins III     *  {@link OnHeaderDecodedListener#onHeaderDecoded onHeaderDecoded} can then
596d84c652a4ebbdd8a42d09e28e2d3d83962a0350dLeon Scroggins III     *  change the decode settings as desired.
5970c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III     */
5980c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III    public static interface OnHeaderDecodedListener {
5990c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III        /**
600d84c652a4ebbdd8a42d09e28e2d3d83962a0350dLeon Scroggins III         *  Called by {@link ImageDecoder} when the header has been decoded and
601d84c652a4ebbdd8a42d09e28e2d3d83962a0350dLeon Scroggins III         *  the image size is known.
6020c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III         *
603d84c652a4ebbdd8a42d09e28e2d3d83962a0350dLeon Scroggins III         *  @param decoder the object performing the decode, for changing
604d84c652a4ebbdd8a42d09e28e2d3d83962a0350dLeon Scroggins III         *      its default settings.
605d84c652a4ebbdd8a42d09e28e2d3d83962a0350dLeon Scroggins III         *  @param info information about the encoded image.
606d84c652a4ebbdd8a42d09e28e2d3d83962a0350dLeon Scroggins III         *  @param source object that created {@code decoder}.
6070c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III         */
608e5de9aa4a9bab9c4d8288212d6352a65e9808737Leon Scroggins III        public void onHeaderDecoded(@NonNull ImageDecoder decoder,
609e5de9aa4a9bab9c4d8288212d6352a65e9808737Leon Scroggins III                @NonNull ImageInfo info, @NonNull Source source);
6100c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III
6110c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III    };
6120c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III
613cf7294fda671a39e6aa21da30be0dac261d71638Leon Scroggins III    /** @removed
614cf7294fda671a39e6aa21da30be0dac261d71638Leon Scroggins III     * @deprecated Replaced by {@link #DecodeException#SOURCE_EXCEPTION}.
615e5de9aa4a9bab9c4d8288212d6352a65e9808737Leon Scroggins III     */
616ac959199e5cf553a1b42a486e91918ead4394ff5Leon Scroggins III    @Deprecated
617e5de9aa4a9bab9c4d8288212d6352a65e9808737Leon Scroggins III    public static final int ERROR_SOURCE_EXCEPTION  = 1;
618e5de9aa4a9bab9c4d8288212d6352a65e9808737Leon Scroggins III
619cf7294fda671a39e6aa21da30be0dac261d71638Leon Scroggins III    /** @removed
620cf7294fda671a39e6aa21da30be0dac261d71638Leon Scroggins III     * @deprecated Replaced by {@link #DecodeException#SOURCE_INCOMPLETE}.
621e5de9aa4a9bab9c4d8288212d6352a65e9808737Leon Scroggins III     */
622ac959199e5cf553a1b42a486e91918ead4394ff5Leon Scroggins III    @Deprecated
623e5de9aa4a9bab9c4d8288212d6352a65e9808737Leon Scroggins III    public static final int ERROR_SOURCE_INCOMPLETE = 2;
624e5de9aa4a9bab9c4d8288212d6352a65e9808737Leon Scroggins III
625cf7294fda671a39e6aa21da30be0dac261d71638Leon Scroggins III    /** @removed
626cf7294fda671a39e6aa21da30be0dac261d71638Leon Scroggins III     * @deprecated Replaced by {@link #DecodeException#SOURCE_MALFORMED_DATA}.
627e5de9aa4a9bab9c4d8288212d6352a65e9808737Leon Scroggins III     */
628ac959199e5cf553a1b42a486e91918ead4394ff5Leon Scroggins III    @Deprecated
629e5de9aa4a9bab9c4d8288212d6352a65e9808737Leon Scroggins III    public static final int ERROR_SOURCE_ERROR      = 3;
630e5de9aa4a9bab9c4d8288212d6352a65e9808737Leon Scroggins III
631e5de9aa4a9bab9c4d8288212d6352a65e9808737Leon Scroggins III    /**
6321d2bf2b846f0a98f7403bbc791adb2969685d87aLeon Scroggins III     *  Information about an interrupted decode.
6331d2bf2b846f0a98f7403bbc791adb2969685d87aLeon Scroggins III     */
6341d2bf2b846f0a98f7403bbc791adb2969685d87aLeon Scroggins III    public static final class DecodeException extends IOException {
635cf7294fda671a39e6aa21da30be0dac261d71638Leon Scroggins III        /**
636cf7294fda671a39e6aa21da30be0dac261d71638Leon Scroggins III         *  An Exception was thrown reading the {@link Source}.
637cf7294fda671a39e6aa21da30be0dac261d71638Leon Scroggins III         */
638cf7294fda671a39e6aa21da30be0dac261d71638Leon Scroggins III        public static final int SOURCE_EXCEPTION  = 1;
639cf7294fda671a39e6aa21da30be0dac261d71638Leon Scroggins III
640cf7294fda671a39e6aa21da30be0dac261d71638Leon Scroggins III        /**
641cf7294fda671a39e6aa21da30be0dac261d71638Leon Scroggins III         *  The encoded data was incomplete.
642cf7294fda671a39e6aa21da30be0dac261d71638Leon Scroggins III         */
643cf7294fda671a39e6aa21da30be0dac261d71638Leon Scroggins III        public static final int SOURCE_INCOMPLETE = 2;
644cf7294fda671a39e6aa21da30be0dac261d71638Leon Scroggins III
645cf7294fda671a39e6aa21da30be0dac261d71638Leon Scroggins III        /**
646cf7294fda671a39e6aa21da30be0dac261d71638Leon Scroggins III         *  The encoded data contained an error.
647cf7294fda671a39e6aa21da30be0dac261d71638Leon Scroggins III         */
648cf7294fda671a39e6aa21da30be0dac261d71638Leon Scroggins III        public static final int SOURCE_MALFORMED_DATA      = 3;
649cf7294fda671a39e6aa21da30be0dac261d71638Leon Scroggins III
650cf7294fda671a39e6aa21da30be0dac261d71638Leon Scroggins III        /** @hide **/
651cf7294fda671a39e6aa21da30be0dac261d71638Leon Scroggins III        @Retention(SOURCE)
652cf7294fda671a39e6aa21da30be0dac261d71638Leon Scroggins III        @IntDef(value = { SOURCE_EXCEPTION, SOURCE_INCOMPLETE, SOURCE_MALFORMED_DATA },
653cf7294fda671a39e6aa21da30be0dac261d71638Leon Scroggins III                prefix = {"SOURCE_"})
654cf7294fda671a39e6aa21da30be0dac261d71638Leon Scroggins III        public @interface Error {};
655cf7294fda671a39e6aa21da30be0dac261d71638Leon Scroggins III
6561d2bf2b846f0a98f7403bbc791adb2969685d87aLeon Scroggins III        @Error final int mError;
6571d2bf2b846f0a98f7403bbc791adb2969685d87aLeon Scroggins III        @NonNull final Source mSource;
6581d2bf2b846f0a98f7403bbc791adb2969685d87aLeon Scroggins III
6591d2bf2b846f0a98f7403bbc791adb2969685d87aLeon Scroggins III        DecodeException(@Error int error, @Nullable Throwable cause, @NonNull Source source) {
6601d2bf2b846f0a98f7403bbc791adb2969685d87aLeon Scroggins III            super(errorMessage(error, cause), cause);
6611d2bf2b846f0a98f7403bbc791adb2969685d87aLeon Scroggins III            mError = error;
6621d2bf2b846f0a98f7403bbc791adb2969685d87aLeon Scroggins III            mSource = source;
6631d2bf2b846f0a98f7403bbc791adb2969685d87aLeon Scroggins III        }
6641d2bf2b846f0a98f7403bbc791adb2969685d87aLeon Scroggins III
6651d2bf2b846f0a98f7403bbc791adb2969685d87aLeon Scroggins III        /**
6661d2bf2b846f0a98f7403bbc791adb2969685d87aLeon Scroggins III         * Private method called by JNI.
6671d2bf2b846f0a98f7403bbc791adb2969685d87aLeon Scroggins III         */
6681d2bf2b846f0a98f7403bbc791adb2969685d87aLeon Scroggins III        @SuppressWarnings("unused")
6691d2bf2b846f0a98f7403bbc791adb2969685d87aLeon Scroggins III        DecodeException(@Error int error, @Nullable String msg, @Nullable Throwable cause,
6701d2bf2b846f0a98f7403bbc791adb2969685d87aLeon Scroggins III                @NonNull Source source) {
6711d2bf2b846f0a98f7403bbc791adb2969685d87aLeon Scroggins III            super(msg + errorMessage(error, cause), cause);
6721d2bf2b846f0a98f7403bbc791adb2969685d87aLeon Scroggins III            mError = error;
6731d2bf2b846f0a98f7403bbc791adb2969685d87aLeon Scroggins III            mSource = source;
6741d2bf2b846f0a98f7403bbc791adb2969685d87aLeon Scroggins III        }
6751d2bf2b846f0a98f7403bbc791adb2969685d87aLeon Scroggins III
6761d2bf2b846f0a98f7403bbc791adb2969685d87aLeon Scroggins III        /**
6771d2bf2b846f0a98f7403bbc791adb2969685d87aLeon Scroggins III         *  Retrieve the reason that decoding was interrupted.
6781d2bf2b846f0a98f7403bbc791adb2969685d87aLeon Scroggins III         *
679cf7294fda671a39e6aa21da30be0dac261d71638Leon Scroggins III         *  <p>If the error is {@link #SOURCE_EXCEPTION}, the underlying
6801d2bf2b846f0a98f7403bbc791adb2969685d87aLeon Scroggins III         *  {@link java.lang.Throwable} can be retrieved with
6811d2bf2b846f0a98f7403bbc791adb2969685d87aLeon Scroggins III         *  {@link java.lang.Throwable#getCause}.</p>
6821d2bf2b846f0a98f7403bbc791adb2969685d87aLeon Scroggins III         */
6831d2bf2b846f0a98f7403bbc791adb2969685d87aLeon Scroggins III        @Error
6841d2bf2b846f0a98f7403bbc791adb2969685d87aLeon Scroggins III        public int getError() {
6851d2bf2b846f0a98f7403bbc791adb2969685d87aLeon Scroggins III            return mError;
6861d2bf2b846f0a98f7403bbc791adb2969685d87aLeon Scroggins III        }
6871d2bf2b846f0a98f7403bbc791adb2969685d87aLeon Scroggins III
6881d2bf2b846f0a98f7403bbc791adb2969685d87aLeon Scroggins III        /**
689d84c652a4ebbdd8a42d09e28e2d3d83962a0350dLeon Scroggins III         *  Retrieve the {@link Source Source} that was interrupted.
6900a87cb3128a7fe8a999544ec1187159d82aa09ddLeon Scroggins III         *
6910a87cb3128a7fe8a999544ec1187159d82aa09ddLeon Scroggins III         *  <p>This can be used for equality checking to find the Source which
6920a87cb3128a7fe8a999544ec1187159d82aa09ddLeon Scroggins III         *  failed to completely decode.</p>
6931d2bf2b846f0a98f7403bbc791adb2969685d87aLeon Scroggins III         */
6941d2bf2b846f0a98f7403bbc791adb2969685d87aLeon Scroggins III        @NonNull
6951d2bf2b846f0a98f7403bbc791adb2969685d87aLeon Scroggins III        public Source getSource() {
6961d2bf2b846f0a98f7403bbc791adb2969685d87aLeon Scroggins III            return mSource;
6971d2bf2b846f0a98f7403bbc791adb2969685d87aLeon Scroggins III        }
6981d2bf2b846f0a98f7403bbc791adb2969685d87aLeon Scroggins III
6991d2bf2b846f0a98f7403bbc791adb2969685d87aLeon Scroggins III        private static String errorMessage(@Error int error, @Nullable Throwable cause) {
7001d2bf2b846f0a98f7403bbc791adb2969685d87aLeon Scroggins III            switch (error) {
701cf7294fda671a39e6aa21da30be0dac261d71638Leon Scroggins III                case SOURCE_EXCEPTION:
7021d2bf2b846f0a98f7403bbc791adb2969685d87aLeon Scroggins III                    return "Exception in input: " + cause;
703cf7294fda671a39e6aa21da30be0dac261d71638Leon Scroggins III                case SOURCE_INCOMPLETE:
7041d2bf2b846f0a98f7403bbc791adb2969685d87aLeon Scroggins III                    return "Input was incomplete.";
705cf7294fda671a39e6aa21da30be0dac261d71638Leon Scroggins III                case SOURCE_MALFORMED_DATA:
7061d2bf2b846f0a98f7403bbc791adb2969685d87aLeon Scroggins III                    return "Input contained an error.";
7071d2bf2b846f0a98f7403bbc791adb2969685d87aLeon Scroggins III                default:
7081d2bf2b846f0a98f7403bbc791adb2969685d87aLeon Scroggins III                    return "";
7091d2bf2b846f0a98f7403bbc791adb2969685d87aLeon Scroggins III            }
7101d2bf2b846f0a98f7403bbc791adb2969685d87aLeon Scroggins III        }
7111d2bf2b846f0a98f7403bbc791adb2969685d87aLeon Scroggins III    }
7121d2bf2b846f0a98f7403bbc791adb2969685d87aLeon Scroggins III
7131d2bf2b846f0a98f7403bbc791adb2969685d87aLeon Scroggins III    /**
714d84c652a4ebbdd8a42d09e28e2d3d83962a0350dLeon Scroggins III     *  Interface for inspecting a {@link DecodeException DecodeException}
715d84c652a4ebbdd8a42d09e28e2d3d83962a0350dLeon Scroggins III     *  and potentially preventing it from being thrown.
716d84c652a4ebbdd8a42d09e28e2d3d83962a0350dLeon Scroggins III     *
717d84c652a4ebbdd8a42d09e28e2d3d83962a0350dLeon Scroggins III     *  <p>If an instance is passed to
718d84c652a4ebbdd8a42d09e28e2d3d83962a0350dLeon Scroggins III     *  {@link #setOnPartialImageListener setOnPartialImageListener}, a
719d84c652a4ebbdd8a42d09e28e2d3d83962a0350dLeon Scroggins III     *  {@link DecodeException DecodeException} that would otherwise have been
720d84c652a4ebbdd8a42d09e28e2d3d83962a0350dLeon Scroggins III     *  thrown can be inspected inside
721d84c652a4ebbdd8a42d09e28e2d3d83962a0350dLeon Scroggins III     *  {@link OnPartialImageListener#onPartialImage onPartialImage}.
722d84c652a4ebbdd8a42d09e28e2d3d83962a0350dLeon Scroggins III     *  If {@link OnPartialImageListener#onPartialImage onPartialImage} returns
723d84c652a4ebbdd8a42d09e28e2d3d83962a0350dLeon Scroggins III     *  {@code true}, a partial image will be created.
7240c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III     */
725edf26d6e40f0723e70d7dcd147a2a2ce07c7c1ccLeon Scroggins III    public static interface OnPartialImageListener {
7260c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III        /**
727d84c652a4ebbdd8a42d09e28e2d3d83962a0350dLeon Scroggins III         *  Called by {@link ImageDecoder} when there is only a partial image to
728d84c652a4ebbdd8a42d09e28e2d3d83962a0350dLeon Scroggins III         *  display.
7290c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III         *
730d84c652a4ebbdd8a42d09e28e2d3d83962a0350dLeon Scroggins III         *  <p>If decoding is interrupted after having decoded a partial image,
731d84c652a4ebbdd8a42d09e28e2d3d83962a0350dLeon Scroggins III         *  this method will be called. The implementation can inspect the
732d84c652a4ebbdd8a42d09e28e2d3d83962a0350dLeon Scroggins III         *  {@link DecodeException DecodeException} and optionally finish the
733d84c652a4ebbdd8a42d09e28e2d3d83962a0350dLeon Scroggins III         *  rest of the decode creation process to create a partial {@link Drawable}
734d84c652a4ebbdd8a42d09e28e2d3d83962a0350dLeon Scroggins III         *  or {@link Bitmap}.
735edf26d6e40f0723e70d7dcd147a2a2ce07c7c1ccLeon Scroggins III         *
736d84c652a4ebbdd8a42d09e28e2d3d83962a0350dLeon Scroggins III         *  @param exception exception containing information about the
737d84c652a4ebbdd8a42d09e28e2d3d83962a0350dLeon Scroggins III         *      decode interruption.
738d84c652a4ebbdd8a42d09e28e2d3d83962a0350dLeon Scroggins III         *  @return {@code true} to create and return a {@link Drawable} or
739d84c652a4ebbdd8a42d09e28e2d3d83962a0350dLeon Scroggins III         *      {@link Bitmap} with partial data. {@code false} (which is the
740d84c652a4ebbdd8a42d09e28e2d3d83962a0350dLeon Scroggins III         *      default) to abort the decode and throw {@code e}. Any undecoded
741d84c652a4ebbdd8a42d09e28e2d3d83962a0350dLeon Scroggins III         *      lines in the image will be blank.
7420c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III         */
743d84c652a4ebbdd8a42d09e28e2d3d83962a0350dLeon Scroggins III        boolean onPartialImage(@NonNull DecodeException exception);
7440c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III    };
7450c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III
7460c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III    // Fields
747671cce2605ed50c9aba73ab5bd530cb7741c53cdLeon Scroggins III    private long          mNativePtr;
748671cce2605ed50c9aba73ab5bd530cb7741c53cdLeon Scroggins III    private final int     mWidth;
749671cce2605ed50c9aba73ab5bd530cb7741c53cdLeon Scroggins III    private final int     mHeight;
750671cce2605ed50c9aba73ab5bd530cb7741c53cdLeon Scroggins III    private final boolean mAnimated;
7517d940ba43d15836ccf32f373c778eebffacf1f5aLeon Scroggins III    private final boolean mIsNinePatch;
7520c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III
7531a69f4598faef083d0123bb9b6bfcd6acfdec4e0Leon Scroggins III    private int        mDesiredWidth;
7541a69f4598faef083d0123bb9b6bfcd6acfdec4e0Leon Scroggins III    private int        mDesiredHeight;
7551a69f4598faef083d0123bb9b6bfcd6acfdec4e0Leon Scroggins III    private int        mAllocator = ALLOCATOR_DEFAULT;
756d62f27250ab99d67242f1de293a31c12c397beb2Leon Scroggins III    private boolean    mUnpremultipliedRequired = false;
7571a69f4598faef083d0123bb9b6bfcd6acfdec4e0Leon Scroggins III    private boolean    mMutable = false;
7581a69f4598faef083d0123bb9b6bfcd6acfdec4e0Leon Scroggins III    private boolean    mConserveMemory = false;
7591a69f4598faef083d0123bb9b6bfcd6acfdec4e0Leon Scroggins III    private boolean    mDecodeAsAlphaMask = false;
7601a69f4598faef083d0123bb9b6bfcd6acfdec4e0Leon Scroggins III    private ColorSpace mDesiredColorSpace = null;
7611a69f4598faef083d0123bb9b6bfcd6acfdec4e0Leon Scroggins III    private Rect       mCropRect;
7621a69f4598faef083d0123bb9b6bfcd6acfdec4e0Leon Scroggins III    private Rect       mOutPaddingRect;
7631a69f4598faef083d0123bb9b6bfcd6acfdec4e0Leon Scroggins III    private Source     mSource;
7640c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III
765e5de9aa4a9bab9c4d8288212d6352a65e9808737Leon Scroggins III    private PostProcessor          mPostProcessor;
766edf26d6e40f0723e70d7dcd147a2a2ce07c7c1ccLeon Scroggins III    private OnPartialImageListener mOnPartialImageListener;
7670c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III
768ed074fd70011cf804a14b5cf53ffd4b529c5f367Leon Scroggins III    // Objects for interacting with the input.
769ed074fd70011cf804a14b5cf53ffd4b529c5f367Leon Scroggins III    private InputStream         mInputStream;
7700b49f5725cabd64d27960b1b017e5c009f701cf8Leon Scroggins III    private boolean             mOwnsInputStream;
771ed074fd70011cf804a14b5cf53ffd4b529c5f367Leon Scroggins III    private byte[]              mTempStorage;
772ed074fd70011cf804a14b5cf53ffd4b529c5f367Leon Scroggins III    private AssetFileDescriptor mAssetFd;
773ed074fd70011cf804a14b5cf53ffd4b529c5f367Leon Scroggins III    private final AtomicBoolean mClosed = new AtomicBoolean();
774ed074fd70011cf804a14b5cf53ffd4b529c5f367Leon Scroggins III    private final CloseGuard    mCloseGuard = CloseGuard.get();
7750c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III
7760c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III    /**
777ed074fd70011cf804a14b5cf53ffd4b529c5f367Leon Scroggins III     * Private constructor called by JNI. {@link #close} must be
7780c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III     * called after decoding to delete native resources.
7790c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III     */
7800c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III    @SuppressWarnings("unused")
781671cce2605ed50c9aba73ab5bd530cb7741c53cdLeon Scroggins III    private ImageDecoder(long nativePtr, int width, int height,
7827d940ba43d15836ccf32f373c778eebffacf1f5aLeon Scroggins III            boolean animated, boolean isNinePatch) {
7830c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III        mNativePtr = nativePtr;
7840c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III        mWidth = width;
7850c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III        mHeight = height;
7860c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III        mDesiredWidth = width;
7870c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III        mDesiredHeight = height;
788671cce2605ed50c9aba73ab5bd530cb7741c53cdLeon Scroggins III        mAnimated = animated;
7897d940ba43d15836ccf32f373c778eebffacf1f5aLeon Scroggins III        mIsNinePatch = isNinePatch;
790ed074fd70011cf804a14b5cf53ffd4b529c5f367Leon Scroggins III        mCloseGuard.open("close");
791ed074fd70011cf804a14b5cf53ffd4b529c5f367Leon Scroggins III    }
792ed074fd70011cf804a14b5cf53ffd4b529c5f367Leon Scroggins III
793ed074fd70011cf804a14b5cf53ffd4b529c5f367Leon Scroggins III    @Override
794ed074fd70011cf804a14b5cf53ffd4b529c5f367Leon Scroggins III    protected void finalize() throws Throwable {
795ed074fd70011cf804a14b5cf53ffd4b529c5f367Leon Scroggins III        try {
796ed074fd70011cf804a14b5cf53ffd4b529c5f367Leon Scroggins III            if (mCloseGuard != null) {
797ed074fd70011cf804a14b5cf53ffd4b529c5f367Leon Scroggins III                mCloseGuard.warnIfOpen();
798ed074fd70011cf804a14b5cf53ffd4b529c5f367Leon Scroggins III            }
799ed074fd70011cf804a14b5cf53ffd4b529c5f367Leon Scroggins III
800127d31a6842b6cca49885c3607e7ea35b1885b6fLeon Scroggins III            // Avoid closing these in finalizer.
801127d31a6842b6cca49885c3607e7ea35b1885b6fLeon Scroggins III            mInputStream = null;
802127d31a6842b6cca49885c3607e7ea35b1885b6fLeon Scroggins III            mAssetFd = null;
803127d31a6842b6cca49885c3607e7ea35b1885b6fLeon Scroggins III
804ed074fd70011cf804a14b5cf53ffd4b529c5f367Leon Scroggins III            close();
805ed074fd70011cf804a14b5cf53ffd4b529c5f367Leon Scroggins III        } finally {
806ed074fd70011cf804a14b5cf53ffd4b529c5f367Leon Scroggins III            super.finalize();
807ed074fd70011cf804a14b5cf53ffd4b529c5f367Leon Scroggins III        }
8080c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III    }
8090c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III
8100c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III    /**
811d84c652a4ebbdd8a42d09e28e2d3d83962a0350dLeon Scroggins III     * Create a new {@link Source Source} from a resource.
8120c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III     *
8130c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III     * @param res the {@link Resources} object containing the image data.
8140c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III     * @param resId resource ID of the image data.
8150c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III     * @return a new Source object, which can be passed to
816d84c652a4ebbdd8a42d09e28e2d3d83962a0350dLeon Scroggins III     *      {@link #decodeDrawable decodeDrawable} or
817d84c652a4ebbdd8a42d09e28e2d3d83962a0350dLeon Scroggins III     *      {@link #decodeBitmap decodeBitmap}.
8180c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III     */
8190a87cb3128a7fe8a999544ec1187159d82aa09ddLeon Scroggins III    @AnyThread
820ed074fd70011cf804a14b5cf53ffd4b529c5f367Leon Scroggins III    @NonNull
8211eccac89c13a79671e04cfce359a9506b284d5feLeon Scroggins III    public static Source createSource(@NonNull Resources res, int resId)
822ed074fd70011cf804a14b5cf53ffd4b529c5f367Leon Scroggins III    {
8230c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III        return new ResourceSource(res, resId);
8240c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III    }
8250c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III
8260c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III    /**
827d84c652a4ebbdd8a42d09e28e2d3d83962a0350dLeon Scroggins III     * Create a new {@link Source Source} from a {@link android.net.Uri}.
828d84c652a4ebbdd8a42d09e28e2d3d83962a0350dLeon Scroggins III     *
829d84c652a4ebbdd8a42d09e28e2d3d83962a0350dLeon Scroggins III     * <h5>Accepts the following URI schemes:</h5>
830d84c652a4ebbdd8a42d09e28e2d3d83962a0350dLeon Scroggins III     * <ul>
831d84c652a4ebbdd8a42d09e28e2d3d83962a0350dLeon Scroggins III     * <li>content ({@link ContentResolver#SCHEME_CONTENT})</li>
832d84c652a4ebbdd8a42d09e28e2d3d83962a0350dLeon Scroggins III     * <li>android.resource ({@link ContentResolver#SCHEME_ANDROID_RESOURCE})</li>
833d84c652a4ebbdd8a42d09e28e2d3d83962a0350dLeon Scroggins III     * <li>file ({@link ContentResolver#SCHEME_FILE})</li>
834d84c652a4ebbdd8a42d09e28e2d3d83962a0350dLeon Scroggins III     * </ul>
835ed074fd70011cf804a14b5cf53ffd4b529c5f367Leon Scroggins III     *
836ed074fd70011cf804a14b5cf53ffd4b529c5f367Leon Scroggins III     * @param cr to retrieve from.
837ed074fd70011cf804a14b5cf53ffd4b529c5f367Leon Scroggins III     * @param uri of the image file.
838ed074fd70011cf804a14b5cf53ffd4b529c5f367Leon Scroggins III     * @return a new Source object, which can be passed to
839d84c652a4ebbdd8a42d09e28e2d3d83962a0350dLeon Scroggins III     *      {@link #decodeDrawable decodeDrawable} or
840d84c652a4ebbdd8a42d09e28e2d3d83962a0350dLeon Scroggins III     *      {@link #decodeBitmap decodeBitmap}.
841ed074fd70011cf804a14b5cf53ffd4b529c5f367Leon Scroggins III     */
8420a87cb3128a7fe8a999544ec1187159d82aa09ddLeon Scroggins III    @AnyThread
843ed074fd70011cf804a14b5cf53ffd4b529c5f367Leon Scroggins III    @NonNull
844ed074fd70011cf804a14b5cf53ffd4b529c5f367Leon Scroggins III    public static Source createSource(@NonNull ContentResolver cr,
845ed074fd70011cf804a14b5cf53ffd4b529c5f367Leon Scroggins III            @NonNull Uri uri) {
846046a99ebbb90f9ecdead7b057ef99764a1d295b9Leon Scroggins III        return new ContentResolverSource(cr, uri, null);
847046a99ebbb90f9ecdead7b057ef99764a1d295b9Leon Scroggins III    }
848046a99ebbb90f9ecdead7b057ef99764a1d295b9Leon Scroggins III
849046a99ebbb90f9ecdead7b057ef99764a1d295b9Leon Scroggins III    /**
850046a99ebbb90f9ecdead7b057ef99764a1d295b9Leon Scroggins III     * Provide Resources for density scaling.
851046a99ebbb90f9ecdead7b057ef99764a1d295b9Leon Scroggins III     *
852046a99ebbb90f9ecdead7b057ef99764a1d295b9Leon Scroggins III     * @hide
853046a99ebbb90f9ecdead7b057ef99764a1d295b9Leon Scroggins III     */
8540a87cb3128a7fe8a999544ec1187159d82aa09ddLeon Scroggins III    @AnyThread
855046a99ebbb90f9ecdead7b057ef99764a1d295b9Leon Scroggins III    @NonNull
856046a99ebbb90f9ecdead7b057ef99764a1d295b9Leon Scroggins III    public static Source createSource(@NonNull ContentResolver cr,
857046a99ebbb90f9ecdead7b057ef99764a1d295b9Leon Scroggins III            @NonNull Uri uri, @Nullable Resources res) {
858046a99ebbb90f9ecdead7b057ef99764a1d295b9Leon Scroggins III        return new ContentResolverSource(cr, uri, res);
859ed074fd70011cf804a14b5cf53ffd4b529c5f367Leon Scroggins III    }
860ed074fd70011cf804a14b5cf53ffd4b529c5f367Leon Scroggins III
861ed074fd70011cf804a14b5cf53ffd4b529c5f367Leon Scroggins III    /**
862d84c652a4ebbdd8a42d09e28e2d3d83962a0350dLeon Scroggins III     * Create a new {@link Source Source} from a file in the "assets" directory.
863121ef98bfb0e34a2726dd0fb9112915017bfcde4Leon Scroggins III     */
8640a87cb3128a7fe8a999544ec1187159d82aa09ddLeon Scroggins III    @AnyThread
865121ef98bfb0e34a2726dd0fb9112915017bfcde4Leon Scroggins III    @NonNull
866121ef98bfb0e34a2726dd0fb9112915017bfcde4Leon Scroggins III    public static Source createSource(@NonNull AssetManager assets, @NonNull String fileName) {
867121ef98bfb0e34a2726dd0fb9112915017bfcde4Leon Scroggins III        return new AssetSource(assets, fileName);
868121ef98bfb0e34a2726dd0fb9112915017bfcde4Leon Scroggins III    }
869121ef98bfb0e34a2726dd0fb9112915017bfcde4Leon Scroggins III
870121ef98bfb0e34a2726dd0fb9112915017bfcde4Leon Scroggins III    /**
871d84c652a4ebbdd8a42d09e28e2d3d83962a0350dLeon Scroggins III     * Create a new {@link Source Source} from a byte array.
872e5de9aa4a9bab9c4d8288212d6352a65e9808737Leon Scroggins III     *
8730c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III     * @param data byte array of compressed image data.
8740c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III     * @param offset offset into data for where the decoder should begin
8750c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III     *      parsing.
8760c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III     * @param length number of bytes, beginning at offset, to parse.
877d84c652a4ebbdd8a42d09e28e2d3d83962a0350dLeon Scroggins III     * @return a new Source object, which can be passed to
878d84c652a4ebbdd8a42d09e28e2d3d83962a0350dLeon Scroggins III     *      {@link #decodeDrawable decodeDrawable} or
879d84c652a4ebbdd8a42d09e28e2d3d83962a0350dLeon Scroggins III     *      {@link #decodeBitmap decodeBitmap}.
8800c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III     * @throws NullPointerException if data is null.
8810c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III     * @throws ArrayIndexOutOfBoundsException if offset and length are
8820c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III     *      not within data.
883e5de9aa4a9bab9c4d8288212d6352a65e9808737Leon Scroggins III     * @hide
8840c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III     */
8850a87cb3128a7fe8a999544ec1187159d82aa09ddLeon Scroggins III    @AnyThread
886e5de9aa4a9bab9c4d8288212d6352a65e9808737Leon Scroggins III    @NonNull
8870c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III    public static Source createSource(@NonNull byte[] data, int offset,
8880c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III            int length) throws ArrayIndexOutOfBoundsException {
8890c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III        if (data == null) {
8900c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III            throw new NullPointerException("null byte[] in createSource!");
8910c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III        }
8920c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III        if (offset < 0 || length < 0 || offset >= data.length ||
8930c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III                offset + length > data.length) {
8940c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III            throw new ArrayIndexOutOfBoundsException(
8950c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III                    "invalid offset/length!");
8960c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III        }
8970c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III        return new ByteArraySource(data, offset, length);
8980c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III    }
8990c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III
9000c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III    /**
901b1cc8e64374832c8b296f609bebabff068ded460Leon Scroggins III     * See {@link #createSource(byte[], int, int).
902e5de9aa4a9bab9c4d8288212d6352a65e9808737Leon Scroggins III     * @hide
903b1cc8e64374832c8b296f609bebabff068ded460Leon Scroggins III     */
9040a87cb3128a7fe8a999544ec1187159d82aa09ddLeon Scroggins III    @AnyThread
905e5de9aa4a9bab9c4d8288212d6352a65e9808737Leon Scroggins III    @NonNull
906b1cc8e64374832c8b296f609bebabff068ded460Leon Scroggins III    public static Source createSource(@NonNull byte[] data) {
907b1cc8e64374832c8b296f609bebabff068ded460Leon Scroggins III        return createSource(data, 0, data.length);
908b1cc8e64374832c8b296f609bebabff068ded460Leon Scroggins III    }
909b1cc8e64374832c8b296f609bebabff068ded460Leon Scroggins III
910b1cc8e64374832c8b296f609bebabff068ded460Leon Scroggins III    /**
911d84c652a4ebbdd8a42d09e28e2d3d83962a0350dLeon Scroggins III     * Create a new {@link Source Source} from a {@link java.nio.ByteBuffer}.
9120c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III     *
913d84c652a4ebbdd8a42d09e28e2d3d83962a0350dLeon Scroggins III     * <p>Decoding will start from {@link java.nio.ByteBuffer#position() buffer.position()}.
914d84c652a4ebbdd8a42d09e28e2d3d83962a0350dLeon Scroggins III     * The position of {@code buffer} will not be affected.</p>
9150c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III     *
916d84c652a4ebbdd8a42d09e28e2d3d83962a0350dLeon Scroggins III     * <p>Note: If this {@code Source} is passed to {@link #decodeDrawable decodeDrawable},
917d84c652a4ebbdd8a42d09e28e2d3d83962a0350dLeon Scroggins III     * and the encoded image is animated, the returned {@link AnimatedImageDrawable}
9184367534058a07fd79ef1bbfec4e27f34275ab5c7Leon Scroggins III     * will continue reading from the {@code buffer}, so its contents must not
9194367534058a07fd79ef1bbfec4e27f34275ab5c7Leon Scroggins III     * be modified, even after the {@code AnimatedImageDrawable} is returned.
9204367534058a07fd79ef1bbfec4e27f34275ab5c7Leon Scroggins III     * {@code buffer}'s contents should never be modified during decode.</p>
921d84c652a4ebbdd8a42d09e28e2d3d83962a0350dLeon Scroggins III     *
922d84c652a4ebbdd8a42d09e28e2d3d83962a0350dLeon Scroggins III     * @return a new Source object, which can be passed to
923d84c652a4ebbdd8a42d09e28e2d3d83962a0350dLeon Scroggins III     *      {@link #decodeDrawable decodeDrawable} or
924d84c652a4ebbdd8a42d09e28e2d3d83962a0350dLeon Scroggins III     *      {@link #decodeBitmap decodeBitmap}.
9250c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III     */
9260a87cb3128a7fe8a999544ec1187159d82aa09ddLeon Scroggins III    @AnyThread
927e5de9aa4a9bab9c4d8288212d6352a65e9808737Leon Scroggins III    @NonNull
928e5de9aa4a9bab9c4d8288212d6352a65e9808737Leon Scroggins III    public static Source createSource(@NonNull ByteBuffer buffer) {
9290a87cb3128a7fe8a999544ec1187159d82aa09ddLeon Scroggins III        return new ByteBufferSource(buffer);
9300c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III    }
9310c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III
9320c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III    /**
93366c6d78908e0203a497c2e97398c824b2591ea19Derek Sollenberger     * Internal API used to generate bitmaps for use by Drawables (i.e. BitmapDrawable)
9340a87cb3128a7fe8a999544ec1187159d82aa09ddLeon Scroggins III     *
9350a87cb3128a7fe8a999544ec1187159d82aa09ddLeon Scroggins III     * <p>Unlike other Sources, this one cannot be reused.</p>
9360a87cb3128a7fe8a999544ec1187159d82aa09ddLeon Scroggins III     *
93766c6d78908e0203a497c2e97398c824b2591ea19Derek Sollenberger     * @hide
93866c6d78908e0203a497c2e97398c824b2591ea19Derek Sollenberger     */
9390a87cb3128a7fe8a999544ec1187159d82aa09ddLeon Scroggins III    @AnyThread
9400a87cb3128a7fe8a999544ec1187159d82aa09ddLeon Scroggins III    @NonNull
94166c6d78908e0203a497c2e97398c824b2591ea19Derek Sollenberger    public static Source createSource(Resources res, InputStream is) {
94266c6d78908e0203a497c2e97398c824b2591ea19Derek Sollenberger        return new InputStreamSource(res, is, Bitmap.getDefaultDensity());
94366c6d78908e0203a497c2e97398c824b2591ea19Derek Sollenberger    }
94466c6d78908e0203a497c2e97398c824b2591ea19Derek Sollenberger
94566c6d78908e0203a497c2e97398c824b2591ea19Derek Sollenberger    /**
94666c6d78908e0203a497c2e97398c824b2591ea19Derek Sollenberger     * Internal API used to generate bitmaps for use by Drawables (i.e. BitmapDrawable)
9470a87cb3128a7fe8a999544ec1187159d82aa09ddLeon Scroggins III     *
9480a87cb3128a7fe8a999544ec1187159d82aa09ddLeon Scroggins III     * <p>Unlike other Sources, this one cannot be reused.</p>
9490a87cb3128a7fe8a999544ec1187159d82aa09ddLeon Scroggins III     *
95066c6d78908e0203a497c2e97398c824b2591ea19Derek Sollenberger     * @hide
95166c6d78908e0203a497c2e97398c824b2591ea19Derek Sollenberger     */
9520a87cb3128a7fe8a999544ec1187159d82aa09ddLeon Scroggins III    @AnyThread
9531d2bf2b846f0a98f7403bbc791adb2969685d87aLeon Scroggins III    @TestApi
9540a87cb3128a7fe8a999544ec1187159d82aa09ddLeon Scroggins III    @NonNull
95566c6d78908e0203a497c2e97398c824b2591ea19Derek Sollenberger    public static Source createSource(Resources res, InputStream is, int density) {
95666c6d78908e0203a497c2e97398c824b2591ea19Derek Sollenberger        return new InputStreamSource(res, is, density);
95766c6d78908e0203a497c2e97398c824b2591ea19Derek Sollenberger    }
95866c6d78908e0203a497c2e97398c824b2591ea19Derek Sollenberger
95966c6d78908e0203a497c2e97398c824b2591ea19Derek Sollenberger    /**
960d84c652a4ebbdd8a42d09e28e2d3d83962a0350dLeon Scroggins III     * Create a new {@link Source Source} from a {@link java.io.File}.
961d84c652a4ebbdd8a42d09e28e2d3d83962a0350dLeon Scroggins III     *
962d84c652a4ebbdd8a42d09e28e2d3d83962a0350dLeon Scroggins III     * @return a new Source object, which can be passed to
963d84c652a4ebbdd8a42d09e28e2d3d83962a0350dLeon Scroggins III     *      {@link #decodeDrawable decodeDrawable} or
964d84c652a4ebbdd8a42d09e28e2d3d83962a0350dLeon Scroggins III     *      {@link #decodeBitmap decodeBitmap}.
965e5de9aa4a9bab9c4d8288212d6352a65e9808737Leon Scroggins III     */
9660a87cb3128a7fe8a999544ec1187159d82aa09ddLeon Scroggins III    @AnyThread
967e5de9aa4a9bab9c4d8288212d6352a65e9808737Leon Scroggins III    @NonNull
968e5de9aa4a9bab9c4d8288212d6352a65e9808737Leon Scroggins III    public static Source createSource(@NonNull File file) {
969e5de9aa4a9bab9c4d8288212d6352a65e9808737Leon Scroggins III        return new FileSource(file);
970e5de9aa4a9bab9c4d8288212d6352a65e9808737Leon Scroggins III    }
971e5de9aa4a9bab9c4d8288212d6352a65e9808737Leon Scroggins III
972e5de9aa4a9bab9c4d8288212d6352a65e9808737Leon Scroggins III    /**
9730c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III     *  Return the width and height of a given sample size.
9740c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III     *
975e5de9aa4a9bab9c4d8288212d6352a65e9808737Leon Scroggins III     *  <p>This takes an input that functions like
9760c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III     *  {@link BitmapFactory.Options#inSampleSize}. It returns a width and
97764481195e13e2dd7197fff569344e5a263b7871aLeon Scroggins III     *  height that can be achieved by sampling the encoded image. Other widths
9780c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III     *  and heights may be supported, but will require an additional (internal)
9790c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III     *  scaling step. Such internal scaling is *not* supported with
980d62f27250ab99d67242f1de293a31c12c397beb2Leon Scroggins III     *  {@link #setUnpremultipliedRequired} set to {@code true}.</p>
9810c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III     *
9820c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III     *  @param sampleSize Sampling rate of the encoded image.
983e5de9aa4a9bab9c4d8288212d6352a65e9808737Leon Scroggins III     *  @return {@link android.util.Size} of the width and height after
984e5de9aa4a9bab9c4d8288212d6352a65e9808737Leon Scroggins III     *      sampling.
98564481195e13e2dd7197fff569344e5a263b7871aLeon Scroggins III     *
98664481195e13e2dd7197fff569344e5a263b7871aLeon Scroggins III     *  @hide
9870c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III     */
988e5de9aa4a9bab9c4d8288212d6352a65e9808737Leon Scroggins III    @NonNull
989e5de9aa4a9bab9c4d8288212d6352a65e9808737Leon Scroggins III    public Size getSampledSize(int sampleSize) {
9900c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III        if (sampleSize <= 0) {
9910c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III            throw new IllegalArgumentException("sampleSize must be positive! "
9920c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III                    + "provided " + sampleSize);
9930c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III        }
9940c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III        if (mNativePtr == 0) {
995ed074fd70011cf804a14b5cf53ffd4b529c5f367Leon Scroggins III            throw new IllegalStateException("ImageDecoder is closed!");
9960c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III        }
9970c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III
9980c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III        return nGetSampledSize(mNativePtr, sampleSize);
9990c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III    }
10000c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III
10010c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III    // Modifiers
100264481195e13e2dd7197fff569344e5a263b7871aLeon Scroggins III    /** @removed
100364481195e13e2dd7197fff569344e5a263b7871aLeon Scroggins III     * @deprecated Renamed to {@link #setTargetSize}.
100464481195e13e2dd7197fff569344e5a263b7871aLeon Scroggins III     */
1005ac959199e5cf553a1b42a486e91918ead4394ff5Leon Scroggins III    @Deprecated
100664481195e13e2dd7197fff569344e5a263b7871aLeon Scroggins III    public ImageDecoder setResize(int width, int height) {
1007d9b53a097d0eec2d1112b25a67b28c203e9251f9Leon Scroggins III        this.setTargetSize(width, height);
1008d9b53a097d0eec2d1112b25a67b28c203e9251f9Leon Scroggins III        return this;
100964481195e13e2dd7197fff569344e5a263b7871aLeon Scroggins III    }
101064481195e13e2dd7197fff569344e5a263b7871aLeon Scroggins III
10110c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III    /**
101264481195e13e2dd7197fff569344e5a263b7871aLeon Scroggins III     *  Specify the size of the output {@link Drawable} or {@link Bitmap}.
101364481195e13e2dd7197fff569344e5a263b7871aLeon Scroggins III     *
101464481195e13e2dd7197fff569344e5a263b7871aLeon Scroggins III     *  <p>By default, the output size will match the size of the encoded
1015d84c652a4ebbdd8a42d09e28e2d3d83962a0350dLeon Scroggins III     *  image, which can be retrieved from the {@link ImageInfo ImageInfo} in
1016d84c652a4ebbdd8a42d09e28e2d3d83962a0350dLeon Scroggins III     *  {@link OnHeaderDecodedListener#onHeaderDecoded onHeaderDecoded}.</p>
1017d84c652a4ebbdd8a42d09e28e2d3d83962a0350dLeon Scroggins III     *
1018d84c652a4ebbdd8a42d09e28e2d3d83962a0350dLeon Scroggins III     *  <p>This will sample or scale the output to an arbitrary size that may
1019d84c652a4ebbdd8a42d09e28e2d3d83962a0350dLeon Scroggins III     *  be smaller or larger than the encoded size.</p>
102064481195e13e2dd7197fff569344e5a263b7871aLeon Scroggins III     *
10211a69f4598faef083d0123bb9b6bfcd6acfdec4e0Leon Scroggins III     *  <p>Only the last call to this or {@link #setTargetSampleSize} is
10221a69f4598faef083d0123bb9b6bfcd6acfdec4e0Leon Scroggins III     *  respected.</p>
10230c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III     *
10240a87cb3128a7fe8a999544ec1187159d82aa09ddLeon Scroggins III     *  <p>Like all setters on ImageDecoder, this must be called inside
1025d84c652a4ebbdd8a42d09e28e2d3d83962a0350dLeon Scroggins III     *  {@link OnHeaderDecodedListener#onHeaderDecoded onHeaderDecoded}.</p>
10260a87cb3128a7fe8a999544ec1187159d82aa09ddLeon Scroggins III     *
1027d97e26428d1c61759910a1b983d5e316c9b893a1Leon Scroggins III     *  @param width width in pixels of the output, must be greater than 0
1028d97e26428d1c61759910a1b983d5e316c9b893a1Leon Scroggins III     *  @param height height in pixels of the output, must be greater than 0
10290c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III     */
1030d97e26428d1c61759910a1b983d5e316c9b893a1Leon Scroggins III    public void setTargetSize(@Px @IntRange(from = 1) int width,
1031d97e26428d1c61759910a1b983d5e316c9b893a1Leon Scroggins III                              @Px @IntRange(from = 1) int height) {
10320c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III        if (width <= 0 || height <= 0) {
10330c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III            throw new IllegalArgumentException("Dimensions must be positive! "
10340c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III                    + "provided (" + width + ", " + height + ")");
10350c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III        }
10360c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III
10370c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III        mDesiredWidth = width;
10380c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III        mDesiredHeight = height;
10390c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III    }
10400c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III
104164481195e13e2dd7197fff569344e5a263b7871aLeon Scroggins III    /** @removed
10421a69f4598faef083d0123bb9b6bfcd6acfdec4e0Leon Scroggins III     * @deprecated Renamed to {@link #setTargetSampleSize}.
104364481195e13e2dd7197fff569344e5a263b7871aLeon Scroggins III     */
1044ac959199e5cf553a1b42a486e91918ead4394ff5Leon Scroggins III    @Deprecated
104564481195e13e2dd7197fff569344e5a263b7871aLeon Scroggins III    public ImageDecoder setResize(int sampleSize) {
1046d9b53a097d0eec2d1112b25a67b28c203e9251f9Leon Scroggins III        this.setTargetSampleSize(sampleSize);
1047d9b53a097d0eec2d1112b25a67b28c203e9251f9Leon Scroggins III        return this;
104864481195e13e2dd7197fff569344e5a263b7871aLeon Scroggins III    }
104964481195e13e2dd7197fff569344e5a263b7871aLeon Scroggins III
105064481195e13e2dd7197fff569344e5a263b7871aLeon Scroggins III    private int getTargetDimension(int original, int sampleSize, int computed) {
105164481195e13e2dd7197fff569344e5a263b7871aLeon Scroggins III        // Sampling will never result in a smaller size than 1.
105264481195e13e2dd7197fff569344e5a263b7871aLeon Scroggins III        if (sampleSize >= original) {
105364481195e13e2dd7197fff569344e5a263b7871aLeon Scroggins III            return 1;
105464481195e13e2dd7197fff569344e5a263b7871aLeon Scroggins III        }
105564481195e13e2dd7197fff569344e5a263b7871aLeon Scroggins III
105664481195e13e2dd7197fff569344e5a263b7871aLeon Scroggins III        // Use integer divide to find the desired size. If that is what
105764481195e13e2dd7197fff569344e5a263b7871aLeon Scroggins III        // getSampledSize computed, that is the size to use.
105864481195e13e2dd7197fff569344e5a263b7871aLeon Scroggins III        int target = original / sampleSize;
105964481195e13e2dd7197fff569344e5a263b7871aLeon Scroggins III        if (computed == target) {
106064481195e13e2dd7197fff569344e5a263b7871aLeon Scroggins III            return computed;
106164481195e13e2dd7197fff569344e5a263b7871aLeon Scroggins III        }
106264481195e13e2dd7197fff569344e5a263b7871aLeon Scroggins III
106364481195e13e2dd7197fff569344e5a263b7871aLeon Scroggins III        // If sampleSize does not divide evenly into original, the decoder
106464481195e13e2dd7197fff569344e5a263b7871aLeon Scroggins III        // may round in either direction. It just needs to get a result that
106564481195e13e2dd7197fff569344e5a263b7871aLeon Scroggins III        // is close.
106664481195e13e2dd7197fff569344e5a263b7871aLeon Scroggins III        int reverse = computed * sampleSize;
106764481195e13e2dd7197fff569344e5a263b7871aLeon Scroggins III        if (Math.abs(reverse - original) < sampleSize) {
106864481195e13e2dd7197fff569344e5a263b7871aLeon Scroggins III            // This is the size that can be decoded most efficiently.
106964481195e13e2dd7197fff569344e5a263b7871aLeon Scroggins III            return computed;
107064481195e13e2dd7197fff569344e5a263b7871aLeon Scroggins III        }
107164481195e13e2dd7197fff569344e5a263b7871aLeon Scroggins III
107264481195e13e2dd7197fff569344e5a263b7871aLeon Scroggins III        // The decoder could not get close (e.g. it is a DNG image).
107364481195e13e2dd7197fff569344e5a263b7871aLeon Scroggins III        return target;
107464481195e13e2dd7197fff569344e5a263b7871aLeon Scroggins III    }
107564481195e13e2dd7197fff569344e5a263b7871aLeon Scroggins III
10760c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III    /**
107764481195e13e2dd7197fff569344e5a263b7871aLeon Scroggins III     *  Set the target size with a sampleSize.
107864481195e13e2dd7197fff569344e5a263b7871aLeon Scroggins III     *
107964481195e13e2dd7197fff569344e5a263b7871aLeon Scroggins III     *  <p>By default, the output size will match the size of the encoded
1080d84c652a4ebbdd8a42d09e28e2d3d83962a0350dLeon Scroggins III     *  image, which can be retrieved from the {@link ImageInfo ImageInfo} in
1081d84c652a4ebbdd8a42d09e28e2d3d83962a0350dLeon Scroggins III     *  {@link OnHeaderDecodedListener#onHeaderDecoded onHeaderDecoded}.</p>
10820c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III     *
108364481195e13e2dd7197fff569344e5a263b7871aLeon Scroggins III     *  <p>Requests the decoder to subsample the original image, returning a
1084d84c652a4ebbdd8a42d09e28e2d3d83962a0350dLeon Scroggins III     *  smaller image to save memory. The {@code sampleSize} is the number of pixels
108564481195e13e2dd7197fff569344e5a263b7871aLeon Scroggins III     *  in either dimension that correspond to a single pixel in the output.
1086d84c652a4ebbdd8a42d09e28e2d3d83962a0350dLeon Scroggins III     *  For example, {@code sampleSize == 4} returns an image that is 1/4 the
108764481195e13e2dd7197fff569344e5a263b7871aLeon Scroggins III     *  width/height of the original, and 1/16 the number of pixels.</p>
108864481195e13e2dd7197fff569344e5a263b7871aLeon Scroggins III     *
108964481195e13e2dd7197fff569344e5a263b7871aLeon Scroggins III     *  <p>Must be greater than or equal to 1.</p>
109064481195e13e2dd7197fff569344e5a263b7871aLeon Scroggins III     *
1091d97e26428d1c61759910a1b983d5e316c9b893a1Leon Scroggins III     *  <p>This has the same effect as calling {@link #setTargetSize} with
1092d97e26428d1c61759910a1b983d5e316c9b893a1Leon Scroggins III     *  dimensions based on the {@code sampleSize}. Unlike dividing the original
1093d97e26428d1c61759910a1b983d5e316c9b893a1Leon Scroggins III     *  width and height by the {@code sampleSize} manually, calling this method
1094d97e26428d1c61759910a1b983d5e316c9b893a1Leon Scroggins III     *  allows {@code ImageDecoder} to round in the direction that it can do most
1095d97e26428d1c61759910a1b983d5e316c9b893a1Leon Scroggins III     *  efficiently.</p>
1096d97e26428d1c61759910a1b983d5e316c9b893a1Leon Scroggins III     *
109764481195e13e2dd7197fff569344e5a263b7871aLeon Scroggins III     *  <p>Only the last call to this or {@link #setTargetSize} is respected.</p>
10980c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III     *
10990a87cb3128a7fe8a999544ec1187159d82aa09ddLeon Scroggins III     *  <p>Like all setters on ImageDecoder, this must be called inside
1100d84c652a4ebbdd8a42d09e28e2d3d83962a0350dLeon Scroggins III     *  {@link OnHeaderDecodedListener#onHeaderDecoded onHeaderDecoded}.</p>
11010a87cb3128a7fe8a999544ec1187159d82aa09ddLeon Scroggins III     *
1102d97e26428d1c61759910a1b983d5e316c9b893a1Leon Scroggins III     *  @param sampleSize sampling rate of the encoded image.
11030c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III     */
1104d97e26428d1c61759910a1b983d5e316c9b893a1Leon Scroggins III    public void setTargetSampleSize(@IntRange(from = 1) int sampleSize) {
1105e5de9aa4a9bab9c4d8288212d6352a65e9808737Leon Scroggins III        Size size = this.getSampledSize(sampleSize);
110664481195e13e2dd7197fff569344e5a263b7871aLeon Scroggins III        int targetWidth = getTargetDimension(mWidth, sampleSize, size.getWidth());
110764481195e13e2dd7197fff569344e5a263b7871aLeon Scroggins III        int targetHeight = getTargetDimension(mHeight, sampleSize, size.getHeight());
1108d9b53a097d0eec2d1112b25a67b28c203e9251f9Leon Scroggins III        this.setTargetSize(targetWidth, targetHeight);
11090c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III    }
11100c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III
111166c6d78908e0203a497c2e97398c824b2591ea19Derek Sollenberger    private boolean requestedResize() {
111266c6d78908e0203a497c2e97398c824b2591ea19Derek Sollenberger        return mWidth != mDesiredWidth || mHeight != mDesiredHeight;
111366c6d78908e0203a497c2e97398c824b2591ea19Derek Sollenberger    }
111466c6d78908e0203a497c2e97398c824b2591ea19Derek Sollenberger
11150c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III    // These need to stay in sync with ImageDecoder.cpp's Allocator enum.
11160c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III    /**
11170c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III     *  Use the default allocation for the pixel memory.
11180c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III     *
11190c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III     *  Will typically result in a {@link Bitmap.Config#HARDWARE}
11200c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III     *  allocation, but may be software for small images. In addition, this will
11210c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III     *  switch to software when HARDWARE is incompatible, e.g.
1122d84c652a4ebbdd8a42d09e28e2d3d83962a0350dLeon Scroggins III     *  {@link #setMutableRequired setMutableRequired(true)} or
1123d84c652a4ebbdd8a42d09e28e2d3d83962a0350dLeon Scroggins III     *  {@link #setDecodeAsAlphaMaskEnabled setDecodeAsAlphaMaskEnabled(true)}.
11240c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III     */
1125e5de9aa4a9bab9c4d8288212d6352a65e9808737Leon Scroggins III    public static final int ALLOCATOR_DEFAULT = 0;
11260c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III
11270c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III    /**
11280c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III     *  Use a software allocation for the pixel memory.
11290c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III     *
1130ac959199e5cf553a1b42a486e91918ead4394ff5Leon Scroggins III     *  <p>Useful for drawing to a software {@link Canvas} or for
11310c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III     *  accessing the pixels on the final output.
11320c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III     */
1133e5de9aa4a9bab9c4d8288212d6352a65e9808737Leon Scroggins III    public static final int ALLOCATOR_SOFTWARE = 1;
11340c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III
11350c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III    /**
11360c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III     *  Use shared memory for the pixel memory.
11370c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III     *
1138ac959199e5cf553a1b42a486e91918ead4394ff5Leon Scroggins III     *  <p>Useful for sharing across processes.
11390c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III     */
1140e5de9aa4a9bab9c4d8288212d6352a65e9808737Leon Scroggins III    public static final int ALLOCATOR_SHARED_MEMORY = 2;
11410c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III
11420c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III    /**
11430c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III     *  Require a {@link Bitmap.Config#HARDWARE} {@link Bitmap}.
11440c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III     *
1145ac959199e5cf553a1b42a486e91918ead4394ff5Leon Scroggins III     *  <p>When this is combined with incompatible options, like
1146d84c652a4ebbdd8a42d09e28e2d3d83962a0350dLeon Scroggins III     *  {@link #setMutableRequired setMutableRequired(true)} or
1147d84c652a4ebbdd8a42d09e28e2d3d83962a0350dLeon Scroggins III     *  {@link #setDecodeAsAlphaMaskEnabled setDecodeAsAlphaMaskEnabled(true)},
1148d84c652a4ebbdd8a42d09e28e2d3d83962a0350dLeon Scroggins III     *  {@link #decodeDrawable decodeDrawable} or {@link #decodeBitmap decodeBitmap}
1149d84c652a4ebbdd8a42d09e28e2d3d83962a0350dLeon Scroggins III     *  will throw an {@link java.lang.IllegalStateException}.
11500c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III     */
1151e5de9aa4a9bab9c4d8288212d6352a65e9808737Leon Scroggins III    public static final int ALLOCATOR_HARDWARE = 3;
11520c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III
11530c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III    /** @hide **/
11540c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III    @Retention(SOURCE)
115562f0800ef4f41f97ddb18b755a63c01fea67b9faLeon Scroggins III    @IntDef(value = { ALLOCATOR_DEFAULT, ALLOCATOR_SOFTWARE,
115662f0800ef4f41f97ddb18b755a63c01fea67b9faLeon Scroggins III              ALLOCATOR_SHARED_MEMORY, ALLOCATOR_HARDWARE },
115762f0800ef4f41f97ddb18b755a63c01fea67b9faLeon Scroggins III              prefix = {"ALLOCATOR_"})
11580c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III    public @interface Allocator {};
11590c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III
11600c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III    /**
11610c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III     *  Choose the backing for the pixel memory.
11620c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III     *
11630a87cb3128a7fe8a999544ec1187159d82aa09ddLeon Scroggins III     *  <p>This is ignored for animated drawables.</p>
11640a87cb3128a7fe8a999544ec1187159d82aa09ddLeon Scroggins III     *
11650a87cb3128a7fe8a999544ec1187159d82aa09ddLeon Scroggins III     *  <p>Like all setters on ImageDecoder, this must be called inside
1166d84c652a4ebbdd8a42d09e28e2d3d83962a0350dLeon Scroggins III     *  {@link OnHeaderDecodedListener#onHeaderDecoded onHeaderDecoded}.</p>
11670c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III     *
11680c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III     *  @param allocator Type of allocator to use.
11690c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III     */
1170d9b53a097d0eec2d1112b25a67b28c203e9251f9Leon Scroggins III    public void setAllocator(@Allocator int allocator) {
1171e5de9aa4a9bab9c4d8288212d6352a65e9808737Leon Scroggins III        if (allocator < ALLOCATOR_DEFAULT || allocator > ALLOCATOR_HARDWARE) {
11720c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III            throw new IllegalArgumentException("invalid allocator " + allocator);
11730c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III        }
11740c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III        mAllocator = allocator;
11750c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III    }
11760c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III
11770c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III    /**
1178746a9fee937969af9be7e060335e26e098971615Leon Scroggins III     *  Return the allocator for the pixel memory.
1179746a9fee937969af9be7e060335e26e098971615Leon Scroggins III     */
1180746a9fee937969af9be7e060335e26e098971615Leon Scroggins III    @Allocator
1181746a9fee937969af9be7e060335e26e098971615Leon Scroggins III    public int getAllocator() {
1182746a9fee937969af9be7e060335e26e098971615Leon Scroggins III        return mAllocator;
1183746a9fee937969af9be7e060335e26e098971615Leon Scroggins III    }
1184746a9fee937969af9be7e060335e26e098971615Leon Scroggins III
1185746a9fee937969af9be7e060335e26e098971615Leon Scroggins III    /**
1186e5de9aa4a9bab9c4d8288212d6352a65e9808737Leon Scroggins III     *  Specify whether the {@link Bitmap} should have unpremultiplied pixels.
11870c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III     *
11885f7e948ad808d3f9c84482594e0da45b4181a6e5Leon Scroggins III     *  <p>By default, ImageDecoder will create a {@link Bitmap} with
11890c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III     *  premultiplied pixels, which is required for drawing with the
11900c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III     *  {@link android.view.View} system (i.e. to a {@link Canvas}). Calling
1191e5de9aa4a9bab9c4d8288212d6352a65e9808737Leon Scroggins III     *  this method with a value of {@code true} will result in
1192e5de9aa4a9bab9c4d8288212d6352a65e9808737Leon Scroggins III     *  {@link #decodeBitmap} returning a {@link Bitmap} with unpremultiplied
1193d84c652a4ebbdd8a42d09e28e2d3d83962a0350dLeon Scroggins III     *  pixels. See {@link Bitmap#isPremultiplied Bitmap.isPremultiplied()}.
1194d84c652a4ebbdd8a42d09e28e2d3d83962a0350dLeon Scroggins III     *  This is incompatible with {@link #decodeDrawable decodeDrawable};
1195d84c652a4ebbdd8a42d09e28e2d3d83962a0350dLeon Scroggins III     *  attempting to decode an unpremultiplied {@link Drawable} will throw an
1196d84c652a4ebbdd8a42d09e28e2d3d83962a0350dLeon Scroggins III     *  {@link java.lang.IllegalStateException}. </p>
11975f7e948ad808d3f9c84482594e0da45b4181a6e5Leon Scroggins III     *
11980a87cb3128a7fe8a999544ec1187159d82aa09ddLeon Scroggins III     *  <p>Like all setters on ImageDecoder, this must be called inside
1199d84c652a4ebbdd8a42d09e28e2d3d83962a0350dLeon Scroggins III     *  {@link OnHeaderDecodedListener#onHeaderDecoded onHeaderDecoded}.</p>
12000c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III     */
1201d9b53a097d0eec2d1112b25a67b28c203e9251f9Leon Scroggins III    public void setUnpremultipliedRequired(boolean unpremultipliedRequired) {
1202d62f27250ab99d67242f1de293a31c12c397beb2Leon Scroggins III        mUnpremultipliedRequired = unpremultipliedRequired;
12030c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III    }
12040c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III
1205d62f27250ab99d67242f1de293a31c12c397beb2Leon Scroggins III    /** @removed
1206d62f27250ab99d67242f1de293a31c12c397beb2Leon Scroggins III     * @deprecated Renamed to {@link #setUnpremultipliedRequired}.
1207d62f27250ab99d67242f1de293a31c12c397beb2Leon Scroggins III     */
1208ac959199e5cf553a1b42a486e91918ead4394ff5Leon Scroggins III    @Deprecated
1209d62f27250ab99d67242f1de293a31c12c397beb2Leon Scroggins III    public ImageDecoder setRequireUnpremultiplied(boolean unpremultipliedRequired) {
1210d9b53a097d0eec2d1112b25a67b28c203e9251f9Leon Scroggins III        this.setUnpremultipliedRequired(unpremultipliedRequired);
1211d9b53a097d0eec2d1112b25a67b28c203e9251f9Leon Scroggins III        return this;
1212d62f27250ab99d67242f1de293a31c12c397beb2Leon Scroggins III    }
1213d62f27250ab99d67242f1de293a31c12c397beb2Leon Scroggins III
12140c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III    /**
1215746a9fee937969af9be7e060335e26e098971615Leon Scroggins III     *  Return whether the {@link Bitmap} will have unpremultiplied pixels.
1216746a9fee937969af9be7e060335e26e098971615Leon Scroggins III     */
1217d62f27250ab99d67242f1de293a31c12c397beb2Leon Scroggins III    public boolean isUnpremultipliedRequired() {
1218d62f27250ab99d67242f1de293a31c12c397beb2Leon Scroggins III        return mUnpremultipliedRequired;
1219d62f27250ab99d67242f1de293a31c12c397beb2Leon Scroggins III    }
1220d62f27250ab99d67242f1de293a31c12c397beb2Leon Scroggins III
1221d62f27250ab99d67242f1de293a31c12c397beb2Leon Scroggins III    /** @removed
1222d62f27250ab99d67242f1de293a31c12c397beb2Leon Scroggins III     * @deprecated Renamed to {@link #isUnpremultipliedRequired}.
1223d62f27250ab99d67242f1de293a31c12c397beb2Leon Scroggins III     */
1224ac959199e5cf553a1b42a486e91918ead4394ff5Leon Scroggins III    @Deprecated
1225746a9fee937969af9be7e060335e26e098971615Leon Scroggins III    public boolean getRequireUnpremultiplied() {
1226d62f27250ab99d67242f1de293a31c12c397beb2Leon Scroggins III        return this.isUnpremultipliedRequired();
1227746a9fee937969af9be7e060335e26e098971615Leon Scroggins III    }
1228746a9fee937969af9be7e060335e26e098971615Leon Scroggins III
1229746a9fee937969af9be7e060335e26e098971615Leon Scroggins III    /**
12300c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III     *  Modify the image after decoding and scaling.
12310c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III     *
1232e5de9aa4a9bab9c4d8288212d6352a65e9808737Leon Scroggins III     *  <p>This allows adding effects prior to returning a {@link Drawable} or
12330c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III     *  {@link Bitmap}. For a {@code Drawable} or an immutable {@code Bitmap},
1234e5de9aa4a9bab9c4d8288212d6352a65e9808737Leon Scroggins III     *  this is the only way to process the image after decoding.</p>
12350c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III     *
1236d84c652a4ebbdd8a42d09e28e2d3d83962a0350dLeon Scroggins III     *  <p>If combined with {@link #setTargetSize} and/or {@link #setCrop},
1237d84c652a4ebbdd8a42d09e28e2d3d83962a0350dLeon Scroggins III     *  {@link PostProcessor#onPostProcess} occurs last.</p>
1238d84c652a4ebbdd8a42d09e28e2d3d83962a0350dLeon Scroggins III     *
1239e5de9aa4a9bab9c4d8288212d6352a65e9808737Leon Scroggins III     *  <p>If set on a nine-patch image, the nine-patch data is ignored.</p>
12400c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III     *
1241e5de9aa4a9bab9c4d8288212d6352a65e9808737Leon Scroggins III     *  <p>For an animated image, the drawing commands drawn on the
1242e5de9aa4a9bab9c4d8288212d6352a65e9808737Leon Scroggins III     *  {@link Canvas} will be recorded immediately and then applied to each
1243e5de9aa4a9bab9c4d8288212d6352a65e9808737Leon Scroggins III     *  frame.</p>
12445f7e948ad808d3f9c84482594e0da45b4181a6e5Leon Scroggins III     *
12450a87cb3128a7fe8a999544ec1187159d82aa09ddLeon Scroggins III     *  <p>Like all setters on ImageDecoder, this must be called inside
1246d84c652a4ebbdd8a42d09e28e2d3d83962a0350dLeon Scroggins III     *  {@link OnHeaderDecodedListener#onHeaderDecoded onHeaderDecoded}.</p>
12470a87cb3128a7fe8a999544ec1187159d82aa09ddLeon Scroggins III     *
12480c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III     */
1249d84c652a4ebbdd8a42d09e28e2d3d83962a0350dLeon Scroggins III    public void setPostProcessor(@Nullable PostProcessor postProcessor) {
1250d84c652a4ebbdd8a42d09e28e2d3d83962a0350dLeon Scroggins III        mPostProcessor = postProcessor;
12510c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III    }
12520c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III
12530c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III    /**
1254746a9fee937969af9be7e060335e26e098971615Leon Scroggins III     *  Return the {@link PostProcessor} currently set.
1255746a9fee937969af9be7e060335e26e098971615Leon Scroggins III     */
1256746a9fee937969af9be7e060335e26e098971615Leon Scroggins III    @Nullable
1257746a9fee937969af9be7e060335e26e098971615Leon Scroggins III    public PostProcessor getPostProcessor() {
1258746a9fee937969af9be7e060335e26e098971615Leon Scroggins III        return mPostProcessor;
1259746a9fee937969af9be7e060335e26e098971615Leon Scroggins III    }
1260746a9fee937969af9be7e060335e26e098971615Leon Scroggins III
1261746a9fee937969af9be7e060335e26e098971615Leon Scroggins III    /**
1262edf26d6e40f0723e70d7dcd147a2a2ce07c7c1ccLeon Scroggins III     *  Set (replace) the {@link OnPartialImageListener} on this object.
12630c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III     *
12645f7e948ad808d3f9c84482594e0da45b4181a6e5Leon Scroggins III     *  <p>Will be called if there is an error in the input. Without one, an
1265d84c652a4ebbdd8a42d09e28e2d3d83962a0350dLeon Scroggins III     *  error will result in an {@code Exception} being thrown.</p>
12665f7e948ad808d3f9c84482594e0da45b4181a6e5Leon Scroggins III     *
12670a87cb3128a7fe8a999544ec1187159d82aa09ddLeon Scroggins III     *  <p>Like all setters on ImageDecoder, this must be called inside
1268d84c652a4ebbdd8a42d09e28e2d3d83962a0350dLeon Scroggins III     *  {@link OnHeaderDecodedListener#onHeaderDecoded onHeaderDecoded}.</p>
12690a87cb3128a7fe8a999544ec1187159d82aa09ddLeon Scroggins III     *
12700c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III     */
1271d84c652a4ebbdd8a42d09e28e2d3d83962a0350dLeon Scroggins III    public void setOnPartialImageListener(@Nullable OnPartialImageListener listener) {
1272d84c652a4ebbdd8a42d09e28e2d3d83962a0350dLeon Scroggins III        mOnPartialImageListener = listener;
12730c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III    }
12740c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III
12750c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III    /**
1276d84c652a4ebbdd8a42d09e28e2d3d83962a0350dLeon Scroggins III     *  Return the {@link OnPartialImageListener OnPartialImageListener} currently set.
1277746a9fee937969af9be7e060335e26e098971615Leon Scroggins III     */
1278746a9fee937969af9be7e060335e26e098971615Leon Scroggins III    @Nullable
1279746a9fee937969af9be7e060335e26e098971615Leon Scroggins III    public OnPartialImageListener getOnPartialImageListener() {
1280746a9fee937969af9be7e060335e26e098971615Leon Scroggins III        return mOnPartialImageListener;
1281746a9fee937969af9be7e060335e26e098971615Leon Scroggins III    }
1282746a9fee937969af9be7e060335e26e098971615Leon Scroggins III
1283746a9fee937969af9be7e060335e26e098971615Leon Scroggins III    /**
12840c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III     *  Crop the output to {@code subset} of the (possibly) scaled image.
12850c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III     *
1286e5de9aa4a9bab9c4d8288212d6352a65e9808737Leon Scroggins III     *  <p>{@code subset} must be contained within the size set by
128764481195e13e2dd7197fff569344e5a263b7871aLeon Scroggins III     *  {@link #setTargetSize} or the bounds of the image if setTargetSize was
128864481195e13e2dd7197fff569344e5a263b7871aLeon Scroggins III     *  not called. Otherwise an {@link IllegalStateException} will be thrown by
1289d84c652a4ebbdd8a42d09e28e2d3d83962a0350dLeon Scroggins III     *  {@link #decodeDrawable decodeDrawable}/{@link #decodeBitmap decodeBitmap}.</p>
12900c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III     *
1291e5de9aa4a9bab9c4d8288212d6352a65e9808737Leon Scroggins III     *  <p>NOT intended as a replacement for
1292d84c652a4ebbdd8a42d09e28e2d3d83962a0350dLeon Scroggins III     *  {@link BitmapRegionDecoder#decodeRegion BitmapRegionDecoder.decodeRegion()}.
1293d84c652a4ebbdd8a42d09e28e2d3d83962a0350dLeon Scroggins III     *  This supports all formats, but merely crops the output.</p>
12945f7e948ad808d3f9c84482594e0da45b4181a6e5Leon Scroggins III     *
12950a87cb3128a7fe8a999544ec1187159d82aa09ddLeon Scroggins III     *  <p>Like all setters on ImageDecoder, this must be called inside
1296d84c652a4ebbdd8a42d09e28e2d3d83962a0350dLeon Scroggins III     *  {@link OnHeaderDecodedListener#onHeaderDecoded onHeaderDecoded}.</p>
12970a87cb3128a7fe8a999544ec1187159d82aa09ddLeon Scroggins III     *
12980c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III     */
1299d9b53a097d0eec2d1112b25a67b28c203e9251f9Leon Scroggins III    public void setCrop(@Nullable Rect subset) {
13000c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III        mCropRect = subset;
13010c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III    }
13020c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III
13030c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III    /**
1304746a9fee937969af9be7e060335e26e098971615Leon Scroggins III     *  Return the cropping rectangle, if set.
1305746a9fee937969af9be7e060335e26e098971615Leon Scroggins III     */
1306746a9fee937969af9be7e060335e26e098971615Leon Scroggins III    @Nullable
1307746a9fee937969af9be7e060335e26e098971615Leon Scroggins III    public Rect getCrop() {
1308746a9fee937969af9be7e060335e26e098971615Leon Scroggins III        return mCropRect;
1309746a9fee937969af9be7e060335e26e098971615Leon Scroggins III    }
1310746a9fee937969af9be7e060335e26e098971615Leon Scroggins III
1311746a9fee937969af9be7e060335e26e098971615Leon Scroggins III    /**
13122f1b06b58fc3c496832afc9b6ceeb2a36ef4bfa6Leon Scroggins III     *  Set a Rect for retrieving nine patch padding.
13132f1b06b58fc3c496832afc9b6ceeb2a36ef4bfa6Leon Scroggins III     *
13142f1b06b58fc3c496832afc9b6ceeb2a36ef4bfa6Leon Scroggins III     *  If the image is a nine patch, this Rect will be set to the padding
13152f1b06b58fc3c496832afc9b6ceeb2a36ef4bfa6Leon Scroggins III     *  rectangle during decode. Otherwise it will not be modified.
13162f1b06b58fc3c496832afc9b6ceeb2a36ef4bfa6Leon Scroggins III     *
13170a87cb3128a7fe8a999544ec1187159d82aa09ddLeon Scroggins III     *  <p>Like all setters on ImageDecoder, this must be called inside
1318d84c652a4ebbdd8a42d09e28e2d3d83962a0350dLeon Scroggins III     *  {@link OnHeaderDecodedListener#onHeaderDecoded onHeaderDecoded}.</p>
13190a87cb3128a7fe8a999544ec1187159d82aa09ddLeon Scroggins III     *
13202f1b06b58fc3c496832afc9b6ceeb2a36ef4bfa6Leon Scroggins III     *  @hide
13212f1b06b58fc3c496832afc9b6ceeb2a36ef4bfa6Leon Scroggins III     */
1322d9b53a097d0eec2d1112b25a67b28c203e9251f9Leon Scroggins III    public void setOutPaddingRect(@NonNull Rect outPadding) {
13232f1b06b58fc3c496832afc9b6ceeb2a36ef4bfa6Leon Scroggins III        mOutPaddingRect = outPadding;
13242f1b06b58fc3c496832afc9b6ceeb2a36ef4bfa6Leon Scroggins III    }
13252f1b06b58fc3c496832afc9b6ceeb2a36ef4bfa6Leon Scroggins III
13262f1b06b58fc3c496832afc9b6ceeb2a36ef4bfa6Leon Scroggins III    /**
1327e5de9aa4a9bab9c4d8288212d6352a65e9808737Leon Scroggins III     *  Specify whether the {@link Bitmap} should be mutable.
13280c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III     *
1329d84c652a4ebbdd8a42d09e28e2d3d83962a0350dLeon Scroggins III     *  <p>By default, a {@link Bitmap} created by {@link #decodeBitmap decodeBitmap}
1330d84c652a4ebbdd8a42d09e28e2d3d83962a0350dLeon Scroggins III     *  will be immutable i.e. {@link Bitmap#isMutable() Bitmap.isMutable()} returns
1331d84c652a4ebbdd8a42d09e28e2d3d83962a0350dLeon Scroggins III     *  {@code false}. This can be changed with {@code setMutableRequired(true)}.
13320c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III     *
1333e5de9aa4a9bab9c4d8288212d6352a65e9808737Leon Scroggins III     *  <p>Mutable Bitmaps are incompatible with {@link #ALLOCATOR_HARDWARE},
1334e5de9aa4a9bab9c4d8288212d6352a65e9808737Leon Scroggins III     *  because {@link Bitmap.Config#HARDWARE} Bitmaps cannot be mutable.
1335e5de9aa4a9bab9c4d8288212d6352a65e9808737Leon Scroggins III     *  Attempting to combine them will throw an
1336e5de9aa4a9bab9c4d8288212d6352a65e9808737Leon Scroggins III     *  {@link java.lang.IllegalStateException}.</p>
13370c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III     *
1338d84c652a4ebbdd8a42d09e28e2d3d83962a0350dLeon Scroggins III     *  <p>Mutable Bitmaps are also incompatible with {@link #decodeDrawable decodeDrawable},
1339e5de9aa4a9bab9c4d8288212d6352a65e9808737Leon Scroggins III     *  which would require retrieving the Bitmap from the returned Drawable in
1340e5de9aa4a9bab9c4d8288212d6352a65e9808737Leon Scroggins III     *  order to modify. Attempting to decode a mutable {@link Drawable} will
1341e5de9aa4a9bab9c4d8288212d6352a65e9808737Leon Scroggins III     *  throw an {@link java.lang.IllegalStateException}.</p>
13425f7e948ad808d3f9c84482594e0da45b4181a6e5Leon Scroggins III     *
13430a87cb3128a7fe8a999544ec1187159d82aa09ddLeon Scroggins III     *  <p>Like all setters on ImageDecoder, this must be called inside
1344d84c652a4ebbdd8a42d09e28e2d3d83962a0350dLeon Scroggins III     *  {@link OnHeaderDecodedListener#onHeaderDecoded onHeaderDecoded}.</p>
13450c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III     */
1346d9b53a097d0eec2d1112b25a67b28c203e9251f9Leon Scroggins III    public void setMutableRequired(boolean mutable) {
1347e5de9aa4a9bab9c4d8288212d6352a65e9808737Leon Scroggins III        mMutable = mutable;
13480c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III    }
13490c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III
1350d62f27250ab99d67242f1de293a31c12c397beb2Leon Scroggins III    /** @removed
1351d62f27250ab99d67242f1de293a31c12c397beb2Leon Scroggins III     * @deprecated Renamed to {@link #setMutableRequired}.
1352d62f27250ab99d67242f1de293a31c12c397beb2Leon Scroggins III     */
1353ac959199e5cf553a1b42a486e91918ead4394ff5Leon Scroggins III    @Deprecated
1354d62f27250ab99d67242f1de293a31c12c397beb2Leon Scroggins III    public ImageDecoder setMutable(boolean mutable) {
1355d9b53a097d0eec2d1112b25a67b28c203e9251f9Leon Scroggins III        this.setMutableRequired(mutable);
1356d9b53a097d0eec2d1112b25a67b28c203e9251f9Leon Scroggins III        return this;
1357d62f27250ab99d67242f1de293a31c12c397beb2Leon Scroggins III    }
1358d62f27250ab99d67242f1de293a31c12c397beb2Leon Scroggins III
13590c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III    /**
1360d84c652a4ebbdd8a42d09e28e2d3d83962a0350dLeon Scroggins III     *  Return whether the decoded {@link Bitmap} will be mutable.
1361746a9fee937969af9be7e060335e26e098971615Leon Scroggins III     */
1362d62f27250ab99d67242f1de293a31c12c397beb2Leon Scroggins III    public boolean isMutableRequired() {
1363746a9fee937969af9be7e060335e26e098971615Leon Scroggins III        return mMutable;
1364746a9fee937969af9be7e060335e26e098971615Leon Scroggins III    }
1365746a9fee937969af9be7e060335e26e098971615Leon Scroggins III
1366d62f27250ab99d67242f1de293a31c12c397beb2Leon Scroggins III    /** @removed
1367d62f27250ab99d67242f1de293a31c12c397beb2Leon Scroggins III     * @deprecated Renamed to {@link #isMutableRequired}.
1368d62f27250ab99d67242f1de293a31c12c397beb2Leon Scroggins III     */
1369ac959199e5cf553a1b42a486e91918ead4394ff5Leon Scroggins III    @Deprecated
1370d62f27250ab99d67242f1de293a31c12c397beb2Leon Scroggins III    public boolean getMutable() {
1371d62f27250ab99d67242f1de293a31c12c397beb2Leon Scroggins III        return this.isMutableRequired();
1372d62f27250ab99d67242f1de293a31c12c397beb2Leon Scroggins III    }
1373d62f27250ab99d67242f1de293a31c12c397beb2Leon Scroggins III
1374746a9fee937969af9be7e060335e26e098971615Leon Scroggins III    /**
1375ac959199e5cf553a1b42a486e91918ead4394ff5Leon Scroggins III     * Save memory if possible by using a denser {@link Bitmap.Config} at the
1376ac959199e5cf553a1b42a486e91918ead4394ff5Leon Scroggins III     * cost of some image quality.
13770c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III     *
1378ac959199e5cf553a1b42a486e91918ead4394ff5Leon Scroggins III     * <p>For example an opaque 8-bit image may be compressed into an
1379ac959199e5cf553a1b42a486e91918ead4394ff5Leon Scroggins III     * {@link Bitmap.Config#RGB_565} configuration, sacrificing image
1380ac959199e5cf553a1b42a486e91918ead4394ff5Leon Scroggins III     * quality to save memory.
1381ac959199e5cf553a1b42a486e91918ead4394ff5Leon Scroggins III     */
1382ac959199e5cf553a1b42a486e91918ead4394ff5Leon Scroggins III    public static final int MEMORY_POLICY_LOW_RAM = 0;
1383ac959199e5cf553a1b42a486e91918ead4394ff5Leon Scroggins III
1384ac959199e5cf553a1b42a486e91918ead4394ff5Leon Scroggins III    /**
1385ac959199e5cf553a1b42a486e91918ead4394ff5Leon Scroggins III     * Use the most natural {@link Bitmap.Config} for the internal {@link Bitmap}.
1386ac959199e5cf553a1b42a486e91918ead4394ff5Leon Scroggins III     *
1387ac959199e5cf553a1b42a486e91918ead4394ff5Leon Scroggins III     * <p>This is the recommended default for most applications and usages. This
1388ac959199e5cf553a1b42a486e91918ead4394ff5Leon Scroggins III     * will use the closest {@link Bitmap.Config} for the encoded source. If the
1389ac959199e5cf553a1b42a486e91918ead4394ff5Leon Scroggins III     * encoded source does not exactly match any {@link Bitmap.Config}, the next
1390ac959199e5cf553a1b42a486e91918ead4394ff5Leon Scroggins III     * highest quality {@link Bitmap.Config} will be used avoiding any loss in
1391ac959199e5cf553a1b42a486e91918ead4394ff5Leon Scroggins III     * image quality.
1392ac959199e5cf553a1b42a486e91918ead4394ff5Leon Scroggins III     */
1393ac959199e5cf553a1b42a486e91918ead4394ff5Leon Scroggins III    public static final int MEMORY_POLICY_DEFAULT  = 1;
1394ac959199e5cf553a1b42a486e91918ead4394ff5Leon Scroggins III
1395ac959199e5cf553a1b42a486e91918ead4394ff5Leon Scroggins III    /** @hide **/
1396ac959199e5cf553a1b42a486e91918ead4394ff5Leon Scroggins III    @Retention(SOURCE)
1397ac959199e5cf553a1b42a486e91918ead4394ff5Leon Scroggins III    @IntDef(value = { MEMORY_POLICY_DEFAULT, MEMORY_POLICY_LOW_RAM },
1398ac959199e5cf553a1b42a486e91918ead4394ff5Leon Scroggins III              prefix = {"MEMORY_POLICY_"})
1399ac959199e5cf553a1b42a486e91918ead4394ff5Leon Scroggins III    public @interface MemoryPolicy {};
1400ac959199e5cf553a1b42a486e91918ead4394ff5Leon Scroggins III
1401ac959199e5cf553a1b42a486e91918ead4394ff5Leon Scroggins III    /**
1402ac959199e5cf553a1b42a486e91918ead4394ff5Leon Scroggins III     *  Specify the memory policy for the decoded {@link Bitmap}.
14035f7e948ad808d3f9c84482594e0da45b4181a6e5Leon Scroggins III     *
14040a87cb3128a7fe8a999544ec1187159d82aa09ddLeon Scroggins III     *  <p>Like all setters on ImageDecoder, this must be called inside
1405d84c652a4ebbdd8a42d09e28e2d3d83962a0350dLeon Scroggins III     *  {@link OnHeaderDecodedListener#onHeaderDecoded onHeaderDecoded}.</p>
14060c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III     */
1407ac959199e5cf553a1b42a486e91918ead4394ff5Leon Scroggins III    public void setMemorySizePolicy(@MemoryPolicy int policy) {
1408ac959199e5cf553a1b42a486e91918ead4394ff5Leon Scroggins III        mConserveMemory = (policy == MEMORY_POLICY_LOW_RAM);
1409ac959199e5cf553a1b42a486e91918ead4394ff5Leon Scroggins III    }
1410ac959199e5cf553a1b42a486e91918ead4394ff5Leon Scroggins III
1411ac959199e5cf553a1b42a486e91918ead4394ff5Leon Scroggins III    /**
1412ac959199e5cf553a1b42a486e91918ead4394ff5Leon Scroggins III     *  Retrieve the memory policy for the decoded {@link Bitmap}.
1413ac959199e5cf553a1b42a486e91918ead4394ff5Leon Scroggins III     */
1414ac959199e5cf553a1b42a486e91918ead4394ff5Leon Scroggins III    @MemoryPolicy
1415ac959199e5cf553a1b42a486e91918ead4394ff5Leon Scroggins III    public int getMemorySizePolicy() {
1416ac959199e5cf553a1b42a486e91918ead4394ff5Leon Scroggins III        return mConserveMemory ? MEMORY_POLICY_LOW_RAM : MEMORY_POLICY_DEFAULT;
1417ac959199e5cf553a1b42a486e91918ead4394ff5Leon Scroggins III    }
1418ac959199e5cf553a1b42a486e91918ead4394ff5Leon Scroggins III
1419ac959199e5cf553a1b42a486e91918ead4394ff5Leon Scroggins III    /** @removed
1420ac959199e5cf553a1b42a486e91918ead4394ff5Leon Scroggins III     * @deprecated Replaced by {@link #setMemorySizePolicy}.
1421ac959199e5cf553a1b42a486e91918ead4394ff5Leon Scroggins III     */
1422ac959199e5cf553a1b42a486e91918ead4394ff5Leon Scroggins III    @Deprecated
1423d9b53a097d0eec2d1112b25a67b28c203e9251f9Leon Scroggins III    public void setConserveMemory(boolean conserveMemory) {
1424a38b2135a4bf4368734567a73d2e56f1c318fee9Leon Scroggins III        mConserveMemory = conserveMemory;
14250c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III    }
14260c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III
1427ac959199e5cf553a1b42a486e91918ead4394ff5Leon Scroggins III    /** @removed
1428ac959199e5cf553a1b42a486e91918ead4394ff5Leon Scroggins III     * @deprecated Replaced by {@link #getMemorySizePolicy}.
1429746a9fee937969af9be7e060335e26e098971615Leon Scroggins III     */
1430ac959199e5cf553a1b42a486e91918ead4394ff5Leon Scroggins III    @Deprecated
1431746a9fee937969af9be7e060335e26e098971615Leon Scroggins III    public boolean getConserveMemory() {
1432746a9fee937969af9be7e060335e26e098971615Leon Scroggins III        return mConserveMemory;
1433746a9fee937969af9be7e060335e26e098971615Leon Scroggins III    }
1434746a9fee937969af9be7e060335e26e098971615Leon Scroggins III
1435746a9fee937969af9be7e060335e26e098971615Leon Scroggins III    /**
1436e5de9aa4a9bab9c4d8288212d6352a65e9808737Leon Scroggins III     *  Specify whether to potentially treat the output as an alpha mask.
14370c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III     *
1438e5de9aa4a9bab9c4d8288212d6352a65e9808737Leon Scroggins III     *  <p>If this is set to {@code true} and the image is encoded in a format
1439e5de9aa4a9bab9c4d8288212d6352a65e9808737Leon Scroggins III     *  with only one channel, treat that channel as alpha. Otherwise this call has
1440e5de9aa4a9bab9c4d8288212d6352a65e9808737Leon Scroggins III     *  no effect.</p>
14410c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III     *
1442d62f27250ab99d67242f1de293a31c12c397beb2Leon Scroggins III     *  <p>This is incompatible with {@link #ALLOCATOR_HARDWARE}. Trying to
1443d84c652a4ebbdd8a42d09e28e2d3d83962a0350dLeon Scroggins III     *  combine them will result in {@link #decodeDrawable decodeDrawable}/
1444d84c652a4ebbdd8a42d09e28e2d3d83962a0350dLeon Scroggins III     *  {@link #decodeBitmap decodeBitmap} throwing an
1445e5de9aa4a9bab9c4d8288212d6352a65e9808737Leon Scroggins III     *  {@link java.lang.IllegalStateException}.</p>
14465f7e948ad808d3f9c84482594e0da45b4181a6e5Leon Scroggins III     *
14470a87cb3128a7fe8a999544ec1187159d82aa09ddLeon Scroggins III     *  <p>Like all setters on ImageDecoder, this must be called inside
1448d84c652a4ebbdd8a42d09e28e2d3d83962a0350dLeon Scroggins III     *  {@link OnHeaderDecodedListener#onHeaderDecoded onHeaderDecoded}.</p>
14490c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III     */
1450d9b53a097d0eec2d1112b25a67b28c203e9251f9Leon Scroggins III    public void setDecodeAsAlphaMaskEnabled(boolean enabled) {
1451d62f27250ab99d67242f1de293a31c12c397beb2Leon Scroggins III        mDecodeAsAlphaMask = enabled;
14520c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III    }
14530c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III
1454746a9fee937969af9be7e060335e26e098971615Leon Scroggins III    /** @removed
1455d62f27250ab99d67242f1de293a31c12c397beb2Leon Scroggins III     * @deprecated Renamed to {@link #setDecodeAsAlphaMaskEnabled}.
1456d62f27250ab99d67242f1de293a31c12c397beb2Leon Scroggins III     */
1457ac959199e5cf553a1b42a486e91918ead4394ff5Leon Scroggins III    @Deprecated
1458d62f27250ab99d67242f1de293a31c12c397beb2Leon Scroggins III    public ImageDecoder setDecodeAsAlphaMask(boolean enabled) {
1459d9b53a097d0eec2d1112b25a67b28c203e9251f9Leon Scroggins III        this.setDecodeAsAlphaMaskEnabled(enabled);
1460d9b53a097d0eec2d1112b25a67b28c203e9251f9Leon Scroggins III        return this;
1461d62f27250ab99d67242f1de293a31c12c397beb2Leon Scroggins III    }
1462d62f27250ab99d67242f1de293a31c12c397beb2Leon Scroggins III
1463d62f27250ab99d67242f1de293a31c12c397beb2Leon Scroggins III    /** @removed
1464d62f27250ab99d67242f1de293a31c12c397beb2Leon Scroggins III     * @deprecated Renamed to {@link #setDecodeAsAlphaMaskEnabled}.
1465746a9fee937969af9be7e060335e26e098971615Leon Scroggins III     */
1466ac959199e5cf553a1b42a486e91918ead4394ff5Leon Scroggins III    @Deprecated
1467746a9fee937969af9be7e060335e26e098971615Leon Scroggins III    public ImageDecoder setAsAlphaMask(boolean asAlphaMask) {
1468d9b53a097d0eec2d1112b25a67b28c203e9251f9Leon Scroggins III        this.setDecodeAsAlphaMask(asAlphaMask);
1469d9b53a097d0eec2d1112b25a67b28c203e9251f9Leon Scroggins III        return this;
1470746a9fee937969af9be7e060335e26e098971615Leon Scroggins III    }
1471746a9fee937969af9be7e060335e26e098971615Leon Scroggins III
1472746a9fee937969af9be7e060335e26e098971615Leon Scroggins III    /**
1473746a9fee937969af9be7e060335e26e098971615Leon Scroggins III     *  Return whether to treat single channel input as alpha.
1474746a9fee937969af9be7e060335e26e098971615Leon Scroggins III     *
1475d62f27250ab99d67242f1de293a31c12c397beb2Leon Scroggins III     *  <p>This returns whether {@link #setDecodeAsAlphaMaskEnabled} was set to
1476d62f27250ab99d67242f1de293a31c12c397beb2Leon Scroggins III     *  {@code true}. It may still return {@code true} even if the image has
1477d62f27250ab99d67242f1de293a31c12c397beb2Leon Scroggins III     *  more than one channel and therefore will not be treated as an alpha
1478d62f27250ab99d67242f1de293a31c12c397beb2Leon Scroggins III     *  mask.</p>
1479d62f27250ab99d67242f1de293a31c12c397beb2Leon Scroggins III     */
1480d62f27250ab99d67242f1de293a31c12c397beb2Leon Scroggins III    public boolean isDecodeAsAlphaMaskEnabled() {
1481d62f27250ab99d67242f1de293a31c12c397beb2Leon Scroggins III        return mDecodeAsAlphaMask;
1482d62f27250ab99d67242f1de293a31c12c397beb2Leon Scroggins III    }
1483d62f27250ab99d67242f1de293a31c12c397beb2Leon Scroggins III
1484d62f27250ab99d67242f1de293a31c12c397beb2Leon Scroggins III    /** @removed
1485d62f27250ab99d67242f1de293a31c12c397beb2Leon Scroggins III     * @deprecated Renamed to {@link #isDecodeAsAlphaMaskEnabled}.
1486746a9fee937969af9be7e060335e26e098971615Leon Scroggins III     */
1487ac959199e5cf553a1b42a486e91918ead4394ff5Leon Scroggins III    @Deprecated
1488746a9fee937969af9be7e060335e26e098971615Leon Scroggins III    public boolean getDecodeAsAlphaMask() {
1489746a9fee937969af9be7e060335e26e098971615Leon Scroggins III        return mDecodeAsAlphaMask;
1490746a9fee937969af9be7e060335e26e098971615Leon Scroggins III    }
1491746a9fee937969af9be7e060335e26e098971615Leon Scroggins III
1492746a9fee937969af9be7e060335e26e098971615Leon Scroggins III    /** @removed
1493d62f27250ab99d67242f1de293a31c12c397beb2Leon Scroggins III     * @deprecated Renamed to {@link #isDecodeAsAlphaMaskEnabled}.
1494746a9fee937969af9be7e060335e26e098971615Leon Scroggins III     */
1495ac959199e5cf553a1b42a486e91918ead4394ff5Leon Scroggins III    @Deprecated
1496746a9fee937969af9be7e060335e26e098971615Leon Scroggins III    public boolean getAsAlphaMask() {
1497746a9fee937969af9be7e060335e26e098971615Leon Scroggins III        return this.getDecodeAsAlphaMask();
1498746a9fee937969af9be7e060335e26e098971615Leon Scroggins III    }
1499746a9fee937969af9be7e060335e26e098971615Leon Scroggins III
15001a69f4598faef083d0123bb9b6bfcd6acfdec4e0Leon Scroggins III    /**
15011a69f4598faef083d0123bb9b6bfcd6acfdec4e0Leon Scroggins III     * Specify the desired {@link ColorSpace} for the output.
15021a69f4598faef083d0123bb9b6bfcd6acfdec4e0Leon Scroggins III     *
1503d84c652a4ebbdd8a42d09e28e2d3d83962a0350dLeon Scroggins III     * <p>If non-null, the decoder will try to decode into {@code colorSpace}.
1504d84c652a4ebbdd8a42d09e28e2d3d83962a0350dLeon Scroggins III     * If it is null, which is the default, or the request cannot be met, the
1505d84c652a4ebbdd8a42d09e28e2d3d83962a0350dLeon Scroggins III     * decoder will pick either the color space embedded in the image or the
1506d84c652a4ebbdd8a42d09e28e2d3d83962a0350dLeon Scroggins III     * {@link ColorSpace} best suited for the requested image configuration
1507d84c652a4ebbdd8a42d09e28e2d3d83962a0350dLeon Scroggins III     * (for instance {@link ColorSpace.Named#SRGB sRGB} for the
1508d84c652a4ebbdd8a42d09e28e2d3d83962a0350dLeon Scroggins III     * {@link Bitmap.Config#ARGB_8888} configuration).</p>
15091a69f4598faef083d0123bb9b6bfcd6acfdec4e0Leon Scroggins III     *
15101a69f4598faef083d0123bb9b6bfcd6acfdec4e0Leon Scroggins III     * <p>{@link Bitmap.Config#RGBA_F16} always uses the
1511d84c652a4ebbdd8a42d09e28e2d3d83962a0350dLeon Scroggins III     * {@link ColorSpace.Named#LINEAR_EXTENDED_SRGB scRGB} color space.
15121a69f4598faef083d0123bb9b6bfcd6acfdec4e0Leon Scroggins III     * Bitmaps in other configurations without an embedded color space are
15131a69f4598faef083d0123bb9b6bfcd6acfdec4e0Leon Scroggins III     * assumed to be in the {@link ColorSpace.Named#SRGB sRGB} color space.</p>
15141a69f4598faef083d0123bb9b6bfcd6acfdec4e0Leon Scroggins III     *
15151a69f4598faef083d0123bb9b6bfcd6acfdec4e0Leon Scroggins III     * <p class="note">Only {@link ColorSpace.Model#RGB} color spaces are
15161a69f4598faef083d0123bb9b6bfcd6acfdec4e0Leon Scroggins III     * currently supported. An <code>IllegalArgumentException</code> will
1517d84c652a4ebbdd8a42d09e28e2d3d83962a0350dLeon Scroggins III     * be thrown by {@link #decodeDrawable decodeDrawable}/
1518d84c652a4ebbdd8a42d09e28e2d3d83962a0350dLeon Scroggins III     * {@link #decodeBitmap decodeBitmap} when setting a non-RGB color space
15191a69f4598faef083d0123bb9b6bfcd6acfdec4e0Leon Scroggins III     * such as {@link ColorSpace.Named#CIE_LAB Lab}.</p>
15201a69f4598faef083d0123bb9b6bfcd6acfdec4e0Leon Scroggins III     *
15211a69f4598faef083d0123bb9b6bfcd6acfdec4e0Leon Scroggins III     * <p class="note">The specified color space's transfer function must be
15221a69f4598faef083d0123bb9b6bfcd6acfdec4e0Leon Scroggins III     * an {@link ColorSpace.Rgb.TransferParameters ICC parametric curve}. An
15231a69f4598faef083d0123bb9b6bfcd6acfdec4e0Leon Scroggins III     * <code>IllegalArgumentException</code> will be thrown by the decode methods
15241a69f4598faef083d0123bb9b6bfcd6acfdec4e0Leon Scroggins III     * if calling {@link ColorSpace.Rgb#getTransferParameters()} on the
15251a69f4598faef083d0123bb9b6bfcd6acfdec4e0Leon Scroggins III     * specified color space returns null.</p>
15260a87cb3128a7fe8a999544ec1187159d82aa09ddLeon Scroggins III     *
15270a87cb3128a7fe8a999544ec1187159d82aa09ddLeon Scroggins III     * <p>Like all setters on ImageDecoder, this must be called inside
1528d84c652a4ebbdd8a42d09e28e2d3d83962a0350dLeon Scroggins III     * {@link OnHeaderDecodedListener#onHeaderDecoded onHeaderDecoded}.</p>
15291a69f4598faef083d0123bb9b6bfcd6acfdec4e0Leon Scroggins III     */
1530d9b53a097d0eec2d1112b25a67b28c203e9251f9Leon Scroggins III    public void setTargetColorSpace(ColorSpace colorSpace) {
15311a69f4598faef083d0123bb9b6bfcd6acfdec4e0Leon Scroggins III        mDesiredColorSpace = colorSpace;
15321a69f4598faef083d0123bb9b6bfcd6acfdec4e0Leon Scroggins III    }
15331a69f4598faef083d0123bb9b6bfcd6acfdec4e0Leon Scroggins III
1534d84c652a4ebbdd8a42d09e28e2d3d83962a0350dLeon Scroggins III    /**
1535d84c652a4ebbdd8a42d09e28e2d3d83962a0350dLeon Scroggins III     * Closes this resource, relinquishing any underlying resources. This method
1536d84c652a4ebbdd8a42d09e28e2d3d83962a0350dLeon Scroggins III     * is invoked automatically on objects managed by the try-with-resources
1537d84c652a4ebbdd8a42d09e28e2d3d83962a0350dLeon Scroggins III     * statement.
1538d84c652a4ebbdd8a42d09e28e2d3d83962a0350dLeon Scroggins III     *
1539d84c652a4ebbdd8a42d09e28e2d3d83962a0350dLeon Scroggins III     * <p>This is an implementation detail of {@link ImageDecoder}, and should
1540d84c652a4ebbdd8a42d09e28e2d3d83962a0350dLeon Scroggins III     * never be called manually.</p>
1541d84c652a4ebbdd8a42d09e28e2d3d83962a0350dLeon Scroggins III     */
1542ed074fd70011cf804a14b5cf53ffd4b529c5f367Leon Scroggins III    @Override
1543ed074fd70011cf804a14b5cf53ffd4b529c5f367Leon Scroggins III    public void close() {
1544ed074fd70011cf804a14b5cf53ffd4b529c5f367Leon Scroggins III        mCloseGuard.close();
1545ed074fd70011cf804a14b5cf53ffd4b529c5f367Leon Scroggins III        if (!mClosed.compareAndSet(false, true)) {
15460c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III            return;
15470c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III        }
1548ed074fd70011cf804a14b5cf53ffd4b529c5f367Leon Scroggins III        nClose(mNativePtr);
15490c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III        mNativePtr = 0;
1550ed074fd70011cf804a14b5cf53ffd4b529c5f367Leon Scroggins III
15510b49f5725cabd64d27960b1b017e5c009f701cf8Leon Scroggins III        if (mOwnsInputStream) {
15520b49f5725cabd64d27960b1b017e5c009f701cf8Leon Scroggins III            IoUtils.closeQuietly(mInputStream);
15530b49f5725cabd64d27960b1b017e5c009f701cf8Leon Scroggins III        }
1554ed074fd70011cf804a14b5cf53ffd4b529c5f367Leon Scroggins III        IoUtils.closeQuietly(mAssetFd);
1555ed074fd70011cf804a14b5cf53ffd4b529c5f367Leon Scroggins III
1556ed074fd70011cf804a14b5cf53ffd4b529c5f367Leon Scroggins III        mInputStream = null;
1557ed074fd70011cf804a14b5cf53ffd4b529c5f367Leon Scroggins III        mAssetFd = null;
1558ed074fd70011cf804a14b5cf53ffd4b529c5f367Leon Scroggins III        mTempStorage = null;
15590c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III    }
15600c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III
15610c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III    private void checkState() {
15620c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III        if (mNativePtr == 0) {
1563ed074fd70011cf804a14b5cf53ffd4b529c5f367Leon Scroggins III            throw new IllegalStateException("Cannot use closed ImageDecoder!");
15640c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III        }
15650c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III
15660c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III        checkSubset(mDesiredWidth, mDesiredHeight, mCropRect);
15670c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III
1568e5de9aa4a9bab9c4d8288212d6352a65e9808737Leon Scroggins III        if (mAllocator == ALLOCATOR_HARDWARE) {
15690c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III            if (mMutable) {
15700c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III                throw new IllegalStateException("Cannot make mutable HARDWARE Bitmap!");
15710c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III            }
1572746a9fee937969af9be7e060335e26e098971615Leon Scroggins III            if (mDecodeAsAlphaMask) {
15730c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III                throw new IllegalStateException("Cannot make HARDWARE Alpha mask Bitmap!");
15740c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III            }
15750c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III        }
15760c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III
1577d62f27250ab99d67242f1de293a31c12c397beb2Leon Scroggins III        if (mPostProcessor != null && mUnpremultipliedRequired) {
15780c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III            throw new IllegalStateException("Cannot draw to unpremultiplied pixels!");
15790c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III        }
15801a69f4598faef083d0123bb9b6bfcd6acfdec4e0Leon Scroggins III
15811a69f4598faef083d0123bb9b6bfcd6acfdec4e0Leon Scroggins III        if (mDesiredColorSpace != null) {
15821a69f4598faef083d0123bb9b6bfcd6acfdec4e0Leon Scroggins III            if (!(mDesiredColorSpace instanceof ColorSpace.Rgb)) {
15831a69f4598faef083d0123bb9b6bfcd6acfdec4e0Leon Scroggins III                throw new IllegalArgumentException("The target color space must use the "
15841a69f4598faef083d0123bb9b6bfcd6acfdec4e0Leon Scroggins III                            + "RGB color model - provided: " + mDesiredColorSpace);
15851a69f4598faef083d0123bb9b6bfcd6acfdec4e0Leon Scroggins III            }
15861a69f4598faef083d0123bb9b6bfcd6acfdec4e0Leon Scroggins III            if (((ColorSpace.Rgb) mDesiredColorSpace).getTransferParameters() == null) {
15871a69f4598faef083d0123bb9b6bfcd6acfdec4e0Leon Scroggins III                throw new IllegalArgumentException("The target color space must use an "
15881a69f4598faef083d0123bb9b6bfcd6acfdec4e0Leon Scroggins III                            + "ICC parametric transfer function - provided: " + mDesiredColorSpace);
15891a69f4598faef083d0123bb9b6bfcd6acfdec4e0Leon Scroggins III            }
15901a69f4598faef083d0123bb9b6bfcd6acfdec4e0Leon Scroggins III        }
15910c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III    }
15920c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III
15930c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III    private static void checkSubset(int width, int height, Rect r) {
15940c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III        if (r == null) {
15950c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III            return;
15960c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III        }
15970c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III        if (r.left < 0 || r.top < 0 || r.right > width || r.bottom > height) {
15980c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III            throw new IllegalStateException("Subset " + r + " not contained by "
15990c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III                    + "scaled image bounds: (" + width + " x " + height + ")");
16000c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III        }
16010c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III    }
16020c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III
16030a87cb3128a7fe8a999544ec1187159d82aa09ddLeon Scroggins III    @WorkerThread
1604e5de9aa4a9bab9c4d8288212d6352a65e9808737Leon Scroggins III    @NonNull
1605c9aa856559ca3b08c9409164b2f86c218c71505fLeon Scroggins III    private Bitmap decodeBitmapInternal() throws IOException {
16068c9d8f2aec65e449005a4a69c54f691ebd514e52Leon Scroggins III        checkState();
16071d2bf2b846f0a98f7403bbc791adb2969685d87aLeon Scroggins III        return nDecodeBitmap(mNativePtr, this, mPostProcessor != null,
16081d2bf2b846f0a98f7403bbc791adb2969685d87aLeon Scroggins III                mDesiredWidth, mDesiredHeight, mCropRect,
1609d62f27250ab99d67242f1de293a31c12c397beb2Leon Scroggins III                mMutable, mAllocator, mUnpremultipliedRequired,
16101a69f4598faef083d0123bb9b6bfcd6acfdec4e0Leon Scroggins III                mConserveMemory, mDecodeAsAlphaMask, mDesiredColorSpace);
16118c9d8f2aec65e449005a4a69c54f691ebd514e52Leon Scroggins III    }
16128c9d8f2aec65e449005a4a69c54f691ebd514e52Leon Scroggins III
1613e5de9aa4a9bab9c4d8288212d6352a65e9808737Leon Scroggins III    private void callHeaderDecoded(@Nullable OnHeaderDecodedListener listener,
1614e5de9aa4a9bab9c4d8288212d6352a65e9808737Leon Scroggins III            @NonNull Source src) {
1615e5de9aa4a9bab9c4d8288212d6352a65e9808737Leon Scroggins III        if (listener != null) {
1616e5de9aa4a9bab9c4d8288212d6352a65e9808737Leon Scroggins III            ImageInfo info = new ImageInfo(this);
1617e5de9aa4a9bab9c4d8288212d6352a65e9808737Leon Scroggins III            try {
1618e5de9aa4a9bab9c4d8288212d6352a65e9808737Leon Scroggins III                listener.onHeaderDecoded(this, info, src);
1619e5de9aa4a9bab9c4d8288212d6352a65e9808737Leon Scroggins III            } finally {
1620e5de9aa4a9bab9c4d8288212d6352a65e9808737Leon Scroggins III                info.mDecoder = null;
1621e5de9aa4a9bab9c4d8288212d6352a65e9808737Leon Scroggins III            }
1622e5de9aa4a9bab9c4d8288212d6352a65e9808737Leon Scroggins III        }
1623e5de9aa4a9bab9c4d8288212d6352a65e9808737Leon Scroggins III    }
1624e5de9aa4a9bab9c4d8288212d6352a65e9808737Leon Scroggins III
16250c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III    /**
1626b1cc8e64374832c8b296f609bebabff068ded460Leon Scroggins III     *  Create a {@link Drawable} from a {@code Source}.
1627b1cc8e64374832c8b296f609bebabff068ded460Leon Scroggins III     *
1628b1cc8e64374832c8b296f609bebabff068ded460Leon Scroggins III     *  @param src representing the encoded image.
1629d84c652a4ebbdd8a42d09e28e2d3d83962a0350dLeon Scroggins III     *  @param listener for learning the {@link ImageInfo ImageInfo} and changing any
1630c9aa856559ca3b08c9409164b2f86c218c71505fLeon Scroggins III     *      default settings on the {@code ImageDecoder}. This will be called on
1631c9aa856559ca3b08c9409164b2f86c218c71505fLeon Scroggins III     *      the same thread as {@code decodeDrawable} before that method returns.
16320a87cb3128a7fe8a999544ec1187159d82aa09ddLeon Scroggins III     *      This is required in order to change any of the default settings.
1633b1cc8e64374832c8b296f609bebabff068ded460Leon Scroggins III     *  @return Drawable for displaying the image.
1634ed074fd70011cf804a14b5cf53ffd4b529c5f367Leon Scroggins III     *  @throws IOException if {@code src} is not found, is an unsupported
1635ed074fd70011cf804a14b5cf53ffd4b529c5f367Leon Scroggins III     *      format, or cannot be decoded for any reason.
16360c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III     */
16370a87cb3128a7fe8a999544ec1187159d82aa09ddLeon Scroggins III    @WorkerThread
1638ed074fd70011cf804a14b5cf53ffd4b529c5f367Leon Scroggins III    @NonNull
1639b1cc8e64374832c8b296f609bebabff068ded460Leon Scroggins III    public static Drawable decodeDrawable(@NonNull Source src,
1640c9aa856559ca3b08c9409164b2f86c218c71505fLeon Scroggins III            @NonNull OnHeaderDecodedListener listener) throws IOException {
1641c9aa856559ca3b08c9409164b2f86c218c71505fLeon Scroggins III        if (listener == null) {
1642c9aa856559ca3b08c9409164b2f86c218c71505fLeon Scroggins III            throw new IllegalArgumentException("listener cannot be null! "
1643c9aa856559ca3b08c9409164b2f86c218c71505fLeon Scroggins III                    + "Use decodeDrawable(Source) to not have a listener");
1644c9aa856559ca3b08c9409164b2f86c218c71505fLeon Scroggins III        }
1645c9aa856559ca3b08c9409164b2f86c218c71505fLeon Scroggins III        return decodeDrawableImpl(src, listener);
1646c9aa856559ca3b08c9409164b2f86c218c71505fLeon Scroggins III    }
1647c9aa856559ca3b08c9409164b2f86c218c71505fLeon Scroggins III
16480a87cb3128a7fe8a999544ec1187159d82aa09ddLeon Scroggins III    @WorkerThread
1649c9aa856559ca3b08c9409164b2f86c218c71505fLeon Scroggins III    @NonNull
1650c9aa856559ca3b08c9409164b2f86c218c71505fLeon Scroggins III    private static Drawable decodeDrawableImpl(@NonNull Source src,
1651b1cc8e64374832c8b296f609bebabff068ded460Leon Scroggins III            @Nullable OnHeaderDecodedListener listener) throws IOException {
1652ed074fd70011cf804a14b5cf53ffd4b529c5f367Leon Scroggins III        try (ImageDecoder decoder = src.createImageDecoder()) {
1653e5de9aa4a9bab9c4d8288212d6352a65e9808737Leon Scroggins III            decoder.mSource = src;
1654e5de9aa4a9bab9c4d8288212d6352a65e9808737Leon Scroggins III            decoder.callHeaderDecoded(listener, src);
16550c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III
1656d62f27250ab99d67242f1de293a31c12c397beb2Leon Scroggins III            if (decoder.mUnpremultipliedRequired) {
1657ed074fd70011cf804a14b5cf53ffd4b529c5f367Leon Scroggins III                // Though this could be supported (ignored) for opaque images,
1658ed074fd70011cf804a14b5cf53ffd4b529c5f367Leon Scroggins III                // it seems better to always report this error.
1659ed074fd70011cf804a14b5cf53ffd4b529c5f367Leon Scroggins III                throw new IllegalStateException("Cannot decode a Drawable " +
1660ed074fd70011cf804a14b5cf53ffd4b529c5f367Leon Scroggins III                                                "with unpremultiplied pixels!");
1661ed074fd70011cf804a14b5cf53ffd4b529c5f367Leon Scroggins III            }
16620c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III
1663ed074fd70011cf804a14b5cf53ffd4b529c5f367Leon Scroggins III            if (decoder.mMutable) {
1664ed074fd70011cf804a14b5cf53ffd4b529c5f367Leon Scroggins III                throw new IllegalStateException("Cannot decode a mutable " +
1665ed074fd70011cf804a14b5cf53ffd4b529c5f367Leon Scroggins III                                                "Drawable!");
1666ed074fd70011cf804a14b5cf53ffd4b529c5f367Leon Scroggins III            }
16670c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III
166866c6d78908e0203a497c2e97398c824b2591ea19Derek Sollenberger            // this call potentially manipulates the decoder so it must be performed prior to
166966c6d78908e0203a497c2e97398c824b2591ea19Derek Sollenberger            // decoding the bitmap and after decode set the density on the resulting bitmap
16707d940ba43d15836ccf32f373c778eebffacf1f5aLeon Scroggins III            final int srcDensity = decoder.computeDensity(src);
1671671cce2605ed50c9aba73ab5bd530cb7741c53cdLeon Scroggins III            if (decoder.mAnimated) {
1672671cce2605ed50c9aba73ab5bd530cb7741c53cdLeon Scroggins III                // AnimatedImageDrawable calls postProcessAndRelease only if
1673e5de9aa4a9bab9c4d8288212d6352a65e9808737Leon Scroggins III                // mPostProcessor exists.
1674e5de9aa4a9bab9c4d8288212d6352a65e9808737Leon Scroggins III                ImageDecoder postProcessPtr = decoder.mPostProcessor == null ?
1675671cce2605ed50c9aba73ab5bd530cb7741c53cdLeon Scroggins III                        null : decoder;
1676671cce2605ed50c9aba73ab5bd530cb7741c53cdLeon Scroggins III                Drawable d = new AnimatedImageDrawable(decoder.mNativePtr,
1677671cce2605ed50c9aba73ab5bd530cb7741c53cdLeon Scroggins III                        postProcessPtr, decoder.mDesiredWidth,
167866c6d78908e0203a497c2e97398c824b2591ea19Derek Sollenberger                        decoder.mDesiredHeight, srcDensity,
167966c6d78908e0203a497c2e97398c824b2591ea19Derek Sollenberger                        src.computeDstDensity(), decoder.mCropRect,
1680671cce2605ed50c9aba73ab5bd530cb7741c53cdLeon Scroggins III                        decoder.mInputStream, decoder.mAssetFd);
1681671cce2605ed50c9aba73ab5bd530cb7741c53cdLeon Scroggins III                // d has taken ownership of these objects.
1682671cce2605ed50c9aba73ab5bd530cb7741c53cdLeon Scroggins III                decoder.mInputStream = null;
1683671cce2605ed50c9aba73ab5bd530cb7741c53cdLeon Scroggins III                decoder.mAssetFd = null;
1684671cce2605ed50c9aba73ab5bd530cb7741c53cdLeon Scroggins III                return d;
1685671cce2605ed50c9aba73ab5bd530cb7741c53cdLeon Scroggins III            }
1686671cce2605ed50c9aba73ab5bd530cb7741c53cdLeon Scroggins III
1687c9aa856559ca3b08c9409164b2f86c218c71505fLeon Scroggins III            Bitmap bm = decoder.decodeBitmapInternal();
168866c6d78908e0203a497c2e97398c824b2591ea19Derek Sollenberger            bm.setDensity(srcDensity);
16890c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III
169066c6d78908e0203a497c2e97398c824b2591ea19Derek Sollenberger            Resources res = src.getResources();
16910c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III            byte[] np = bm.getNinePatchChunk();
16920c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III            if (np != null && NinePatch.isNinePatchChunk(np)) {
16930c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III                Rect opticalInsets = new Rect();
16940c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III                bm.getOpticalInsets(opticalInsets);
16952f1b06b58fc3c496832afc9b6ceeb2a36ef4bfa6Leon Scroggins III                Rect padding = decoder.mOutPaddingRect;
16962f1b06b58fc3c496832afc9b6ceeb2a36ef4bfa6Leon Scroggins III                if (padding == null) {
16972f1b06b58fc3c496832afc9b6ceeb2a36ef4bfa6Leon Scroggins III                    padding = new Rect();
16982f1b06b58fc3c496832afc9b6ceeb2a36ef4bfa6Leon Scroggins III                }
16990c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III                nGetPadding(decoder.mNativePtr, padding);
17000c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III                return new NinePatchDrawable(res, bm, np, padding,
17010c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III                        opticalInsets, null);
17020c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III            }
17030c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III
17040c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III            return new BitmapDrawable(res, bm);
17050c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III        }
17060c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III    }
17070c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III
17080c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III    /**
17090a87cb3128a7fe8a999544ec1187159d82aa09ddLeon Scroggins III     *  Create a {@link Drawable} from a {@code Source}.
17100a87cb3128a7fe8a999544ec1187159d82aa09ddLeon Scroggins III     *
1711d84c652a4ebbdd8a42d09e28e2d3d83962a0350dLeon Scroggins III     *  <p>Since there is no {@link OnHeaderDecodedListener OnHeaderDecodedListener},
1712d84c652a4ebbdd8a42d09e28e2d3d83962a0350dLeon Scroggins III     *  the default settings will be used. In order to change any settings, call
17130a87cb3128a7fe8a999544ec1187159d82aa09ddLeon Scroggins III     *  {@link #decodeDrawable(Source, OnHeaderDecodedListener)} instead.</p>
17140a87cb3128a7fe8a999544ec1187159d82aa09ddLeon Scroggins III     *
17150a87cb3128a7fe8a999544ec1187159d82aa09ddLeon Scroggins III     *  @param src representing the encoded image.
17160a87cb3128a7fe8a999544ec1187159d82aa09ddLeon Scroggins III     *  @return Drawable for displaying the image.
17170a87cb3128a7fe8a999544ec1187159d82aa09ddLeon Scroggins III     *  @throws IOException if {@code src} is not found, is an unsupported
17180a87cb3128a7fe8a999544ec1187159d82aa09ddLeon Scroggins III     *      format, or cannot be decoded for any reason.
1719b1cc8e64374832c8b296f609bebabff068ded460Leon Scroggins III     */
17200a87cb3128a7fe8a999544ec1187159d82aa09ddLeon Scroggins III    @WorkerThread
1721b1cc8e64374832c8b296f609bebabff068ded460Leon Scroggins III    @NonNull
1722b1cc8e64374832c8b296f609bebabff068ded460Leon Scroggins III    public static Drawable decodeDrawable(@NonNull Source src)
1723b1cc8e64374832c8b296f609bebabff068ded460Leon Scroggins III            throws IOException {
1724c9aa856559ca3b08c9409164b2f86c218c71505fLeon Scroggins III        return decodeDrawableImpl(src, null);
1725b1cc8e64374832c8b296f609bebabff068ded460Leon Scroggins III    }
1726b1cc8e64374832c8b296f609bebabff068ded460Leon Scroggins III
1727b1cc8e64374832c8b296f609bebabff068ded460Leon Scroggins III    /**
1728b1cc8e64374832c8b296f609bebabff068ded460Leon Scroggins III     *  Create a {@link Bitmap} from a {@code Source}.
1729b1cc8e64374832c8b296f609bebabff068ded460Leon Scroggins III     *
1730b1cc8e64374832c8b296f609bebabff068ded460Leon Scroggins III     *  @param src representing the encoded image.
1731d84c652a4ebbdd8a42d09e28e2d3d83962a0350dLeon Scroggins III     *  @param listener for learning the {@link ImageInfo ImageInfo} and changing any
1732c9aa856559ca3b08c9409164b2f86c218c71505fLeon Scroggins III     *      default settings on the {@code ImageDecoder}. This will be called on
1733c9aa856559ca3b08c9409164b2f86c218c71505fLeon Scroggins III     *      the same thread as {@code decodeBitmap} before that method returns.
17340a87cb3128a7fe8a999544ec1187159d82aa09ddLeon Scroggins III     *      This is required in order to change any of the default settings.
1735b1cc8e64374832c8b296f609bebabff068ded460Leon Scroggins III     *  @return Bitmap containing the image.
1736ed074fd70011cf804a14b5cf53ffd4b529c5f367Leon Scroggins III     *  @throws IOException if {@code src} is not found, is an unsupported
1737ed074fd70011cf804a14b5cf53ffd4b529c5f367Leon Scroggins III     *      format, or cannot be decoded for any reason.
17380c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III     */
17390a87cb3128a7fe8a999544ec1187159d82aa09ddLeon Scroggins III    @WorkerThread
1740ed074fd70011cf804a14b5cf53ffd4b529c5f367Leon Scroggins III    @NonNull
1741b1cc8e64374832c8b296f609bebabff068ded460Leon Scroggins III    public static Bitmap decodeBitmap(@NonNull Source src,
1742c9aa856559ca3b08c9409164b2f86c218c71505fLeon Scroggins III            @NonNull OnHeaderDecodedListener listener) throws IOException {
1743c9aa856559ca3b08c9409164b2f86c218c71505fLeon Scroggins III        if (listener == null) {
1744c9aa856559ca3b08c9409164b2f86c218c71505fLeon Scroggins III            throw new IllegalArgumentException("listener cannot be null! "
1745c9aa856559ca3b08c9409164b2f86c218c71505fLeon Scroggins III                    + "Use decodeBitmap(Source) to not have a listener");
1746c9aa856559ca3b08c9409164b2f86c218c71505fLeon Scroggins III        }
1747c9aa856559ca3b08c9409164b2f86c218c71505fLeon Scroggins III        return decodeBitmapImpl(src, listener);
1748c9aa856559ca3b08c9409164b2f86c218c71505fLeon Scroggins III    }
1749c9aa856559ca3b08c9409164b2f86c218c71505fLeon Scroggins III
17500a87cb3128a7fe8a999544ec1187159d82aa09ddLeon Scroggins III    @WorkerThread
1751c9aa856559ca3b08c9409164b2f86c218c71505fLeon Scroggins III    @NonNull
1752c9aa856559ca3b08c9409164b2f86c218c71505fLeon Scroggins III    private static Bitmap decodeBitmapImpl(@NonNull Source src,
1753b1cc8e64374832c8b296f609bebabff068ded460Leon Scroggins III            @Nullable OnHeaderDecodedListener listener) throws IOException {
1754ed074fd70011cf804a14b5cf53ffd4b529c5f367Leon Scroggins III        try (ImageDecoder decoder = src.createImageDecoder()) {
1755e5de9aa4a9bab9c4d8288212d6352a65e9808737Leon Scroggins III            decoder.mSource = src;
1756e5de9aa4a9bab9c4d8288212d6352a65e9808737Leon Scroggins III            decoder.callHeaderDecoded(listener, src);
17570c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III
175866c6d78908e0203a497c2e97398c824b2591ea19Derek Sollenberger            // this call potentially manipulates the decoder so it must be performed prior to
175966c6d78908e0203a497c2e97398c824b2591ea19Derek Sollenberger            // decoding the bitmap
17607d940ba43d15836ccf32f373c778eebffacf1f5aLeon Scroggins III            final int srcDensity = decoder.computeDensity(src);
1761c9aa856559ca3b08c9409164b2f86c218c71505fLeon Scroggins III            Bitmap bm = decoder.decodeBitmapInternal();
176266c6d78908e0203a497c2e97398c824b2591ea19Derek Sollenberger            bm.setDensity(srcDensity);
17632f1b06b58fc3c496832afc9b6ceeb2a36ef4bfa6Leon Scroggins III
17642f1b06b58fc3c496832afc9b6ceeb2a36ef4bfa6Leon Scroggins III            Rect padding = decoder.mOutPaddingRect;
17652f1b06b58fc3c496832afc9b6ceeb2a36ef4bfa6Leon Scroggins III            if (padding != null) {
17662f1b06b58fc3c496832afc9b6ceeb2a36ef4bfa6Leon Scroggins III                byte[] np = bm.getNinePatchChunk();
17672f1b06b58fc3c496832afc9b6ceeb2a36ef4bfa6Leon Scroggins III                if (np != null && NinePatch.isNinePatchChunk(np)) {
17682f1b06b58fc3c496832afc9b6ceeb2a36ef4bfa6Leon Scroggins III                    nGetPadding(decoder.mNativePtr, padding);
17692f1b06b58fc3c496832afc9b6ceeb2a36ef4bfa6Leon Scroggins III                }
17702f1b06b58fc3c496832afc9b6ceeb2a36ef4bfa6Leon Scroggins III            }
17712f1b06b58fc3c496832afc9b6ceeb2a36ef4bfa6Leon Scroggins III
177266c6d78908e0203a497c2e97398c824b2591ea19Derek Sollenberger            return bm;
177366c6d78908e0203a497c2e97398c824b2591ea19Derek Sollenberger        }
177466c6d78908e0203a497c2e97398c824b2591ea19Derek Sollenberger    }
177566c6d78908e0203a497c2e97398c824b2591ea19Derek Sollenberger
177666c6d78908e0203a497c2e97398c824b2591ea19Derek Sollenberger    // This method may modify the decoder so it must be called prior to performing the decode
17777d940ba43d15836ccf32f373c778eebffacf1f5aLeon Scroggins III    private int computeDensity(@NonNull Source src) {
177866c6d78908e0203a497c2e97398c824b2591ea19Derek Sollenberger        // if the caller changed the size then we treat the density as unknown
17797d940ba43d15836ccf32f373c778eebffacf1f5aLeon Scroggins III        if (this.requestedResize()) {
178066c6d78908e0203a497c2e97398c824b2591ea19Derek Sollenberger            return Bitmap.DENSITY_NONE;
178166c6d78908e0203a497c2e97398c824b2591ea19Derek Sollenberger        }
178266c6d78908e0203a497c2e97398c824b2591ea19Derek Sollenberger
17837d940ba43d15836ccf32f373c778eebffacf1f5aLeon Scroggins III        final int srcDensity = src.getDensity();
17847d940ba43d15836ccf32f373c778eebffacf1f5aLeon Scroggins III        if (srcDensity == Bitmap.DENSITY_NONE) {
17857d940ba43d15836ccf32f373c778eebffacf1f5aLeon Scroggins III            return srcDensity;
17867d940ba43d15836ccf32f373c778eebffacf1f5aLeon Scroggins III        }
17877d940ba43d15836ccf32f373c778eebffacf1f5aLeon Scroggins III
17887d940ba43d15836ccf32f373c778eebffacf1f5aLeon Scroggins III        // Scaling up nine-patch divs is imprecise and is better handled
17897d940ba43d15836ccf32f373c778eebffacf1f5aLeon Scroggins III        // at draw time. An app won't be relying on the internal Bitmap's
17907d940ba43d15836ccf32f373c778eebffacf1f5aLeon Scroggins III        // size, so it is safe to let NinePatchDrawable handle scaling.
17917d940ba43d15836ccf32f373c778eebffacf1f5aLeon Scroggins III        // mPostProcessor disables nine-patching, so behave normally if
17927d940ba43d15836ccf32f373c778eebffacf1f5aLeon Scroggins III        // it is present.
17937d940ba43d15836ccf32f373c778eebffacf1f5aLeon Scroggins III        if (mIsNinePatch && mPostProcessor == null) {
17947d940ba43d15836ccf32f373c778eebffacf1f5aLeon Scroggins III            return srcDensity;
17957d940ba43d15836ccf32f373c778eebffacf1f5aLeon Scroggins III        }
17967d940ba43d15836ccf32f373c778eebffacf1f5aLeon Scroggins III
179766c6d78908e0203a497c2e97398c824b2591ea19Derek Sollenberger        // Special stuff for compatibility mode: if the target density is not
179866c6d78908e0203a497c2e97398c824b2591ea19Derek Sollenberger        // the same as the display density, but the resource -is- the same as
179966c6d78908e0203a497c2e97398c824b2591ea19Derek Sollenberger        // the display density, then don't scale it down to the target density.
180066c6d78908e0203a497c2e97398c824b2591ea19Derek Sollenberger        // This allows us to load the system's density-correct resources into
180166c6d78908e0203a497c2e97398c824b2591ea19Derek Sollenberger        // an application in compatibility mode, without scaling those down
180266c6d78908e0203a497c2e97398c824b2591ea19Derek Sollenberger        // to the compatibility density only to have them scaled back up when
180366c6d78908e0203a497c2e97398c824b2591ea19Derek Sollenberger        // drawn to the screen.
180466c6d78908e0203a497c2e97398c824b2591ea19Derek Sollenberger        Resources res = src.getResources();
180566c6d78908e0203a497c2e97398c824b2591ea19Derek Sollenberger        if (res != null && res.getDisplayMetrics().noncompatDensityDpi == srcDensity) {
180666c6d78908e0203a497c2e97398c824b2591ea19Derek Sollenberger            return srcDensity;
18070c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III        }
180866c6d78908e0203a497c2e97398c824b2591ea19Derek Sollenberger
18097d940ba43d15836ccf32f373c778eebffacf1f5aLeon Scroggins III        final int dstDensity = src.computeDstDensity();
18107d940ba43d15836ccf32f373c778eebffacf1f5aLeon Scroggins III        if (srcDensity == dstDensity) {
18117d940ba43d15836ccf32f373c778eebffacf1f5aLeon Scroggins III            return srcDensity;
18127d940ba43d15836ccf32f373c778eebffacf1f5aLeon Scroggins III        }
18137d940ba43d15836ccf32f373c778eebffacf1f5aLeon Scroggins III
18148290eaba47b99398fbe0bd59138f902bde558ecbLeon Scroggins III        // For P and above, only resize if it would be a downscale. Scale up prior
18158290eaba47b99398fbe0bd59138f902bde558ecbLeon Scroggins III        // to P in case the app relies on the Bitmap's size without considering density.
18167d940ba43d15836ccf32f373c778eebffacf1f5aLeon Scroggins III        if (srcDensity < dstDensity && sApiLevel >= Build.VERSION_CODES.P) {
18178290eaba47b99398fbe0bd59138f902bde558ecbLeon Scroggins III            return srcDensity;
181866c6d78908e0203a497c2e97398c824b2591ea19Derek Sollenberger        }
181966c6d78908e0203a497c2e97398c824b2591ea19Derek Sollenberger
18208290eaba47b99398fbe0bd59138f902bde558ecbLeon Scroggins III        float scale = (float) dstDensity / srcDensity;
18217d940ba43d15836ccf32f373c778eebffacf1f5aLeon Scroggins III        int scaledWidth = (int) (mWidth * scale + 0.5f);
18227d940ba43d15836ccf32f373c778eebffacf1f5aLeon Scroggins III        int scaledHeight = (int) (mHeight * scale + 0.5f);
18237d940ba43d15836ccf32f373c778eebffacf1f5aLeon Scroggins III        this.setTargetSize(scaledWidth, scaledHeight);
18248290eaba47b99398fbe0bd59138f902bde558ecbLeon Scroggins III        return dstDensity;
18250c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III    }
18260c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III
1827e5de9aa4a9bab9c4d8288212d6352a65e9808737Leon Scroggins III    @NonNull
18281fad09d4d3f43112abd842da4c94cf00fb1cb46dLeon Scroggins III    private String getMimeType() {
18291fad09d4d3f43112abd842da4c94cf00fb1cb46dLeon Scroggins III        return nGetMimeType(mNativePtr);
18301fad09d4d3f43112abd842da4c94cf00fb1cb46dLeon Scroggins III    }
18311fad09d4d3f43112abd842da4c94cf00fb1cb46dLeon Scroggins III
18321a69f4598faef083d0123bb9b6bfcd6acfdec4e0Leon Scroggins III    @Nullable
18331a69f4598faef083d0123bb9b6bfcd6acfdec4e0Leon Scroggins III    private ColorSpace getColorSpace() {
18341a69f4598faef083d0123bb9b6bfcd6acfdec4e0Leon Scroggins III        return nGetColorSpace(mNativePtr);
18351a69f4598faef083d0123bb9b6bfcd6acfdec4e0Leon Scroggins III    }
18361a69f4598faef083d0123bb9b6bfcd6acfdec4e0Leon Scroggins III
1837b1cc8e64374832c8b296f609bebabff068ded460Leon Scroggins III    /**
18380a87cb3128a7fe8a999544ec1187159d82aa09ddLeon Scroggins III     *  Create a {@link Bitmap} from a {@code Source}.
18390a87cb3128a7fe8a999544ec1187159d82aa09ddLeon Scroggins III     *
1840d84c652a4ebbdd8a42d09e28e2d3d83962a0350dLeon Scroggins III     *  <p>Since there is no {@link OnHeaderDecodedListener OnHeaderDecodedListener},
1841d84c652a4ebbdd8a42d09e28e2d3d83962a0350dLeon Scroggins III     *  the default settings will be used. In order to change any settings, call
18420a87cb3128a7fe8a999544ec1187159d82aa09ddLeon Scroggins III     *  {@link #decodeBitmap(Source, OnHeaderDecodedListener)} instead.</p>
18430a87cb3128a7fe8a999544ec1187159d82aa09ddLeon Scroggins III     *
18440a87cb3128a7fe8a999544ec1187159d82aa09ddLeon Scroggins III     *  @param src representing the encoded image.
18450a87cb3128a7fe8a999544ec1187159d82aa09ddLeon Scroggins III     *  @return Bitmap containing the image.
18460a87cb3128a7fe8a999544ec1187159d82aa09ddLeon Scroggins III     *  @throws IOException if {@code src} is not found, is an unsupported
18470a87cb3128a7fe8a999544ec1187159d82aa09ddLeon Scroggins III     *      format, or cannot be decoded for any reason.
1848b1cc8e64374832c8b296f609bebabff068ded460Leon Scroggins III     */
18490a87cb3128a7fe8a999544ec1187159d82aa09ddLeon Scroggins III    @WorkerThread
1850b1cc8e64374832c8b296f609bebabff068ded460Leon Scroggins III    @NonNull
1851b1cc8e64374832c8b296f609bebabff068ded460Leon Scroggins III    public static Bitmap decodeBitmap(@NonNull Source src) throws IOException {
1852c9aa856559ca3b08c9409164b2f86c218c71505fLeon Scroggins III        return decodeBitmapImpl(src, null);
1853b1cc8e64374832c8b296f609bebabff068ded460Leon Scroggins III    }
1854b1cc8e64374832c8b296f609bebabff068ded460Leon Scroggins III
18558c9d8f2aec65e449005a4a69c54f691ebd514e52Leon Scroggins III    /**
18568c9d8f2aec65e449005a4a69c54f691ebd514e52Leon Scroggins III     * Private method called by JNI.
18578c9d8f2aec65e449005a4a69c54f691ebd514e52Leon Scroggins III     */
18588c9d8f2aec65e449005a4a69c54f691ebd514e52Leon Scroggins III    @SuppressWarnings("unused")
1859e5de9aa4a9bab9c4d8288212d6352a65e9808737Leon Scroggins III    private int postProcessAndRelease(@NonNull Canvas canvas) {
18608c9d8f2aec65e449005a4a69c54f691ebd514e52Leon Scroggins III        try {
1861e5de9aa4a9bab9c4d8288212d6352a65e9808737Leon Scroggins III            return mPostProcessor.onPostProcess(canvas);
18628c9d8f2aec65e449005a4a69c54f691ebd514e52Leon Scroggins III        } finally {
18638c9d8f2aec65e449005a4a69c54f691ebd514e52Leon Scroggins III            canvas.release();
18648c9d8f2aec65e449005a4a69c54f691ebd514e52Leon Scroggins III        }
18658c9d8f2aec65e449005a4a69c54f691ebd514e52Leon Scroggins III    }
18668c9d8f2aec65e449005a4a69c54f691ebd514e52Leon Scroggins III
1867e5de9aa4a9bab9c4d8288212d6352a65e9808737Leon Scroggins III    /**
1868e5de9aa4a9bab9c4d8288212d6352a65e9808737Leon Scroggins III     * Private method called by JNI.
1869e5de9aa4a9bab9c4d8288212d6352a65e9808737Leon Scroggins III     */
1870e5de9aa4a9bab9c4d8288212d6352a65e9808737Leon Scroggins III    @SuppressWarnings("unused")
1871cf7294fda671a39e6aa21da30be0dac261d71638Leon Scroggins III    private void onPartialImage(@DecodeException.Error int error, @Nullable Throwable cause)
18721d2bf2b846f0a98f7403bbc791adb2969685d87aLeon Scroggins III            throws DecodeException {
18731d2bf2b846f0a98f7403bbc791adb2969685d87aLeon Scroggins III        DecodeException exception = new DecodeException(error, cause, mSource);
18741d2bf2b846f0a98f7403bbc791adb2969685d87aLeon Scroggins III        if (mOnPartialImageListener == null
18751d2bf2b846f0a98f7403bbc791adb2969685d87aLeon Scroggins III                || !mOnPartialImageListener.onPartialImage(exception)) {
18761d2bf2b846f0a98f7403bbc791adb2969685d87aLeon Scroggins III            throw exception;
18771d2bf2b846f0a98f7403bbc791adb2969685d87aLeon Scroggins III        }
1878e5de9aa4a9bab9c4d8288212d6352a65e9808737Leon Scroggins III    }
1879e5de9aa4a9bab9c4d8288212d6352a65e9808737Leon Scroggins III
18801d2bf2b846f0a98f7403bbc791adb2969685d87aLeon Scroggins III    private static native ImageDecoder nCreate(long asset, Source src) throws IOException;
18811d2bf2b846f0a98f7403bbc791adb2969685d87aLeon Scroggins III    private static native ImageDecoder nCreate(ByteBuffer buffer, int position,
18821d2bf2b846f0a98f7403bbc791adb2969685d87aLeon Scroggins III                                               int limit, Source src) throws IOException;
18831d2bf2b846f0a98f7403bbc791adb2969685d87aLeon Scroggins III    private static native ImageDecoder nCreate(byte[] data, int offset, int length,
18841d2bf2b846f0a98f7403bbc791adb2969685d87aLeon Scroggins III                                               Source src) throws IOException;
18851d2bf2b846f0a98f7403bbc791adb2969685d87aLeon Scroggins III    private static native ImageDecoder nCreate(InputStream is, byte[] storage,
18861d2bf2b846f0a98f7403bbc791adb2969685d87aLeon Scroggins III                                               Source src) throws IOException;
1887e5de9aa4a9bab9c4d8288212d6352a65e9808737Leon Scroggins III    // The fd must be seekable.
18881d2bf2b846f0a98f7403bbc791adb2969685d87aLeon Scroggins III    private static native ImageDecoder nCreate(FileDescriptor fd, Source src) throws IOException;
1889ed074fd70011cf804a14b5cf53ffd4b529c5f367Leon Scroggins III    @NonNull
18900c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III    private static native Bitmap nDecodeBitmap(long nativePtr,
18911d2bf2b846f0a98f7403bbc791adb2969685d87aLeon Scroggins III            @NonNull ImageDecoder decoder,
18921d2bf2b846f0a98f7403bbc791adb2969685d87aLeon Scroggins III            boolean doPostProcess,
18930c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III            int width, int height,
1894e5de9aa4a9bab9c4d8288212d6352a65e9808737Leon Scroggins III            @Nullable Rect cropRect, boolean mutable,
1895d62f27250ab99d67242f1de293a31c12c397beb2Leon Scroggins III            int allocator, boolean unpremulRequired,
18961a69f4598faef083d0123bb9b6bfcd6acfdec4e0Leon Scroggins III            boolean conserveMemory, boolean decodeAsAlphaMask,
18971a69f4598faef083d0123bb9b6bfcd6acfdec4e0Leon Scroggins III            @Nullable ColorSpace desiredColorSpace)
1898ed074fd70011cf804a14b5cf53ffd4b529c5f367Leon Scroggins III        throws IOException;
1899e5de9aa4a9bab9c4d8288212d6352a65e9808737Leon Scroggins III    private static native Size nGetSampledSize(long nativePtr,
1900e5de9aa4a9bab9c4d8288212d6352a65e9808737Leon Scroggins III                                               int sampleSize);
1901e5de9aa4a9bab9c4d8288212d6352a65e9808737Leon Scroggins III    private static native void nGetPadding(long nativePtr, @NonNull Rect outRect);
1902ed074fd70011cf804a14b5cf53ffd4b529c5f367Leon Scroggins III    private static native void nClose(long nativePtr);
19031fad09d4d3f43112abd842da4c94cf00fb1cb46dLeon Scroggins III    private static native String nGetMimeType(long nativePtr);
19041a69f4598faef083d0123bb9b6bfcd6acfdec4e0Leon Scroggins III    private static native ColorSpace nGetColorSpace(long nativePtr);
19050c01dbf8f283b7bcaf6babf540a501735c73b4f5Leon Scroggins III}
1906