From 65327c05c4040a580edba906d8ac517a664d63fd Mon Sep 17 00:00:00 2001 From: Jernej Virag Date: Wed, 3 May 2023 14:30:45 +0200 Subject: Add ability to decode only image information with ImageDecoder This creates a @hide API which only retrieves ImageInfo object without continuing the decode of full image. It mirrors BitmapOptions.inJustDecodeBounds behaviour and allows checking dimensions and color space configuration of images without proceeding to full decode (if able). Bug: 280572656 Test: atest android.graphics.ImageDecoderTest android.graphics.cts.ImageDecoderTest Change-Id: I704ec6c41d76f655222da7ee322e3b0e4954533d --- graphics/java/android/graphics/ImageDecoder.java | 61 +++++++++++++++++++----- 1 file changed, 48 insertions(+), 13 deletions(-) (limited to 'graphics/java/android') diff --git a/graphics/java/android/graphics/ImageDecoder.java b/graphics/java/android/graphics/ImageDecoder.java index dd4b58eb83dc..b2da233fc21e 100644 --- a/graphics/java/android/graphics/ImageDecoder.java +++ b/graphics/java/android/graphics/ImageDecoder.java @@ -627,11 +627,19 @@ public final class ImageDecoder implements AutoCloseable { */ public static class ImageInfo { private final Size mSize; - private ImageDecoder mDecoder; + private final boolean mIsAnimated; + private final String mMimeType; + private final ColorSpace mColorSpace; - private ImageInfo(@NonNull ImageDecoder decoder) { - mSize = new Size(decoder.mWidth, decoder.mHeight); - mDecoder = decoder; + private ImageInfo( + @NonNull Size size, + boolean isAnimated, + @NonNull String mimeType, + @Nullable ColorSpace colorSpace) { + mSize = size; + mIsAnimated = isAnimated; + mMimeType = mimeType; + mColorSpace = colorSpace; } /** @@ -647,7 +655,7 @@ public final class ImageDecoder implements AutoCloseable { */ @NonNull public String getMimeType() { - return mDecoder.getMimeType(); + return mMimeType; } /** @@ -657,7 +665,7 @@ public final class ImageDecoder implements AutoCloseable { * return an {@link AnimatedImageDrawable}.

*/ public boolean isAnimated() { - return mDecoder.mAnimated; + return mIsAnimated; } /** @@ -669,7 +677,7 @@ public final class ImageDecoder implements AutoCloseable { */ @Nullable public ColorSpace getColorSpace() { - return mDecoder.getColorSpace(); + return mColorSpace; } }; @@ -1798,12 +1806,39 @@ public final class ImageDecoder implements AutoCloseable { private void callHeaderDecoded(@Nullable OnHeaderDecodedListener listener, @NonNull Source src) { if (listener != null) { - ImageInfo info = new ImageInfo(this); - try { - listener.onHeaderDecoded(this, info, src); - } finally { - info.mDecoder = null; - } + ImageInfo info = + new ImageInfo( + new Size(mWidth, mHeight), mAnimated, getMimeType(), getColorSpace()); + listener.onHeaderDecoded(this, info, src); + } + } + + /** + * Return {@link ImageInfo} from a {@code Source}. + * + *

Returns the same {@link ImageInfo} object that a usual decoding process would return as + * part of {@link OnHeaderDecodedListener}. + * + * @param src representing the encoded image. + * @return ImageInfo describing the image. + * @throws IOException if {@code src} is not found, is an unsupported format, or cannot be + * decoded for any reason. + * @hide + */ + @WorkerThread + @NonNull + public static ImageInfo decodeHeader(@NonNull Source src) throws IOException { + Trace.traceBegin(Trace.TRACE_TAG_RESOURCES, "ImageDecoder#decodeHeader"); + try (ImageDecoder decoder = src.createImageDecoder(true /*preferAnimation*/)) { + // We don't want to leak decoder so resolve all properties immediately. + return new ImageInfo( + new Size(decoder.mWidth, decoder.mHeight), + decoder.mAnimated, + decoder.getMimeType(), + decoder.getColorSpace()); + } finally { + // Close the ImageDecoder#decodeHeader trace. + Trace.traceEnd(Trace.TRACE_TAG_RESOURCES); } } -- cgit v1.2.3-59-g8ed1b