Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit e00b4100 authored by Treehugger Robot's avatar Treehugger Robot Committed by Automerger Merge Worker
Browse files

Merge "Add ability to decode only image information with ImageDecoder" into udc-dev am: c5557807

parents f895e3b9 c5557807
Loading
Loading
Loading
Loading
+24.2 KiB
Loading image diff...
+80 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2023 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package android.graphics;

import static com.google.common.truth.Truth.assertThat;

import android.content.Context;

import androidx.test.ext.junit.runners.AndroidJUnit4;
import androidx.test.filters.SmallTest;
import androidx.test.platform.app.InstrumentationRegistry;

import com.android.frameworks.coretests.R;

import org.junit.Test;
import org.junit.runner.RunWith;

import java.io.File;
import java.io.IOException;

@SmallTest
@RunWith(AndroidJUnit4.class)
public class ImageDecoderTest {

    private final Context mContext = InstrumentationRegistry.getInstrumentation().getContext();

    @Test
    public void onDecodeHeader_png_returnsPopulatedData() throws IOException {
        ImageDecoder.Source src =
                ImageDecoder.createSource(mContext.getResources(), R.drawable.gettysburg);
        ImageDecoder.ImageInfo info = ImageDecoder.decodeHeader(src);
        assertThat(info.getSize().getWidth()).isEqualTo(432);
        assertThat(info.getSize().getHeight()).isEqualTo(291);
        assertThat(info.getMimeType()).isEqualTo("image/png");
        assertThat(info.getColorSpace()).isNotNull();
        assertThat(info.getColorSpace().getModel()).isEqualTo(ColorSpace.Model.RGB);
        assertThat(info.getColorSpace().getId()).isEqualTo(0);
        assertThat(info.isAnimated()).isFalse();
    }

    @Test
    public void onDecodeHeader_animatedWebP_returnsPopulatedData() throws IOException {
        ImageDecoder.Source src =
                ImageDecoder.createSource(mContext.getResources(), R.drawable.animated_webp);
        ImageDecoder.ImageInfo info = ImageDecoder.decodeHeader(src);
        assertThat(info.getSize().getWidth()).isEqualTo(278);
        assertThat(info.getSize().getHeight()).isEqualTo(183);
        assertThat(info.getMimeType()).isEqualTo("image/webp");
        assertThat(info.getColorSpace()).isNotNull();
        assertThat(info.getColorSpace().getModel()).isEqualTo(ColorSpace.Model.RGB);
        assertThat(info.getColorSpace().getId()).isEqualTo(0);
        assertThat(info.isAnimated()).isTrue();
    }

    @Test(expected = IOException.class)
    public void onDecodeHeader_invalidSource_throwsException() throws IOException {
        ImageDecoder.Source src = ImageDecoder.createSource(new File("/this/file/does/not/exist"));
        ImageDecoder.decodeHeader(src);
    }

    @Test(expected = IOException.class)
    public void onDecodeHeader_invalidResource_throwsException() throws IOException {
        ImageDecoder.Source src =
                ImageDecoder.createSource(mContext.getResources(), R.drawable.box);
        ImageDecoder.decodeHeader(src);
    }
}
+48 −13
Original line number Diff line number Diff line
@@ -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}.</p>
         */
        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,13 +1806,40 @@ public final class ImageDecoder implements AutoCloseable {
    private void callHeaderDecoded(@Nullable OnHeaderDecodedListener listener,
            @NonNull Source src) {
        if (listener != null) {
            ImageInfo info = new ImageInfo(this);
            try {
            ImageInfo info =
                    new ImageInfo(
                            new Size(mWidth, mHeight), mAnimated, getMimeType(), getColorSpace());
            listener.onHeaderDecoded(this, info, src);
            } finally {
                info.mDecoder = null;
        }
    }

    /**
     * Return {@link ImageInfo} from a {@code Source}.
     *
     * <p>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);
        }
    }

    /**