Loading core/jni/android/graphics/ImageDecoder.cpp +26 −20 Original line number Diff line number Diff line Loading @@ -78,14 +78,18 @@ static jobject throw_exception(JNIEnv* env, ImageDecoder::Error error, const cha return nullptr; } static jobject native_create(JNIEnv* env, std::unique_ptr<SkStream> stream, jobject source) { static jobject native_create(JNIEnv* env, std::unique_ptr<SkStream> stream, jobject source, jboolean preferAnimation) { if (!stream.get()) { return throw_exception(env, ImageDecoder::kSourceMalformedData, "Failed to create a stream", nullptr, source); } std::unique_ptr<ImageDecoder> decoder(new ImageDecoder); SkCodec::Result result; auto codec = SkCodec::MakeFromStream(std::move(stream), &result, decoder->mPeeker.get()); auto codec = SkCodec::MakeFromStream( std::move(stream), &result, decoder->mPeeker.get(), preferAnimation ? SkCodec::SelectionPolicy::kPreferAnimation : SkCodec::SelectionPolicy::kPreferStillImage); if (jthrowable jexception = get_and_clear_exception(env)) { return throw_exception(env, ImageDecoder::kSourceException, "", jexception, source); } Loading Loading @@ -124,7 +128,7 @@ static jobject native_create(JNIEnv* env, std::unique_ptr<SkStream> stream, jobj } static jobject ImageDecoder_nCreateFd(JNIEnv* env, jobject /*clazz*/, jobject fileDescriptor, jobject source) { jobject fileDescriptor, jboolean preferAnimation, jobject source) { int descriptor = jniGetFDFromFileDescriptor(env, fileDescriptor); struct stat fdStat; Loading @@ -142,11 +146,11 @@ static jobject ImageDecoder_nCreateFd(JNIEnv* env, jobject /*clazz*/, } std::unique_ptr<SkFILEStream> fileStream(new SkFILEStream(file)); return native_create(env, std::move(fileStream), source); return native_create(env, std::move(fileStream), source, preferAnimation); } static jobject ImageDecoder_nCreateInputStream(JNIEnv* env, jobject /*clazz*/, jobject is, jbyteArray storage, jobject source) { jobject is, jbyteArray storage, jboolean preferAnimation, jobject source) { std::unique_ptr<SkStream> stream(CreateJavaInputStreamAdaptor(env, is, storage, false)); if (!stream.get()) { Loading @@ -157,31 +161,33 @@ static jobject ImageDecoder_nCreateInputStream(JNIEnv* env, jobject /*clazz*/, std::unique_ptr<SkStream> bufferedStream( SkFrontBufferedStream::Make(std::move(stream), SkCodec::MinBufferedBytesNeeded())); return native_create(env, std::move(bufferedStream), source); return native_create(env, std::move(bufferedStream), source, preferAnimation); } static jobject ImageDecoder_nCreateAsset(JNIEnv* env, jobject /*clazz*/, jlong assetPtr, jobject source) { static jobject ImageDecoder_nCreateAsset(JNIEnv* env, jobject /*clazz*/, jlong assetPtr, jboolean preferAnimation, jobject source) { Asset* asset = reinterpret_cast<Asset*>(assetPtr); std::unique_ptr<SkStream> stream(new AssetStreamAdaptor(asset)); return native_create(env, std::move(stream), source); return native_create(env, std::move(stream), source, preferAnimation); } static jobject ImageDecoder_nCreateByteBuffer(JNIEnv* env, jobject /*clazz*/, jobject jbyteBuffer, jint initialPosition, jint limit, jobject source) { static jobject ImageDecoder_nCreateByteBuffer(JNIEnv* env, jobject /*clazz*/, jobject jbyteBuffer, jint initialPosition, jint limit, jboolean preferAnimation, jobject source) { std::unique_ptr<SkStream> stream = CreateByteBufferStreamAdaptor(env, jbyteBuffer, initialPosition, limit); if (!stream) { return throw_exception(env, ImageDecoder::kSourceMalformedData, "Failed to read ByteBuffer", nullptr, source); } return native_create(env, std::move(stream), source); return native_create(env, std::move(stream), source, preferAnimation); } static jobject ImageDecoder_nCreateByteArray(JNIEnv* env, jobject /*clazz*/, jbyteArray byteArray, jint offset, jint length, jobject source) { static jobject ImageDecoder_nCreateByteArray(JNIEnv* env, jobject /*clazz*/, jbyteArray byteArray, jint offset, jint length, jboolean preferAnimation, jobject source) { std::unique_ptr<SkStream> stream(CreateByteArrayStreamAdaptor(env, byteArray, offset, length)); return native_create(env, std::move(stream), source); return native_create(env, std::move(stream), source, preferAnimation); } jint postProcessAndRelease(JNIEnv* env, jobject jimageDecoder, std::unique_ptr<Canvas> canvas) { Loading Loading @@ -514,11 +520,11 @@ static jobject ImageDecoder_nGetColorSpace(JNIEnv* env, jobject /*clazz*/, jlong } static const JNINativeMethod gImageDecoderMethods[] = { { "nCreate", "(JLandroid/graphics/ImageDecoder$Source;)Landroid/graphics/ImageDecoder;", (void*) ImageDecoder_nCreateAsset }, { "nCreate", "(Ljava/nio/ByteBuffer;IILandroid/graphics/ImageDecoder$Source;)Landroid/graphics/ImageDecoder;", (void*) ImageDecoder_nCreateByteBuffer }, { "nCreate", "([BIILandroid/graphics/ImageDecoder$Source;)Landroid/graphics/ImageDecoder;", (void*) ImageDecoder_nCreateByteArray }, { "nCreate", "(Ljava/io/InputStream;[BLandroid/graphics/ImageDecoder$Source;)Landroid/graphics/ImageDecoder;", (void*) ImageDecoder_nCreateInputStream }, { "nCreate", "(Ljava/io/FileDescriptor;Landroid/graphics/ImageDecoder$Source;)Landroid/graphics/ImageDecoder;", (void*) ImageDecoder_nCreateFd }, { "nCreate", "(JZLandroid/graphics/ImageDecoder$Source;)Landroid/graphics/ImageDecoder;", (void*) ImageDecoder_nCreateAsset }, { "nCreate", "(Ljava/nio/ByteBuffer;IIZLandroid/graphics/ImageDecoder$Source;)Landroid/graphics/ImageDecoder;", (void*) ImageDecoder_nCreateByteBuffer }, { "nCreate", "([BIIZLandroid/graphics/ImageDecoder$Source;)Landroid/graphics/ImageDecoder;", (void*) ImageDecoder_nCreateByteArray }, { "nCreate", "(Ljava/io/InputStream;[BZLandroid/graphics/ImageDecoder$Source;)Landroid/graphics/ImageDecoder;", (void*) ImageDecoder_nCreateInputStream }, { "nCreate", "(Ljava/io/FileDescriptor;ZLandroid/graphics/ImageDecoder$Source;)Landroid/graphics/ImageDecoder;", (void*) ImageDecoder_nCreateFd }, { "nDecodeBitmap", "(JLandroid/graphics/ImageDecoder;ZIILandroid/graphics/Rect;ZIZZZJZ)Landroid/graphics/Bitmap;", (void*) ImageDecoder_nDecodeBitmap }, { "nGetSampledSize","(JI)Landroid/util/Size;", (void*) ImageDecoder_nGetSampledSize }, Loading graphics/java/android/graphics/ImageDecoder.java +41 −39 Original line number Diff line number Diff line Loading @@ -214,7 +214,7 @@ public final class ImageDecoder implements AutoCloseable { /* @hide */ @NonNull abstract ImageDecoder createImageDecoder() throws IOException; abstract ImageDecoder createImageDecoder(boolean preferAnimation) throws IOException; }; private static class ByteArraySource extends Source { Loading @@ -228,8 +228,8 @@ public final class ImageDecoder implements AutoCloseable { private final int mLength; @Override public ImageDecoder createImageDecoder() throws IOException { return nCreate(mData, mOffset, mLength, this); public ImageDecoder createImageDecoder(boolean preferAnimation) throws IOException { return nCreate(mData, mOffset, mLength, preferAnimation, this); } } Loading @@ -240,14 +240,14 @@ public final class ImageDecoder implements AutoCloseable { private final ByteBuffer mBuffer; @Override public ImageDecoder createImageDecoder() throws IOException { public ImageDecoder createImageDecoder(boolean preferAnimation) throws IOException { if (!mBuffer.isDirect() && mBuffer.hasArray()) { int offset = mBuffer.arrayOffset() + mBuffer.position(); int length = mBuffer.limit() - mBuffer.position(); return nCreate(mBuffer.array(), offset, length, this); return nCreate(mBuffer.array(), offset, length, preferAnimation, this); } ByteBuffer buffer = mBuffer.slice(); return nCreate(buffer, buffer.position(), buffer.limit(), this); return nCreate(buffer, buffer.position(), buffer.limit(), preferAnimation, this); } } Loading @@ -267,7 +267,7 @@ public final class ImageDecoder implements AutoCloseable { Resources getResources() { return mResources; } @Override public ImageDecoder createImageDecoder() throws IOException { public ImageDecoder createImageDecoder(boolean preferAnimation) throws IOException { AssetFileDescriptor assetFd = null; try { if (mUri.getScheme() == ContentResolver.SCHEME_CONTENT) { Loading @@ -284,26 +284,26 @@ public final class ImageDecoder implements AutoCloseable { throw new FileNotFoundException(mUri.toString()); } return createFromStream(is, true, this); return createFromStream(is, true, preferAnimation, this); } return createFromAssetFileDescriptor(assetFd, this); return createFromAssetFileDescriptor(assetFd, preferAnimation, this); } } @NonNull private static ImageDecoder createFromFile(@NonNull File file, @NonNull Source source) throws IOException { boolean preferAnimation, @NonNull Source source) throws IOException { FileInputStream stream = new FileInputStream(file); FileDescriptor fd = stream.getFD(); try { Os.lseek(fd, 0, SEEK_CUR); } catch (ErrnoException e) { return createFromStream(stream, true, source); return createFromStream(stream, true, preferAnimation, source); } ImageDecoder decoder = null; try { decoder = nCreate(fd, source); decoder = nCreate(fd, preferAnimation, source); } finally { if (decoder == null) { IoUtils.closeQuietly(stream); Loading @@ -317,12 +317,12 @@ public final class ImageDecoder implements AutoCloseable { @NonNull private static ImageDecoder createFromStream(@NonNull InputStream is, boolean closeInputStream, Source source) throws IOException { boolean closeInputStream, boolean preferAnimation, Source source) throws IOException { // Arbitrary size matches BitmapFactory. byte[] storage = new byte[16 * 1024]; ImageDecoder decoder = null; try { decoder = nCreate(is, storage, source); decoder = nCreate(is, storage, preferAnimation, source); } finally { if (decoder == null) { if (closeInputStream) { Loading @@ -340,7 +340,7 @@ public final class ImageDecoder implements AutoCloseable { @NonNull private static ImageDecoder createFromAssetFileDescriptor(@NonNull AssetFileDescriptor assetFd, Source source) throws IOException { boolean preferAnimation, Source source) throws IOException { final FileDescriptor fd = assetFd.getFileDescriptor(); final long offset = assetFd.getStartOffset(); Loading @@ -348,9 +348,9 @@ public final class ImageDecoder implements AutoCloseable { try { try { Os.lseek(fd, offset, SEEK_SET); decoder = nCreate(fd, source); decoder = nCreate(fd, preferAnimation, source); } catch (ErrnoException e) { decoder = createFromStream(new FileInputStream(fd), true, source); decoder = createFromStream(new FileInputStream(fd), true, preferAnimation, source); } } finally { if (decoder == null) { Loading Loading @@ -388,7 +388,7 @@ public final class ImageDecoder implements AutoCloseable { public int getDensity() { return mInputDensity; } @Override public ImageDecoder createImageDecoder() throws IOException { public ImageDecoder createImageDecoder(boolean preferAnimation) throws IOException { synchronized (this) { if (mInputStream == null) { Loading @@ -396,7 +396,7 @@ public final class ImageDecoder implements AutoCloseable { } InputStream is = mInputStream; mInputStream = null; return createFromStream(is, false, this); return createFromStream(is, false, preferAnimation, this); } } } Loading Loading @@ -434,14 +434,14 @@ public final class ImageDecoder implements AutoCloseable { } @Override public ImageDecoder createImageDecoder() throws IOException { public ImageDecoder createImageDecoder(boolean preferAnimation) throws IOException { synchronized (this) { if (mAssetInputStream == null) { throw new IOException("Cannot reuse AssetInputStreamSource"); } AssetInputStream ais = mAssetInputStream; mAssetInputStream = null; return createFromAsset(ais, this); return createFromAsset(ais, preferAnimation, this); } } } Loading Loading @@ -469,7 +469,7 @@ public final class ImageDecoder implements AutoCloseable { } @Override public ImageDecoder createImageDecoder() throws IOException { public ImageDecoder createImageDecoder(boolean preferAnimation) throws IOException { TypedValue value = new TypedValue(); // This is just used in order to access the underlying Asset and // keep it alive. Loading @@ -483,7 +483,7 @@ public final class ImageDecoder implements AutoCloseable { } } return createFromAsset((AssetInputStream) is, this); return createFromAsset((AssetInputStream) is, preferAnimation, this); } } Loading @@ -491,11 +491,11 @@ public final class ImageDecoder implements AutoCloseable { * ImageDecoder will own the AssetInputStream. */ private static ImageDecoder createFromAsset(AssetInputStream ais, Source source) throws IOException { boolean preferAnimation, Source source) throws IOException { ImageDecoder decoder = null; try { long asset = ais.getNativeAsset(); decoder = nCreate(asset, source); decoder = nCreate(asset, preferAnimation, source); } finally { if (decoder == null) { IoUtils.closeQuietly(ais); Loading @@ -517,9 +517,9 @@ public final class ImageDecoder implements AutoCloseable { private final String mFileName; @Override public ImageDecoder createImageDecoder() throws IOException { public ImageDecoder createImageDecoder(boolean preferAnimation) throws IOException { InputStream is = mAssets.open(mFileName); return createFromAsset((AssetInputStream) is, this); return createFromAsset((AssetInputStream) is, preferAnimation, this); } } Loading @@ -531,8 +531,8 @@ public final class ImageDecoder implements AutoCloseable { private final File mFile; @Override public ImageDecoder createImageDecoder() throws IOException { return createFromFile(mFile, this); public ImageDecoder createImageDecoder(boolean preferAnimation) throws IOException { return createFromFile(mFile, preferAnimation, this); } } Loading @@ -544,7 +544,7 @@ public final class ImageDecoder implements AutoCloseable { private final Callable<AssetFileDescriptor> mCallable; @Override public ImageDecoder createImageDecoder() throws IOException { public ImageDecoder createImageDecoder(boolean preferAnimation) throws IOException { AssetFileDescriptor assetFd = null; try { assetFd = mCallable.call(); Loading @@ -555,7 +555,7 @@ public final class ImageDecoder implements AutoCloseable { throw new IOException(e); } } return createFromAssetFileDescriptor(assetFd, this); return createFromAssetFileDescriptor(assetFd, preferAnimation, this); } } Loading Loading @@ -1740,7 +1740,7 @@ public final class ImageDecoder implements AutoCloseable { @NonNull private static Drawable decodeDrawableImpl(@NonNull Source src, @Nullable OnHeaderDecodedListener listener) throws IOException { try (ImageDecoder decoder = src.createImageDecoder()) { try (ImageDecoder decoder = src.createImageDecoder(true /*preferAnimation*/)) { decoder.mSource = src; decoder.callHeaderDecoded(listener, src); Loading Loading @@ -1844,7 +1844,7 @@ public final class ImageDecoder implements AutoCloseable { @NonNull private static Bitmap decodeBitmapImpl(@NonNull Source src, @Nullable OnHeaderDecodedListener listener) throws IOException { try (ImageDecoder decoder = src.createImageDecoder()) { try (ImageDecoder decoder = src.createImageDecoder(false /*preferAnimation*/)) { decoder.mSource = src; decoder.callHeaderDecoded(listener, src); Loading Loading @@ -1971,15 +1971,17 @@ public final class ImageDecoder implements AutoCloseable { } } private static native ImageDecoder nCreate(long asset, Source src) throws IOException; private static native ImageDecoder nCreate(ByteBuffer buffer, int position, int limit, Source src) throws IOException; private static native ImageDecoder nCreate(long asset, boolean preferAnimation, Source src) throws IOException; private static native ImageDecoder nCreate(ByteBuffer buffer, int position, int limit, boolean preferAnimation, Source src) throws IOException; private static native ImageDecoder nCreate(byte[] data, int offset, int length, Source src) throws IOException; boolean preferAnimation, Source src) throws IOException; private static native ImageDecoder nCreate(InputStream is, byte[] storage, Source src) throws IOException; boolean preferAnimation, Source src) throws IOException; // The fd must be seekable. private static native ImageDecoder nCreate(FileDescriptor fd, Source src) throws IOException; private static native ImageDecoder nCreate(FileDescriptor fd, boolean preferAnimation, Source src) throws IOException; @NonNull private static native Bitmap nDecodeBitmap(long nativePtr, @NonNull ImageDecoder decoder, Loading Loading
core/jni/android/graphics/ImageDecoder.cpp +26 −20 Original line number Diff line number Diff line Loading @@ -78,14 +78,18 @@ static jobject throw_exception(JNIEnv* env, ImageDecoder::Error error, const cha return nullptr; } static jobject native_create(JNIEnv* env, std::unique_ptr<SkStream> stream, jobject source) { static jobject native_create(JNIEnv* env, std::unique_ptr<SkStream> stream, jobject source, jboolean preferAnimation) { if (!stream.get()) { return throw_exception(env, ImageDecoder::kSourceMalformedData, "Failed to create a stream", nullptr, source); } std::unique_ptr<ImageDecoder> decoder(new ImageDecoder); SkCodec::Result result; auto codec = SkCodec::MakeFromStream(std::move(stream), &result, decoder->mPeeker.get()); auto codec = SkCodec::MakeFromStream( std::move(stream), &result, decoder->mPeeker.get(), preferAnimation ? SkCodec::SelectionPolicy::kPreferAnimation : SkCodec::SelectionPolicy::kPreferStillImage); if (jthrowable jexception = get_and_clear_exception(env)) { return throw_exception(env, ImageDecoder::kSourceException, "", jexception, source); } Loading Loading @@ -124,7 +128,7 @@ static jobject native_create(JNIEnv* env, std::unique_ptr<SkStream> stream, jobj } static jobject ImageDecoder_nCreateFd(JNIEnv* env, jobject /*clazz*/, jobject fileDescriptor, jobject source) { jobject fileDescriptor, jboolean preferAnimation, jobject source) { int descriptor = jniGetFDFromFileDescriptor(env, fileDescriptor); struct stat fdStat; Loading @@ -142,11 +146,11 @@ static jobject ImageDecoder_nCreateFd(JNIEnv* env, jobject /*clazz*/, } std::unique_ptr<SkFILEStream> fileStream(new SkFILEStream(file)); return native_create(env, std::move(fileStream), source); return native_create(env, std::move(fileStream), source, preferAnimation); } static jobject ImageDecoder_nCreateInputStream(JNIEnv* env, jobject /*clazz*/, jobject is, jbyteArray storage, jobject source) { jobject is, jbyteArray storage, jboolean preferAnimation, jobject source) { std::unique_ptr<SkStream> stream(CreateJavaInputStreamAdaptor(env, is, storage, false)); if (!stream.get()) { Loading @@ -157,31 +161,33 @@ static jobject ImageDecoder_nCreateInputStream(JNIEnv* env, jobject /*clazz*/, std::unique_ptr<SkStream> bufferedStream( SkFrontBufferedStream::Make(std::move(stream), SkCodec::MinBufferedBytesNeeded())); return native_create(env, std::move(bufferedStream), source); return native_create(env, std::move(bufferedStream), source, preferAnimation); } static jobject ImageDecoder_nCreateAsset(JNIEnv* env, jobject /*clazz*/, jlong assetPtr, jobject source) { static jobject ImageDecoder_nCreateAsset(JNIEnv* env, jobject /*clazz*/, jlong assetPtr, jboolean preferAnimation, jobject source) { Asset* asset = reinterpret_cast<Asset*>(assetPtr); std::unique_ptr<SkStream> stream(new AssetStreamAdaptor(asset)); return native_create(env, std::move(stream), source); return native_create(env, std::move(stream), source, preferAnimation); } static jobject ImageDecoder_nCreateByteBuffer(JNIEnv* env, jobject /*clazz*/, jobject jbyteBuffer, jint initialPosition, jint limit, jobject source) { static jobject ImageDecoder_nCreateByteBuffer(JNIEnv* env, jobject /*clazz*/, jobject jbyteBuffer, jint initialPosition, jint limit, jboolean preferAnimation, jobject source) { std::unique_ptr<SkStream> stream = CreateByteBufferStreamAdaptor(env, jbyteBuffer, initialPosition, limit); if (!stream) { return throw_exception(env, ImageDecoder::kSourceMalformedData, "Failed to read ByteBuffer", nullptr, source); } return native_create(env, std::move(stream), source); return native_create(env, std::move(stream), source, preferAnimation); } static jobject ImageDecoder_nCreateByteArray(JNIEnv* env, jobject /*clazz*/, jbyteArray byteArray, jint offset, jint length, jobject source) { static jobject ImageDecoder_nCreateByteArray(JNIEnv* env, jobject /*clazz*/, jbyteArray byteArray, jint offset, jint length, jboolean preferAnimation, jobject source) { std::unique_ptr<SkStream> stream(CreateByteArrayStreamAdaptor(env, byteArray, offset, length)); return native_create(env, std::move(stream), source); return native_create(env, std::move(stream), source, preferAnimation); } jint postProcessAndRelease(JNIEnv* env, jobject jimageDecoder, std::unique_ptr<Canvas> canvas) { Loading Loading @@ -514,11 +520,11 @@ static jobject ImageDecoder_nGetColorSpace(JNIEnv* env, jobject /*clazz*/, jlong } static const JNINativeMethod gImageDecoderMethods[] = { { "nCreate", "(JLandroid/graphics/ImageDecoder$Source;)Landroid/graphics/ImageDecoder;", (void*) ImageDecoder_nCreateAsset }, { "nCreate", "(Ljava/nio/ByteBuffer;IILandroid/graphics/ImageDecoder$Source;)Landroid/graphics/ImageDecoder;", (void*) ImageDecoder_nCreateByteBuffer }, { "nCreate", "([BIILandroid/graphics/ImageDecoder$Source;)Landroid/graphics/ImageDecoder;", (void*) ImageDecoder_nCreateByteArray }, { "nCreate", "(Ljava/io/InputStream;[BLandroid/graphics/ImageDecoder$Source;)Landroid/graphics/ImageDecoder;", (void*) ImageDecoder_nCreateInputStream }, { "nCreate", "(Ljava/io/FileDescriptor;Landroid/graphics/ImageDecoder$Source;)Landroid/graphics/ImageDecoder;", (void*) ImageDecoder_nCreateFd }, { "nCreate", "(JZLandroid/graphics/ImageDecoder$Source;)Landroid/graphics/ImageDecoder;", (void*) ImageDecoder_nCreateAsset }, { "nCreate", "(Ljava/nio/ByteBuffer;IIZLandroid/graphics/ImageDecoder$Source;)Landroid/graphics/ImageDecoder;", (void*) ImageDecoder_nCreateByteBuffer }, { "nCreate", "([BIIZLandroid/graphics/ImageDecoder$Source;)Landroid/graphics/ImageDecoder;", (void*) ImageDecoder_nCreateByteArray }, { "nCreate", "(Ljava/io/InputStream;[BZLandroid/graphics/ImageDecoder$Source;)Landroid/graphics/ImageDecoder;", (void*) ImageDecoder_nCreateInputStream }, { "nCreate", "(Ljava/io/FileDescriptor;ZLandroid/graphics/ImageDecoder$Source;)Landroid/graphics/ImageDecoder;", (void*) ImageDecoder_nCreateFd }, { "nDecodeBitmap", "(JLandroid/graphics/ImageDecoder;ZIILandroid/graphics/Rect;ZIZZZJZ)Landroid/graphics/Bitmap;", (void*) ImageDecoder_nDecodeBitmap }, { "nGetSampledSize","(JI)Landroid/util/Size;", (void*) ImageDecoder_nGetSampledSize }, Loading
graphics/java/android/graphics/ImageDecoder.java +41 −39 Original line number Diff line number Diff line Loading @@ -214,7 +214,7 @@ public final class ImageDecoder implements AutoCloseable { /* @hide */ @NonNull abstract ImageDecoder createImageDecoder() throws IOException; abstract ImageDecoder createImageDecoder(boolean preferAnimation) throws IOException; }; private static class ByteArraySource extends Source { Loading @@ -228,8 +228,8 @@ public final class ImageDecoder implements AutoCloseable { private final int mLength; @Override public ImageDecoder createImageDecoder() throws IOException { return nCreate(mData, mOffset, mLength, this); public ImageDecoder createImageDecoder(boolean preferAnimation) throws IOException { return nCreate(mData, mOffset, mLength, preferAnimation, this); } } Loading @@ -240,14 +240,14 @@ public final class ImageDecoder implements AutoCloseable { private final ByteBuffer mBuffer; @Override public ImageDecoder createImageDecoder() throws IOException { public ImageDecoder createImageDecoder(boolean preferAnimation) throws IOException { if (!mBuffer.isDirect() && mBuffer.hasArray()) { int offset = mBuffer.arrayOffset() + mBuffer.position(); int length = mBuffer.limit() - mBuffer.position(); return nCreate(mBuffer.array(), offset, length, this); return nCreate(mBuffer.array(), offset, length, preferAnimation, this); } ByteBuffer buffer = mBuffer.slice(); return nCreate(buffer, buffer.position(), buffer.limit(), this); return nCreate(buffer, buffer.position(), buffer.limit(), preferAnimation, this); } } Loading @@ -267,7 +267,7 @@ public final class ImageDecoder implements AutoCloseable { Resources getResources() { return mResources; } @Override public ImageDecoder createImageDecoder() throws IOException { public ImageDecoder createImageDecoder(boolean preferAnimation) throws IOException { AssetFileDescriptor assetFd = null; try { if (mUri.getScheme() == ContentResolver.SCHEME_CONTENT) { Loading @@ -284,26 +284,26 @@ public final class ImageDecoder implements AutoCloseable { throw new FileNotFoundException(mUri.toString()); } return createFromStream(is, true, this); return createFromStream(is, true, preferAnimation, this); } return createFromAssetFileDescriptor(assetFd, this); return createFromAssetFileDescriptor(assetFd, preferAnimation, this); } } @NonNull private static ImageDecoder createFromFile(@NonNull File file, @NonNull Source source) throws IOException { boolean preferAnimation, @NonNull Source source) throws IOException { FileInputStream stream = new FileInputStream(file); FileDescriptor fd = stream.getFD(); try { Os.lseek(fd, 0, SEEK_CUR); } catch (ErrnoException e) { return createFromStream(stream, true, source); return createFromStream(stream, true, preferAnimation, source); } ImageDecoder decoder = null; try { decoder = nCreate(fd, source); decoder = nCreate(fd, preferAnimation, source); } finally { if (decoder == null) { IoUtils.closeQuietly(stream); Loading @@ -317,12 +317,12 @@ public final class ImageDecoder implements AutoCloseable { @NonNull private static ImageDecoder createFromStream(@NonNull InputStream is, boolean closeInputStream, Source source) throws IOException { boolean closeInputStream, boolean preferAnimation, Source source) throws IOException { // Arbitrary size matches BitmapFactory. byte[] storage = new byte[16 * 1024]; ImageDecoder decoder = null; try { decoder = nCreate(is, storage, source); decoder = nCreate(is, storage, preferAnimation, source); } finally { if (decoder == null) { if (closeInputStream) { Loading @@ -340,7 +340,7 @@ public final class ImageDecoder implements AutoCloseable { @NonNull private static ImageDecoder createFromAssetFileDescriptor(@NonNull AssetFileDescriptor assetFd, Source source) throws IOException { boolean preferAnimation, Source source) throws IOException { final FileDescriptor fd = assetFd.getFileDescriptor(); final long offset = assetFd.getStartOffset(); Loading @@ -348,9 +348,9 @@ public final class ImageDecoder implements AutoCloseable { try { try { Os.lseek(fd, offset, SEEK_SET); decoder = nCreate(fd, source); decoder = nCreate(fd, preferAnimation, source); } catch (ErrnoException e) { decoder = createFromStream(new FileInputStream(fd), true, source); decoder = createFromStream(new FileInputStream(fd), true, preferAnimation, source); } } finally { if (decoder == null) { Loading Loading @@ -388,7 +388,7 @@ public final class ImageDecoder implements AutoCloseable { public int getDensity() { return mInputDensity; } @Override public ImageDecoder createImageDecoder() throws IOException { public ImageDecoder createImageDecoder(boolean preferAnimation) throws IOException { synchronized (this) { if (mInputStream == null) { Loading @@ -396,7 +396,7 @@ public final class ImageDecoder implements AutoCloseable { } InputStream is = mInputStream; mInputStream = null; return createFromStream(is, false, this); return createFromStream(is, false, preferAnimation, this); } } } Loading Loading @@ -434,14 +434,14 @@ public final class ImageDecoder implements AutoCloseable { } @Override public ImageDecoder createImageDecoder() throws IOException { public ImageDecoder createImageDecoder(boolean preferAnimation) throws IOException { synchronized (this) { if (mAssetInputStream == null) { throw new IOException("Cannot reuse AssetInputStreamSource"); } AssetInputStream ais = mAssetInputStream; mAssetInputStream = null; return createFromAsset(ais, this); return createFromAsset(ais, preferAnimation, this); } } } Loading Loading @@ -469,7 +469,7 @@ public final class ImageDecoder implements AutoCloseable { } @Override public ImageDecoder createImageDecoder() throws IOException { public ImageDecoder createImageDecoder(boolean preferAnimation) throws IOException { TypedValue value = new TypedValue(); // This is just used in order to access the underlying Asset and // keep it alive. Loading @@ -483,7 +483,7 @@ public final class ImageDecoder implements AutoCloseable { } } return createFromAsset((AssetInputStream) is, this); return createFromAsset((AssetInputStream) is, preferAnimation, this); } } Loading @@ -491,11 +491,11 @@ public final class ImageDecoder implements AutoCloseable { * ImageDecoder will own the AssetInputStream. */ private static ImageDecoder createFromAsset(AssetInputStream ais, Source source) throws IOException { boolean preferAnimation, Source source) throws IOException { ImageDecoder decoder = null; try { long asset = ais.getNativeAsset(); decoder = nCreate(asset, source); decoder = nCreate(asset, preferAnimation, source); } finally { if (decoder == null) { IoUtils.closeQuietly(ais); Loading @@ -517,9 +517,9 @@ public final class ImageDecoder implements AutoCloseable { private final String mFileName; @Override public ImageDecoder createImageDecoder() throws IOException { public ImageDecoder createImageDecoder(boolean preferAnimation) throws IOException { InputStream is = mAssets.open(mFileName); return createFromAsset((AssetInputStream) is, this); return createFromAsset((AssetInputStream) is, preferAnimation, this); } } Loading @@ -531,8 +531,8 @@ public final class ImageDecoder implements AutoCloseable { private final File mFile; @Override public ImageDecoder createImageDecoder() throws IOException { return createFromFile(mFile, this); public ImageDecoder createImageDecoder(boolean preferAnimation) throws IOException { return createFromFile(mFile, preferAnimation, this); } } Loading @@ -544,7 +544,7 @@ public final class ImageDecoder implements AutoCloseable { private final Callable<AssetFileDescriptor> mCallable; @Override public ImageDecoder createImageDecoder() throws IOException { public ImageDecoder createImageDecoder(boolean preferAnimation) throws IOException { AssetFileDescriptor assetFd = null; try { assetFd = mCallable.call(); Loading @@ -555,7 +555,7 @@ public final class ImageDecoder implements AutoCloseable { throw new IOException(e); } } return createFromAssetFileDescriptor(assetFd, this); return createFromAssetFileDescriptor(assetFd, preferAnimation, this); } } Loading Loading @@ -1740,7 +1740,7 @@ public final class ImageDecoder implements AutoCloseable { @NonNull private static Drawable decodeDrawableImpl(@NonNull Source src, @Nullable OnHeaderDecodedListener listener) throws IOException { try (ImageDecoder decoder = src.createImageDecoder()) { try (ImageDecoder decoder = src.createImageDecoder(true /*preferAnimation*/)) { decoder.mSource = src; decoder.callHeaderDecoded(listener, src); Loading Loading @@ -1844,7 +1844,7 @@ public final class ImageDecoder implements AutoCloseable { @NonNull private static Bitmap decodeBitmapImpl(@NonNull Source src, @Nullable OnHeaderDecodedListener listener) throws IOException { try (ImageDecoder decoder = src.createImageDecoder()) { try (ImageDecoder decoder = src.createImageDecoder(false /*preferAnimation*/)) { decoder.mSource = src; decoder.callHeaderDecoded(listener, src); Loading Loading @@ -1971,15 +1971,17 @@ public final class ImageDecoder implements AutoCloseable { } } private static native ImageDecoder nCreate(long asset, Source src) throws IOException; private static native ImageDecoder nCreate(ByteBuffer buffer, int position, int limit, Source src) throws IOException; private static native ImageDecoder nCreate(long asset, boolean preferAnimation, Source src) throws IOException; private static native ImageDecoder nCreate(ByteBuffer buffer, int position, int limit, boolean preferAnimation, Source src) throws IOException; private static native ImageDecoder nCreate(byte[] data, int offset, int length, Source src) throws IOException; boolean preferAnimation, Source src) throws IOException; private static native ImageDecoder nCreate(InputStream is, byte[] storage, Source src) throws IOException; boolean preferAnimation, Source src) throws IOException; // The fd must be seekable. private static native ImageDecoder nCreate(FileDescriptor fd, Source src) throws IOException; private static native ImageDecoder nCreate(FileDescriptor fd, boolean preferAnimation, Source src) throws IOException; @NonNull private static native Bitmap nDecodeBitmap(long nativePtr, @NonNull ImageDecoder decoder, Loading