12bbc2c945bb0ecf18fd6473af74ad1a2f5e727a7scroggo@google.com/*
22bbc2c945bb0ecf18fd6473af74ad1a2f5e727a7scroggo@google.com * Copyright 2013 Google Inc.
32bbc2c945bb0ecf18fd6473af74ad1a2f5e727a7scroggo@google.com *
42bbc2c945bb0ecf18fd6473af74ad1a2f5e727a7scroggo@google.com * Use of this source code is governed by a BSD-style license that can be
52bbc2c945bb0ecf18fd6473af74ad1a2f5e727a7scroggo@google.com * found in the LICENSE file.
62bbc2c945bb0ecf18fd6473af74ad1a2f5e727a7scroggo@google.com */
72bbc2c945bb0ecf18fd6473af74ad1a2f5e727a7scroggo@google.com
8bcbc1788b478b1e54079318ad073e8490aa66faetfarina#include "Resources.h"
92bbc2c945bb0ecf18fd6473af74ad1a2f5e727a7scroggo@google.com#include "SkBitmap.h"
10826d63af970dca7c47f4cded1cfcb918bc5785a9scroggo@google.com#include "SkCanvas.h"
11826d63af970dca7c47f4cded1cfcb918bc5785a9scroggo@google.com#include "SkColor.h"
122bbc2c945bb0ecf18fd6473af74ad1a2f5e727a7scroggo@google.com#include "SkColorPriv.h"
13826d63af970dca7c47f4cded1cfcb918bc5785a9scroggo@google.com#include "SkData.h"
14dedd44adea3b87faea4bcd833c6a508a6db8fcfdhalcanary@google.com#include "SkDecodingImageGenerator.h"
153d50ea1b87132833d7eab38964f40315ba553205halcanary@google.com#include "SkDiscardableMemoryPool.h"
162bbc2c945bb0ecf18fd6473af74ad1a2f5e727a7scroggo@google.com#include "SkForceLinking.h"
17826d63af970dca7c47f4cded1cfcb918bc5785a9scroggo@google.com#include "SkGradientShader.h"
182bbc2c945bb0ecf18fd6473af74ad1a2f5e727a7scroggo@google.com#include "SkImageDecoder.h"
19826d63af970dca7c47f4cded1cfcb918bc5785a9scroggo@google.com#include "SkImageEncoder.h"
202d970b5128f7270cd01a93e4ce68d0c3ea67ac71commit-bot@chromium.org#include "SkImageGeneratorPriv.h"
213d50ea1b87132833d7eab38964f40315ba553205halcanary@google.com#include "SkImagePriv.h"
222bbc2c945bb0ecf18fd6473af74ad1a2f5e727a7scroggo@google.com#include "SkOSFile.h"
23826d63af970dca7c47f4cded1cfcb918bc5785a9scroggo@google.com#include "SkPoint.h"
24826d63af970dca7c47f4cded1cfcb918bc5785a9scroggo@google.com#include "SkShader.h"
252bbc2c945bb0ecf18fd6473af74ad1a2f5e727a7scroggo@google.com#include "SkStream.h"
262bbc2c945bb0ecf18fd6473af74ad1a2f5e727a7scroggo@google.com#include "SkString.h"
278f6884aab8aecd7657cf3f9cdbc682f0deca29c5tfarina@chromium.org#include "Test.h"
282bbc2c945bb0ecf18fd6473af74ad1a2f5e727a7scroggo@google.com
292bbc2c945bb0ecf18fd6473af74ad1a2f5e727a7scroggo@google.com__SK_FORCE_IMAGE_DECODER_LINKING;
302bbc2c945bb0ecf18fd6473af74ad1a2f5e727a7scroggo@google.com
312bbc2c945bb0ecf18fd6473af74ad1a2f5e727a7scroggo@google.com/**
322bbc2c945bb0ecf18fd6473af74ad1a2f5e727a7scroggo@google.com *  Interprets c as an unpremultiplied color, and returns the
332bbc2c945bb0ecf18fd6473af74ad1a2f5e727a7scroggo@google.com *  premultiplied equivalent.
342bbc2c945bb0ecf18fd6473af74ad1a2f5e727a7scroggo@google.com */
352bbc2c945bb0ecf18fd6473af74ad1a2f5e727a7scroggo@google.comstatic SkPMColor premultiply_unpmcolor(SkPMColor c) {
362bbc2c945bb0ecf18fd6473af74ad1a2f5e727a7scroggo@google.com    U8CPU a = SkGetPackedA32(c);
372bbc2c945bb0ecf18fd6473af74ad1a2f5e727a7scroggo@google.com    U8CPU r = SkGetPackedR32(c);
382bbc2c945bb0ecf18fd6473af74ad1a2f5e727a7scroggo@google.com    U8CPU g = SkGetPackedG32(c);
392bbc2c945bb0ecf18fd6473af74ad1a2f5e727a7scroggo@google.com    U8CPU b = SkGetPackedB32(c);
402bbc2c945bb0ecf18fd6473af74ad1a2f5e727a7scroggo@google.com    return SkPreMultiplyARGB(a, r, g, b);
412bbc2c945bb0ecf18fd6473af74ad1a2f5e727a7scroggo@google.com}
422bbc2c945bb0ecf18fd6473af74ad1a2f5e727a7scroggo@google.com
432bbc2c945bb0ecf18fd6473af74ad1a2f5e727a7scroggo@google.com/**
442bbc2c945bb0ecf18fd6473af74ad1a2f5e727a7scroggo@google.com *  Return true if this stream format should be skipped, due
452bbc2c945bb0ecf18fd6473af74ad1a2f5e727a7scroggo@google.com *  to do being an opaque format or not a valid format.
462bbc2c945bb0ecf18fd6473af74ad1a2f5e727a7scroggo@google.com */
472bbc2c945bb0ecf18fd6473af74ad1a2f5e727a7scroggo@google.comstatic bool skip_image_format(SkImageDecoder::Format format) {
482bbc2c945bb0ecf18fd6473af74ad1a2f5e727a7scroggo@google.com    switch (format) {
492bbc2c945bb0ecf18fd6473af74ad1a2f5e727a7scroggo@google.com        case SkImageDecoder::kPNG_Format:
502bbc2c945bb0ecf18fd6473af74ad1a2f5e727a7scroggo@google.com        case SkImageDecoder::kWEBP_Format:
512bbc2c945bb0ecf18fd6473af74ad1a2f5e727a7scroggo@google.com            return false;
522bbc2c945bb0ecf18fd6473af74ad1a2f5e727a7scroggo@google.com        // Skip unknown since it will not be decoded anyway.
532bbc2c945bb0ecf18fd6473af74ad1a2f5e727a7scroggo@google.com        case SkImageDecoder::kUnknown_Format:
542bbc2c945bb0ecf18fd6473af74ad1a2f5e727a7scroggo@google.com        // Technically ICO and BMP supports alpha channels, but our image
552bbc2c945bb0ecf18fd6473af74ad1a2f5e727a7scroggo@google.com        // decoders do not, so skip them as well.
562bbc2c945bb0ecf18fd6473af74ad1a2f5e727a7scroggo@google.com        case SkImageDecoder::kICO_Format:
572bbc2c945bb0ecf18fd6473af74ad1a2f5e727a7scroggo@google.com        case SkImageDecoder::kBMP_Format:
5899ffe24200d8940ceba20f6fbf8c460f994d3cd1krajcevski        // KTX is a Texture format so it's not particularly clear how to
5999ffe24200d8940ceba20f6fbf8c460f994d3cd1krajcevski        // decode the alpha from it.
6099ffe24200d8940ceba20f6fbf8c460f994d3cd1krajcevski        case SkImageDecoder::kKTX_Format:
612bbc2c945bb0ecf18fd6473af74ad1a2f5e727a7scroggo@google.com        // The rest of these are opaque.
628cf81e0f4fa2a8054ac4cea1e7490028809cb893robertphillips@google.com        case SkImageDecoder::kPKM_Format:
632bbc2c945bb0ecf18fd6473af74ad1a2f5e727a7scroggo@google.com        case SkImageDecoder::kWBMP_Format:
642bbc2c945bb0ecf18fd6473af74ad1a2f5e727a7scroggo@google.com        case SkImageDecoder::kGIF_Format:
652bbc2c945bb0ecf18fd6473af74ad1a2f5e727a7scroggo@google.com        case SkImageDecoder::kJPEG_Format:
662bbc2c945bb0ecf18fd6473af74ad1a2f5e727a7scroggo@google.com            return true;
672bbc2c945bb0ecf18fd6473af74ad1a2f5e727a7scroggo@google.com    }
682bbc2c945bb0ecf18fd6473af74ad1a2f5e727a7scroggo@google.com    SkASSERT(false);
692bbc2c945bb0ecf18fd6473af74ad1a2f5e727a7scroggo@google.com    return true;
702bbc2c945bb0ecf18fd6473af74ad1a2f5e727a7scroggo@google.com}
712bbc2c945bb0ecf18fd6473af74ad1a2f5e727a7scroggo@google.com
722bbc2c945bb0ecf18fd6473af74ad1a2f5e727a7scroggo@google.com/**
732bbc2c945bb0ecf18fd6473af74ad1a2f5e727a7scroggo@google.com *  Test decoding an image in premultiplied mode and unpremultiplied mode and compare
742bbc2c945bb0ecf18fd6473af74ad1a2f5e727a7scroggo@google.com *  them.
752bbc2c945bb0ecf18fd6473af74ad1a2f5e727a7scroggo@google.com */
762bbc2c945bb0ecf18fd6473af74ad1a2f5e727a7scroggo@google.comstatic void compare_unpremul(skiatest::Reporter* reporter, const SkString& filename) {
772bbc2c945bb0ecf18fd6473af74ad1a2f5e727a7scroggo@google.com    // Decode a resource:
782bbc2c945bb0ecf18fd6473af74ad1a2f5e727a7scroggo@google.com    SkBitmap bm8888;
792bbc2c945bb0ecf18fd6473af74ad1a2f5e727a7scroggo@google.com    SkBitmap bm8888Unpremul;
802bbc2c945bb0ecf18fd6473af74ad1a2f5e727a7scroggo@google.com
812bbc2c945bb0ecf18fd6473af74ad1a2f5e727a7scroggo@google.com    SkFILEStream stream(filename.c_str());
822bbc2c945bb0ecf18fd6473af74ad1a2f5e727a7scroggo@google.com
832bbc2c945bb0ecf18fd6473af74ad1a2f5e727a7scroggo@google.com    SkImageDecoder::Format format = SkImageDecoder::GetStreamFormat(&stream);
842bbc2c945bb0ecf18fd6473af74ad1a2f5e727a7scroggo@google.com    if (skip_image_format(format)) {
852bbc2c945bb0ecf18fd6473af74ad1a2f5e727a7scroggo@google.com        return;
862bbc2c945bb0ecf18fd6473af74ad1a2f5e727a7scroggo@google.com    }
872bbc2c945bb0ecf18fd6473af74ad1a2f5e727a7scroggo@google.com
882bbc2c945bb0ecf18fd6473af74ad1a2f5e727a7scroggo@google.com    SkAutoTDelete<SkImageDecoder> decoder(SkImageDecoder::Factory(&stream));
892bbc2c945bb0ecf18fd6473af74ad1a2f5e727a7scroggo@google.com    if (NULL == decoder.get()) {
902bbc2c945bb0ecf18fd6473af74ad1a2f5e727a7scroggo@google.com        SkDebugf("couldn't decode %s\n", filename.c_str());
912bbc2c945bb0ecf18fd6473af74ad1a2f5e727a7scroggo@google.com        return;
922bbc2c945bb0ecf18fd6473af74ad1a2f5e727a7scroggo@google.com    }
932bbc2c945bb0ecf18fd6473af74ad1a2f5e727a7scroggo@google.com
94bfefc7c95fc0e8ebd5000c68f6d16e1a3ea0e71ereed    bool success = decoder->decode(&stream, &bm8888, kN32_SkColorType,
952bbc2c945bb0ecf18fd6473af74ad1a2f5e727a7scroggo@google.com                                   SkImageDecoder::kDecodePixels_Mode);
962bbc2c945bb0ecf18fd6473af74ad1a2f5e727a7scroggo@google.com    if (!success) {
972bbc2c945bb0ecf18fd6473af74ad1a2f5e727a7scroggo@google.com        return;
982bbc2c945bb0ecf18fd6473af74ad1a2f5e727a7scroggo@google.com    }
992bbc2c945bb0ecf18fd6473af74ad1a2f5e727a7scroggo@google.com
1002bbc2c945bb0ecf18fd6473af74ad1a2f5e727a7scroggo@google.com    success = stream.rewind();
1012bbc2c945bb0ecf18fd6473af74ad1a2f5e727a7scroggo@google.com    REPORTER_ASSERT(reporter, success);
1022bbc2c945bb0ecf18fd6473af74ad1a2f5e727a7scroggo@google.com    if (!success) {
1032bbc2c945bb0ecf18fd6473af74ad1a2f5e727a7scroggo@google.com        return;
1042bbc2c945bb0ecf18fd6473af74ad1a2f5e727a7scroggo@google.com    }
1052bbc2c945bb0ecf18fd6473af74ad1a2f5e727a7scroggo@google.com
1062bbc2c945bb0ecf18fd6473af74ad1a2f5e727a7scroggo@google.com    decoder->setRequireUnpremultipliedColors(true);
107bfefc7c95fc0e8ebd5000c68f6d16e1a3ea0e71ereed    success = decoder->decode(&stream, &bm8888Unpremul, kN32_SkColorType,
1082bbc2c945bb0ecf18fd6473af74ad1a2f5e727a7scroggo@google.com                              SkImageDecoder::kDecodePixels_Mode);
1092bbc2c945bb0ecf18fd6473af74ad1a2f5e727a7scroggo@google.com    if (!success) {
1102bbc2c945bb0ecf18fd6473af74ad1a2f5e727a7scroggo@google.com        return;
1112bbc2c945bb0ecf18fd6473af74ad1a2f5e727a7scroggo@google.com    }
1122bbc2c945bb0ecf18fd6473af74ad1a2f5e727a7scroggo@google.com
1132bbc2c945bb0ecf18fd6473af74ad1a2f5e727a7scroggo@google.com    bool dimensionsMatch = bm8888.width() == bm8888Unpremul.width()
1142bbc2c945bb0ecf18fd6473af74ad1a2f5e727a7scroggo@google.com                           && bm8888.height() == bm8888Unpremul.height();
1152bbc2c945bb0ecf18fd6473af74ad1a2f5e727a7scroggo@google.com    REPORTER_ASSERT(reporter, dimensionsMatch);
1162bbc2c945bb0ecf18fd6473af74ad1a2f5e727a7scroggo@google.com    if (!dimensionsMatch) {
1172bbc2c945bb0ecf18fd6473af74ad1a2f5e727a7scroggo@google.com        return;
1182bbc2c945bb0ecf18fd6473af74ad1a2f5e727a7scroggo@google.com    }
1192bbc2c945bb0ecf18fd6473af74ad1a2f5e727a7scroggo@google.com
1202bbc2c945bb0ecf18fd6473af74ad1a2f5e727a7scroggo@google.com    // Only do the comparison if the two bitmaps are both 8888.
121bfefc7c95fc0e8ebd5000c68f6d16e1a3ea0e71ereed    if (bm8888.colorType() != kN32_SkColorType || bm8888Unpremul.colorType() != kN32_SkColorType) {
1222bbc2c945bb0ecf18fd6473af74ad1a2f5e727a7scroggo@google.com        return;
1232bbc2c945bb0ecf18fd6473af74ad1a2f5e727a7scroggo@google.com    }
1242bbc2c945bb0ecf18fd6473af74ad1a2f5e727a7scroggo@google.com
1252bbc2c945bb0ecf18fd6473af74ad1a2f5e727a7scroggo@google.com    // Now compare the two bitmaps.
1262bbc2c945bb0ecf18fd6473af74ad1a2f5e727a7scroggo@google.com    for (int i = 0; i < bm8888.width(); ++i) {
1272bbc2c945bb0ecf18fd6473af74ad1a2f5e727a7scroggo@google.com        for (int j = 0; j < bm8888.height(); ++j) {
1282bbc2c945bb0ecf18fd6473af74ad1a2f5e727a7scroggo@google.com            // "c0" is the color of the premultiplied bitmap at (i, j).
1292bbc2c945bb0ecf18fd6473af74ad1a2f5e727a7scroggo@google.com            const SkPMColor c0 = *bm8888.getAddr32(i, j);
1302bbc2c945bb0ecf18fd6473af74ad1a2f5e727a7scroggo@google.com            // "c1" is the result of premultiplying the color of the unpremultiplied
1312bbc2c945bb0ecf18fd6473af74ad1a2f5e727a7scroggo@google.com            // bitmap at (i, j).
1322bbc2c945bb0ecf18fd6473af74ad1a2f5e727a7scroggo@google.com            const SkPMColor c1 = premultiply_unpmcolor(*bm8888Unpremul.getAddr32(i, j));
1332bbc2c945bb0ecf18fd6473af74ad1a2f5e727a7scroggo@google.com            // Compute the difference for each component.
1342bbc2c945bb0ecf18fd6473af74ad1a2f5e727a7scroggo@google.com            int da = SkAbs32(SkGetPackedA32(c0) - SkGetPackedA32(c1));
1352bbc2c945bb0ecf18fd6473af74ad1a2f5e727a7scroggo@google.com            int dr = SkAbs32(SkGetPackedR32(c0) - SkGetPackedR32(c1));
1362bbc2c945bb0ecf18fd6473af74ad1a2f5e727a7scroggo@google.com            int dg = SkAbs32(SkGetPackedG32(c0) - SkGetPackedG32(c1));
1372bbc2c945bb0ecf18fd6473af74ad1a2f5e727a7scroggo@google.com            int db = SkAbs32(SkGetPackedB32(c0) - SkGetPackedB32(c1));
1382bbc2c945bb0ecf18fd6473af74ad1a2f5e727a7scroggo@google.com
1392bbc2c945bb0ecf18fd6473af74ad1a2f5e727a7scroggo@google.com            // Alpha component must be exactly the same.
1402bbc2c945bb0ecf18fd6473af74ad1a2f5e727a7scroggo@google.com            REPORTER_ASSERT(reporter, 0 == da);
141daaea2d51f145fd43221a2b923721b218c8ff777scroggo@google.com
142daaea2d51f145fd43221a2b923721b218c8ff777scroggo@google.com            // Color components may not match exactly due to rounding error.
143daaea2d51f145fd43221a2b923721b218c8ff777scroggo@google.com            REPORTER_ASSERT(reporter, dr <= 1);
144daaea2d51f145fd43221a2b923721b218c8ff777scroggo@google.com            REPORTER_ASSERT(reporter, dg <= 1);
145daaea2d51f145fd43221a2b923721b218c8ff777scroggo@google.com            REPORTER_ASSERT(reporter, db <= 1);
1462bbc2c945bb0ecf18fd6473af74ad1a2f5e727a7scroggo@google.com        }
1472bbc2c945bb0ecf18fd6473af74ad1a2f5e727a7scroggo@google.com    }
1482bbc2c945bb0ecf18fd6473af74ad1a2f5e727a7scroggo@google.com}
1492bbc2c945bb0ecf18fd6473af74ad1a2f5e727a7scroggo@google.com
150f698c8262df397a7015662e91b1a727e1134c418scroggo@google.comstatic void test_unpremul(skiatest::Reporter* reporter) {
1512bbc2c945bb0ecf18fd6473af74ad1a2f5e727a7scroggo@google.com    // This test cannot run if there is no resource path.
152bcbc1788b478b1e54079318ad073e8490aa66faetfarina    SkString resourcePath = GetResourcePath();
1532bbc2c945bb0ecf18fd6473af74ad1a2f5e727a7scroggo@google.com    if (resourcePath.isEmpty()) {
1543c996f8a15e5d8fada9550d978e9b5344b81d276bungeman@google.com        SkDebugf("Could not run unpremul test because resourcePath not specified.");
1552bbc2c945bb0ecf18fd6473af74ad1a2f5e727a7scroggo@google.com        return;
1562bbc2c945bb0ecf18fd6473af74ad1a2f5e727a7scroggo@google.com    }
1572bbc2c945bb0ecf18fd6473af74ad1a2f5e727a7scroggo@google.com    SkOSFile::Iter iter(resourcePath.c_str());
1582bbc2c945bb0ecf18fd6473af74ad1a2f5e727a7scroggo@google.com    SkString basename;
1592bbc2c945bb0ecf18fd6473af74ad1a2f5e727a7scroggo@google.com    if (iter.next(&basename)) {
1602bbc2c945bb0ecf18fd6473af74ad1a2f5e727a7scroggo@google.com        do {
1612bbc2c945bb0ecf18fd6473af74ad1a2f5e727a7scroggo@google.com            SkString filename = SkOSPath::SkPathJoin(resourcePath.c_str(), basename.c_str());
1623d50ea1b87132833d7eab38964f40315ba553205halcanary@google.com            // SkDebugf("about to decode \"%s\"\n", filename.c_str());
1632bbc2c945bb0ecf18fd6473af74ad1a2f5e727a7scroggo@google.com            compare_unpremul(reporter, filename);
1642bbc2c945bb0ecf18fd6473af74ad1a2f5e727a7scroggo@google.com        } while (iter.next(&basename));
1652bbc2c945bb0ecf18fd6473af74ad1a2f5e727a7scroggo@google.com    } else {
1662bbc2c945bb0ecf18fd6473af74ad1a2f5e727a7scroggo@google.com        SkDebugf("Failed to find any files :(\n");
1672bbc2c945bb0ecf18fd6473af74ad1a2f5e727a7scroggo@google.com    }
1682bbc2c945bb0ecf18fd6473af74ad1a2f5e727a7scroggo@google.com}
1692bbc2c945bb0ecf18fd6473af74ad1a2f5e727a7scroggo@google.com
170915b972a818d0279eb926af38ba6952daa17a63ecommit-bot@chromium.org#if defined(SK_BUILD_FOR_ANDROID) || defined(SK_BUILD_FOR_UNIX)
171915b972a818d0279eb926af38ba6952daa17a63ecommit-bot@chromium.org// Test that the alpha type is what we expect.
172915b972a818d0279eb926af38ba6952daa17a63ecommit-bot@chromium.orgstatic void test_alphaType(skiatest::Reporter* reporter, const SkString& filename,
173915b972a818d0279eb926af38ba6952daa17a63ecommit-bot@chromium.org                           bool requireUnpremul) {
174915b972a818d0279eb926af38ba6952daa17a63ecommit-bot@chromium.org    SkBitmap bm;
175915b972a818d0279eb926af38ba6952daa17a63ecommit-bot@chromium.org    SkFILEStream stream(filename.c_str());
176915b972a818d0279eb926af38ba6952daa17a63ecommit-bot@chromium.org
177915b972a818d0279eb926af38ba6952daa17a63ecommit-bot@chromium.org    SkAutoTDelete<SkImageDecoder> decoder(SkImageDecoder::Factory(&stream));
178915b972a818d0279eb926af38ba6952daa17a63ecommit-bot@chromium.org    if (NULL == decoder.get()) {
179915b972a818d0279eb926af38ba6952daa17a63ecommit-bot@chromium.org        return;
180915b972a818d0279eb926af38ba6952daa17a63ecommit-bot@chromium.org    }
181915b972a818d0279eb926af38ba6952daa17a63ecommit-bot@chromium.org
182915b972a818d0279eb926af38ba6952daa17a63ecommit-bot@chromium.org    decoder->setRequireUnpremultipliedColors(requireUnpremul);
183915b972a818d0279eb926af38ba6952daa17a63ecommit-bot@chromium.org
184915b972a818d0279eb926af38ba6952daa17a63ecommit-bot@chromium.org    // Decode just the bounds. This should always succeed.
185bfefc7c95fc0e8ebd5000c68f6d16e1a3ea0e71ereed    bool success = decoder->decode(&stream, &bm, kN32_SkColorType,
186915b972a818d0279eb926af38ba6952daa17a63ecommit-bot@chromium.org                                   SkImageDecoder::kDecodeBounds_Mode);
187915b972a818d0279eb926af38ba6952daa17a63ecommit-bot@chromium.org    REPORTER_ASSERT(reporter, success);
188915b972a818d0279eb926af38ba6952daa17a63ecommit-bot@chromium.org    if (!success) {
189915b972a818d0279eb926af38ba6952daa17a63ecommit-bot@chromium.org        return;
190915b972a818d0279eb926af38ba6952daa17a63ecommit-bot@chromium.org    }
191915b972a818d0279eb926af38ba6952daa17a63ecommit-bot@chromium.org
192915b972a818d0279eb926af38ba6952daa17a63ecommit-bot@chromium.org    // Keep track of the alpha type for testing later. If the full decode
193915b972a818d0279eb926af38ba6952daa17a63ecommit-bot@chromium.org    // succeeds, the alpha type should be the same, unless the full decode
194915b972a818d0279eb926af38ba6952daa17a63ecommit-bot@chromium.org    // determined that the alpha type should actually be opaque, which may
195915b972a818d0279eb926af38ba6952daa17a63ecommit-bot@chromium.org    // not be known when only decoding the bounds.
196915b972a818d0279eb926af38ba6952daa17a63ecommit-bot@chromium.org    const SkAlphaType boundsAlphaType = bm.alphaType();
197915b972a818d0279eb926af38ba6952daa17a63ecommit-bot@chromium.org
198915b972a818d0279eb926af38ba6952daa17a63ecommit-bot@chromium.org    // rewind should always succeed on SkFILEStream.
199915b972a818d0279eb926af38ba6952daa17a63ecommit-bot@chromium.org    success = stream.rewind();
200915b972a818d0279eb926af38ba6952daa17a63ecommit-bot@chromium.org    REPORTER_ASSERT(reporter, success);
201915b972a818d0279eb926af38ba6952daa17a63ecommit-bot@chromium.org    if (!success) {
202915b972a818d0279eb926af38ba6952daa17a63ecommit-bot@chromium.org        return;
203915b972a818d0279eb926af38ba6952daa17a63ecommit-bot@chromium.org    }
204915b972a818d0279eb926af38ba6952daa17a63ecommit-bot@chromium.org
205bfefc7c95fc0e8ebd5000c68f6d16e1a3ea0e71ereed    success = decoder->decode(&stream, &bm, kN32_SkColorType, SkImageDecoder::kDecodePixels_Mode);
206915b972a818d0279eb926af38ba6952daa17a63ecommit-bot@chromium.org
207915b972a818d0279eb926af38ba6952daa17a63ecommit-bot@chromium.org    if (!success) {
208915b972a818d0279eb926af38ba6952daa17a63ecommit-bot@chromium.org        // When the decoder is set to require unpremul, if it does not support
209915b972a818d0279eb926af38ba6952daa17a63ecommit-bot@chromium.org        // unpremul it will fail. This is the only reason the decode should
210915b972a818d0279eb926af38ba6952daa17a63ecommit-bot@chromium.org        // fail (since we know the files we are using to test can be decoded).
211915b972a818d0279eb926af38ba6952daa17a63ecommit-bot@chromium.org        REPORTER_ASSERT(reporter, requireUnpremul);
212915b972a818d0279eb926af38ba6952daa17a63ecommit-bot@chromium.org        return;
213915b972a818d0279eb926af38ba6952daa17a63ecommit-bot@chromium.org    }
214915b972a818d0279eb926af38ba6952daa17a63ecommit-bot@chromium.org
215915b972a818d0279eb926af38ba6952daa17a63ecommit-bot@chromium.org    // The bounds decode should return with either the requested
216915b972a818d0279eb926af38ba6952daa17a63ecommit-bot@chromium.org    // premul/unpremul or opaque, if that value could be determined when only
217915b972a818d0279eb926af38ba6952daa17a63ecommit-bot@chromium.org    // decoding the bounds.
218915b972a818d0279eb926af38ba6952daa17a63ecommit-bot@chromium.org    if (requireUnpremul) {
219915b972a818d0279eb926af38ba6952daa17a63ecommit-bot@chromium.org        REPORTER_ASSERT(reporter, kUnpremul_SkAlphaType == boundsAlphaType
220915b972a818d0279eb926af38ba6952daa17a63ecommit-bot@chromium.org                                  || kOpaque_SkAlphaType == boundsAlphaType);
221915b972a818d0279eb926af38ba6952daa17a63ecommit-bot@chromium.org    } else {
222915b972a818d0279eb926af38ba6952daa17a63ecommit-bot@chromium.org        REPORTER_ASSERT(reporter, kPremul_SkAlphaType == boundsAlphaType
223915b972a818d0279eb926af38ba6952daa17a63ecommit-bot@chromium.org                                  || kOpaque_SkAlphaType == boundsAlphaType);
224915b972a818d0279eb926af38ba6952daa17a63ecommit-bot@chromium.org    }
225915b972a818d0279eb926af38ba6952daa17a63ecommit-bot@chromium.org
226915b972a818d0279eb926af38ba6952daa17a63ecommit-bot@chromium.org    // When decoding the full image, the alpha type should match the one
227915b972a818d0279eb926af38ba6952daa17a63ecommit-bot@chromium.org    // returned by the bounds decode, unless the full decode determined that
228915b972a818d0279eb926af38ba6952daa17a63ecommit-bot@chromium.org    // the alpha type is actually opaque.
229915b972a818d0279eb926af38ba6952daa17a63ecommit-bot@chromium.org    REPORTER_ASSERT(reporter, bm.alphaType() == boundsAlphaType
230915b972a818d0279eb926af38ba6952daa17a63ecommit-bot@chromium.org                              || bm.alphaType() == kOpaque_SkAlphaType);
231915b972a818d0279eb926af38ba6952daa17a63ecommit-bot@chromium.org}
232915b972a818d0279eb926af38ba6952daa17a63ecommit-bot@chromium.org
233915b972a818d0279eb926af38ba6952daa17a63ecommit-bot@chromium.orgDEF_TEST(ImageDecoding_alphaType, reporter) {
234bcbc1788b478b1e54079318ad073e8490aa66faetfarina    SkString resourcePath = GetResourcePath();
235915b972a818d0279eb926af38ba6952daa17a63ecommit-bot@chromium.org    if (resourcePath.isEmpty()) {
236915b972a818d0279eb926af38ba6952daa17a63ecommit-bot@chromium.org        SkDebugf("Could not run alphaType test because resourcePath not specified.");
237915b972a818d0279eb926af38ba6952daa17a63ecommit-bot@chromium.org        return;
238915b972a818d0279eb926af38ba6952daa17a63ecommit-bot@chromium.org    }
239915b972a818d0279eb926af38ba6952daa17a63ecommit-bot@chromium.org
240915b972a818d0279eb926af38ba6952daa17a63ecommit-bot@chromium.org    SkOSFile::Iter iter(resourcePath.c_str());
241915b972a818d0279eb926af38ba6952daa17a63ecommit-bot@chromium.org    SkString basename;
242915b972a818d0279eb926af38ba6952daa17a63ecommit-bot@chromium.org    if (iter.next(&basename)) {
243915b972a818d0279eb926af38ba6952daa17a63ecommit-bot@chromium.org        do {
244915b972a818d0279eb926af38ba6952daa17a63ecommit-bot@chromium.org            SkString filename = SkOSPath::SkPathJoin(resourcePath.c_str(), basename.c_str());
245915b972a818d0279eb926af38ba6952daa17a63ecommit-bot@chromium.org            for (int truth = 0; truth <= 1; ++truth) {
246915b972a818d0279eb926af38ba6952daa17a63ecommit-bot@chromium.org                test_alphaType(reporter, filename, SkToBool(truth));
247915b972a818d0279eb926af38ba6952daa17a63ecommit-bot@chromium.org            }
248915b972a818d0279eb926af38ba6952daa17a63ecommit-bot@chromium.org        } while (iter.next(&basename));
249915b972a818d0279eb926af38ba6952daa17a63ecommit-bot@chromium.org    } else {
250915b972a818d0279eb926af38ba6952daa17a63ecommit-bot@chromium.org        SkDebugf("Failed to find any files :(\n");
251915b972a818d0279eb926af38ba6952daa17a63ecommit-bot@chromium.org    }
252915b972a818d0279eb926af38ba6952daa17a63ecommit-bot@chromium.org
253915b972a818d0279eb926af38ba6952daa17a63ecommit-bot@chromium.org}
254915b972a818d0279eb926af38ba6952daa17a63ecommit-bot@chromium.org
255915b972a818d0279eb926af38ba6952daa17a63ecommit-bot@chromium.org// Using known images, test that decoding into unpremul and premul behave as expected.
256915b972a818d0279eb926af38ba6952daa17a63ecommit-bot@chromium.orgDEF_TEST(ImageDecoding_unpremul, reporter) {
257bcbc1788b478b1e54079318ad073e8490aa66faetfarina    SkString resourcePath = GetResourcePath();
258915b972a818d0279eb926af38ba6952daa17a63ecommit-bot@chromium.org    if (resourcePath.isEmpty()) {
259915b972a818d0279eb926af38ba6952daa17a63ecommit-bot@chromium.org        SkDebugf("Could not run unpremul test because resourcePath not specified.");
260915b972a818d0279eb926af38ba6952daa17a63ecommit-bot@chromium.org        return;
261915b972a818d0279eb926af38ba6952daa17a63ecommit-bot@chromium.org    }
262915b972a818d0279eb926af38ba6952daa17a63ecommit-bot@chromium.org    const char* root = "half-transparent-white-pixel";
263915b972a818d0279eb926af38ba6952daa17a63ecommit-bot@chromium.org    const char* suffixes[] = { ".png", ".webp" };
264915b972a818d0279eb926af38ba6952daa17a63ecommit-bot@chromium.org
265915b972a818d0279eb926af38ba6952daa17a63ecommit-bot@chromium.org    for (size_t i = 0; i < SK_ARRAY_COUNT(suffixes); ++i) {
266915b972a818d0279eb926af38ba6952daa17a63ecommit-bot@chromium.org        SkString basename = SkStringPrintf("%s%s", root, suffixes[i]);
267915b972a818d0279eb926af38ba6952daa17a63ecommit-bot@chromium.org        SkString fullName = SkOSPath::SkPathJoin(resourcePath.c_str(), basename.c_str());
268915b972a818d0279eb926af38ba6952daa17a63ecommit-bot@chromium.org
269915b972a818d0279eb926af38ba6952daa17a63ecommit-bot@chromium.org        SkBitmap bm;
270915b972a818d0279eb926af38ba6952daa17a63ecommit-bot@chromium.org        SkFILEStream stream(fullName.c_str());
271915b972a818d0279eb926af38ba6952daa17a63ecommit-bot@chromium.org
272915b972a818d0279eb926af38ba6952daa17a63ecommit-bot@chromium.org        if (!stream.isValid()) {
273915b972a818d0279eb926af38ba6952daa17a63ecommit-bot@chromium.org            SkDebugf("file %s missing from resource directoy %s\n",
274915b972a818d0279eb926af38ba6952daa17a63ecommit-bot@chromium.org                     basename.c_str(), resourcePath.c_str());
275915b972a818d0279eb926af38ba6952daa17a63ecommit-bot@chromium.org            continue;
276915b972a818d0279eb926af38ba6952daa17a63ecommit-bot@chromium.org        }
277915b972a818d0279eb926af38ba6952daa17a63ecommit-bot@chromium.org
278915b972a818d0279eb926af38ba6952daa17a63ecommit-bot@chromium.org        // This should never fail since we know the images we're decoding.
279915b972a818d0279eb926af38ba6952daa17a63ecommit-bot@chromium.org        SkAutoTDelete<SkImageDecoder> decoder(SkImageDecoder::Factory(&stream));
280915b972a818d0279eb926af38ba6952daa17a63ecommit-bot@chromium.org        REPORTER_ASSERT(reporter, NULL != decoder.get());
281915b972a818d0279eb926af38ba6952daa17a63ecommit-bot@chromium.org        if (NULL == decoder.get()) {
282915b972a818d0279eb926af38ba6952daa17a63ecommit-bot@chromium.org            continue;
283915b972a818d0279eb926af38ba6952daa17a63ecommit-bot@chromium.org        }
284915b972a818d0279eb926af38ba6952daa17a63ecommit-bot@chromium.org
285915b972a818d0279eb926af38ba6952daa17a63ecommit-bot@chromium.org        // Test unpremultiplied. We know what color this should result in.
286915b972a818d0279eb926af38ba6952daa17a63ecommit-bot@chromium.org        decoder->setRequireUnpremultipliedColors(true);
287bfefc7c95fc0e8ebd5000c68f6d16e1a3ea0e71ereed        bool success = decoder->decode(&stream, &bm, kN32_SkColorType,
288915b972a818d0279eb926af38ba6952daa17a63ecommit-bot@chromium.org                                       SkImageDecoder::kDecodePixels_Mode);
289915b972a818d0279eb926af38ba6952daa17a63ecommit-bot@chromium.org        REPORTER_ASSERT(reporter, success);
290915b972a818d0279eb926af38ba6952daa17a63ecommit-bot@chromium.org        if (!success) {
291915b972a818d0279eb926af38ba6952daa17a63ecommit-bot@chromium.org            continue;
292915b972a818d0279eb926af38ba6952daa17a63ecommit-bot@chromium.org        }
293915b972a818d0279eb926af38ba6952daa17a63ecommit-bot@chromium.org
294915b972a818d0279eb926af38ba6952daa17a63ecommit-bot@chromium.org        REPORTER_ASSERT(reporter, bm.width() == 1 && bm.height() == 1);
295915b972a818d0279eb926af38ba6952daa17a63ecommit-bot@chromium.org        {
296915b972a818d0279eb926af38ba6952daa17a63ecommit-bot@chromium.org            SkAutoLockPixels alp(bm);
297915b972a818d0279eb926af38ba6952daa17a63ecommit-bot@chromium.org            REPORTER_ASSERT(reporter, bm.getAddr32(0, 0)[0] == 0x7fffffff);
298915b972a818d0279eb926af38ba6952daa17a63ecommit-bot@chromium.org        }
299915b972a818d0279eb926af38ba6952daa17a63ecommit-bot@chromium.org
300915b972a818d0279eb926af38ba6952daa17a63ecommit-bot@chromium.org        success = stream.rewind();
301915b972a818d0279eb926af38ba6952daa17a63ecommit-bot@chromium.org        REPORTER_ASSERT(reporter, success);
302915b972a818d0279eb926af38ba6952daa17a63ecommit-bot@chromium.org        if (!success) {
303915b972a818d0279eb926af38ba6952daa17a63ecommit-bot@chromium.org            continue;
304915b972a818d0279eb926af38ba6952daa17a63ecommit-bot@chromium.org        }
305915b972a818d0279eb926af38ba6952daa17a63ecommit-bot@chromium.org
306915b972a818d0279eb926af38ba6952daa17a63ecommit-bot@chromium.org        // Test premultiplied. Once again, we know which color this should
307915b972a818d0279eb926af38ba6952daa17a63ecommit-bot@chromium.org        // result in.
308915b972a818d0279eb926af38ba6952daa17a63ecommit-bot@chromium.org        decoder->setRequireUnpremultipliedColors(false);
309bfefc7c95fc0e8ebd5000c68f6d16e1a3ea0e71ereed        success = decoder->decode(&stream, &bm, kN32_SkColorType,
310915b972a818d0279eb926af38ba6952daa17a63ecommit-bot@chromium.org                                  SkImageDecoder::kDecodePixels_Mode);
311915b972a818d0279eb926af38ba6952daa17a63ecommit-bot@chromium.org        REPORTER_ASSERT(reporter, success);
312915b972a818d0279eb926af38ba6952daa17a63ecommit-bot@chromium.org        if (!success) {
313915b972a818d0279eb926af38ba6952daa17a63ecommit-bot@chromium.org            continue;
314915b972a818d0279eb926af38ba6952daa17a63ecommit-bot@chromium.org        }
315915b972a818d0279eb926af38ba6952daa17a63ecommit-bot@chromium.org
316915b972a818d0279eb926af38ba6952daa17a63ecommit-bot@chromium.org        REPORTER_ASSERT(reporter, bm.width() == 1 && bm.height() == 1);
317915b972a818d0279eb926af38ba6952daa17a63ecommit-bot@chromium.org        {
318915b972a818d0279eb926af38ba6952daa17a63ecommit-bot@chromium.org            SkAutoLockPixels alp(bm);
319915b972a818d0279eb926af38ba6952daa17a63ecommit-bot@chromium.org            REPORTER_ASSERT(reporter, bm.getAddr32(0, 0)[0] == 0x7f7f7f7f);
320915b972a818d0279eb926af38ba6952daa17a63ecommit-bot@chromium.org        }
321915b972a818d0279eb926af38ba6952daa17a63ecommit-bot@chromium.org    }
322915b972a818d0279eb926af38ba6952daa17a63ecommit-bot@chromium.org}
323915b972a818d0279eb926af38ba6952daa17a63ecommit-bot@chromium.org#endif // SK_BUILD_FOR_UNIX/ANDROID skbug.com/2388
324915b972a818d0279eb926af38ba6952daa17a63ecommit-bot@chromium.org
325826d63af970dca7c47f4cded1cfcb918bc5785a9scroggo@google.com#ifdef SK_DEBUG
326826d63af970dca7c47f4cded1cfcb918bc5785a9scroggo@google.com// Create a stream containing a bitmap encoded to Type type.
327b5571b3324cf18629a255ec85e189447069c9b14scroggo@google.comstatic SkMemoryStream* create_image_stream(SkImageEncoder::Type type) {
328826d63af970dca7c47f4cded1cfcb918bc5785a9scroggo@google.com    SkBitmap bm;
329826d63af970dca7c47f4cded1cfcb918bc5785a9scroggo@google.com    const int size = 50;
330deee496cd30070e52556dcb538c2e5eb39b66b81mike@reedtribe.org    bm.allocN32Pixels(size, size);
331826d63af970dca7c47f4cded1cfcb918bc5785a9scroggo@google.com    SkCanvas canvas(bm);
332826d63af970dca7c47f4cded1cfcb918bc5785a9scroggo@google.com    SkPoint points[2] = {
333826d63af970dca7c47f4cded1cfcb918bc5785a9scroggo@google.com        { SkIntToScalar(0), SkIntToScalar(0) },
334826d63af970dca7c47f4cded1cfcb918bc5785a9scroggo@google.com        { SkIntToScalar(size), SkIntToScalar(size) }
335826d63af970dca7c47f4cded1cfcb918bc5785a9scroggo@google.com    };
336826d63af970dca7c47f4cded1cfcb918bc5785a9scroggo@google.com    SkColor colors[2] = { SK_ColorWHITE, SK_ColorBLUE };
337826d63af970dca7c47f4cded1cfcb918bc5785a9scroggo@google.com    SkShader* shader = SkGradientShader::CreateLinear(points, colors, NULL,
338826d63af970dca7c47f4cded1cfcb918bc5785a9scroggo@google.com                                                      SK_ARRAY_COUNT(colors),
339826d63af970dca7c47f4cded1cfcb918bc5785a9scroggo@google.com                                                      SkShader::kClamp_TileMode);
340826d63af970dca7c47f4cded1cfcb918bc5785a9scroggo@google.com    SkPaint paint;
341826d63af970dca7c47f4cded1cfcb918bc5785a9scroggo@google.com    paint.setShader(shader)->unref();
342826d63af970dca7c47f4cded1cfcb918bc5785a9scroggo@google.com    canvas.drawPaint(paint);
343826d63af970dca7c47f4cded1cfcb918bc5785a9scroggo@google.com    // Now encode it to a stream.
344826d63af970dca7c47f4cded1cfcb918bc5785a9scroggo@google.com    SkAutoTUnref<SkData> data(SkImageEncoder::EncodeData(bm, type, 100));
345826d63af970dca7c47f4cded1cfcb918bc5785a9scroggo@google.com    if (NULL == data.get()) {
346826d63af970dca7c47f4cded1cfcb918bc5785a9scroggo@google.com        return NULL;
347826d63af970dca7c47f4cded1cfcb918bc5785a9scroggo@google.com    }
348826d63af970dca7c47f4cded1cfcb918bc5785a9scroggo@google.com    return SkNEW_ARGS(SkMemoryStream, (data.get()));
349826d63af970dca7c47f4cded1cfcb918bc5785a9scroggo@google.com}
350826d63af970dca7c47f4cded1cfcb918bc5785a9scroggo@google.com
351826d63af970dca7c47f4cded1cfcb918bc5785a9scroggo@google.com// For every format that supports tile based decoding, ensure that
352826d63af970dca7c47f4cded1cfcb918bc5785a9scroggo@google.com// calling decodeSubset will not fail if the caller has unreffed the
353826d63af970dca7c47f4cded1cfcb918bc5785a9scroggo@google.com// stream provided in buildTileIndex.
354826d63af970dca7c47f4cded1cfcb918bc5785a9scroggo@google.com// Only runs in debug mode since we are testing for a crash.
355826d63af970dca7c47f4cded1cfcb918bc5785a9scroggo@google.comstatic void test_stream_life() {
356826d63af970dca7c47f4cded1cfcb918bc5785a9scroggo@google.com    const SkImageEncoder::Type gTypes[] = {
357826d63af970dca7c47f4cded1cfcb918bc5785a9scroggo@google.com#ifdef SK_BUILD_FOR_ANDROID
358d79277f67824392876b82cf5635cc11f819e64dfscroggo@google.com        SkImageEncoder::kJPEG_Type,
359826d63af970dca7c47f4cded1cfcb918bc5785a9scroggo@google.com        SkImageEncoder::kPNG_Type,
360826d63af970dca7c47f4cded1cfcb918bc5785a9scroggo@google.com#endif
361826d63af970dca7c47f4cded1cfcb918bc5785a9scroggo@google.com        SkImageEncoder::kWEBP_Type,
362826d63af970dca7c47f4cded1cfcb918bc5785a9scroggo@google.com    };
363826d63af970dca7c47f4cded1cfcb918bc5785a9scroggo@google.com    for (size_t i = 0; i < SK_ARRAY_COUNT(gTypes); ++i) {
3643d50ea1b87132833d7eab38964f40315ba553205halcanary@google.com        // SkDebugf("encoding to %i\n", i);
365b5571b3324cf18629a255ec85e189447069c9b14scroggo@google.com        SkAutoTUnref<SkMemoryStream> stream(create_image_stream(gTypes[i]));
366826d63af970dca7c47f4cded1cfcb918bc5785a9scroggo@google.com        if (NULL == stream.get()) {
367826d63af970dca7c47f4cded1cfcb918bc5785a9scroggo@google.com            SkDebugf("no stream\n");
368826d63af970dca7c47f4cded1cfcb918bc5785a9scroggo@google.com            continue;
369826d63af970dca7c47f4cded1cfcb918bc5785a9scroggo@google.com        }
370826d63af970dca7c47f4cded1cfcb918bc5785a9scroggo@google.com        SkAutoTDelete<SkImageDecoder> decoder(SkImageDecoder::Factory(stream));
371826d63af970dca7c47f4cded1cfcb918bc5785a9scroggo@google.com        if (NULL == decoder.get()) {
372826d63af970dca7c47f4cded1cfcb918bc5785a9scroggo@google.com            SkDebugf("no decoder\n");
373826d63af970dca7c47f4cded1cfcb918bc5785a9scroggo@google.com            continue;
374826d63af970dca7c47f4cded1cfcb918bc5785a9scroggo@google.com        }
375826d63af970dca7c47f4cded1cfcb918bc5785a9scroggo@google.com        int width, height;
376826d63af970dca7c47f4cded1cfcb918bc5785a9scroggo@google.com        if (!decoder->buildTileIndex(stream.get(), &width, &height)) {
377826d63af970dca7c47f4cded1cfcb918bc5785a9scroggo@google.com            SkDebugf("could not build a tile index\n");
378826d63af970dca7c47f4cded1cfcb918bc5785a9scroggo@google.com            continue;
379826d63af970dca7c47f4cded1cfcb918bc5785a9scroggo@google.com        }
380826d63af970dca7c47f4cded1cfcb918bc5785a9scroggo@google.com        // Now unref the stream to make sure it survives
381826d63af970dca7c47f4cded1cfcb918bc5785a9scroggo@google.com        stream.reset(NULL);
382826d63af970dca7c47f4cded1cfcb918bc5785a9scroggo@google.com        SkBitmap bm;
383bfefc7c95fc0e8ebd5000c68f6d16e1a3ea0e71ereed        decoder->decodeSubset(&bm, SkIRect::MakeWH(width, height), kN32_SkColorType);
384826d63af970dca7c47f4cded1cfcb918bc5785a9scroggo@google.com    }
385826d63af970dca7c47f4cded1cfcb918bc5785a9scroggo@google.com}
3868d2392487cd97e68c0a71da9fd5d2b42ecac5ec8scroggo@google.com
3878d2392487cd97e68c0a71da9fd5d2b42ecac5ec8scroggo@google.com// Test inside SkScaledBitmapSampler.cpp
3888d2392487cd97e68c0a71da9fd5d2b42ecac5ec8scroggo@google.comextern void test_row_proc_choice();
3898d2392487cd97e68c0a71da9fd5d2b42ecac5ec8scroggo@google.com
3903d50ea1b87132833d7eab38964f40315ba553205halcanary@google.com#endif  // SK_DEBUG
391826d63af970dca7c47f4cded1cfcb918bc5785a9scroggo@google.com
392e4fafb146e85cdfcf9d5418597b6818aa0754adatfarina@chromium.orgDEF_TEST(ImageDecoding, reporter) {
393f698c8262df397a7015662e91b1a727e1134c418scroggo@google.com    test_unpremul(reporter);
394826d63af970dca7c47f4cded1cfcb918bc5785a9scroggo@google.com#ifdef SK_DEBUG
395826d63af970dca7c47f4cded1cfcb918bc5785a9scroggo@google.com    test_stream_life();
3968d2392487cd97e68c0a71da9fd5d2b42ecac5ec8scroggo@google.com    test_row_proc_choice();
397826d63af970dca7c47f4cded1cfcb918bc5785a9scroggo@google.com#endif
398f698c8262df397a7015662e91b1a727e1134c418scroggo@google.com}
399dedd44adea3b87faea4bcd833c6a508a6db8fcfdhalcanary@google.com
4003d50ea1b87132833d7eab38964f40315ba553205halcanary@google.com// expected output for 8x8 bitmap
40158674817a7a5003556a1d0b5b8fa522782a729fatfarina@chromium.orgstatic const int kExpectedWidth = 8;
40258674817a7a5003556a1d0b5b8fa522782a729fatfarina@chromium.orgstatic const int kExpectedHeight = 8;
40358674817a7a5003556a1d0b5b8fa522782a729fatfarina@chromium.orgstatic const SkColor kExpectedPixels[] = {
4043d50ea1b87132833d7eab38964f40315ba553205halcanary@google.com    0xffbba570, 0xff395f5d, 0xffe25c39, 0xff197666,
4053d50ea1b87132833d7eab38964f40315ba553205halcanary@google.com    0xff3cba27, 0xffdefcb0, 0xffc13874, 0xfffa0093,
4063d50ea1b87132833d7eab38964f40315ba553205halcanary@google.com    0xffbda60e, 0xffc01db6, 0xff2bd688, 0xff9362d4,
4073d50ea1b87132833d7eab38964f40315ba553205halcanary@google.com    0xffc641b2, 0xffa5cede, 0xff606eba, 0xff8f4bf3,
4083d50ea1b87132833d7eab38964f40315ba553205halcanary@google.com    0xff3bf742, 0xff8f02a8, 0xff5509df, 0xffc7027e,
4093d50ea1b87132833d7eab38964f40315ba553205halcanary@google.com    0xff24aa8a, 0xff886c96, 0xff625481, 0xff403689,
4103d50ea1b87132833d7eab38964f40315ba553205halcanary@google.com    0xffc52152, 0xff78ccd6, 0xffdcb4ab, 0xff09d27d,
4113d50ea1b87132833d7eab38964f40315ba553205halcanary@google.com    0xffca00f3, 0xff605d47, 0xff446fb2, 0xff576e46,
4123d50ea1b87132833d7eab38964f40315ba553205halcanary@google.com    0xff273df9, 0xffb41a83, 0xfff812c3, 0xffccab67,
4133d50ea1b87132833d7eab38964f40315ba553205halcanary@google.com    0xff034218, 0xff7db9a7, 0xff821048, 0xfffe4ab4,
4143d50ea1b87132833d7eab38964f40315ba553205halcanary@google.com    0xff6fac98, 0xff941d27, 0xff5fe411, 0xfffbb283,
4153d50ea1b87132833d7eab38964f40315ba553205halcanary@google.com    0xffd86e99, 0xff169162, 0xff71128c, 0xff39cab4,
4163d50ea1b87132833d7eab38964f40315ba553205halcanary@google.com    0xffa7fe63, 0xff4c956b, 0xffbc22e0, 0xffb272e4,
4173d50ea1b87132833d7eab38964f40315ba553205halcanary@google.com    0xff129f4a, 0xffe34513, 0xff3d3742, 0xffbd190a,
4183d50ea1b87132833d7eab38964f40315ba553205halcanary@google.com    0xffb07222, 0xff2e23f8, 0xfff089d9, 0xffb35738,
4193d50ea1b87132833d7eab38964f40315ba553205halcanary@google.com    0xffa86022, 0xff3340fe, 0xff95fe71, 0xff6a71df
4203d50ea1b87132833d7eab38964f40315ba553205halcanary@google.com};
4213d50ea1b87132833d7eab38964f40315ba553205halcanary@google.comSK_COMPILE_ASSERT((kExpectedWidth * kExpectedHeight)
4223d50ea1b87132833d7eab38964f40315ba553205halcanary@google.com                  == SK_ARRAY_COUNT(kExpectedPixels), array_size_mismatch);
423dedd44adea3b87faea4bcd833c6a508a6db8fcfdhalcanary@google.com
424dedd44adea3b87faea4bcd833c6a508a6db8fcfdhalcanary@google.comDEF_TEST(WebP, reporter) {
425dedd44adea3b87faea4bcd833c6a508a6db8fcfdhalcanary@google.com    const unsigned char encodedWebP[] = {
426dedd44adea3b87faea4bcd833c6a508a6db8fcfdhalcanary@google.com        0x52, 0x49, 0x46, 0x46, 0x2c, 0x01, 0x00, 0x00, 0x57, 0x45, 0x42, 0x50,
427dedd44adea3b87faea4bcd833c6a508a6db8fcfdhalcanary@google.com        0x56, 0x50, 0x38, 0x4c, 0x20, 0x01, 0x00, 0x00, 0x2f, 0x07, 0xc0, 0x01,
428dedd44adea3b87faea4bcd833c6a508a6db8fcfdhalcanary@google.com        0x00, 0xff, 0x01, 0x45, 0x03, 0x00, 0xe2, 0xd5, 0xae, 0x60, 0x2b, 0xad,
429dedd44adea3b87faea4bcd833c6a508a6db8fcfdhalcanary@google.com        0xd9, 0x68, 0x76, 0xb6, 0x8d, 0x6a, 0x1d, 0xc0, 0xe6, 0x19, 0xd6, 0x16,
430dedd44adea3b87faea4bcd833c6a508a6db8fcfdhalcanary@google.com        0xb7, 0xb4, 0xef, 0xcf, 0xc3, 0x15, 0x6c, 0xb3, 0xbd, 0x77, 0x0d, 0x85,
431dedd44adea3b87faea4bcd833c6a508a6db8fcfdhalcanary@google.com        0x6d, 0x1b, 0xa9, 0xb1, 0x2b, 0xdc, 0x3d, 0x83, 0xdb, 0x00, 0x00, 0xc8,
432dedd44adea3b87faea4bcd833c6a508a6db8fcfdhalcanary@google.com        0x26, 0xe5, 0x01, 0x99, 0x8a, 0xd5, 0xdd, 0xfc, 0x82, 0xcd, 0xcd, 0x9a,
433dedd44adea3b87faea4bcd833c6a508a6db8fcfdhalcanary@google.com        0x8c, 0x13, 0xcc, 0x1b, 0xba, 0xf5, 0x05, 0xdb, 0xee, 0x6a, 0xdb, 0x38,
434dedd44adea3b87faea4bcd833c6a508a6db8fcfdhalcanary@google.com        0x60, 0xfe, 0x43, 0x2c, 0xd4, 0x6a, 0x99, 0x4d, 0xc6, 0xc0, 0xd3, 0x28,
435dedd44adea3b87faea4bcd833c6a508a6db8fcfdhalcanary@google.com        0x1b, 0xc1, 0xb1, 0x17, 0x4e, 0x43, 0x0e, 0x3d, 0x27, 0xe9, 0xe4, 0x84,
436dedd44adea3b87faea4bcd833c6a508a6db8fcfdhalcanary@google.com        0x4f, 0x24, 0x62, 0x69, 0x85, 0x43, 0x8d, 0xc2, 0x04, 0x00, 0x07, 0x59,
437dedd44adea3b87faea4bcd833c6a508a6db8fcfdhalcanary@google.com        0x60, 0xfd, 0x8b, 0x4d, 0x60, 0x32, 0x72, 0xcf, 0x88, 0x0c, 0x2f, 0x2f,
438dedd44adea3b87faea4bcd833c6a508a6db8fcfdhalcanary@google.com        0xad, 0x62, 0xbd, 0x27, 0x09, 0x16, 0x70, 0x78, 0x6c, 0xd9, 0x82, 0xef,
439dedd44adea3b87faea4bcd833c6a508a6db8fcfdhalcanary@google.com        0x1a, 0xa2, 0xcc, 0xf0, 0xf1, 0x6f, 0xd8, 0x78, 0x2e, 0x39, 0xa1, 0xcf,
440dedd44adea3b87faea4bcd833c6a508a6db8fcfdhalcanary@google.com        0x14, 0x4b, 0x89, 0xb4, 0x1b, 0x48, 0x15, 0x7c, 0x48, 0x6f, 0x8c, 0x20,
441dedd44adea3b87faea4bcd833c6a508a6db8fcfdhalcanary@google.com        0xb7, 0x00, 0xcf, 0xfc, 0xdb, 0xd0, 0xe9, 0xe7, 0x42, 0x09, 0xa4, 0x03,
442dedd44adea3b87faea4bcd833c6a508a6db8fcfdhalcanary@google.com        0x40, 0xac, 0xda, 0x40, 0x01, 0x00, 0x5f, 0xa1, 0x3d, 0x64, 0xe1, 0xf4,
443dedd44adea3b87faea4bcd833c6a508a6db8fcfdhalcanary@google.com        0x03, 0x45, 0x29, 0xe0, 0xe2, 0x4a, 0xc3, 0xa2, 0xe8, 0xe0, 0x25, 0x12,
444dedd44adea3b87faea4bcd833c6a508a6db8fcfdhalcanary@google.com        0x74, 0xc6, 0xe8, 0xfb, 0x93, 0x4f, 0x9f, 0x5e, 0xc0, 0xa6, 0x91, 0x1b,
445dedd44adea3b87faea4bcd833c6a508a6db8fcfdhalcanary@google.com        0xa4, 0x24, 0x82, 0xc3, 0x61, 0x07, 0x4c, 0x49, 0x4f, 0x53, 0xae, 0x5f,
446dedd44adea3b87faea4bcd833c6a508a6db8fcfdhalcanary@google.com        0x5d, 0x39, 0x36, 0xc0, 0x5b, 0x57, 0x54, 0x60, 0x10, 0x00, 0x00, 0xd1,
447dedd44adea3b87faea4bcd833c6a508a6db8fcfdhalcanary@google.com        0x68, 0xb6, 0x6d, 0xdb, 0x36, 0x22, 0xfa, 0x1f, 0x35, 0x75, 0x22, 0xec,
448dedd44adea3b87faea4bcd833c6a508a6db8fcfdhalcanary@google.com        0x31, 0xbc, 0x5d, 0x8f, 0x87, 0x53, 0xa2, 0x05, 0x8c, 0x2f, 0xcd, 0xa8,
449dedd44adea3b87faea4bcd833c6a508a6db8fcfdhalcanary@google.com        0xa7, 0xf3, 0xa3, 0xbd, 0x83, 0x8b, 0x2a, 0xc8, 0x58, 0xf5, 0xac, 0x80,
450dedd44adea3b87faea4bcd833c6a508a6db8fcfdhalcanary@google.com        0xe3, 0xfe, 0x66, 0xa4, 0x7c, 0x1b, 0x6c, 0xd1, 0xa9, 0xd8, 0x14, 0xd0,
451dedd44adea3b87faea4bcd833c6a508a6db8fcfdhalcanary@google.com        0xc5, 0xb5, 0x39, 0x71, 0x97, 0x19, 0x19, 0x1b
452dedd44adea3b87faea4bcd833c6a508a6db8fcfdhalcanary@google.com    };
453dedd44adea3b87faea4bcd833c6a508a6db8fcfdhalcanary@google.com    SkAutoDataUnref encoded(SkData::NewWithCopy(encodedWebP,
454dedd44adea3b87faea4bcd833c6a508a6db8fcfdhalcanary@google.com                                                sizeof(encodedWebP)));
455dedd44adea3b87faea4bcd833c6a508a6db8fcfdhalcanary@google.com    SkBitmap bm;
4563d50ea1b87132833d7eab38964f40315ba553205halcanary@google.com
4573d50ea1b87132833d7eab38964f40315ba553205halcanary@google.com    bool success = SkInstallDiscardablePixelRef(
4583d50ea1b87132833d7eab38964f40315ba553205halcanary@google.com        SkDecodingImageGenerator::Create(encoded,
4592d970b5128f7270cd01a93e4ce68d0c3ea67ac71commit-bot@chromium.org            SkDecodingImageGenerator::Options()), &bm);
4603d50ea1b87132833d7eab38964f40315ba553205halcanary@google.com
461dedd44adea3b87faea4bcd833c6a508a6db8fcfdhalcanary@google.com    REPORTER_ASSERT(reporter, success);
462dedd44adea3b87faea4bcd833c6a508a6db8fcfdhalcanary@google.com    if (!success) {
463dedd44adea3b87faea4bcd833c6a508a6db8fcfdhalcanary@google.com        return;
464dedd44adea3b87faea4bcd833c6a508a6db8fcfdhalcanary@google.com    }
465dedd44adea3b87faea4bcd833c6a508a6db8fcfdhalcanary@google.com    SkAutoLockPixels alp(bm);
4663d50ea1b87132833d7eab38964f40315ba553205halcanary@google.com
467862020763d9d2fb1900b2c84e55dadf46482246dskia.committer@gmail.com    bool rightSize = ((kExpectedWidth == bm.width())
4683d50ea1b87132833d7eab38964f40315ba553205halcanary@google.com                      && (kExpectedHeight == bm.height()));
469dedd44adea3b87faea4bcd833c6a508a6db8fcfdhalcanary@google.com    REPORTER_ASSERT(reporter, rightSize);
470dedd44adea3b87faea4bcd833c6a508a6db8fcfdhalcanary@google.com    if (rightSize) {
471dedd44adea3b87faea4bcd833c6a508a6db8fcfdhalcanary@google.com        bool error = false;
4723d50ea1b87132833d7eab38964f40315ba553205halcanary@google.com        const SkColor* correctPixel = kExpectedPixels;
473dedd44adea3b87faea4bcd833c6a508a6db8fcfdhalcanary@google.com        for (int y = 0; y < bm.height(); ++y) {
474dedd44adea3b87faea4bcd833c6a508a6db8fcfdhalcanary@google.com            for (int x = 0; x < bm.width(); ++x) {
475dedd44adea3b87faea4bcd833c6a508a6db8fcfdhalcanary@google.com                error |= (*correctPixel != bm.getColor(x, y));
476dedd44adea3b87faea4bcd833c6a508a6db8fcfdhalcanary@google.com                ++correctPixel;
477dedd44adea3b87faea4bcd833c6a508a6db8fcfdhalcanary@google.com            }
478dedd44adea3b87faea4bcd833c6a508a6db8fcfdhalcanary@google.com        }
479dedd44adea3b87faea4bcd833c6a508a6db8fcfdhalcanary@google.com        REPORTER_ASSERT(reporter, !error);
480dedd44adea3b87faea4bcd833c6a508a6db8fcfdhalcanary@google.com    }
481dedd44adea3b87faea4bcd833c6a508a6db8fcfdhalcanary@google.com}
4823d50ea1b87132833d7eab38964f40315ba553205halcanary@google.com
4833d50ea1b87132833d7eab38964f40315ba553205halcanary@google.com////////////////////////////////////////////////////////////////////////////////
4843d50ea1b87132833d7eab38964f40315ba553205halcanary@google.com
4853d50ea1b87132833d7eab38964f40315ba553205halcanary@google.com// example of how Android will do this inside their BitmapFactory
4863d50ea1b87132833d7eab38964f40315ba553205halcanary@google.comstatic SkPixelRef* install_pixel_ref(SkBitmap* bitmap,
4873d50ea1b87132833d7eab38964f40315ba553205halcanary@google.com                                     SkStreamRewindable* stream,
4883d50ea1b87132833d7eab38964f40315ba553205halcanary@google.com                                     int sampleSize, bool ditherImage) {
4893d50ea1b87132833d7eab38964f40315ba553205halcanary@google.com    SkASSERT(bitmap != NULL);
4903d50ea1b87132833d7eab38964f40315ba553205halcanary@google.com    SkASSERT(stream != NULL);
4913d50ea1b87132833d7eab38964f40315ba553205halcanary@google.com    SkASSERT(stream->rewind());
4923d50ea1b87132833d7eab38964f40315ba553205halcanary@google.com    SkASSERT(stream->unique());
49361e96cd44624c9faceb625519c1b29775b161f45commit-bot@chromium.org    SkColorType colorType = bitmap->colorType();
4943d50ea1b87132833d7eab38964f40315ba553205halcanary@google.com    SkDecodingImageGenerator::Options opts(sampleSize, ditherImage, colorType);
495e5a8e66668a1594e49b2c221f26da4c6d2a4e99fcommit-bot@chromium.org    if (SkInstallDiscardablePixelRef(
496e5a8e66668a1594e49b2c221f26da4c6d2a4e99fcommit-bot@chromium.org                SkDecodingImageGenerator::Create(stream, opts), bitmap)) {
4973d50ea1b87132833d7eab38964f40315ba553205halcanary@google.com        return bitmap->pixelRef();
4983d50ea1b87132833d7eab38964f40315ba553205halcanary@google.com    }
4993d50ea1b87132833d7eab38964f40315ba553205halcanary@google.com    return NULL;
5003d50ea1b87132833d7eab38964f40315ba553205halcanary@google.com}
5013d50ea1b87132833d7eab38964f40315ba553205halcanary@google.com/**
5023d50ea1b87132833d7eab38964f40315ba553205halcanary@google.com *  A test for the SkDecodingImageGenerator::Create and
5033d50ea1b87132833d7eab38964f40315ba553205halcanary@google.com *  SkInstallDiscardablePixelRef functions.
5043d50ea1b87132833d7eab38964f40315ba553205halcanary@google.com */
5053d50ea1b87132833d7eab38964f40315ba553205halcanary@google.comDEF_TEST(ImprovedBitmapFactory, reporter) {
506bcbc1788b478b1e54079318ad073e8490aa66faetfarina    SkString resourcePath = GetResourcePath();
507b7acbfe0ee940863b5e2350b0b0c3795e01751f5halcanary@google.com    SkString path = SkOSPath::SkPathJoin(
508b7acbfe0ee940863b5e2350b0b0c3795e01751f5halcanary@google.com            resourcePath.c_str(), "randPixels.png");
5093d50ea1b87132833d7eab38964f40315ba553205halcanary@google.com    SkAutoTUnref<SkStreamRewindable> stream(
5103d50ea1b87132833d7eab38964f40315ba553205halcanary@google.com        SkStream::NewFromFile(path.c_str()));
5113d50ea1b87132833d7eab38964f40315ba553205halcanary@google.com    if (sk_exists(path.c_str())) {
5123d50ea1b87132833d7eab38964f40315ba553205halcanary@google.com        SkBitmap bm;
513a3264e53ee3f3c5d6a2c813df7e44b5b96d207f2commit-bot@chromium.org        SkAssertResult(bm.setInfo(SkImageInfo::MakeN32Premul(1, 1)));
5143d50ea1b87132833d7eab38964f40315ba553205halcanary@google.com        REPORTER_ASSERT(reporter,
5153d50ea1b87132833d7eab38964f40315ba553205halcanary@google.com            NULL != install_pixel_ref(&bm, stream.detach(), 1, true));
5163d50ea1b87132833d7eab38964f40315ba553205halcanary@google.com        SkAutoLockPixels alp(bm);
5173d50ea1b87132833d7eab38964f40315ba553205halcanary@google.com        REPORTER_ASSERT(reporter, NULL != bm.getPixels());
5183d50ea1b87132833d7eab38964f40315ba553205halcanary@google.com    }
5193d50ea1b87132833d7eab38964f40315ba553205halcanary@google.com}
5203d50ea1b87132833d7eab38964f40315ba553205halcanary@google.com
5213d50ea1b87132833d7eab38964f40315ba553205halcanary@google.com
5223d50ea1b87132833d7eab38964f40315ba553205halcanary@google.com////////////////////////////////////////////////////////////////////////////////
5233d50ea1b87132833d7eab38964f40315ba553205halcanary@google.com
5243d50ea1b87132833d7eab38964f40315ba553205halcanary@google.com#if defined(SK_BUILD_FOR_ANDROID) || defined(SK_BUILD_FOR_UNIX)
5253d50ea1b87132833d7eab38964f40315ba553205halcanary@google.comstatic inline bool check_rounding(int value, int dividend, int divisor) {
526b7acbfe0ee940863b5e2350b0b0c3795e01751f5halcanary@google.com    // returns true if the value is greater than floor(dividend/divisor)
527b7acbfe0ee940863b5e2350b0b0c3795e01751f5halcanary@google.com    // and less than SkNextPow2(ceil(dividend - divisor))
5283d50ea1b87132833d7eab38964f40315ba553205halcanary@google.com    return (((divisor * value) > (dividend - divisor))
529b7acbfe0ee940863b5e2350b0b0c3795e01751f5halcanary@google.com            && value <= SkNextPow2(((dividend - 1) / divisor) + 1));
5303d50ea1b87132833d7eab38964f40315ba553205halcanary@google.com}
5313d50ea1b87132833d7eab38964f40315ba553205halcanary@google.com#endif  // SK_BUILD_FOR_ANDROID || SK_BUILD_FOR_UNIX
5323d50ea1b87132833d7eab38964f40315ba553205halcanary@google.com
5333d50ea1b87132833d7eab38964f40315ba553205halcanary@google.com
5343d50ea1b87132833d7eab38964f40315ba553205halcanary@google.com#if SK_PMCOLOR_BYTE_ORDER(B,G,R,A)
5353d50ea1b87132833d7eab38964f40315ba553205halcanary@google.com    #define kBackwards_SkColorType kRGBA_8888_SkColorType
5363d50ea1b87132833d7eab38964f40315ba553205halcanary@google.com#elif SK_PMCOLOR_BYTE_ORDER(R,G,B,A)
5373d50ea1b87132833d7eab38964f40315ba553205halcanary@google.com    #define kBackwards_SkColorType kBGRA_8888_SkColorType
5383d50ea1b87132833d7eab38964f40315ba553205halcanary@google.com#else
5393d50ea1b87132833d7eab38964f40315ba553205halcanary@google.com    #error "SK_*32_SHFIT values must correspond to BGRA or RGBA byte order"
5403d50ea1b87132833d7eab38964f40315ba553205halcanary@google.com#endif
5413d50ea1b87132833d7eab38964f40315ba553205halcanary@google.com
5423d50ea1b87132833d7eab38964f40315ba553205halcanary@google.comstatic inline const char* SkColorType_to_string(SkColorType colorType) {
5433d50ea1b87132833d7eab38964f40315ba553205halcanary@google.com    switch(colorType) {
5443d50ea1b87132833d7eab38964f40315ba553205halcanary@google.com        case kAlpha_8_SkColorType:   return "Alpha_8";
5453d50ea1b87132833d7eab38964f40315ba553205halcanary@google.com        case kRGB_565_SkColorType:   return "RGB_565";
5463d50ea1b87132833d7eab38964f40315ba553205halcanary@google.com        case kARGB_4444_SkColorType: return "ARGB_4444";
54728fcae2ec77eb16a79e155f8d788b20457f1c951commit-bot@chromium.org        case kN32_SkColorType:       return "N32";
5483d50ea1b87132833d7eab38964f40315ba553205halcanary@google.com        case kBackwards_SkColorType: return "Backwards";
5493d50ea1b87132833d7eab38964f40315ba553205halcanary@google.com        case kIndex_8_SkColorType:   return "Index_8";
5503d50ea1b87132833d7eab38964f40315ba553205halcanary@google.com        default:                     return "ERROR";
5513d50ea1b87132833d7eab38964f40315ba553205halcanary@google.com    }
5523d50ea1b87132833d7eab38964f40315ba553205halcanary@google.com}
5533d50ea1b87132833d7eab38964f40315ba553205halcanary@google.com
554a9325fa237dde2654bc841c2bb0a05fc3e57696ahalcanary@google.comstatic inline const char* options_colorType(
555a9325fa237dde2654bc841c2bb0a05fc3e57696ahalcanary@google.com        const SkDecodingImageGenerator::Options& opts) {
556a9325fa237dde2654bc841c2bb0a05fc3e57696ahalcanary@google.com    if (opts.fUseRequestedColorType) {
557a9325fa237dde2654bc841c2bb0a05fc3e57696ahalcanary@google.com        return SkColorType_to_string(opts.fRequestedColorType);
558a9325fa237dde2654bc841c2bb0a05fc3e57696ahalcanary@google.com    } else {
559a9325fa237dde2654bc841c2bb0a05fc3e57696ahalcanary@google.com        return "(none)";
560a9325fa237dde2654bc841c2bb0a05fc3e57696ahalcanary@google.com    }
561a9325fa237dde2654bc841c2bb0a05fc3e57696ahalcanary@google.com}
562a9325fa237dde2654bc841c2bb0a05fc3e57696ahalcanary@google.com
563a9325fa237dde2654bc841c2bb0a05fc3e57696ahalcanary@google.comstatic inline const char* yn(bool value) {
564a9325fa237dde2654bc841c2bb0a05fc3e57696ahalcanary@google.com    if (value) {
565a9325fa237dde2654bc841c2bb0a05fc3e57696ahalcanary@google.com        return "yes";
566a9325fa237dde2654bc841c2bb0a05fc3e57696ahalcanary@google.com    } else {
567a9325fa237dde2654bc841c2bb0a05fc3e57696ahalcanary@google.com        return "no";
568a9325fa237dde2654bc841c2bb0a05fc3e57696ahalcanary@google.com    }
569a9325fa237dde2654bc841c2bb0a05fc3e57696ahalcanary@google.com}
570a9325fa237dde2654bc841c2bb0a05fc3e57696ahalcanary@google.com
5713d50ea1b87132833d7eab38964f40315ba553205halcanary@google.com/**
5723d50ea1b87132833d7eab38964f40315ba553205halcanary@google.com * Given either a SkStream or a SkData, try to decode the encoded
5733d50ea1b87132833d7eab38964f40315ba553205halcanary@google.com * image using the specified options and report errors.
5743d50ea1b87132833d7eab38964f40315ba553205halcanary@google.com */
5753d50ea1b87132833d7eab38964f40315ba553205halcanary@google.comstatic void test_options(skiatest::Reporter* reporter,
5763d50ea1b87132833d7eab38964f40315ba553205halcanary@google.com                         const SkDecodingImageGenerator::Options& opts,
5773d50ea1b87132833d7eab38964f40315ba553205halcanary@google.com                         SkStreamRewindable* encodedStream,
5783d50ea1b87132833d7eab38964f40315ba553205halcanary@google.com                         SkData* encodedData,
5793d50ea1b87132833d7eab38964f40315ba553205halcanary@google.com                         bool useData,
5803d50ea1b87132833d7eab38964f40315ba553205halcanary@google.com                         const SkString& path) {
5813d50ea1b87132833d7eab38964f40315ba553205halcanary@google.com    SkBitmap bm;
5823d50ea1b87132833d7eab38964f40315ba553205halcanary@google.com    bool success = false;
5833d50ea1b87132833d7eab38964f40315ba553205halcanary@google.com    if (useData) {
5843d50ea1b87132833d7eab38964f40315ba553205halcanary@google.com        if (NULL == encodedData) {
5853d50ea1b87132833d7eab38964f40315ba553205halcanary@google.com            return;
5863d50ea1b87132833d7eab38964f40315ba553205halcanary@google.com        }
5873d50ea1b87132833d7eab38964f40315ba553205halcanary@google.com        success = SkInstallDiscardablePixelRef(
5882d970b5128f7270cd01a93e4ce68d0c3ea67ac71commit-bot@chromium.org            SkDecodingImageGenerator::Create(encodedData, opts), &bm);
5893d50ea1b87132833d7eab38964f40315ba553205halcanary@google.com    } else {
5903d50ea1b87132833d7eab38964f40315ba553205halcanary@google.com        if (NULL == encodedStream) {
5913d50ea1b87132833d7eab38964f40315ba553205halcanary@google.com            return;
5923d50ea1b87132833d7eab38964f40315ba553205halcanary@google.com        }
5933d50ea1b87132833d7eab38964f40315ba553205halcanary@google.com        success = SkInstallDiscardablePixelRef(
5942d970b5128f7270cd01a93e4ce68d0c3ea67ac71commit-bot@chromium.org            SkDecodingImageGenerator::Create(encodedStream->duplicate(), opts), &bm);
5953d50ea1b87132833d7eab38964f40315ba553205halcanary@google.com    }
5963d50ea1b87132833d7eab38964f40315ba553205halcanary@google.com    if (!success) {
5973d50ea1b87132833d7eab38964f40315ba553205halcanary@google.com        if (opts.fUseRequestedColorType
5983d50ea1b87132833d7eab38964f40315ba553205halcanary@google.com            && (kARGB_4444_SkColorType == opts.fRequestedColorType)) {
5993d50ea1b87132833d7eab38964f40315ba553205halcanary@google.com            return;  // Ignore known conversion inabilities.
6003d50ea1b87132833d7eab38964f40315ba553205halcanary@google.com        }
6013d50ea1b87132833d7eab38964f40315ba553205halcanary@google.com        // If we get here, it's a failure and we will need more
6023d50ea1b87132833d7eab38964f40315ba553205halcanary@google.com        // information about why it failed.
603a9325fa237dde2654bc841c2bb0a05fc3e57696ahalcanary@google.com        ERRORF(reporter, "Bounds decode failed [sampleSize=%d dither=%s "
604a9325fa237dde2654bc841c2bb0a05fc3e57696ahalcanary@google.com               "colorType=%s %s]", opts.fSampleSize, yn(opts.fDitherImage),
605a9325fa237dde2654bc841c2bb0a05fc3e57696ahalcanary@google.com               options_colorType(opts), path.c_str());
6063d50ea1b87132833d7eab38964f40315ba553205halcanary@google.com        return;
6073d50ea1b87132833d7eab38964f40315ba553205halcanary@google.com    }
6083d50ea1b87132833d7eab38964f40315ba553205halcanary@google.com    #if defined(SK_BUILD_FOR_ANDROID) || defined(SK_BUILD_FOR_UNIX)
6093d50ea1b87132833d7eab38964f40315ba553205halcanary@google.com    // Android is the only system that use Skia's image decoders in
6103d50ea1b87132833d7eab38964f40315ba553205halcanary@google.com    // production.  For now, we'll only verify that samplesize works
6113d50ea1b87132833d7eab38964f40315ba553205halcanary@google.com    // on systems where it already is known to work.
6123d50ea1b87132833d7eab38964f40315ba553205halcanary@google.com    REPORTER_ASSERT(reporter, check_rounding(bm.height(), kExpectedHeight,
6133d50ea1b87132833d7eab38964f40315ba553205halcanary@google.com                                             opts.fSampleSize));
6143d50ea1b87132833d7eab38964f40315ba553205halcanary@google.com    REPORTER_ASSERT(reporter, check_rounding(bm.width(), kExpectedWidth,
6153d50ea1b87132833d7eab38964f40315ba553205halcanary@google.com                                             opts.fSampleSize));
616b7acbfe0ee940863b5e2350b0b0c3795e01751f5halcanary@google.com    // The ImageDecoder API doesn't guarantee that SampleSize does
617b7acbfe0ee940863b5e2350b0b0c3795e01751f5halcanary@google.com    // anything at all, but the decoders that this test excercises all
618b7acbfe0ee940863b5e2350b0b0c3795e01751f5halcanary@google.com    // produce an output size in the following range:
619b7acbfe0ee940863b5e2350b0b0c3795e01751f5halcanary@google.com    //    (((sample_size * out_size) > (in_size - sample_size))
620b7acbfe0ee940863b5e2350b0b0c3795e01751f5halcanary@google.com    //     && out_size <= SkNextPow2(((in_size - 1) / sample_size) + 1));
6213d50ea1b87132833d7eab38964f40315ba553205halcanary@google.com    #endif  // SK_BUILD_FOR_ANDROID || SK_BUILD_FOR_UNIX
6223d50ea1b87132833d7eab38964f40315ba553205halcanary@google.com    SkAutoLockPixels alp(bm);
6233d50ea1b87132833d7eab38964f40315ba553205halcanary@google.com    if (bm.getPixels() == NULL) {
624a9325fa237dde2654bc841c2bb0a05fc3e57696ahalcanary@google.com        ERRORF(reporter, "Pixel decode failed [sampleSize=%d dither=%s "
625a9325fa237dde2654bc841c2bb0a05fc3e57696ahalcanary@google.com               "colorType=%s %s]", opts.fSampleSize, yn(opts.fDitherImage),
626a9325fa237dde2654bc841c2bb0a05fc3e57696ahalcanary@google.com               options_colorType(opts), path.c_str());
6273d50ea1b87132833d7eab38964f40315ba553205halcanary@google.com        return;
6283d50ea1b87132833d7eab38964f40315ba553205halcanary@google.com    }
6293d50ea1b87132833d7eab38964f40315ba553205halcanary@google.com
630bfefc7c95fc0e8ebd5000c68f6d16e1a3ea0e71ereed    SkColorType requestedColorType = opts.fRequestedColorType;
6313d50ea1b87132833d7eab38964f40315ba553205halcanary@google.com    REPORTER_ASSERT(reporter,
6323d50ea1b87132833d7eab38964f40315ba553205halcanary@google.com                    (!opts.fUseRequestedColorType)
633bfefc7c95fc0e8ebd5000c68f6d16e1a3ea0e71ereed                    || (bm.colorType() == requestedColorType));
6343d50ea1b87132833d7eab38964f40315ba553205halcanary@google.com
6353d50ea1b87132833d7eab38964f40315ba553205halcanary@google.com    // Condition under which we should check the decoding results:
636bfefc7c95fc0e8ebd5000c68f6d16e1a3ea0e71ereed    if ((kN32_SkColorType == bm.colorType())
6373d50ea1b87132833d7eab38964f40315ba553205halcanary@google.com        && (!path.endsWith(".jpg"))  // lossy
6383d50ea1b87132833d7eab38964f40315ba553205halcanary@google.com        && (opts.fSampleSize == 1)) {  // scaled
6393d50ea1b87132833d7eab38964f40315ba553205halcanary@google.com        const SkColor* correctPixels = kExpectedPixels;
6403d50ea1b87132833d7eab38964f40315ba553205halcanary@google.com        SkASSERT(bm.height() == kExpectedHeight);
6413d50ea1b87132833d7eab38964f40315ba553205halcanary@google.com        SkASSERT(bm.width() == kExpectedWidth);
6423d50ea1b87132833d7eab38964f40315ba553205halcanary@google.com        int pixelErrors = 0;
6433d50ea1b87132833d7eab38964f40315ba553205halcanary@google.com        for (int y = 0; y < bm.height(); ++y) {
6443d50ea1b87132833d7eab38964f40315ba553205halcanary@google.com            for (int x = 0; x < bm.width(); ++x) {
6453d50ea1b87132833d7eab38964f40315ba553205halcanary@google.com                if (*correctPixels != bm.getColor(x, y)) {
6463d50ea1b87132833d7eab38964f40315ba553205halcanary@google.com                    ++pixelErrors;
6473d50ea1b87132833d7eab38964f40315ba553205halcanary@google.com                }
6483d50ea1b87132833d7eab38964f40315ba553205halcanary@google.com                ++correctPixels;
6493d50ea1b87132833d7eab38964f40315ba553205halcanary@google.com            }
6503d50ea1b87132833d7eab38964f40315ba553205halcanary@google.com        }
6513d50ea1b87132833d7eab38964f40315ba553205halcanary@google.com        if (pixelErrors != 0) {
652a9325fa237dde2654bc841c2bb0a05fc3e57696ahalcanary@google.com            ERRORF(reporter, "Pixel-level mismatch (%d of %d) "
653a9325fa237dde2654bc841c2bb0a05fc3e57696ahalcanary@google.com                   "[sampleSize=%d dither=%s colorType=%s %s]",
654a9325fa237dde2654bc841c2bb0a05fc3e57696ahalcanary@google.com                   pixelErrors, kExpectedHeight * kExpectedWidth,
655a9325fa237dde2654bc841c2bb0a05fc3e57696ahalcanary@google.com                   opts.fSampleSize, yn(opts.fDitherImage),
656a9325fa237dde2654bc841c2bb0a05fc3e57696ahalcanary@google.com                   options_colorType(opts), path.c_str());
6573d50ea1b87132833d7eab38964f40315ba553205halcanary@google.com        }
6583d50ea1b87132833d7eab38964f40315ba553205halcanary@google.com    }
6593d50ea1b87132833d7eab38964f40315ba553205halcanary@google.com}
6603d50ea1b87132833d7eab38964f40315ba553205halcanary@google.com
6613d50ea1b87132833d7eab38964f40315ba553205halcanary@google.com/**
6623d50ea1b87132833d7eab38964f40315ba553205halcanary@google.com *  SkDecodingImageGenerator has an Options struct which lets the
6633d50ea1b87132833d7eab38964f40315ba553205halcanary@google.com *  client of the generator set sample size, dithering, and bitmap
6643d50ea1b87132833d7eab38964f40315ba553205halcanary@google.com *  config.  This test loops through many possible options and tries
6653d50ea1b87132833d7eab38964f40315ba553205halcanary@google.com *  them on a set of 5 small encoded images (each in a different
6663d50ea1b87132833d7eab38964f40315ba553205halcanary@google.com *  format).  We test both SkData and SkStreamRewindable decoding.
6673d50ea1b87132833d7eab38964f40315ba553205halcanary@google.com */
6683d50ea1b87132833d7eab38964f40315ba553205halcanary@google.comDEF_TEST(ImageDecoderOptions, reporter) {
6693d50ea1b87132833d7eab38964f40315ba553205halcanary@google.com    const char* files[]  = {
6703d50ea1b87132833d7eab38964f40315ba553205halcanary@google.com        "randPixels.bmp",
6713d50ea1b87132833d7eab38964f40315ba553205halcanary@google.com        "randPixels.jpg",
6723d50ea1b87132833d7eab38964f40315ba553205halcanary@google.com        "randPixels.png",
6733d50ea1b87132833d7eab38964f40315ba553205halcanary@google.com        "randPixels.webp",
6743d50ea1b87132833d7eab38964f40315ba553205halcanary@google.com        #if !defined(SK_BUILD_FOR_WIN)
6753d50ea1b87132833d7eab38964f40315ba553205halcanary@google.com        // TODO(halcanary): Find out why this fails sometimes.
6763d50ea1b87132833d7eab38964f40315ba553205halcanary@google.com        "randPixels.gif",
6773d50ea1b87132833d7eab38964f40315ba553205halcanary@google.com        #endif
6783d50ea1b87132833d7eab38964f40315ba553205halcanary@google.com    };
6793d50ea1b87132833d7eab38964f40315ba553205halcanary@google.com
680bcbc1788b478b1e54079318ad073e8490aa66faetfarina    SkString resourceDir = GetResourcePath();
681b7acbfe0ee940863b5e2350b0b0c3795e01751f5halcanary@google.com    if (!sk_exists(resourceDir.c_str())) {
6823d50ea1b87132833d7eab38964f40315ba553205halcanary@google.com        return;
6833d50ea1b87132833d7eab38964f40315ba553205halcanary@google.com    }
6843d50ea1b87132833d7eab38964f40315ba553205halcanary@google.com
6853d50ea1b87132833d7eab38964f40315ba553205halcanary@google.com    int scaleList[] = {1, 2, 3, 4};
6863d50ea1b87132833d7eab38964f40315ba553205halcanary@google.com    bool ditherList[] = {true, false};
6873d50ea1b87132833d7eab38964f40315ba553205halcanary@google.com    SkColorType colorList[] = {
6883d50ea1b87132833d7eab38964f40315ba553205halcanary@google.com        kAlpha_8_SkColorType,
6893d50ea1b87132833d7eab38964f40315ba553205halcanary@google.com        kRGB_565_SkColorType,
6903d50ea1b87132833d7eab38964f40315ba553205halcanary@google.com        kARGB_4444_SkColorType,  // Most decoders will fail on 4444.
69128fcae2ec77eb16a79e155f8d788b20457f1c951commit-bot@chromium.org        kN32_SkColorType
6923d50ea1b87132833d7eab38964f40315ba553205halcanary@google.com        // Note that indexed color is left out of the list.  Lazy
6933d50ea1b87132833d7eab38964f40315ba553205halcanary@google.com        // decoding doesn't do indexed color.
6943d50ea1b87132833d7eab38964f40315ba553205halcanary@google.com    };
6953d50ea1b87132833d7eab38964f40315ba553205halcanary@google.com    const bool useDataList[] = {true, false};
6963d50ea1b87132833d7eab38964f40315ba553205halcanary@google.com
6973d50ea1b87132833d7eab38964f40315ba553205halcanary@google.com    for (size_t fidx = 0; fidx < SK_ARRAY_COUNT(files); ++fidx) {
698b7acbfe0ee940863b5e2350b0b0c3795e01751f5halcanary@google.com        SkString path = SkOSPath::SkPathJoin(resourceDir.c_str(), files[fidx]);
6993d50ea1b87132833d7eab38964f40315ba553205halcanary@google.com        if (!sk_exists(path.c_str())) {
7003d50ea1b87132833d7eab38964f40315ba553205halcanary@google.com            continue;
7013d50ea1b87132833d7eab38964f40315ba553205halcanary@google.com        }
7023d50ea1b87132833d7eab38964f40315ba553205halcanary@google.com
7033d50ea1b87132833d7eab38964f40315ba553205halcanary@google.com        SkAutoDataUnref encodedData(SkData::NewFromFileName(path.c_str()));
7043d50ea1b87132833d7eab38964f40315ba553205halcanary@google.com        REPORTER_ASSERT(reporter, encodedData.get() != NULL);
7053d50ea1b87132833d7eab38964f40315ba553205halcanary@google.com        SkAutoTUnref<SkStreamRewindable> encodedStream(
7063d50ea1b87132833d7eab38964f40315ba553205halcanary@google.com            SkStream::NewFromFile(path.c_str()));
7073d50ea1b87132833d7eab38964f40315ba553205halcanary@google.com        REPORTER_ASSERT(reporter, encodedStream.get() != NULL);
7083d50ea1b87132833d7eab38964f40315ba553205halcanary@google.com
7093d50ea1b87132833d7eab38964f40315ba553205halcanary@google.com        for (size_t i = 0; i < SK_ARRAY_COUNT(scaleList); ++i) {
7103d50ea1b87132833d7eab38964f40315ba553205halcanary@google.com            for (size_t j = 0; j < SK_ARRAY_COUNT(ditherList); ++j) {
7113d50ea1b87132833d7eab38964f40315ba553205halcanary@google.com                for (size_t m = 0; m < SK_ARRAY_COUNT(useDataList); ++m) {
7123d50ea1b87132833d7eab38964f40315ba553205halcanary@google.com                    for (size_t k = 0; k < SK_ARRAY_COUNT(colorList); ++k) {
7133d50ea1b87132833d7eab38964f40315ba553205halcanary@google.com                        SkDecodingImageGenerator::Options opts(scaleList[i],
7143d50ea1b87132833d7eab38964f40315ba553205halcanary@google.com                                                               ditherList[j],
7153d50ea1b87132833d7eab38964f40315ba553205halcanary@google.com                                                               colorList[k]);
7163d50ea1b87132833d7eab38964f40315ba553205halcanary@google.com                        test_options(reporter, opts, encodedStream, encodedData,
7173d50ea1b87132833d7eab38964f40315ba553205halcanary@google.com                                     useDataList[m], path);
7183d50ea1b87132833d7eab38964f40315ba553205halcanary@google.com
7193d50ea1b87132833d7eab38964f40315ba553205halcanary@google.com                    }
7203d50ea1b87132833d7eab38964f40315ba553205halcanary@google.com                    SkDecodingImageGenerator::Options options(scaleList[i],
7213d50ea1b87132833d7eab38964f40315ba553205halcanary@google.com                                                              ditherList[j]);
7223d50ea1b87132833d7eab38964f40315ba553205halcanary@google.com                    test_options(reporter, options, encodedStream, encodedData,
7233d50ea1b87132833d7eab38964f40315ba553205halcanary@google.com                                 useDataList[m], path);
7243d50ea1b87132833d7eab38964f40315ba553205halcanary@google.com                }
7253d50ea1b87132833d7eab38964f40315ba553205halcanary@google.com            }
7263d50ea1b87132833d7eab38964f40315ba553205halcanary@google.com        }
7273d50ea1b87132833d7eab38964f40315ba553205halcanary@google.com    }
7283d50ea1b87132833d7eab38964f40315ba553205halcanary@google.com}
729