| Index: tests/CodecTest.cpp
|
| diff --git a/tests/CodecTest.cpp b/tests/CodecTest.cpp
|
| index bdb5e7792e983c686a3de82a4d4064da76846d73..117ce959244f6e27068a0b185fbba1f65e2763ac 100644
|
| --- a/tests/CodecTest.cpp
|
| +++ b/tests/CodecTest.cpp
|
| @@ -83,6 +83,66 @@ SkIRect generate_random_subset(SkRandom* rand, int w, int h) {
|
| return rect;
|
| }
|
|
|
| +static void test_incremental_decode(skiatest::Reporter* r, SkCodec* codec, const SkImageInfo& info,
|
| + const SkMD5::Digest& goodDigest) {
|
| + SkBitmap bm;
|
| + bm.allocPixels(info);
|
| + SkAutoLockPixels autoLockPixels(bm);
|
| +
|
| + REPORTER_ASSERT(r, SkCodec::kSuccess == codec->startIncrementalDecode(info));
|
| +
|
| + REPORTER_ASSERT(r, SkCodec::kSuccess == codec->incrementalDecode(
|
| + [&bm](int rowNum) -> void* {
|
| + return bm.getAddr(0, rowNum);
|
| + }));
|
| +
|
| + compare_to_good_digest(r, goodDigest, bm);
|
| +}
|
| +
|
| +// Test in stripes, similar to DM's kStripe_Mode
|
| +static void test_in_stripes(skiatest::Reporter* r, SkCodec* codec, const SkImageInfo& info,
|
| + const SkMD5::Digest& goodDigest) {
|
| + SkBitmap bm;
|
| + bm.allocPixels(info);
|
| + bm.eraseColor(SK_ColorYELLOW);
|
| +
|
| + const int height = info.height();
|
| + // Note that if numStripes does not evenly divide height there will be an extra
|
| + // stripe.
|
| + const int numStripes = 4;
|
| +
|
| + if (numStripes > height) {
|
| + // Image is too small.
|
| + return;
|
| + }
|
| +
|
| + const int stripeHeight = height / numStripes;
|
| +
|
| + // Iterate through the image twice. Once to decode odd stripes, and once for even.
|
| + for (int oddEven = 1; oddEven >= 0; oddEven--) {
|
| + for (int y = oddEven * stripeHeight; y < height; y += 2 * stripeHeight) {
|
| + SkIRect subset = SkIRect::MakeLTRB(0, y, info.width(),
|
| + SkTMin(y + stripeHeight, height));
|
| + SkCodec::Options options;
|
| + options.fSubset = ⊂
|
| + if (SkCodec::kSuccess != codec->startIncrementalDecode(info, &options)) {
|
| + ERRORF(r, "failed to start incremental decode!\ttop: %i\tbottom%i\n",
|
| + subset.top(), subset.bottom());
|
| + return;
|
| + }
|
| + if (SkCodec::kSuccess != codec->incrementalDecode(
|
| + [&bm](int rowNum) -> void* {
|
| + return bm.getAddr(0, rowNum);
|
| + })) {
|
| + ERRORF(r, "failed incremental decode starting from line %i\n", y);
|
| + return;
|
| + }
|
| + }
|
| + }
|
| +
|
| + compare_to_good_digest(r, goodDigest, bm);
|
| +}
|
| +
|
| template<typename Codec>
|
| static void test_codec(skiatest::Reporter* r, Codec* codec, SkBitmap& bm, const SkImageInfo& info,
|
| const SkISize& size, SkCodec::Result expectedResult, SkMD5::Digest* digest,
|
| @@ -151,12 +211,14 @@ static bool supports_partial_scanlines(const char path[]) {
|
| return false;
|
| }
|
|
|
| +// FIXME: Break up this giant function
|
| static void check(skiatest::Reporter* r,
|
| const char path[],
|
| SkISize size,
|
| bool supportsScanlineDecoding,
|
| bool supportsSubsetDecoding,
|
| - bool supportsIncomplete = true) {
|
| + bool supportsIncomplete,
|
| + bool supportsNewScanlineDecoding = false) {
|
|
|
| SkAutoTDelete<SkStream> stream(resource(path));
|
| if (!stream) {
|
| @@ -186,12 +248,15 @@ static void check(skiatest::Reporter* r,
|
| test_codec(r, codec.get(), bm, info, size, expectedResult, &codecDigest, nullptr);
|
|
|
| // Scanline decoding follows.
|
| - // Need to call startScanlineDecode() first.
|
| - REPORTER_ASSERT(r, codec->getScanlines(bm.getAddr(0, 0), 1, 0)
|
| - == 0);
|
| - REPORTER_ASSERT(r, codec->skipScanlines(1)
|
| - == 0);
|
|
|
| + if (supportsNewScanlineDecoding && !isIncomplete) {
|
| + test_incremental_decode(r, codec, info, codecDigest);
|
| + test_in_stripes(r, codec, info, codecDigest);
|
| + }
|
| +
|
| + // Need to call startScanlineDecode() first.
|
| + REPORTER_ASSERT(r, codec->getScanlines(bm.getAddr(0, 0), 1, 0) == 0);
|
| + REPORTER_ASSERT(r, !codec->skipScanlines(1));
|
| const SkCodec::Result startResult = codec->startScanlineDecode(info);
|
| if (supportsScanlineDecoding) {
|
| bm.eraseColor(SK_ColorYELLOW);
|
| @@ -286,7 +351,7 @@ static void check(skiatest::Reporter* r,
|
| }
|
|
|
| // SkAndroidCodec tests
|
| - if (supportsScanlineDecoding || supportsSubsetDecoding) {
|
| + if (supportsScanlineDecoding || supportsSubsetDecoding || supportsNewScanlineDecoding) {
|
|
|
| SkAutoTDelete<SkStream> stream(resource(path));
|
| if (!stream) {
|
| @@ -343,16 +408,16 @@ static void check(skiatest::Reporter* r,
|
|
|
| DEF_TEST(Codec, r) {
|
| // WBMP
|
| - check(r, "mandrill.wbmp", SkISize::Make(512, 512), true, false);
|
| + check(r, "mandrill.wbmp", SkISize::Make(512, 512), true, false, true);
|
|
|
| // WEBP
|
| - check(r, "baby_tux.webp", SkISize::Make(386, 395), false, true);
|
| - check(r, "color_wheel.webp", SkISize::Make(128, 128), false, true);
|
| - check(r, "yellow_rose.webp", SkISize::Make(400, 301), false, true);
|
| + check(r, "baby_tux.webp", SkISize::Make(386, 395), false, true, true);
|
| + check(r, "color_wheel.webp", SkISize::Make(128, 128), false, true, true);
|
| + check(r, "yellow_rose.webp", SkISize::Make(400, 301), false, true, true);
|
|
|
| // BMP
|
| - check(r, "randPixels.bmp", SkISize::Make(8, 8), true, false);
|
| - check(r, "rle.bmp", SkISize::Make(320, 240), true, false);
|
| + check(r, "randPixels.bmp", SkISize::Make(8, 8), true, false, true);
|
| + check(r, "rle.bmp", SkISize::Make(320, 240), true, false, true);
|
|
|
| // ICO
|
| // FIXME: We are not ready to test incomplete ICOs
|
| @@ -360,7 +425,7 @@ DEF_TEST(Codec, r) {
|
| // Decodes an embedded BMP image
|
| check(r, "color_wheel.ico", SkISize::Make(128, 128), true, false, false);
|
| // Decodes an embedded PNG image
|
| - check(r, "google_chrome.ico", SkISize::Make(256, 256), true, false, false);
|
| + check(r, "google_chrome.ico", SkISize::Make(256, 256), false, false, false, true);
|
|
|
| // GIF
|
| // FIXME: We are not ready to test incomplete GIFs
|
| @@ -370,30 +435,30 @@ DEF_TEST(Codec, r) {
|
| check(r, "randPixels.gif", SkISize::Make(8, 8), true, false, false);
|
|
|
| // JPG
|
| - check(r, "CMYK.jpg", SkISize::Make(642, 516), true, false);
|
| - check(r, "color_wheel.jpg", SkISize::Make(128, 128), true, false);
|
| + check(r, "CMYK.jpg", SkISize::Make(642, 516), true, false, true);
|
| + check(r, "color_wheel.jpg", SkISize::Make(128, 128), true, false, true);
|
| // grayscale.jpg is too small to test incomplete
|
| check(r, "grayscale.jpg", SkISize::Make(128, 128), true, false, false);
|
| - check(r, "mandrill_512_q075.jpg", SkISize::Make(512, 512), true, false);
|
| + check(r, "mandrill_512_q075.jpg", SkISize::Make(512, 512), true, false, true);
|
| // randPixels.jpg is too small to test incomplete
|
| check(r, "randPixels.jpg", SkISize::Make(8, 8), true, false, false);
|
|
|
| // PNG
|
| - check(r, "arrow.png", SkISize::Make(187, 312), true, false, false);
|
| - check(r, "baby_tux.png", SkISize::Make(240, 246), true, false, false);
|
| - check(r, "color_wheel.png", SkISize::Make(128, 128), true, false, false);
|
| - check(r, "half-transparent-white-pixel.png", SkISize::Make(1, 1), true, false, false);
|
| - check(r, "mandrill_128.png", SkISize::Make(128, 128), true, false, false);
|
| - check(r, "mandrill_16.png", SkISize::Make(16, 16), true, false, false);
|
| - check(r, "mandrill_256.png", SkISize::Make(256, 256), true, false, false);
|
| - check(r, "mandrill_32.png", SkISize::Make(32, 32), true, false, false);
|
| - check(r, "mandrill_512.png", SkISize::Make(512, 512), true, false, false);
|
| - check(r, "mandrill_64.png", SkISize::Make(64, 64), true, false, false);
|
| - check(r, "plane.png", SkISize::Make(250, 126), true, false, false);
|
| - // FIXME: We are not ready to test incomplete interlaced pngs
|
| - check(r, "plane_interlaced.png", SkISize::Make(250, 126), true, false, false);
|
| - check(r, "randPixels.png", SkISize::Make(8, 8), true, false, false);
|
| - check(r, "yellow_rose.png", SkISize::Make(400, 301), true, false, false);
|
| + check(r, "arrow.png", SkISize::Make(187, 312), false, false, true, true);
|
| + check(r, "baby_tux.png", SkISize::Make(240, 246), false, false, true, true);
|
| + check(r, "color_wheel.png", SkISize::Make(128, 128), false, false, true, true);
|
| + // half-transparent-white-pixel.png is too small to test incomplete
|
| + check(r, "half-transparent-white-pixel.png", SkISize::Make(1, 1), false, false, false, true);
|
| + check(r, "mandrill_128.png", SkISize::Make(128, 128), false, false, true, true);
|
| + check(r, "mandrill_16.png", SkISize::Make(16, 16), false, false, true, true);
|
| + check(r, "mandrill_256.png", SkISize::Make(256, 256), false, false, true, true);
|
| + check(r, "mandrill_32.png", SkISize::Make(32, 32), false, false, true, true);
|
| + check(r, "mandrill_512.png", SkISize::Make(512, 512), false, false, true, true);
|
| + check(r, "mandrill_64.png", SkISize::Make(64, 64), false, false, true, true);
|
| + check(r, "plane.png", SkISize::Make(250, 126), false, false, true, true);
|
| + check(r, "plane_interlaced.png", SkISize::Make(250, 126), false, false, true, true);
|
| + check(r, "randPixels.png", SkISize::Make(8, 8), false, false, true, true);
|
| + check(r, "yellow_rose.png", SkISize::Make(400, 301), false, false, true, true);
|
|
|
| // RAW
|
| // Disable RAW tests for Win32.
|
| @@ -404,97 +469,6 @@ DEF_TEST(Codec, r) {
|
| #endif
|
| }
|
|
|
| -// Test interlaced PNG in stripes, similar to DM's kStripe_Mode
|
| -DEF_TEST(Codec_stripes, r) {
|
| - const char * path = "plane_interlaced.png";
|
| - SkAutoTDelete<SkStream> stream(resource(path));
|
| - if (!stream) {
|
| - SkDebugf("Missing resource '%s'\n", path);
|
| - }
|
| -
|
| - SkAutoTDelete<SkCodec> codec(SkCodec::NewFromStream(stream.release()));
|
| - REPORTER_ASSERT(r, codec);
|
| -
|
| - if (!codec) {
|
| - return;
|
| - }
|
| -
|
| - switch (codec->getScanlineOrder()) {
|
| - case SkCodec::kBottomUp_SkScanlineOrder:
|
| - case SkCodec::kOutOfOrder_SkScanlineOrder:
|
| - ERRORF(r, "This scanline order will not match the original.");
|
| - return;
|
| - default:
|
| - break;
|
| - }
|
| -
|
| - // Baseline for what the image should look like, using N32.
|
| - const SkImageInfo info = codec->getInfo().makeColorType(kN32_SkColorType);
|
| -
|
| - SkBitmap bm;
|
| - bm.allocPixels(info);
|
| - SkAutoLockPixels autoLockPixels(bm);
|
| - SkCodec::Result result = codec->getPixels(info, bm.getPixels(), bm.rowBytes());
|
| - REPORTER_ASSERT(r, result == SkCodec::kSuccess);
|
| -
|
| - SkMD5::Digest digest;
|
| - md5(bm, &digest);
|
| -
|
| - // Now decode in stripes
|
| - const int height = info.height();
|
| - const int numStripes = 4;
|
| - int stripeHeight;
|
| - int remainingLines;
|
| - SkTDivMod(height, numStripes, &stripeHeight, &remainingLines);
|
| -
|
| - bm.eraseColor(SK_ColorYELLOW);
|
| -
|
| - result = codec->startScanlineDecode(info);
|
| - REPORTER_ASSERT(r, result == SkCodec::kSuccess);
|
| -
|
| - // Odd stripes
|
| - for (int i = 1; i < numStripes; i += 2) {
|
| - // Skip the even stripes
|
| - bool skipResult = codec->skipScanlines(stripeHeight);
|
| - REPORTER_ASSERT(r, skipResult);
|
| -
|
| - int linesDecoded = codec->getScanlines(bm.getAddr(0, i * stripeHeight), stripeHeight,
|
| - bm.rowBytes());
|
| - REPORTER_ASSERT(r, linesDecoded == stripeHeight);
|
| - }
|
| -
|
| - // Even stripes
|
| - result = codec->startScanlineDecode(info);
|
| - REPORTER_ASSERT(r, result == SkCodec::kSuccess);
|
| -
|
| - for (int i = 0; i < numStripes; i += 2) {
|
| - int linesDecoded = codec->getScanlines(bm.getAddr(0, i * stripeHeight), stripeHeight,
|
| - bm.rowBytes());
|
| - REPORTER_ASSERT(r, linesDecoded == stripeHeight);
|
| -
|
| - // Skip the odd stripes
|
| - if (i + 1 < numStripes) {
|
| - bool skipResult = codec->skipScanlines(stripeHeight);
|
| - REPORTER_ASSERT(r, skipResult);
|
| - }
|
| - }
|
| -
|
| - // Remainder at the end
|
| - if (remainingLines > 0) {
|
| - result = codec->startScanlineDecode(info);
|
| - REPORTER_ASSERT(r, result == SkCodec::kSuccess);
|
| -
|
| - bool skipResult = codec->skipScanlines(height - remainingLines);
|
| - REPORTER_ASSERT(r, skipResult);
|
| -
|
| - int linesDecoded = codec->getScanlines(bm.getAddr(0, height - remainingLines),
|
| - remainingLines, bm.rowBytes());
|
| - REPORTER_ASSERT(r, linesDecoded == remainingLines);
|
| - }
|
| -
|
| - compare_to_good_digest(r, digest, bm);
|
| -}
|
| -
|
| static void test_invalid_stream(skiatest::Reporter* r, const void* stream, size_t len) {
|
| // Neither of these calls should return a codec. Bots should catch us if we leaked anything.
|
| SkCodec* codec = SkCodec::NewFromStream(new SkMemoryStream(stream, len, false));
|
| @@ -638,25 +612,32 @@ static void test_invalid_parameters(skiatest::Reporter* r, const char path[]) {
|
| }
|
| SkAutoTDelete<SkCodec> decoder(SkCodec::NewFromStream(stream.release()));
|
|
|
| + const SkImageInfo info = decoder->getInfo().makeColorType(kIndex_8_SkColorType);
|
| +
|
| // This should return kSuccess because kIndex8 is supported.
|
| SkPMColor colorStorage[256];
|
| int colorCount;
|
| - SkCodec::Result result = decoder->startScanlineDecode(
|
| - decoder->getInfo().makeColorType(kIndex_8_SkColorType), nullptr, colorStorage, &colorCount);
|
| - REPORTER_ASSERT(r, SkCodec::kSuccess == result);
|
| - // The rest of the test is uninteresting if kIndex8 is not supported
|
| - if (SkCodec::kSuccess != result) {
|
| + SkCodec::Result result = decoder->startScanlineDecode(info, nullptr, colorStorage,
|
| + &colorCount);
|
| + if (SkCodec::kSuccess == result) {
|
| + // This should return kInvalidParameters because, in kIndex_8 mode, we must pass in a valid
|
| + // colorPtr and a valid colorCountPtr.
|
| + result = decoder->startScanlineDecode(info, nullptr, nullptr, nullptr);
|
| + REPORTER_ASSERT(r, SkCodec::kInvalidParameters == result);
|
| + result = decoder->startScanlineDecode(info);
|
| + REPORTER_ASSERT(r, SkCodec::kInvalidParameters == result);
|
| + } else if (SkCodec::kUnimplemented == result) {
|
| + // New method should be supported:
|
| + result = decoder->startIncrementalDecode(info, nullptr, colorStorage, &colorCount);
|
| + REPORTER_ASSERT(r, SkCodec::kSuccess == result);
|
| + result = decoder->startIncrementalDecode(info);
|
| + REPORTER_ASSERT(r, SkCodec::kInvalidParameters == result);
|
| + } else {
|
| + // The test is uninteresting if kIndex8 is not supported
|
| + ERRORF(r, "Should not call test_invalid_parameters for non-Index8 file: %s\n", path);
|
| return;
|
| }
|
|
|
| - // This should return kInvalidParameters because, in kIndex_8 mode, we must pass in a valid
|
| - // colorPtr and a valid colorCountPtr.
|
| - result = decoder->startScanlineDecode(
|
| - decoder->getInfo().makeColorType(kIndex_8_SkColorType), nullptr, nullptr, nullptr);
|
| - REPORTER_ASSERT(r, SkCodec::kInvalidParameters == result);
|
| - result = decoder->startScanlineDecode(
|
| - decoder->getInfo().makeColorType(kIndex_8_SkColorType));
|
| - REPORTER_ASSERT(r, SkCodec::kInvalidParameters == result);
|
| }
|
|
|
| DEF_TEST(Codec_Params, r) {
|
|
|