Index: tests/CodexTest.cpp |
diff --git a/tests/CodexTest.cpp b/tests/CodexTest.cpp |
index 63631822de45b16c3f3a31bd0406139a7d8b7343..c2979056ab4960aae334e751d350e823d63dc317 100644 |
--- a/tests/CodexTest.cpp |
+++ b/tests/CodexTest.cpp |
@@ -8,6 +8,7 @@ |
#include "Resources.h" |
#include "SkBitmap.h" |
#include "SkCodec.h" |
+#include "SkData.h" |
#include "SkMD5.h" |
#include "SkRandom.h" |
#include "SkScaledCodec.h" |
@@ -75,14 +76,15 @@ SkIRect generate_random_subset(SkRandom* rand, int w, int h) { |
} |
static void test_codec(skiatest::Reporter* r, SkCodec* codec, SkBitmap& bm, const SkImageInfo& info, |
- const SkISize& size, bool supports565, SkMD5::Digest* digest, |
- const SkMD5::Digest* goodDigest) { |
+ const SkISize& size, bool supports565, SkCodec::Result expectedResult, |
+ SkMD5::Digest* digest, const SkMD5::Digest* goodDigest) { |
+ |
REPORTER_ASSERT(r, info.dimensions() == size); |
bm.allocPixels(info); |
SkAutoLockPixels autoLockPixels(bm); |
SkCodec::Result result = codec->getPixels(info, bm.getPixels(), bm.rowBytes()); |
- REPORTER_ASSERT(r, result == SkCodec::kSuccess); |
+ REPORTER_ASSERT(r, result == expectedResult); |
md5(bm, digest); |
if (goodDigest) { |
@@ -92,16 +94,16 @@ static void test_codec(skiatest::Reporter* r, SkCodec* codec, SkBitmap& bm, cons |
{ |
// Test decoding to 565 |
SkImageInfo info565 = info.makeColorType(kRGB_565_SkColorType); |
- SkCodec::Result expected = (supports565 && info.alphaType() == kOpaque_SkAlphaType) ? |
- SkCodec::kSuccess : SkCodec::kInvalidConversion; |
- test_info(r, codec, info565, expected, nullptr); |
+ SkCodec::Result expected565 = (supports565 && info.alphaType() == kOpaque_SkAlphaType) ? |
+ expectedResult : SkCodec::kInvalidConversion; |
+ test_info(r, codec, info565, expected565, nullptr); |
} |
// Verify that re-decoding gives the same result. It is interesting to check this after |
// a decode to 565, since choosing to decode to 565 may result in some of the decode |
// options being modified. These options should return to their defaults on another |
// decode to kN32, so the new digest should match the old digest. |
- test_info(r, codec, info, SkCodec::kSuccess, digest); |
+ test_info(r, codec, info, expectedResult, digest); |
{ |
// Check alpha type conversions |
@@ -121,7 +123,7 @@ static void test_codec(skiatest::Reporter* r, SkCodec* codec, SkBitmap& bm, cons |
otherAt = kPremul_SkAlphaType; |
} |
// The other non-opaque alpha type should always succeed, but not match. |
- test_info(r, codec, info.makeAlphaType(otherAt), SkCodec::kSuccess, nullptr); |
+ test_info(r, codec, info.makeAlphaType(otherAt), expectedResult, nullptr); |
} |
} |
} |
@@ -131,14 +133,24 @@ static void check(skiatest::Reporter* r, |
SkISize size, |
bool supportsScanlineDecoding, |
bool supportsSubsetDecoding, |
- bool supports565 = true) { |
+ bool supports565 = true, |
+ bool supportsIncomplete = true) { |
SkAutoTDelete<SkStream> stream(resource(path)); |
if (!stream) { |
SkDebugf("Missing resource '%s'\n", path); |
return; |
} |
- SkAutoTDelete<SkCodec> codec(SkCodec::NewFromStream(stream.detach())); |
+ |
+ SkAutoTDelete<SkCodec> codec(nullptr); |
+ bool isIncomplete = supportsIncomplete; |
+ if (isIncomplete) { |
+ size_t size = stream->getLength(); |
+ SkAutoTUnref<SkData> data((SkData::NewFromStream(stream, 2 * size / 3))); |
+ codec.reset(SkCodec::NewFromData(data)); |
+ } else { |
+ codec.reset(SkCodec::NewFromStream(stream.detach())); |
+ } |
if (!codec) { |
ERRORF(r, "Unable to decode '%s'", path); |
return; |
@@ -148,14 +160,15 @@ static void check(skiatest::Reporter* r, |
SkMD5::Digest codecDigest; |
SkImageInfo info = codec->getInfo().makeColorType(kN32_SkColorType); |
SkBitmap bm; |
- test_codec(r, codec, bm, info, size, supports565, &codecDigest, nullptr); |
+ SkCodec::Result expectedResult = isIncomplete ? SkCodec::kIncompleteInput : SkCodec::kSuccess; |
+ test_codec(r, codec, bm, info, size, supports565, expectedResult, &codecDigest, nullptr); |
// Scanline decoding follows. |
// Need to call startScanlineDecode() first. |
REPORTER_ASSERT(r, codec->getScanlines(bm.getAddr(0, 0), 1, 0) |
- == SkCodec::kScanlineDecodingNotStarted); |
+ == 0); |
REPORTER_ASSERT(r, codec->skipScanlines(1) |
- == SkCodec::kScanlineDecodingNotStarted); |
+ == 0); |
const SkCodec::Result startResult = codec->startScanlineDecode(info); |
if (supportsScanlineDecoding) { |
@@ -164,8 +177,10 @@ static void check(skiatest::Reporter* r, |
REPORTER_ASSERT(r, startResult == SkCodec::kSuccess); |
for (int y = 0; y < info.height(); y++) { |
- SkCodec::Result result = codec->getScanlines(bm.getAddr(0, y), 1, 0); |
- REPORTER_ASSERT(r, result == SkCodec::kSuccess); |
+ const int lines = codec->getScanlines(bm.getAddr(0, y), 1, 0); |
+ if (!isIncomplete) { |
+ REPORTER_ASSERT(r, 1 == lines); |
+ } |
} |
// verify that scanline decoding gives the same result. |
if (SkCodec::kTopDown_SkScanlineOrder == codec->getScanlineOrder()) { |
@@ -174,19 +189,21 @@ static void check(skiatest::Reporter* r, |
// Cannot continue to decode scanlines beyond the end |
REPORTER_ASSERT(r, codec->getScanlines(bm.getAddr(0, 0), 1, 0) |
- == SkCodec::kInvalidParameters); |
+ == 0); |
// Interrupting a scanline decode with a full decode starts from |
// scratch |
REPORTER_ASSERT(r, codec->startScanlineDecode(info) == SkCodec::kSuccess); |
- REPORTER_ASSERT(r, codec->getScanlines(bm.getAddr(0, 0), 1, 0) |
- == SkCodec::kSuccess); |
+ const int lines = codec->getScanlines(bm.getAddr(0, 0), 1, 0); |
+ if (!isIncomplete) { |
+ REPORTER_ASSERT(r, lines == 1); |
+ } |
REPORTER_ASSERT(r, codec->getPixels(bm.info(), bm.getPixels(), bm.rowBytes()) |
- == SkCodec::kSuccess); |
+ == expectedResult); |
REPORTER_ASSERT(r, codec->getScanlines(bm.getAddr(0, 0), 1, 0) |
- == SkCodec::kScanlineDecodingNotStarted); |
+ == 0); |
REPORTER_ASSERT(r, codec->skipScanlines(1) |
- == SkCodec::kScanlineDecodingNotStarted); |
+ == 0); |
} else { |
REPORTER_ASSERT(r, startResult == SkCodec::kUnimplemented); |
} |
@@ -216,7 +233,7 @@ static void check(skiatest::Reporter* r, |
&opts, nullptr, nullptr); |
if (supportsSubsetDecoding) { |
- REPORTER_ASSERT(r, result == SkCodec::kSuccess); |
+ REPORTER_ASSERT(r, result == expectedResult); |
// Webp is the only codec that supports subsets, and it will have modified the subset |
// to have even left/top. |
REPORTER_ASSERT(r, SkIsAlign2(subset.fLeft) && SkIsAlign2(subset.fTop)); |
@@ -233,7 +250,15 @@ static void check(skiatest::Reporter* r, |
SkDebugf("Missing resource '%s'\n", path); |
return; |
} |
- SkAutoTDelete<SkCodec> codec(SkScaledCodec::NewFromStream(stream.detach())); |
+ |
+ SkAutoTDelete<SkCodec> codec(nullptr); |
+ if (isIncomplete) { |
+ size_t size = stream->getLength(); |
+ SkAutoTUnref<SkData> data((SkData::NewFromStream(stream, 2 * size / 3))); |
+ codec.reset(SkScaledCodec::NewFromData(data)); |
+ } else { |
+ codec.reset(SkScaledCodec::NewFromStream(stream.detach())); |
+ } |
if (!codec) { |
ERRORF(r, "Unable to decode '%s'", path); |
return; |
@@ -241,7 +266,13 @@ static void check(skiatest::Reporter* r, |
SkBitmap bm; |
SkMD5::Digest scaledCodecDigest; |
- test_codec(r, codec, bm, info, size, supports565, &scaledCodecDigest, &codecDigest); |
+ test_codec(r, codec, bm, info, size, supports565, expectedResult, &scaledCodecDigest, |
+ &codecDigest); |
+ } |
+ |
+ // If we've just tested incomplete decodes, let's run the same test again on full decodes. |
+ if (isIncomplete) { |
+ check(r, path, size, supportsScanlineDecoding, supportsSubsetDecoding, supports565, false); |
} |
} |
@@ -258,39 +289,45 @@ DEF_TEST(Codec, r) { |
check(r, "randPixels.bmp", SkISize::Make(8, 8), true, false); |
// ICO |
+ // FIXME: We are not ready to test incomplete ICOs |
// These two tests examine interestingly different behavior: |
// Decodes an embedded BMP image |
- check(r, "color_wheel.ico", SkISize::Make(128, 128), false, false); |
+ check(r, "color_wheel.ico", SkISize::Make(128, 128), false, false, true, false); |
// Decodes an embedded PNG image |
- check(r, "google_chrome.ico", SkISize::Make(256, 256), false, false); |
+ check(r, "google_chrome.ico", SkISize::Make(256, 256), false, false, true, false); |
// GIF |
- check(r, "box.gif", SkISize::Make(200, 55), true, false); |
- check(r, "color_wheel.gif", SkISize::Make(128, 128), true, false); |
- check(r, "randPixels.gif", SkISize::Make(8, 8), true, false); |
+ // FIXME: We are not ready to test incomplete GIFs |
+ check(r, "box.gif", SkISize::Make(200, 55), true, false, true, false); |
+ check(r, "color_wheel.gif", SkISize::Make(128, 128), true, false, true, false); |
+ // randPixels.gif is too small to test incomplete |
+ check(r, "randPixels.gif", SkISize::Make(8, 8), true, false, true, false); |
// JPG |
check(r, "CMYK.jpg", SkISize::Make(642, 516), true, false, false); |
check(r, "color_wheel.jpg", SkISize::Make(128, 128), true, false); |
- check(r, "grayscale.jpg", SkISize::Make(128, 128), true, false); |
+ // grayscale.jpg is too small to test incomplete |
+ check(r, "grayscale.jpg", SkISize::Make(128, 128), true, false, true, false); |
check(r, "mandrill_512_q075.jpg", SkISize::Make(512, 512), true, false); |
- check(r, "randPixels.jpg", SkISize::Make(8, 8), true, false); |
+ // randPixels.jpg is too small to test incomplete |
+ check(r, "randPixels.jpg", SkISize::Make(8, 8), true, false, true, false); |
// PNG |
- check(r, "arrow.png", SkISize::Make(187, 312), true, false); |
- check(r, "baby_tux.png", SkISize::Make(240, 246), true, false); |
- check(r, "color_wheel.png", SkISize::Make(128, 128), true, false); |
- check(r, "half-transparent-white-pixel.png", SkISize::Make(1, 1), true, false); |
- check(r, "mandrill_128.png", SkISize::Make(128, 128), true, false); |
- check(r, "mandrill_16.png", SkISize::Make(16, 16), true, false); |
- check(r, "mandrill_256.png", SkISize::Make(256, 256), true, false); |
- check(r, "mandrill_32.png", SkISize::Make(32, 32), true, false); |
- check(r, "mandrill_512.png", SkISize::Make(512, 512), true, false); |
- check(r, "mandrill_64.png", SkISize::Make(64, 64), true, false); |
- check(r, "plane.png", SkISize::Make(250, 126), true, false); |
- check(r, "plane_interlaced.png", SkISize::Make(250, 126), true, false); |
- check(r, "randPixels.png", SkISize::Make(8, 8), true, false); |
- check(r, "yellow_rose.png", SkISize::Make(400, 301), true, false); |
+ check(r, "arrow.png", SkISize::Make(187, 312), true, false, true, false); |
+ check(r, "baby_tux.png", SkISize::Make(240, 246), true, false, true, false); |
+ check(r, "color_wheel.png", SkISize::Make(128, 128), true, false, true, false); |
+ check(r, "half-transparent-white-pixel.png", SkISize::Make(1, 1), true, false, true, false); |
+ check(r, "mandrill_128.png", SkISize::Make(128, 128), true, false, true, false); |
+ check(r, "mandrill_16.png", SkISize::Make(16, 16), true, false, true, false); |
+ check(r, "mandrill_256.png", SkISize::Make(256, 256), true, false, true, false); |
+ check(r, "mandrill_32.png", SkISize::Make(32, 32), true, false, true, false); |
+ check(r, "mandrill_512.png", SkISize::Make(512, 512), true, false, true, false); |
+ check(r, "mandrill_64.png", SkISize::Make(64, 64), true, false, true, false); |
+ check(r, "plane.png", SkISize::Make(250, 126), true, false, true, false); |
+ // FIXME: We are not ready to test incomplete interlaced pngs |
+ check(r, "plane_interlaced.png", SkISize::Make(250, 126), true, false, true, false); |
+ check(r, "randPixels.png", SkISize::Make(8, 8), true, false, true, false); |
+ check(r, "yellow_rose.png", SkISize::Make(400, 301), true, false, true, false); |
} |
// Test interlaced PNG in stripes, similar to DM's kStripe_Mode |
@@ -344,12 +381,12 @@ DEF_TEST(Codec_stripes, r) { |
// Odd stripes |
for (int i = 1; i < numStripes; i += 2) { |
// Skip the even stripes |
- result = codec->skipScanlines(stripeHeight); |
- REPORTER_ASSERT(r, result == SkCodec::kSuccess); |
+ bool skipResult = codec->skipScanlines(stripeHeight); |
+ REPORTER_ASSERT(r, skipResult); |
- result = codec->getScanlines(bm.getAddr(0, i * stripeHeight), stripeHeight, |
+ int linesDecoded = codec->getScanlines(bm.getAddr(0, i * stripeHeight), stripeHeight, |
bm.rowBytes()); |
- REPORTER_ASSERT(r, result == SkCodec::kSuccess); |
+ REPORTER_ASSERT(r, linesDecoded == stripeHeight); |
} |
// Even stripes |
@@ -357,14 +394,14 @@ DEF_TEST(Codec_stripes, r) { |
REPORTER_ASSERT(r, result == SkCodec::kSuccess); |
for (int i = 0; i < numStripes; i += 2) { |
- result = codec->getScanlines(bm.getAddr(0, i * stripeHeight), stripeHeight, |
+ int linesDecoded = codec->getScanlines(bm.getAddr(0, i * stripeHeight), stripeHeight, |
bm.rowBytes()); |
- REPORTER_ASSERT(r, result == SkCodec::kSuccess); |
+ REPORTER_ASSERT(r, linesDecoded == stripeHeight); |
// Skip the odd stripes |
if (i + 1 < numStripes) { |
- result = codec->skipScanlines(stripeHeight); |
- REPORTER_ASSERT(r, result == SkCodec::kSuccess); |
+ bool skipResult = codec->skipScanlines(stripeHeight); |
+ REPORTER_ASSERT(r, skipResult); |
} |
} |
@@ -373,12 +410,12 @@ DEF_TEST(Codec_stripes, r) { |
result = codec->startScanlineDecode(info); |
REPORTER_ASSERT(r, result == SkCodec::kSuccess); |
- result = codec->skipScanlines(height - remainingLines); |
- REPORTER_ASSERT(r, result == SkCodec::kSuccess); |
+ bool skipResult = codec->skipScanlines(height - remainingLines); |
+ REPORTER_ASSERT(r, skipResult); |
- result = codec->getScanlines(bm.getAddr(0, height - remainingLines), |
+ int linesDecoded = codec->getScanlines(bm.getAddr(0, height - remainingLines), |
remainingLines, bm.rowBytes()); |
- REPORTER_ASSERT(r, result == SkCodec::kSuccess); |
+ REPORTER_ASSERT(r, linesDecoded == remainingLines); |
} |
compare_to_good_digest(r, digest, bm); |