From d62f27250ab99d67242f1de293a31c12c397beb2 Mon Sep 17 00:00:00 2001 From: Leon Scroggins III Date: Thu, 29 Mar 2018 14:52:29 -0400 Subject: [PATCH 1/2] Rename getters and setters on ImageDecoder Bug: 76448408 Test: Ib8782ff10072c81a5ed2a1031a70475fffee7ccf - Use "is" prefix for booleans instead of "get" - Reverse "require" and "unpremultiplied" for a more natural sound - Add "Required" to "Mutable" methods - Add "Enabled" to "DecodeAsAlphaMask" methods Change-Id: I644ddccd37898d89609e4534ece4ea70f74587c4 --- api/current.txt | 12 +-- api/removed.txt | 6 ++ .../java/android/graphics/ImageDecoder.java | 93 ++++++++++++++----- 3 files changed, 83 insertions(+), 28 deletions(-) diff --git a/api/current.txt b/api/current.txt index 2837091a400b7..cc6ef71818c9a 100644 --- a/api/current.txt +++ b/api/current.txt @@ -13630,22 +13630,22 @@ package android.graphics { method public int getAllocator(); method public boolean getConserveMemory(); method public android.graphics.Rect getCrop(); - method public boolean getDecodeAsAlphaMask(); - method public boolean getMutable(); method public android.graphics.ImageDecoder.OnPartialImageListener getOnPartialImageListener(); method public android.graphics.PostProcessor getPostProcessor(); - method public boolean getRequireUnpremultiplied(); + method public boolean isDecodeAsAlphaMaskEnabled(); + method public boolean isMutableRequired(); + method public boolean isUnpremultipliedRequired(); method public android.graphics.ImageDecoder setAllocator(int); method public android.graphics.ImageDecoder setConserveMemory(boolean); method public android.graphics.ImageDecoder setCrop(android.graphics.Rect); - method public android.graphics.ImageDecoder setDecodeAsAlphaMask(boolean); - method public android.graphics.ImageDecoder setMutable(boolean); + method public android.graphics.ImageDecoder setDecodeAsAlphaMaskEnabled(boolean); + method public android.graphics.ImageDecoder setMutableRequired(boolean); method public android.graphics.ImageDecoder setOnPartialImageListener(android.graphics.ImageDecoder.OnPartialImageListener); method public android.graphics.ImageDecoder setPostProcessor(android.graphics.PostProcessor); - method public android.graphics.ImageDecoder setRequireUnpremultiplied(boolean); method public android.graphics.ImageDecoder setTargetColorSpace(android.graphics.ColorSpace); method public android.graphics.ImageDecoder setTargetSampleSize(int); method public android.graphics.ImageDecoder setTargetSize(int, int); + method public android.graphics.ImageDecoder setUnpremultipliedRequired(boolean); field public static final int ALLOCATOR_DEFAULT = 0; // 0x0 field public static final int ALLOCATOR_HARDWARE = 3; // 0x3 field public static final int ALLOCATOR_SHARED_MEMORY = 2; // 0x2 diff --git a/api/removed.txt b/api/removed.txt index 5863e777bb149..2d76c5a575a0e 100644 --- a/api/removed.txt +++ b/api/removed.txt @@ -183,7 +183,13 @@ package android.graphics { public final class ImageDecoder implements java.lang.AutoCloseable { method public deprecated boolean getAsAlphaMask(); + method public deprecated boolean getDecodeAsAlphaMask(); + method public deprecated boolean getMutable(); + method public deprecated boolean getRequireUnpremultiplied(); method public deprecated android.graphics.ImageDecoder setAsAlphaMask(boolean); + method public deprecated android.graphics.ImageDecoder setDecodeAsAlphaMask(boolean); + method public deprecated android.graphics.ImageDecoder setMutable(boolean); + method public deprecated android.graphics.ImageDecoder setRequireUnpremultiplied(boolean); method public deprecated android.graphics.ImageDecoder setResize(int, int); method public deprecated android.graphics.ImageDecoder setResize(int); field public static final deprecated int ERROR_SOURCE_ERROR = 3; // 0x3 diff --git a/graphics/java/android/graphics/ImageDecoder.java b/graphics/java/android/graphics/ImageDecoder.java index 6051f88733bfb..1ed6bfbebf38f 100644 --- a/graphics/java/android/graphics/ImageDecoder.java +++ b/graphics/java/android/graphics/ImageDecoder.java @@ -597,7 +597,7 @@ public final class ImageDecoder implements AutoCloseable { private int mDesiredWidth; private int mDesiredHeight; private int mAllocator = ALLOCATOR_DEFAULT; - private boolean mRequireUnpremultiplied = false; + private boolean mUnpremultipliedRequired = false; private boolean mMutable = false; private boolean mConserveMemory = false; private boolean mDecodeAsAlphaMask = false; @@ -782,7 +782,7 @@ public final class ImageDecoder implements AutoCloseable { * height that can be achieved by sampling the encoded image. Other widths * and heights may be supported, but will require an additional (internal) * scaling step. Such internal scaling is *not* supported with - * {@link #setRequireUnpremultiplied} set to {@code true}.

+ * {@link #setUnpremultipliedRequired} set to {@code true}.

* * @param sampleSize Sampling rate of the encoded image. * @return {@link android.util.Size} of the width and height after @@ -909,7 +909,7 @@ public final class ImageDecoder implements AutoCloseable { * Will typically result in a {@link Bitmap.Config#HARDWARE} * allocation, but may be software for small images. In addition, this will * switch to software when HARDWARE is incompatible, e.g. - * {@link #setMutable}, {@link #setDecodeAsAlphaMask}. + * {@link #setMutableRequired}, {@link #setDecodeAsAlphaMaskEnabled}. */ public static final int ALLOCATOR_DEFAULT = 0; @@ -932,8 +932,8 @@ public final class ImageDecoder implements AutoCloseable { * Require a {@link Bitmap.Config#HARDWARE} {@link Bitmap}. * * When this is combined with incompatible options, like - * {@link #setMutable} or {@link #setDecodeAsAlphaMask}, {@link #decodeDrawable} - * / {@link #decodeBitmap} will throw an + * {@link #setMutableRequired} or {@link #setDecodeAsAlphaMaskEnabled}, + * {@link #decodeDrawable} / {@link #decodeBitmap} will throw an * {@link java.lang.IllegalStateException}. */ public static final int ALLOCATOR_HARDWARE = 3; @@ -984,16 +984,32 @@ public final class ImageDecoder implements AutoCloseable { * * @return this object for chaining. */ - public ImageDecoder setRequireUnpremultiplied(boolean requireUnpremultiplied) { - mRequireUnpremultiplied = requireUnpremultiplied; + public ImageDecoder setUnpremultipliedRequired(boolean unpremultipliedRequired) { + mUnpremultipliedRequired = unpremultipliedRequired; return this; } + /** @removed + * @deprecated Renamed to {@link #setUnpremultipliedRequired}. + */ + @java.lang.Deprecated + public ImageDecoder setRequireUnpremultiplied(boolean unpremultipliedRequired) { + return this.setUnpremultipliedRequired(unpremultipliedRequired); + } + /** * Return whether the {@link Bitmap} will have unpremultiplied pixels. */ + public boolean isUnpremultipliedRequired() { + return mUnpremultipliedRequired; + } + + /** @removed + * @deprecated Renamed to {@link #isUnpremultipliedRequired}. + */ + @java.lang.Deprecated public boolean getRequireUnpremultiplied() { - return mRequireUnpremultiplied; + return this.isUnpremultipliedRequired(); } /** @@ -1105,18 +1121,34 @@ public final class ImageDecoder implements AutoCloseable { * * @return this object for chaining. */ - public ImageDecoder setMutable(boolean mutable) { + public ImageDecoder setMutableRequired(boolean mutable) { mMutable = mutable; return this; } + /** @removed + * @deprecated Renamed to {@link #setMutableRequired}. + */ + @java.lang.Deprecated + public ImageDecoder setMutable(boolean mutable) { + return this.setMutableRequired(mutable); + } + /** * Return whether the {@link Bitmap} will be mutable. */ - public boolean getMutable() { + public boolean isMutableRequired() { return mMutable; } + /** @removed + * @deprecated Renamed to {@link #isMutableRequired}. + */ + @java.lang.Deprecated + public boolean getMutable() { + return this.isMutableRequired(); + } + /** * Specify whether to potentially save RAM at the expense of quality. * @@ -1154,20 +1186,28 @@ public final class ImageDecoder implements AutoCloseable { * with only one channel, treat that channel as alpha. Otherwise this call has * no effect.

* - *

setDecodeAsAlphaMask is incompatible with {@link #ALLOCATOR_HARDWARE}. Trying to + *

This is incompatible with {@link #ALLOCATOR_HARDWARE}. Trying to * combine them will result in {@link #decodeDrawable}/ * {@link #decodeBitmap} throwing an * {@link java.lang.IllegalStateException}.

* * @return this object for chaining. */ - public ImageDecoder setDecodeAsAlphaMask(boolean decodeAsAlphaMask) { - mDecodeAsAlphaMask = decodeAsAlphaMask; + public ImageDecoder setDecodeAsAlphaMaskEnabled(boolean enabled) { + mDecodeAsAlphaMask = enabled; return this; } /** @removed - * @deprecated Call {@link #setDecodeAsAlphaMask} instead. + * @deprecated Renamed to {@link #setDecodeAsAlphaMaskEnabled}. + */ + @java.lang.Deprecated + public ImageDecoder setDecodeAsAlphaMask(boolean enabled) { + return this.setDecodeAsAlphaMaskEnabled(enabled); + } + + /** @removed + * @deprecated Renamed to {@link #setDecodeAsAlphaMaskEnabled}. */ @java.lang.Deprecated public ImageDecoder setAsAlphaMask(boolean asAlphaMask) { @@ -1177,16 +1217,25 @@ public final class ImageDecoder implements AutoCloseable { /** * Return whether to treat single channel input as alpha. * - *

This returns whether {@link #setDecodeAsAlphaMask} was set to {@code true}. - * It may still return {@code true} even if the image has more than one - * channel and therefore will not be treated as an alpha mask.

+ *

This returns whether {@link #setDecodeAsAlphaMaskEnabled} was set to + * {@code true}. It may still return {@code true} even if the image has + * more than one channel and therefore will not be treated as an alpha + * mask.

*/ + public boolean isDecodeAsAlphaMaskEnabled() { + return mDecodeAsAlphaMask; + } + + /** @removed + * @deprecated Renamed to {@link #isDecodeAsAlphaMaskEnabled}. + */ + @java.lang.Deprecated public boolean getDecodeAsAlphaMask() { return mDecodeAsAlphaMask; } /** @removed - * @deprecated Call {@link #getDecodeAsAlphaMask} instead. + * @deprecated Renamed to {@link #isDecodeAsAlphaMaskEnabled}. */ @java.lang.Deprecated public boolean getAsAlphaMask() { @@ -1259,7 +1308,7 @@ public final class ImageDecoder implements AutoCloseable { } } - if (mPostProcessor != null && mRequireUnpremultiplied) { + if (mPostProcessor != null && mUnpremultipliedRequired) { throw new IllegalStateException("Cannot draw to unpremultiplied pixels!"); } @@ -1290,7 +1339,7 @@ public final class ImageDecoder implements AutoCloseable { checkState(); return nDecodeBitmap(mNativePtr, this, mPostProcessor != null, mDesiredWidth, mDesiredHeight, mCropRect, - mMutable, mAllocator, mRequireUnpremultiplied, + mMutable, mAllocator, mUnpremultipliedRequired, mConserveMemory, mDecodeAsAlphaMask, mDesiredColorSpace); } @@ -1334,7 +1383,7 @@ public final class ImageDecoder implements AutoCloseable { decoder.mSource = src; decoder.callHeaderDecoded(listener, src); - if (decoder.mRequireUnpremultiplied) { + if (decoder.mUnpremultipliedRequired) { // Though this could be supported (ignored) for opaque images, // it seems better to always report this error. throw new IllegalStateException("Cannot decode a Drawable " + @@ -1534,7 +1583,7 @@ public final class ImageDecoder implements AutoCloseable { boolean doPostProcess, int width, int height, @Nullable Rect cropRect, boolean mutable, - int allocator, boolean requireUnpremul, + int allocator, boolean unpremulRequired, boolean conserveMemory, boolean decodeAsAlphaMask, @Nullable ColorSpace desiredColorSpace) throws IOException; From 0a87cb3128a7fe8a999544ec1187159d82aa09dd Mon Sep 17 00:00:00 2001 From: Leon Scroggins III Date: Thu, 29 Mar 2018 15:54:59 -0400 Subject: [PATCH 2/2] Add documentation for ImageDecoder and its Source Bug: 76448408 Bug: 76462125 Test: Iec21bad971dc9cffc807a412bb6329757c499baa - Document DecodeException.getSource - Add thread annotations - slice() ByteBuffer inside createImageDecoder, so it can be reused - Make ResourceSource thread safe by locking around mResDensity - Specify that OnHeaderDecodedListener is necessary for changing default settings Change-Id: I3b55d3ba1b0a2276938cb521449bceb7aa9f96e2 --- .../java/android/graphics/ImageDecoder.java | 129 ++++++++++++++++-- 1 file changed, 119 insertions(+), 10 deletions(-) diff --git a/graphics/java/android/graphics/ImageDecoder.java b/graphics/java/android/graphics/ImageDecoder.java index 1ed6bfbebf38f..5261c0486acf7 100644 --- a/graphics/java/android/graphics/ImageDecoder.java +++ b/graphics/java/android/graphics/ImageDecoder.java @@ -21,10 +21,12 @@ import static android.system.OsConstants.SEEK_SET; import static java.lang.annotation.RetentionPolicy.SOURCE; +import android.annotation.AnyThread; import android.annotation.IntDef; import android.annotation.NonNull; import android.annotation.Nullable; import android.annotation.TestApi; +import android.annotation.WorkerThread; import android.content.ContentResolver; import android.content.res.AssetFileDescriptor; import android.content.res.AssetManager; @@ -65,6 +67,16 @@ public final class ImageDecoder implements AutoCloseable { /** * Source of the encoded image data. + * + *

This object references the data that will be used to decode a + * Drawable or Bitmap in {@link #decodeDrawable} or {@link #decodeBitmap}. + * Constructing a {@code Source} (with one of the overloads of + * {@code createSource}) can be done on any thread because the construction + * simply captures values. The real work is done in decodeDrawable or + * decodeBitmap.

+ * + *

Further, a Source object can be reused with different settings, or + * even used simultaneously in multiple threads.

*/ public static abstract class Source { private Source() {} @@ -120,7 +132,8 @@ public final class ImageDecoder implements AutoCloseable { int length = mBuffer.limit() - mBuffer.position(); return nCreate(mBuffer.array(), offset, length, this); } - return nCreate(mBuffer, mBuffer.position(), mBuffer.limit(), this); + ByteBuffer buffer = mBuffer.slice(); + return nCreate(buffer, buffer.position(), buffer.limit(), this); } } @@ -232,6 +245,8 @@ public final class ImageDecoder implements AutoCloseable { /** * For backwards compatibility, this does *not* close the InputStream. + * + * Further, unlike other Sources, this one is not reusable. */ private static class InputStreamSource extends Source { InputStreamSource(Resources res, InputStream is, int inputDensity) { @@ -322,12 +337,17 @@ public final class ImageDecoder implements AutoCloseable { final Resources mResources; final int mResId; int mResDensity; + private Object mLock = new Object(); @Override public Resources getResources() { return mResources; } @Override - public int getDensity() { return mResDensity; } + public int getDensity() { + synchronized (mLock) { + return mResDensity; + } + } @Override public ImageDecoder createImageDecoder() throws IOException { @@ -336,10 +356,12 @@ public final class ImageDecoder implements AutoCloseable { // keep it alive. InputStream is = mResources.openRawResource(mResId, value); - if (value.density == TypedValue.DENSITY_DEFAULT) { - mResDensity = DisplayMetrics.DENSITY_DEFAULT; - } else if (value.density != TypedValue.DENSITY_NONE) { - mResDensity = value.density; + synchronized (mLock) { + if (value.density == TypedValue.DENSITY_DEFAULT) { + mResDensity = DisplayMetrics.DENSITY_DEFAULT; + } else if (value.density != TypedValue.DENSITY_NONE) { + mResDensity = value.density; + } } return createFromAsset((AssetInputStream) is, this); @@ -455,6 +477,9 @@ public final class ImageDecoder implements AutoCloseable { /** * Optional listener supplied to {@link #decodeDrawable} or * {@link #decodeBitmap}. + * + *

This is necessary in order to change the default settings of the + * decode.

*/ public static interface OnHeaderDecodedListener { /** @@ -546,6 +571,9 @@ public final class ImageDecoder implements AutoCloseable { /** * Retrieve the {@link Source} that was interrupted. + * + *

This can be used for equality checking to find the Source which + * failed to completely decode.

*/ @NonNull public Source getSource() { @@ -658,6 +686,7 @@ public final class ImageDecoder implements AutoCloseable { * @return a new Source object, which can be passed to * {@link #decodeDrawable} or {@link #decodeBitmap}. */ + @AnyThread @NonNull public static Source createSource(@NonNull Resources res, int resId) { @@ -672,6 +701,7 @@ public final class ImageDecoder implements AutoCloseable { * @return a new Source object, which can be passed to * {@link #decodeDrawable} or {@link #decodeBitmap}. */ + @AnyThread @NonNull public static Source createSource(@NonNull ContentResolver cr, @NonNull Uri uri) { @@ -683,6 +713,7 @@ public final class ImageDecoder implements AutoCloseable { * * @hide */ + @AnyThread @NonNull public static Source createSource(@NonNull ContentResolver cr, @NonNull Uri uri, @Nullable Resources res) { @@ -692,6 +723,7 @@ public final class ImageDecoder implements AutoCloseable { /** * Create a new {@link Source} from a file in the "assets" directory. */ + @AnyThread @NonNull public static Source createSource(@NonNull AssetManager assets, @NonNull String fileName) { return new AssetSource(assets, fileName); @@ -709,6 +741,7 @@ public final class ImageDecoder implements AutoCloseable { * not within data. * @hide */ + @AnyThread @NonNull public static Source createSource(@NonNull byte[] data, int offset, int length) throws ArrayIndexOutOfBoundsException { @@ -727,6 +760,7 @@ public final class ImageDecoder implements AutoCloseable { * See {@link #createSource(byte[], int, int). * @hide */ + @AnyThread @NonNull public static Source createSource(@NonNull byte[] data) { return createSource(data, 0, data.length); @@ -744,24 +778,35 @@ public final class ImageDecoder implements AutoCloseable { * be modified, even after the {@code AnimatedImageDrawable} is returned. * {@code buffer}'s contents should never be modified during decode.

*/ + @AnyThread @NonNull public static Source createSource(@NonNull ByteBuffer buffer) { - return new ByteBufferSource(buffer.slice()); + return new ByteBufferSource(buffer); } /** * Internal API used to generate bitmaps for use by Drawables (i.e. BitmapDrawable) + * + *

Unlike other Sources, this one cannot be reused.

+ * * @hide */ + @AnyThread + @NonNull public static Source createSource(Resources res, InputStream is) { return new InputStreamSource(res, is, Bitmap.getDefaultDensity()); } /** * Internal API used to generate bitmaps for use by Drawables (i.e. BitmapDrawable) + * + *

Unlike other Sources, this one cannot be reused.

+ * * @hide */ + @AnyThread @TestApi + @NonNull public static Source createSource(Resources res, InputStream is, int density) { return new InputStreamSource(res, is, density); } @@ -769,6 +814,7 @@ public final class ImageDecoder implements AutoCloseable { /** * Create a new {@link Source} from a {@link java.io.File}. */ + @AnyThread @NonNull public static Source createSource(@NonNull File file) { return new FileSource(file); @@ -822,6 +868,9 @@ public final class ImageDecoder implements AutoCloseable { *

Only the last call to this or {@link #setTargetSampleSize} is * respected.

* + *

Like all setters on ImageDecoder, this must be called inside + * {@link OnHeaderDecodedListener#onHeaderDecoded}.

+ * * @param width must be greater than 0. * @param height must be greater than 0. * @return this object for chaining. @@ -888,6 +937,9 @@ public final class ImageDecoder implements AutoCloseable { * *

Only the last call to this or {@link #setTargetSize} is respected.

* + *

Like all setters on ImageDecoder, this must be called inside + * {@link OnHeaderDecodedListener#onHeaderDecoded}.

+ * * @param sampleSize Sampling rate of the encoded image. * @return this object for chaining. */ @@ -948,7 +1000,10 @@ public final class ImageDecoder implements AutoCloseable { /** * Choose the backing for the pixel memory. * - * This is ignored for animated drawables. + *

This is ignored for animated drawables.

+ * + *

Like all setters on ImageDecoder, this must be called inside + * {@link OnHeaderDecodedListener#onHeaderDecoded}.

* * @param allocator Type of allocator to use. * @return this object for chaining. @@ -982,6 +1037,9 @@ public final class ImageDecoder implements AutoCloseable { * {@link Drawable} will throw an {@link java.lang.IllegalStateException}. *

* + *

Like all setters on ImageDecoder, this must be called inside + * {@link OnHeaderDecodedListener#onHeaderDecoded}.

+ * * @return this object for chaining. */ public ImageDecoder setUnpremultipliedRequired(boolean unpremultipliedRequired) { @@ -1025,6 +1083,9 @@ public final class ImageDecoder implements AutoCloseable { * {@link Canvas} will be recorded immediately and then applied to each * frame.

* + *

Like all setters on ImageDecoder, this must be called inside + * {@link OnHeaderDecodedListener#onHeaderDecoded}.

+ * * @return this object for chaining. */ public ImageDecoder setPostProcessor(@Nullable PostProcessor p) { @@ -1046,6 +1107,9 @@ public final class ImageDecoder implements AutoCloseable { *

Will be called if there is an error in the input. Without one, an * error will result in an Exception being thrown.

* + *

Like all setters on ImageDecoder, this must be called inside + * {@link OnHeaderDecodedListener#onHeaderDecoded}.

+ * * @return this object for chaining. */ public ImageDecoder setOnPartialImageListener(@Nullable OnPartialImageListener l) { @@ -1073,6 +1137,9 @@ public final class ImageDecoder implements AutoCloseable { * {@link BitmapRegionDecoder#decodeRegion}. This supports all formats, * but merely crops the output.

* + *

Like all setters on ImageDecoder, this must be called inside + * {@link OnHeaderDecodedListener#onHeaderDecoded}.

+ * * @return this object for chaining. */ public ImageDecoder setCrop(@Nullable Rect subset) { @@ -1094,6 +1161,9 @@ public final class ImageDecoder implements AutoCloseable { * If the image is a nine patch, this Rect will be set to the padding * rectangle during decode. Otherwise it will not be modified. * + *

Like all setters on ImageDecoder, this must be called inside + * {@link OnHeaderDecodedListener#onHeaderDecoded}.

+ * * @return this object for chaining. * * @hide @@ -1119,6 +1189,9 @@ public final class ImageDecoder implements AutoCloseable { * order to modify. Attempting to decode a mutable {@link Drawable} will * throw an {@link java.lang.IllegalStateException}.

* + *

Like all setters on ImageDecoder, this must be called inside + * {@link OnHeaderDecodedListener#onHeaderDecoded}.

+ * * @return this object for chaining. */ public ImageDecoder setMutableRequired(boolean mutable) { @@ -1161,6 +1234,9 @@ public final class ImageDecoder implements AutoCloseable { * This necessarily lowers the quality of the output, but saves half * the memory used.

* + *

Like all setters on ImageDecoder, this must be called inside + * {@link OnHeaderDecodedListener#onHeaderDecoded}.

+ * * @return this object for chaining. */ public ImageDecoder setConserveMemory(boolean conserveMemory) { @@ -1191,6 +1267,9 @@ public final class ImageDecoder implements AutoCloseable { * {@link #decodeBitmap} throwing an * {@link java.lang.IllegalStateException}.

* + *

Like all setters on ImageDecoder, this must be called inside + * {@link OnHeaderDecodedListener#onHeaderDecoded}.

+ * * @return this object for chaining. */ public ImageDecoder setDecodeAsAlphaMaskEnabled(boolean enabled) { @@ -1267,6 +1346,9 @@ public final class ImageDecoder implements AutoCloseable { * IllegalArgumentException will be thrown by the decode methods * if calling {@link ColorSpace.Rgb#getTransferParameters()} on the * specified color space returns null.

+ * + *

Like all setters on ImageDecoder, this must be called inside + * {@link OnHeaderDecodedListener#onHeaderDecoded}.

*/ public ImageDecoder setTargetColorSpace(ColorSpace colorSpace) { mDesiredColorSpace = colorSpace; @@ -1334,6 +1416,7 @@ public final class ImageDecoder implements AutoCloseable { } } + @WorkerThread @NonNull private Bitmap decodeBitmapInternal() throws IOException { checkState(); @@ -1362,10 +1445,12 @@ public final class ImageDecoder implements AutoCloseable { * @param listener for learning the {@link ImageInfo} and changing any * default settings on the {@code ImageDecoder}. This will be called on * the same thread as {@code decodeDrawable} before that method returns. + * This is required in order to change any of the default settings. * @return Drawable for displaying the image. * @throws IOException if {@code src} is not found, is an unsupported * format, or cannot be decoded for any reason. */ + @WorkerThread @NonNull public static Drawable decodeDrawable(@NonNull Source src, @NonNull OnHeaderDecodedListener listener) throws IOException { @@ -1376,6 +1461,7 @@ public final class ImageDecoder implements AutoCloseable { return decodeDrawableImpl(src, listener); } + @WorkerThread @NonNull private static Drawable decodeDrawableImpl(@NonNull Source src, @Nullable OnHeaderDecodedListener listener) throws IOException { @@ -1436,8 +1522,18 @@ public final class ImageDecoder implements AutoCloseable { } /** - * See {@link #decodeDrawable(Source, OnHeaderDecodedListener)}. + * Create a {@link Drawable} from a {@code Source}. + * + *

Since there is no {@link OnHeaderDecodedListener}, the default + * settings will be used. In order to change any settings, call + * {@link #decodeDrawable(Source, OnHeaderDecodedListener)} instead.

+ * + * @param src representing the encoded image. + * @return Drawable for displaying the image. + * @throws IOException if {@code src} is not found, is an unsupported + * format, or cannot be decoded for any reason. */ + @WorkerThread @NonNull public static Drawable decodeDrawable(@NonNull Source src) throws IOException { @@ -1451,10 +1547,12 @@ public final class ImageDecoder implements AutoCloseable { * @param listener for learning the {@link ImageInfo} and changing any * default settings on the {@code ImageDecoder}. This will be called on * the same thread as {@code decodeBitmap} before that method returns. + * This is required in order to change any of the default settings. * @return Bitmap containing the image. * @throws IOException if {@code src} is not found, is an unsupported * format, or cannot be decoded for any reason. */ + @WorkerThread @NonNull public static Bitmap decodeBitmap(@NonNull Source src, @NonNull OnHeaderDecodedListener listener) throws IOException { @@ -1465,6 +1563,7 @@ public final class ImageDecoder implements AutoCloseable { return decodeBitmapImpl(src, listener); } + @WorkerThread @NonNull private static Bitmap decodeBitmapImpl(@NonNull Source src, @Nullable OnHeaderDecodedListener listener) throws IOException { @@ -1536,8 +1635,18 @@ public final class ImageDecoder implements AutoCloseable { } /** - * See {@link #decodeBitmap(Source, OnHeaderDecodedListener)}. + * Create a {@link Bitmap} from a {@code Source}. + * + *

Since there is no {@link OnHeaderDecodedListener}, the default + * settings will be used. In order to change any settings, call + * {@link #decodeBitmap(Source, OnHeaderDecodedListener)} instead.

+ * + * @param src representing the encoded image. + * @return Bitmap containing the image. + * @throws IOException if {@code src} is not found, is an unsupported + * format, or cannot be decoded for any reason. */ + @WorkerThread @NonNull public static Bitmap decodeBitmap(@NonNull Source src) throws IOException { return decodeBitmapImpl(src, null);