diff options
3 files changed, 42 insertions, 30 deletions
diff --git a/core/jni/android/graphics/AnimatedImageDrawable.cpp b/core/jni/android/graphics/AnimatedImageDrawable.cpp index 8dd5f5f0e561..12900261bddd 100644 --- a/core/jni/android/graphics/AnimatedImageDrawable.cpp +++ b/core/jni/android/graphics/AnimatedImageDrawable.cpp @@ -35,14 +35,14 @@ static jmethodID gAnimatedImageDrawable_onAnimationEndMethodID; // Note: jpostProcess holds a handle to the ImageDecoder. static jlong AnimatedImageDrawable_nCreate(JNIEnv* env, jobject /*clazz*/, jlong nativeImageDecoder, jobject jpostProcess, - jint width, jint height, jobject jsubset) { + jint width, jint height, jlong colorSpaceHandle, + jboolean extended, jobject jsubset) { if (nativeImageDecoder == 0) { doThrowIOE(env, "Cannot create AnimatedImageDrawable from null!"); return 0; } auto* imageDecoder = reinterpret_cast<ImageDecoder*>(nativeImageDecoder); - const SkISize scaledSize = SkISize::Make(width, height); SkIRect subset; if (jsubset) { GraphicsJNI::jrect_to_irect(env, jsubset, &subset); @@ -50,15 +50,8 @@ static jlong AnimatedImageDrawable_nCreate(JNIEnv* env, jobject /*clazz*/, subset = SkIRect::MakeWH(width, height); } - auto info = imageDecoder->mCodec->getInfo(); bool hasRestoreFrame = false; - if (imageDecoder->mCodec->getEncodedFormat() == SkEncodedImageFormat::kWEBP) { - if (width < info.width() && height < info.height()) { - // WebP will scale its SkBitmap to the scaled size. - // FIXME: b/73529447 GIF should do the same. - info = info.makeWH(width, height); - } - } else { + if (imageDecoder->mCodec->getEncodedFormat() != SkEncodedImageFormat::kWEBP) { const int frameCount = imageDecoder->mCodec->codec()->getFrameCount(); for (int i = 0; i < frameCount; ++i) { SkCodec::FrameInfo frameInfo; @@ -73,6 +66,12 @@ static jlong AnimatedImageDrawable_nCreate(JNIEnv* env, jobject /*clazz*/, } } + auto info = imageDecoder->mCodec->getInfo().makeWH(width, height) + .makeColorSpace(GraphicsJNI::getNativeColorSpace(colorSpaceHandle)); + if (extended) { + info = info.makeColorType(kRGBA_F16_SkColorType); + } + size_t bytesUsed = info.computeMinByteSize(); // SkAnimatedImage has one SkBitmap for decoding, plus an extra one if there is a // kRestorePrevious frame. AnimatedImageDrawable has two SkPictures storing the current @@ -96,7 +95,7 @@ static jlong AnimatedImageDrawable_nCreate(JNIEnv* env, jobject /*clazz*/, sk_sp<SkAnimatedImage> animatedImg = SkAnimatedImage::Make(std::move(imageDecoder->mCodec), - scaledSize, subset, + info, subset, std::move(picture)); if (!animatedImg) { doThrowIOE(env, "Failed to create drawable"); @@ -246,7 +245,7 @@ static void AnimatedImageDrawable_nSetMirrored(JNIEnv* env, jobject /*clazz*/, j } static const JNINativeMethod gAnimatedImageDrawableMethods[] = { - { "nCreate", "(JLandroid/graphics/ImageDecoder;IILandroid/graphics/Rect;)J", (void*) AnimatedImageDrawable_nCreate }, + { "nCreate", "(JLandroid/graphics/ImageDecoder;IIJZLandroid/graphics/Rect;)J",(void*) AnimatedImageDrawable_nCreate }, { "nGetNativeFinalizer", "()J", (void*) AnimatedImageDrawable_nGetNativeFinalizer }, { "nDraw", "(JJ)J", (void*) AnimatedImageDrawable_nDraw }, { "nSetAlpha", "(JI)V", (void*) AnimatedImageDrawable_nSetAlpha }, diff --git a/graphics/java/android/graphics/ImageDecoder.java b/graphics/java/android/graphics/ImageDecoder.java index 2cf802bb9631..2d5babc5ebdb 100644 --- a/graphics/java/android/graphics/ImageDecoder.java +++ b/graphics/java/android/graphics/ImageDecoder.java @@ -1642,14 +1642,16 @@ public final class ImageDecoder implements AutoCloseable { mTempStorage = null; } - private void checkState() { + private void checkState(boolean animated) { if (mNativePtr == 0) { throw new IllegalStateException("Cannot use closed ImageDecoder!"); } checkSubset(mDesiredWidth, mDesiredHeight, mCropRect); - if (mAllocator == ALLOCATOR_HARDWARE) { + // animated ignores the allocator, so no need to check for incompatible + // fields. + if (!animated && mAllocator == ALLOCATOR_HARDWARE) { if (mMutable) { throw new IllegalStateException("Cannot make mutable HARDWARE Bitmap!"); } @@ -1673,21 +1675,30 @@ public final class ImageDecoder implements AutoCloseable { } } + private boolean checkForExtended() { + if (mDesiredColorSpace == null) { + return false; + } + return mDesiredColorSpace == ColorSpace.get(ColorSpace.Named.EXTENDED_SRGB) + || mDesiredColorSpace == ColorSpace.get(ColorSpace.Named.LINEAR_EXTENDED_SRGB); + } + + private long getColorSpacePtr() { + if (mDesiredColorSpace == null) { + return 0; + } + return mDesiredColorSpace.getNativeInstance(); + } + @WorkerThread @NonNull private Bitmap decodeBitmapInternal() throws IOException { - checkState(); - long colorSpacePtr = 0; - boolean extended = false; - if (mDesiredColorSpace != null) { - colorSpacePtr = mDesiredColorSpace.getNativeInstance(); - extended = mDesiredColorSpace == ColorSpace.get(ColorSpace.Named.EXTENDED_SRGB) - || mDesiredColorSpace == ColorSpace.get(ColorSpace.Named.LINEAR_EXTENDED_SRGB); - } + checkState(false); return nDecodeBitmap(mNativePtr, this, mPostProcessor != null, mDesiredWidth, mDesiredHeight, mCropRect, mMutable, mAllocator, mUnpremultipliedRequired, - mConserveMemory, mDecodeAsAlphaMask, colorSpacePtr, extended); + mConserveMemory, mDecodeAsAlphaMask, getColorSpacePtr(), + checkForExtended()); } private void callHeaderDecoded(@Nullable OnHeaderDecodedListener listener, @@ -1753,9 +1764,11 @@ public final class ImageDecoder implements AutoCloseable { // mPostProcessor exists. ImageDecoder postProcessPtr = decoder.mPostProcessor == null ? null : decoder; + decoder.checkState(true); Drawable d = new AnimatedImageDrawable(decoder.mNativePtr, postProcessPtr, decoder.mDesiredWidth, - decoder.mDesiredHeight, srcDensity, + decoder.mDesiredHeight, decoder.getColorSpacePtr(), + decoder.checkForExtended(), srcDensity, src.computeDstDensity(), decoder.mCropRect, decoder.mInputStream, decoder.mAssetFd); // d has taken ownership of these objects. diff --git a/graphics/java/android/graphics/drawable/AnimatedImageDrawable.java b/graphics/java/android/graphics/drawable/AnimatedImageDrawable.java index 3aaec3123d7d..bb6bf243bc76 100644 --- a/graphics/java/android/graphics/drawable/AnimatedImageDrawable.java +++ b/graphics/java/android/graphics/drawable/AnimatedImageDrawable.java @@ -291,8 +291,8 @@ public class AnimatedImageDrawable extends Drawable implements Animatable2 { */ public AnimatedImageDrawable(long nativeImageDecoder, @Nullable ImageDecoder decoder, int width, int height, - int srcDensity, int dstDensity, Rect cropRect, - InputStream inputStream, AssetFileDescriptor afd) + long colorSpaceHandle, boolean extended, int srcDensity, int dstDensity, + Rect cropRect, InputStream inputStream, AssetFileDescriptor afd) throws IOException { width = Bitmap.scaleFromDensity(width, srcDensity, dstDensity); height = Bitmap.scaleFromDensity(height, srcDensity, dstDensity); @@ -309,8 +309,8 @@ public class AnimatedImageDrawable extends Drawable implements Animatable2 { mIntrinsicHeight = cropRect.height(); } - mState = new State(nCreate(nativeImageDecoder, decoder, width, height, cropRect), - inputStream, afd); + mState = new State(nCreate(nativeImageDecoder, decoder, width, height, colorSpaceHandle, + extended, cropRect), inputStream, afd); final long nativeSize = nNativeByteSize(mState.mNativePtr); NativeAllocationRegistry registry = new NativeAllocationRegistry( @@ -574,8 +574,8 @@ public class AnimatedImageDrawable extends Drawable implements Animatable2 { private static native long nCreate(long nativeImageDecoder, - @Nullable ImageDecoder decoder, int width, int height, Rect cropRect) - throws IOException; + @Nullable ImageDecoder decoder, int width, int height, long colorSpaceHandle, + boolean extended, Rect cropRect) throws IOException; @FastNative private static native long nGetNativeFinalizer(); private static native long nDraw(long nativePtr, long canvasNativePtr); |