/*
 * 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 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.Rect;
import android.os.ParcelFileDescriptor;
import android.test.InstrumentationTestCase;
import android.util.Log;

import android.graphics.cts.R;


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;

public class BitmapRegionDecoderTest extends InstrumentationTestCase {
    private static final String TAG = "BitmapRegionDecoderTest";
    private ArrayList<File> mFilesCreated = new ArrayList<File>(
            NAMES_TEMP_FILES.length);

    private Resources mRes;

    // The test images, including baseline JPEGs and progressive JPEGs, a PNG,
    // a WEBP, a GIF and a BMP.
    private static 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 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"
    };

    // The width and height of the above image.
    // -1 denotes that the image format is not supported by BitmapRegionDecoder
    private static int WIDTHS[] = new int[] {
            1280, 1280, 1280, 1280, 640, 640, -1, -1};
    private static 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 int NUM_TEST_IMAGES = 6;

    private static int TILE_SIZE = 256;

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

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

    // 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 int mMseMargin = 3 * (1 * 1);

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


    @Override
    protected void setUp() throws Exception {
        super.setUp();
        mRes = getInstrumentation().getTargetContext().getResources();
    }

    @Override
    protected void tearDown() throws Exception {
        for (File file : mFilesCreated) {
            file.delete();
        }
        super.tearDown();
    }

    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();
                }
            }
        }
    }

    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);
            }
        }
    }

    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);
            }
        }
    }

    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, mMseMarginWebPConfigRgb565,
                                              wholeImage);
                    } else {
                        compareRegionByRegion(decoder, opts, mMseMargin, wholeImage);
                    }
                    wholeImage.recycle();
                }
            }
        }
    }

    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, mMseMarginWebPConfigRgb565,
                                              wholeImage);
                    } else {
                        compareRegionByRegion(decoder, opts, mMseMargin, wholeImage);
                    }
                    wholeImage.recycle();
                }
            }
        }
    }

    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, mMseMarginWebPConfigRgb565,
                                              wholeImage);
                    } else {
                        compareRegionByRegion(decoder, opts, mMseMargin, wholeImage);
                    }
                    wholeImage.recycle();
                }
            }
        }
    }

    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, mMseMarginWebPConfigRgb565,
                                              wholeImage);
                    } else {
                        compareRegionByRegion(decoder, opts, mMseMargin, 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, mMseMarginWebPConfigRgb565,
                                              wholeImage);
                    } else {
                        compareRegionByRegion(decoder, opts, mMseMargin, wholeImage);
                    }
                    wholeImage.recycle();
                }
            }
        }
    }

    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.
    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);
                        }
                    }
                }
            }
        }
    }

    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 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 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 = getInstrumentation().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 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 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;
    }
}
