aboutsummaryrefslogtreecommitdiffhomepage
path: root/tests/CodexTest.cpp
diff options
context:
space:
mode:
authorGravatar scroggo <scroggo@google.com>2015-12-08 18:54:13 -0800
committerGravatar Commit bot <commit-bot@chromium.org>2015-12-08 18:54:13 -0800
commitdb30be2f9470d21fe37b63d145c1fcca9a6ad98c (patch)
tree885e9e207682233ab03acaba6461c34779c288ee /tests/CodexTest.cpp
parent0671b967eb02d44c8951dc4dc39df09fac15b097 (diff)
Make SkCodec support peek() and read()
- Update SkCodec's dox to point out that some of the data must be read twice in order to decode - Add an accessor that reports how much is needed for reading twice - Make SkCodec default to use peek() If an input stream supports peek()ing, peek() instead of reading. This way the stream need not implement rewind() - Make SkCodec use read() + rewind() as a backup So that streams without peek() implemented can still function properly (assuming they can rewind). - read everything we may need to determine the format once In SkCodec::NewFromStream, peek()/read() 14 bytes, which is enough to read all of the types we support. Pass the buffer to each subtype, which will have enough info to determine whether it is the right type. This simplifies the code and results in less reading and rewinding. - NOTE: SkWbmpCodec needs the following number of bytes for the header + 1 (type) + 1 (reserved) + 3 (width - bytes needed to support up to 0xFFFF) + 3 (height - bytes needed to support up to 0xFFFF) = 8 - in SkWebpCodec, support using read + rewind as a backup if peek does not work. A change in Android will add peek() to JavaInputStreamAdapter. BUG=skia:3257 Review URL: https://codereview.chromium.org/1472123002
Diffstat (limited to 'tests/CodexTest.cpp')
-rw-r--r--tests/CodexTest.cpp77
1 files changed, 77 insertions, 0 deletions
diff --git a/tests/CodexTest.cpp b/tests/CodexTest.cpp
index 03dd16f583..94eea65b93 100644
--- a/tests/CodexTest.cpp
+++ b/tests/CodexTest.cpp
@@ -848,6 +848,54 @@ DEF_TEST(Codec_pngChunkReader, r) {
}
#endif // PNG_READ_UNKNOWN_CHUNKS_SUPPORTED
+// Stream that can only peek up to a limit
+class LimitedPeekingMemStream : public SkStream {
+public:
+ LimitedPeekingMemStream(SkData* data, size_t limit)
+ : fStream(data)
+ , fLimit(limit) {}
+
+ size_t peek(void* buf, size_t bytes) const override {
+ return fStream.peek(buf, SkTMin(bytes, fLimit));
+ }
+ size_t read(void* buf, size_t bytes) override {
+ return fStream.read(buf, bytes);
+ }
+ bool rewind() override {
+ return fStream.rewind();
+ }
+ bool isAtEnd() const override {
+ return false;
+ }
+private:
+ SkMemoryStream fStream;
+ const size_t fLimit;
+};
+
+// Test that even if webp_parse_header fails to peek enough, it will fall back to read()
+// + rewind() and succeed.
+DEF_TEST(Codec_webp_peek, r) {
+ const char* path = "baby_tux.webp";
+ SkString fullPath(GetResourcePath(path));
+ SkAutoTUnref<SkData> data(SkData::NewFromFileName(fullPath.c_str()));
+ if (!data) {
+ SkDebugf("Missing resource '%s'\n", path);
+ return;
+ }
+
+ // The limit is less than webp needs to peek or read.
+ SkAutoTDelete<SkCodec> codec(SkCodec::NewFromStream(new LimitedPeekingMemStream(data, 25)));
+ REPORTER_ASSERT(r, codec);
+
+ test_info(r, codec, codec->getInfo(), SkCodec::kSuccess, nullptr);
+
+ // Similarly, a stream which does not peek should still succeed.
+ codec.reset(SkCodec::NewFromStream(new LimitedPeekingMemStream(data, 0)));
+ REPORTER_ASSERT(r, codec);
+
+ test_info(r, codec, codec->getInfo(), SkCodec::kSuccess, nullptr);
+}
+
// SkCodec's wbmp decoder was initially more restrictive than SkImageDecoder.
// It required the second byte to be zero. But SkImageDecoder allowed a couple
// of bits to be 1 (so long as they do not overlap with 0x9F). Test that
@@ -877,3 +925,32 @@ DEF_TEST(Codec_wbmp, r) {
}
test_info(r, codec, codec->getInfo(), SkCodec::kSuccess, nullptr);
}
+
+// wbmp images have a header that can be arbitrarily large, depending on the
+// size of the image. We cap the size at 65535, meaning we only need to look at
+// 8 bytes to determine whether we can read the image. This is important
+// because SkCodec only passes 14 bytes to SkWbmpCodec to determine whether the
+// image is a wbmp.
+DEF_TEST(Codec_wbmp_max_size, r) {
+ const unsigned char maxSizeWbmp[] = { 0x00, 0x00, // Header
+ 0x83, 0xFF, 0x7F, // W: 65535
+ 0x83, 0xFF, 0x7F }; // H: 65535
+ SkAutoTDelete<SkStream> stream(new SkMemoryStream(maxSizeWbmp, sizeof(maxSizeWbmp), false));
+ SkAutoTDelete<SkCodec> codec(SkCodec::NewFromStream(stream.detach()));
+
+ REPORTER_ASSERT(r, codec);
+ if (!codec) return;
+
+ REPORTER_ASSERT(r, codec->getInfo().width() == 65535);
+ REPORTER_ASSERT(r, codec->getInfo().height() == 65535);
+
+ // Now test an image which is too big. Any image with a larger header (i.e.
+ // has bigger width/height) is also too big.
+ const unsigned char tooBigWbmp[] = { 0x00, 0x00, // Header
+ 0x84, 0x80, 0x00, // W: 65536
+ 0x84, 0x80, 0x00 }; // H: 65536
+ stream.reset(new SkMemoryStream(tooBigWbmp, sizeof(tooBigWbmp), false));
+ codec.reset(SkCodec::NewFromStream(stream.detach()));
+
+ REPORTER_ASSERT(r, !codec);
+}