/*
 * Copyright (C) 2010 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.cts;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertSame;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;

import android.content.res.Resources;
import android.graphics.Bitmap;
import android.graphics.Bitmap.Config;
import android.graphics.BitmapFactory;
import android.graphics.BitmapFactory.Options;
import android.graphics.BitmapRegionDecoder;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.ColorSpace;
import android.graphics.Rect;
import android.os.ParcelFileDescriptor;

import androidx.test.InstrumentationRegistry;
import androidx.test.filters.LargeTest;
import androidx.test.filters.SmallTest;
import androidx.test.runner.AndroidJUnit4;

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

import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileDescriptor;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;

@SmallTest
@RunWith(AndroidJUnit4.class)
public class BitmapRegionDecoderTest {
    // The test images, including baseline JPEGs and progressive JPEGs, a PNG,
    // a WEBP, a GIF and a BMP.
    private static final int[] RES_IDS = new int[] {
            R.drawable.baseline_jpeg, R.drawable.progressive_jpeg,
            R.drawable.baseline_restart_jpeg,
            R.drawable.progressive_restart_jpeg,
            R.drawable.png_test, R.drawable.webp_test,
            R.drawable.gif_test, R.drawable.bmp_test
    };
    private static final String[] NAMES_TEMP_FILES = new String[] {
            "baseline_temp.jpg", "progressive_temp.jpg", "baseline_restart_temp.jpg",
            "progressive_restart_temp.jpg", "png_temp.png", "webp_temp.webp",
            "gif_temp.gif", "bmp_temp.bmp"
    };

    // Do not change the order!
    private static final String[] ASSET_NAMES = {
            "prophoto-rgba16f.png",
            "green-p3.png",
            "red-adobergb.png",
            "green-srgb.png",
    };
    private static final ColorSpace.Named[][] ASSET_COLOR_SPACES = {
            // ARGB8888
            {
                    ColorSpace.Named.LINEAR_EXTENDED_SRGB,
                    ColorSpace.Named.DISPLAY_P3,
                    ColorSpace.Named.ADOBE_RGB,
                    ColorSpace.Named.SRGB
            },
            // RGB565
            {
                    ColorSpace.Named.SRGB,
                    ColorSpace.Named.SRGB,
                    ColorSpace.Named.SRGB,
                    ColorSpace.Named.SRGB
            }
    };

    // The width and height of the above image.
    // -1 denotes that the image format is not supported by BitmapRegionDecoder
    private static final int WIDTHS[] = new int[] {
            1280, 1280, 1280, 1280, 640, 640, -1, -1};
    private static final int HEIGHTS[] = new int[] {960, 960, 960, 960, 480, 480, -1, -1};

    // The number of test images, format of which is supported by BitmapRegionDecoder
    private static final int NUM_TEST_IMAGES = 6;

    private static final int TILE_SIZE = 256;
    private static final int SMALL_TILE_SIZE = 16;

    // Configurations for BitmapFactory.Options
    private static final Config[] COLOR_CONFIGS = new Config[] {Config.ARGB_8888,
            Config.RGB_565};
    private static final int[] SAMPLESIZES = new int[] {1, 4};

    // We allow a certain degree of discrepancy between the tile-based decoding
    // result and the regular decoding result, because the two decoders may have
    // different implementations. The allowable discrepancy is set to a mean
    // square error of 3 * (1 * 1) among the RGB values.
    private static final int MSE_MARGIN = 3 * (1 * 1);

    // MSE margin for WebP Region-Decoding for 'Config.RGB_565' is little bigger.
    private static final int MSE_MARGIN_WEB_P_CONFIG_RGB_565 = 8;

    private final int[] mExpectedColors = new int [TILE_SIZE * TILE_SIZE];
    private final int[] mActualColors = new int [TILE_SIZE * TILE_SIZE];

    private ArrayList<File> mFilesCreated = new ArrayList<>(NAMES_TEMP_FILES.length);

    private Resources mRes;

    @Before
    public void setup() {
        mRes = InstrumentationRegistry.getTargetContext().getResources();
    }

    @After
    public void teardown() {
        for (File file : mFilesCreated) {
            file.delete();
        }
    }

    @Test
    public void testNewInstanceInputStream() throws IOException {
        for (int i = 0; i < RES_IDS.length; ++i) {
            InputStream is = obtainInputStream(RES_IDS[i]);
            try {
                BitmapRegionDecoder decoder =
                        BitmapRegionDecoder.newInstance(is, false);
                assertEquals(WIDTHS[i], decoder.getWidth());
                assertEquals(HEIGHTS[i], decoder.getHeight());
            } catch (IOException e) {
                assertEquals(WIDTHS[i], -1);
                assertEquals(HEIGHTS[i], -1);
            } finally {
                if (is != null) {
                    is.close();
                }
            }
        }
    }

    @Test
    public void testNewInstanceByteArray() throws IOException {
        for (int i = 0; i < RES_IDS.length; ++i) {
            byte[] imageData = obtainByteArray(RES_IDS[i]);
            try {
                BitmapRegionDecoder decoder = BitmapRegionDecoder
                        .newInstance(imageData, 0, imageData.length, false);
                assertEquals(WIDTHS[i], decoder.getWidth());
                assertEquals(HEIGHTS[i], decoder.getHeight());
            } catch (IOException e) {
                assertEquals(WIDTHS[i], -1);
                assertEquals(HEIGHTS[i], -1);
            }
        }
    }

    @Test
    public void testNewInstanceStringAndFileDescriptor() throws IOException {
        for (int i = 0; i < RES_IDS.length; ++i) {
            String filepath = obtainPath(i);
            ParcelFileDescriptor pfd = obtainParcelDescriptor(filepath);
            FileDescriptor fd = pfd.getFileDescriptor();
            try {
                BitmapRegionDecoder decoder1 =
                        BitmapRegionDecoder.newInstance(filepath, false);
                assertEquals(WIDTHS[i], decoder1.getWidth());
                assertEquals(HEIGHTS[i], decoder1.getHeight());

                BitmapRegionDecoder decoder2 =
                        BitmapRegionDecoder.newInstance(fd, false);
                assertEquals(WIDTHS[i], decoder2.getWidth());
                assertEquals(HEIGHTS[i], decoder2.getHeight());
            } catch (IOException e) {
                assertEquals(WIDTHS[i], -1);
                assertEquals(HEIGHTS[i], -1);
            }
        }
    }

    @LargeTest
    @Test
    public void testDecodeRegionInputStream() throws IOException {
        Options opts = new BitmapFactory.Options();
        for (int i = 0; i < NUM_TEST_IMAGES; ++i) {
            for (int j = 0; j < SAMPLESIZES.length; ++j) {
                for (int k = 0; k < COLOR_CONFIGS.length; ++k) {
                    opts.inSampleSize = SAMPLESIZES[j];
                    opts.inPreferredConfig = COLOR_CONFIGS[k];

                    InputStream is1 = obtainInputStream(RES_IDS[i]);
                    BitmapRegionDecoder decoder = BitmapRegionDecoder.newInstance(is1, false);
                    InputStream is2 = obtainInputStream(RES_IDS[i]);
                    Bitmap wholeImage = BitmapFactory.decodeStream(is2, null, opts);

                    if (RES_IDS[i] == R.drawable.webp_test && COLOR_CONFIGS[k] == Config.RGB_565) {
                        compareRegionByRegion(decoder, opts, MSE_MARGIN_WEB_P_CONFIG_RGB_565,
                                              wholeImage);
                    } else {
                        compareRegionByRegion(decoder, opts, MSE_MARGIN, wholeImage);
                    }
                    wholeImage.recycle();
                }
            }
        }
    }

    @LargeTest
    @Test
    public void testDecodeRegionInputStreamInBitmap() throws IOException {
        Options opts = new BitmapFactory.Options();
        for (int i = 0; i < NUM_TEST_IMAGES; ++i) {
            for (int j = 0; j < SAMPLESIZES.length; ++j) {
                for (int k = 0; k < COLOR_CONFIGS.length; ++k) {
                    opts.inSampleSize = SAMPLESIZES[j];
                    opts.inPreferredConfig = COLOR_CONFIGS[k];
                    opts.inBitmap = null;

                    InputStream is1 = obtainInputStream(RES_IDS[i]);
                    BitmapRegionDecoder decoder = BitmapRegionDecoder.newInstance(is1, false);
                    InputStream is2 = obtainInputStream(RES_IDS[i]);
                    Bitmap wholeImage = BitmapFactory.decodeStream(is2, null, opts);

                    // setting inBitmap enables several checks within compareRegionByRegion
                    opts.inBitmap = Bitmap.createBitmap(
                            wholeImage.getWidth(), wholeImage.getHeight(), opts.inPreferredConfig);

                    if (RES_IDS[i] == R.drawable.webp_test && COLOR_CONFIGS[k] == Config.RGB_565) {
                        compareRegionByRegion(decoder, opts, MSE_MARGIN_WEB_P_CONFIG_RGB_565,
                                              wholeImage);
                    } else {
                        compareRegionByRegion(decoder, opts, MSE_MARGIN, wholeImage);
                    }
                    wholeImage.recycle();
                }
            }
        }
    }

    @LargeTest
    @Test
    public void testDecodeRegionByteArray() throws IOException {
        Options opts = new BitmapFactory.Options();
        for (int i = 0; i < NUM_TEST_IMAGES; ++i) {
            for (int j = 0; j < SAMPLESIZES.length; ++j) {
                for (int k = 0; k < COLOR_CONFIGS.length; ++k) {
                    opts.inSampleSize = SAMPLESIZES[j];
                    opts.inPreferredConfig = COLOR_CONFIGS[k];

                    byte[] imageData = obtainByteArray(RES_IDS[i]);
                    BitmapRegionDecoder decoder = BitmapRegionDecoder
                            .newInstance(imageData, 0, imageData.length, false);
                    Bitmap wholeImage = BitmapFactory.decodeByteArray(imageData,
                            0, imageData.length, opts);

                    if (RES_IDS[i] == R.drawable.webp_test && COLOR_CONFIGS[k] == Config.RGB_565) {
                        compareRegionByRegion(decoder, opts, MSE_MARGIN_WEB_P_CONFIG_RGB_565,
                                              wholeImage);
                    } else {
                        compareRegionByRegion(decoder, opts, MSE_MARGIN, wholeImage);
                    }
                    wholeImage.recycle();
                }
            }
        }
    }

    @LargeTest
    @Test
    public void testDecodeRegionStringAndFileDescriptor() throws IOException {
        Options opts = new BitmapFactory.Options();
        for (int i = 0; i < NUM_TEST_IMAGES; ++i) {
            String filepath = obtainPath(i);
            for (int j = 0; j < SAMPLESIZES.length; ++j) {
                for (int k = 0; k < COLOR_CONFIGS.length; ++k) {
                    opts.inSampleSize = SAMPLESIZES[j];
                    opts.inPreferredConfig = COLOR_CONFIGS[k];

                    BitmapRegionDecoder decoder =
                        BitmapRegionDecoder.newInstance(filepath, false);
                    Bitmap wholeImage = BitmapFactory.decodeFile(filepath, opts);
                    if (RES_IDS[i] == R.drawable.webp_test && COLOR_CONFIGS[k] == Config.RGB_565) {
                        compareRegionByRegion(decoder, opts, MSE_MARGIN_WEB_P_CONFIG_RGB_565,
                                              wholeImage);
                    } else {
                        compareRegionByRegion(decoder, opts, MSE_MARGIN, wholeImage);
                    }

                    ParcelFileDescriptor pfd1 = obtainParcelDescriptor(filepath);
                    FileDescriptor fd1 = pfd1.getFileDescriptor();
                    decoder = BitmapRegionDecoder.newInstance(fd1, false);
                    ParcelFileDescriptor pfd2 = obtainParcelDescriptor(filepath);
                    FileDescriptor fd2 = pfd2.getFileDescriptor();
                    if (RES_IDS[i] == R.drawable.webp_test && COLOR_CONFIGS[k] == Config.RGB_565) {
                        compareRegionByRegion(decoder, opts, MSE_MARGIN_WEB_P_CONFIG_RGB_565,
                                              wholeImage);
                    } else {
                        compareRegionByRegion(decoder, opts, MSE_MARGIN, wholeImage);
                    }
                    wholeImage.recycle();
                }
            }
        }
    }

    @Test
    public void testRecycle() throws IOException {
        InputStream is = obtainInputStream(RES_IDS[0]);
        BitmapRegionDecoder decoder = BitmapRegionDecoder.newInstance(is, false);
        decoder.recycle();
        assertTrue(decoder.isRecycled());
        try {
            decoder.getWidth();
            fail("Should throw an exception!");
        } catch (Exception e) {
        }

        try {
            decoder.getHeight();
            fail("Should throw an exception!");
        } catch (Exception e) {
        }

        Rect rect = new Rect(0, 0, WIDTHS[0], HEIGHTS[0]);
        BitmapFactory.Options opts = new BitmapFactory.Options();
        try {
            decoder.decodeRegion(rect, opts);
            fail("Should throw an exception!");
        } catch (Exception e) {
        }
    }

    // The documentation for BitmapRegionDecoder guarantees that, when reusing a
    // bitmap, "the provided Bitmap's width, height, and Bitmap.Config will not
    // be changed".  If the inBitmap is too small, decoded content will be
    // clipped into inBitmap.  Here we test that:
    //     (1) If inBitmap is specified, it is always used.
    //     (2) The width, height, and Config of inBitmap are never changed.
    //     (3) All of the pixels decoded into inBitmap exactly match the pixels
    //         of a decode where inBitmap is NULL.
    @LargeTest
    @Test
    public void testInBitmapReuse() throws IOException {
        Options defaultOpts = new BitmapFactory.Options();
        Options reuseOpts = new BitmapFactory.Options();
        Rect subset = new Rect(0, 0, TILE_SIZE, TILE_SIZE);

        for (int i = 0; i < NUM_TEST_IMAGES; i++) {
            InputStream is = obtainInputStream(RES_IDS[i]);
            BitmapRegionDecoder decoder = BitmapRegionDecoder.newInstance(is, false);
            for (int j = 0; j < SAMPLESIZES.length; j++) {
                int sampleSize = SAMPLESIZES[j];
                defaultOpts.inSampleSize = sampleSize;
                reuseOpts.inSampleSize = sampleSize;

                // We don't need to worry about rounding here because sampleSize
                // divides evenly into TILE_SIZE.
                assertEquals(0, TILE_SIZE % sampleSize);
                int scaledDim = TILE_SIZE / sampleSize;
                int chunkSize = scaledDim / 2;
                for (int k = 0; k < COLOR_CONFIGS.length; k++) {
                    Config config = COLOR_CONFIGS[k];
                    defaultOpts.inPreferredConfig = config;
                    reuseOpts.inPreferredConfig = config;

                    // For both the width and the height of inBitmap, we test three
                    // interesting cases:
                    // (1) inBitmap dimension is smaller than scaledDim.  The decoded
                    //     pixels that fit inside inBitmap should exactly match the
                    //     corresponding decoded pixels from the same region decode,
                    //     performed without an inBitmap.  The pixels that do not fit
                    //     inside inBitmap should be clipped.
                    // (2) inBitmap dimension matches scaledDim.  After the decode,
                    //     the pixels and dimensions of inBitmap should exactly match
                    //     those of the result bitmap of the same region decode,
                    //     performed without an inBitmap.
                    // (3) inBitmap dimension is larger than scaledDim.  After the
                    //     decode, inBitmap should contain decoded pixels for the
                    //     entire region, exactly matching the decoded pixels
                    //     produced when inBitmap is not specified.  The additional
                    //     pixels in inBitmap are left the same as before the decode.
                    for (int w = chunkSize; w <= 3 * chunkSize; w += chunkSize) {
                        for (int h = chunkSize; h <= 3 * chunkSize; h += chunkSize) {
                            // Decode reusing inBitmap.
                            reuseOpts.inBitmap = Bitmap.createBitmap(w, h, config);
                            Bitmap reuseResult = decoder.decodeRegion(subset, reuseOpts);
                            assertSame(reuseOpts.inBitmap, reuseResult);
                            assertEquals(reuseResult.getWidth(), w);
                            assertEquals(reuseResult.getHeight(), h);
                            assertEquals(reuseResult.getConfig(), config);

                            // Decode into a new bitmap.
                            Bitmap defaultResult = decoder.decodeRegion(subset, defaultOpts);
                            assertEquals(defaultResult.getWidth(), scaledDim);
                            assertEquals(defaultResult.getHeight(), scaledDim);

                            // Ensure that the decoded pixels of reuseResult and defaultResult
                            // are identical.
                            int cropWidth = Math.min(w, scaledDim);
                            int cropHeight = Math.min(h, scaledDim);
                            Rect crop = new Rect(0 ,0, cropWidth, cropHeight);
                            Bitmap reuseCropped = cropBitmap(reuseResult, crop);
                            Bitmap defaultCropped = cropBitmap(defaultResult, crop);
                            compareBitmaps(reuseCropped, defaultCropped, 0, true);
                        }
                    }
                }
            }
        }
    }

    @Test
    public void testDecodeHardwareBitmap() throws IOException {
        BitmapFactory.Options options = new BitmapFactory.Options();
        options.inPreferredConfig = Bitmap.Config.HARDWARE;
        InputStream is = obtainInputStream(RES_IDS[0]);
        BitmapRegionDecoder decoder = BitmapRegionDecoder.newInstance(is, false);
        Bitmap hardwareBitmap = decoder.decodeRegion(new Rect(0, 0, 10, 10), options);
        assertNotNull(hardwareBitmap);
        // Test that checks that correct bitmap was obtained is in uirendering/HardwareBitmapTests
        assertEquals(Config.HARDWARE, hardwareBitmap.getConfig());
    }

    @Test
    public void testOutColorType() throws IOException {
        Options opts = new BitmapFactory.Options();
        for (int i = 0; i < NUM_TEST_IMAGES; ++i) {
            for (int j = 0; j < SAMPLESIZES.length; ++j) {
                for (int k = 0; k < COLOR_CONFIGS.length; ++k) {
                    opts.inSampleSize = SAMPLESIZES[j];
                    opts.inPreferredConfig = COLOR_CONFIGS[k];

                    InputStream is1 = obtainInputStream(RES_IDS[i]);
                    BitmapRegionDecoder decoder = BitmapRegionDecoder.newInstance(is1, false);
                    Bitmap region = decoder.decodeRegion(
                            new Rect(0, 0, TILE_SIZE, TILE_SIZE), opts);
                    decoder.recycle();

                    assertSame(opts.inPreferredConfig, opts.outConfig);
                    assertSame(opts.outConfig, region.getConfig());
                    region.recycle();
                }
            }
        }
    }

    @Test
    public void testOutColorSpace() throws IOException {
        Options opts = new BitmapFactory.Options();
        for (int i = 0; i < ASSET_NAMES.length; i++) {
            for (int j = 0; j < SAMPLESIZES.length; ++j) {
                for (int k = 0; k < COLOR_CONFIGS.length; ++k) {
                    opts.inPreferredConfig = COLOR_CONFIGS[k];

                    String assetName = ASSET_NAMES[i];
                    InputStream is1 = obtainInputStream(assetName);
                    BitmapRegionDecoder decoder = BitmapRegionDecoder.newInstance(is1, false);
                    Bitmap region = decoder.decodeRegion(
                            new Rect(0, 0, SMALL_TILE_SIZE, SMALL_TILE_SIZE), opts);
                    decoder.recycle();

                    ColorSpace expected = ColorSpace.get(ASSET_COLOR_SPACES[k][i]);
                    assertSame(expected, opts.outColorSpace);
                    assertSame(expected, region.getColorSpace());
                    region.recycle();
                }
            }
        }
    }

    @Test
    public void testReusedColorSpace() throws IOException {
        Bitmap b = Bitmap.createBitmap(SMALL_TILE_SIZE, SMALL_TILE_SIZE, Config.ARGB_8888,
                false, ColorSpace.get(ColorSpace.Named.ADOBE_RGB));

        Options opts = new BitmapFactory.Options();
        opts.inBitmap = b;

        // sRGB
        BitmapRegionDecoder decoder = BitmapRegionDecoder.newInstance(
                obtainInputStream(ASSET_NAMES[3]), false);
        Bitmap region = decoder.decodeRegion(
                new Rect(0, 0, SMALL_TILE_SIZE, SMALL_TILE_SIZE), opts);
        decoder.recycle();

        assertEquals(ColorSpace.get(ColorSpace.Named.SRGB), region.getColorSpace());

        // DisplayP3
        decoder = BitmapRegionDecoder.newInstance(obtainInputStream(ASSET_NAMES[1]), false);
        region = decoder.decodeRegion(new Rect(0, 0, SMALL_TILE_SIZE, SMALL_TILE_SIZE), opts);
        decoder.recycle();

        assertEquals(ColorSpace.get(ColorSpace.Named.DISPLAY_P3), region.getColorSpace());
    }

    @Test
    public void testInColorSpace() throws IOException {
        Options opts = new BitmapFactory.Options();
        for (int i = 0; i < NUM_TEST_IMAGES; ++i) {
            for (int j = 0; j < SAMPLESIZES.length; ++j) {
                opts.inSampleSize = SAMPLESIZES[j];
                opts.inPreferredColorSpace = ColorSpace.get(ColorSpace.Named.DISPLAY_P3);

                InputStream is1 = obtainInputStream(RES_IDS[i]);
                BitmapRegionDecoder decoder = BitmapRegionDecoder.newInstance(is1, false);
                Bitmap region = decoder.decodeRegion(new Rect(0, 0, TILE_SIZE, TILE_SIZE), opts);
                decoder.recycle();

                assertSame(ColorSpace.get(ColorSpace.Named.DISPLAY_P3), opts.outColorSpace);
                assertSame(opts.outColorSpace, region.getColorSpace());
                region.recycle();
            }
        }
    }

    @Test
    public void testInColorSpaceRGBA16F() throws IOException {
        Options opts = new BitmapFactory.Options();
        opts.inPreferredColorSpace = ColorSpace.get(ColorSpace.Named.ADOBE_RGB);

        InputStream is1 = obtainInputStream(ASSET_NAMES[0]); // ProPhoto 16 bit
        BitmapRegionDecoder decoder = BitmapRegionDecoder.newInstance(is1, false);
        Bitmap region = decoder.decodeRegion(new Rect(0, 0, SMALL_TILE_SIZE, SMALL_TILE_SIZE), opts);
        decoder.recycle();

        assertSame(ColorSpace.get(ColorSpace.Named.LINEAR_EXTENDED_SRGB), region.getColorSpace());
        region.recycle();
    }

    @Test
    public void testInColorSpace565() throws IOException {
        Options opts = new BitmapFactory.Options();
        opts.inPreferredConfig = Config.RGB_565;
        opts.inPreferredColorSpace = ColorSpace.get(ColorSpace.Named.ADOBE_RGB);

        InputStream is1 = obtainInputStream(ASSET_NAMES[1]); // Display P3
        BitmapRegionDecoder decoder = BitmapRegionDecoder.newInstance(is1, false);
        Bitmap region = decoder.decodeRegion(new Rect(0, 0, SMALL_TILE_SIZE, SMALL_TILE_SIZE), opts);
        decoder.recycle();

        assertSame(ColorSpace.get(ColorSpace.Named.SRGB), region.getColorSpace());
        region.recycle();
    }

    @Test
    public void testF16WithInBitmap() throws IOException {
        // This image normally decodes to F16, but if there is an inBitmap,
        // decoding will match the Config of that Bitmap.
        InputStream is = obtainInputStream(ASSET_NAMES[0]); // F16
        BitmapRegionDecoder decoder = BitmapRegionDecoder.newInstance(is, false);

        Options opts = new BitmapFactory.Options();
        for (Bitmap.Config config : new Bitmap.Config[] {
                null, // Do not use inBitmap
                Bitmap.Config.ARGB_8888,
                Bitmap.Config.RGB_565}) {
            Bitmap.Config expected = config;
            if (expected == null) {
                expected = Bitmap.Config.RGBA_F16;
                opts.inBitmap = null;
            } else {
                opts.inBitmap = Bitmap.createBitmap(decoder.getWidth(),
                        decoder.getHeight(), config);
            }
            Bitmap result = decoder.decodeRegion(new Rect(0, 0, decoder.getWidth(),
                        decoder.getHeight()), opts);
            assertNotNull(result);
            assertEquals(expected, result.getConfig());
        }
    }

    @Test(expected = IllegalArgumentException.class)
    public void testInColorSpaceNotRgb() throws IOException {
        Options opts = new BitmapFactory.Options();
        opts.inPreferredColorSpace = ColorSpace.get(ColorSpace.Named.CIE_LAB);
        InputStream is1 = obtainInputStream(RES_IDS[0]);
        BitmapRegionDecoder decoder = BitmapRegionDecoder.newInstance(is1, false);
        Bitmap region = decoder.decodeRegion(new Rect(0, 0, TILE_SIZE, TILE_SIZE), opts);
    }

    @Test(expected = IllegalArgumentException.class)
    public void testInColorSpaceNoTransferParameters() throws IOException {
        Options opts = new BitmapFactory.Options();
        opts.inPreferredColorSpace = ColorSpace.get(ColorSpace.Named.EXTENDED_SRGB);
        InputStream is1 = obtainInputStream(RES_IDS[0]);
        BitmapRegionDecoder decoder = BitmapRegionDecoder.newInstance(is1, false);
        Bitmap region = decoder.decodeRegion(new Rect(0, 0, TILE_SIZE, TILE_SIZE), opts);
    }

    @Test(expected = IllegalArgumentException.class)
    public void testHardwareBitmapIn() throws IOException {
        Options opts = new BitmapFactory.Options();
        Bitmap bitmap = Bitmap.createBitmap(TILE_SIZE, TILE_SIZE, Config.ARGB_8888)
                .copy(Config.HARDWARE, false);
        opts.inBitmap = bitmap;
        InputStream is = obtainInputStream(RES_IDS[0]);
        BitmapRegionDecoder decoder = BitmapRegionDecoder.newInstance(is, false);
        decoder.decodeRegion(new Rect(0, 0, TILE_SIZE, TILE_SIZE), opts);
    }

    private void compareRegionByRegion(BitmapRegionDecoder decoder,
            Options opts, int mseMargin, Bitmap wholeImage) {
        int width = decoder.getWidth();
        int height = decoder.getHeight();
        Rect rect = new Rect(0, 0, width, height);
        int numCols = (width + TILE_SIZE - 1) / TILE_SIZE;
        int numRows = (height + TILE_SIZE - 1) / TILE_SIZE;
        Bitmap actual;
        Bitmap expected;

        for (int i = 0; i < numCols; ++i) {
            for (int j = 0; j < numRows; ++j) {
                Rect rect1 = new Rect(i * TILE_SIZE, j * TILE_SIZE,
                        (i + 1) * TILE_SIZE, (j + 1) * TILE_SIZE);
                rect1.intersect(rect);
                actual = decoder.decodeRegion(rect1, opts);
                int left = rect1.left / opts.inSampleSize;
                int top = rect1.top / opts.inSampleSize;
                if (opts.inBitmap != null) {
                    // bitmap reuse path - ensure reuse worked
                    assertSame(opts.inBitmap, actual);
                    int currentWidth = rect1.width() / opts.inSampleSize;
                    int currentHeight = rect1.height() / opts.inSampleSize;
                    Rect actualRect = new Rect(0, 0, currentWidth, currentHeight);
                    // crop 'actual' to the size to be tested (and avoid recycling inBitmap)
                    actual = cropBitmap(actual, actualRect);
                }
                Rect expectedRect = new Rect(left, top, left + actual.getWidth(),
                        top + actual.getHeight());
                expected = cropBitmap(wholeImage, expectedRect);
                compareBitmaps(expected, actual, mseMargin, true);
                actual.recycle();
                expected.recycle();
            }
        }
    }

    private static Bitmap cropBitmap(Bitmap wholeImage, Rect rect) {
        Bitmap cropped = Bitmap.createBitmap(rect.width(), rect.height(),
                wholeImage.getConfig());
        Canvas canvas = new Canvas(cropped);
        Rect dst = new Rect(0, 0, rect.width(), rect.height());
        canvas.drawBitmap(wholeImage, rect, dst, null);
        return cropped;
    }

    private InputStream obtainInputStream(int resId) {
        return mRes.openRawResource(resId);
    }

    private InputStream obtainInputStream(String assetName) throws IOException {
        return mRes.getAssets().open(assetName);
    }

    private byte[] obtainByteArray(int resId) throws IOException {
        InputStream is = obtainInputStream(resId);
        ByteArrayOutputStream os = new ByteArrayOutputStream();
        byte[] buffer = new byte[1024];
        int readLength;
        while ((readLength = is.read(buffer)) != -1) {
            os.write(buffer, 0, readLength);
        }
        byte[] data = os.toByteArray();
        is.close();
        os.close();
        return data;
    }

    private String obtainPath(int idx) throws IOException {
        File dir = InstrumentationRegistry.getTargetContext().getFilesDir();
        dir.mkdirs();
        File file = new File(dir, NAMES_TEMP_FILES[idx]);
        InputStream is = obtainInputStream(RES_IDS[idx]);
        FileOutputStream fOutput = new FileOutputStream(file);
        mFilesCreated.add(file);
        byte[] dataBuffer = new byte[1024];
        int readLength = 0;
        while ((readLength = is.read(dataBuffer)) != -1) {
            fOutput.write(dataBuffer, 0, readLength);
        }
        is.close();
        fOutput.close();
        return (file.getPath());
    }

    private static ParcelFileDescriptor obtainParcelDescriptor(String path)
            throws IOException {
        File file = new File(path);
        return ParcelFileDescriptor.open(file, ParcelFileDescriptor.MODE_READ_ONLY);
    }


    // Compare expected to actual to see if their diff is less then mseMargin.
    // lessThanMargin is to indicate whether we expect the diff to be
    // "less than" or "no less than".
    private void compareBitmaps(Bitmap expected, Bitmap actual,
            int mseMargin, boolean lessThanMargin) {
        assertEquals("mismatching widths", expected.getWidth(),
                actual.getWidth());
        assertEquals("mismatching heights", expected.getHeight(),
                actual.getHeight());

        double mse = 0;
        int width = expected.getWidth();
        int height = expected.getHeight();
        int[] expectedColors;
        int[] actualColors;
        if (width == TILE_SIZE && height == TILE_SIZE) {
            expectedColors = mExpectedColors;
            actualColors = mActualColors;
        } else {
            expectedColors = new int [width * height];
            actualColors = new int [width * height];
        }

        expected.getPixels(expectedColors, 0, width, 0, 0, width, height);
        actual.getPixels(actualColors, 0, width, 0, 0, width, height);

        for (int row = 0; row < height; ++row) {
            for (int col = 0; col < width; ++col) {
                int idx = row * width + col;
                mse += distance(expectedColors[idx], actualColors[idx]);
            }
        }
        mse /= width * height;

        if (lessThanMargin) {
            assertTrue("MSE too large for normal case: " + mse,
                    mse <= mseMargin);
        } else {
            assertFalse("MSE too small for abnormal case: " + mse,
                    mse <= mseMargin);
        }
    }

    private static double distance(int exp, int actual) {
        int r = Color.red(actual) - Color.red(exp);
        int g = Color.green(actual) - Color.green(exp);
        int b = Color.blue(actual) - Color.blue(exp);
        return r * r + g * g + b * b;
    }
}
