Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(373)

Unified Diff: tests/CodecAnimTest.cpp

Issue 2045293002: Add support for multiple frames in SkCodec (Closed) Base URL: https://skia.googlesource.com/skia.git@master
Patch Set: Cache all frames in the GM Created 4 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: tests/CodecAnimTest.cpp
diff --git a/tests/CodecAnimTest.cpp b/tests/CodecAnimTest.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..397ac39ebe77c381a9ecc11b38190115313f3a33
--- /dev/null
+++ b/tests/CodecAnimTest.cpp
@@ -0,0 +1,138 @@
+/*
+ * Copyright 2016 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#include "SkCodec.h"
+#include "SkStream.h"
+
+#include "Resources.h"
+#include "Test.h"
+
+#include <initializer_list>
+#include <vector>
+
+DEF_TEST(Codec_frames, r) {
+ static const struct {
+ const char* fName;
+ size_t fFrameCount;
+ // One less than fFramecount, since the first frame is always
+ // independent.
+ std::vector<size_t> fRequiredFrames;
+ std::vector<size_t> fDurations;
+ } gRecs[] = {
+ { "box.gif", 1, {}, {} },
+ { "color_wheel.gif", 1, {}, {} },
+ { "test640x479.gif", 4, { 0, 1, 2 }, { 20, 20, 20, 20 } },
+
+ { "arrow.png", 1, {}, {} },
+ { "google_chrome.ico", 1, {}, {} },
+ { "brickwork-texture.jpg", 1, {}, {} },
+ { "dng_with_preview.dng", 1, {}, {} },
+ { "mandrill.wbmp", 1, {}, {} },
+ { "randPixels.bmp", 1, {}, {} },
+ { "yellow_rose.webp", 1, {}, {} },
+ };
+
+ for (auto rec : gRecs) {
+ std::unique_ptr<SkStream> stream(GetResourceAsStream(rec.fName));
+ if (!stream) {
+ // Useful error statement, but sometimes people run tests without
+ // resources, and they do not want to see these messages.
+ //ERRORF(r, "Missing resources? Could not find '%s'", rec.fName);
+ continue;
+ }
+
+ std::unique_ptr<SkCodec> codec(SkCodec::NewFromStream(stream.release()));
+ if (!codec) {
+ ERRORF(r, "Failed to create an SkCodec from '%s'", rec.fName);
+ continue;
+ }
+
+ const size_t expected = rec.fFrameCount;
+ const size_t frameCount = codec->getFrameCount();
+ if (frameCount != expected) {
+ ERRORF(r, "'%s' expected frame count: %i\tactual: %i", rec.fName, expected, frameCount);
+ continue;
+ }
+
+ REPORTER_ASSERT(r, codec->getRequiredFrame(0) == SkCodec::kIndependentFrame);
+
+ if (rec.fRequiredFrames.size() + 1 != expected) {
+ ERRORF(r, "'%s' has wrong number entries in fRequiredFrames; expected: %i\tactual: %i",
+ rec.fName, expected, rec.fRequiredFrames.size());
+ continue;
+ }
+
+ if (1 == frameCount) {
+ continue;
+ }
+
+ // From here on, we are only concerned with animated images.
+ for (size_t i = 1; i < frameCount; i++) {
+ REPORTER_ASSERT(r, rec.fRequiredFrames[i-1] == codec->getRequiredFrame(i));
+ }
+
+ // Compare decoding in two ways:
+ // 1. Provide the frame that a frame depends on, so the codec just has to blend.
+ // (in the array cachedFrames)
+ // 2. Do not provide the frame that a frame depends on, so the codec has to decode all the
+ // way back to a key-frame. (in a local variable uncachedFrame)
+ // The two should look the same.
+ std::vector<SkBitmap> cachedFrames(frameCount);
+ const auto& info = codec->getInfo().makeColorType(kN32_SkColorType);
+
+ auto decode = [&](SkBitmap* bm, bool cached, size_t index) {
+ bm->allocPixels(info);
+ if (cached) {
+ // First copy the pixels from the cached frame
+ const size_t requiredFrame = codec->getRequiredFrame(index);
+ if (requiredFrame != SkCodec::kIndependentFrame) {
+ const bool success = cachedFrames[requiredFrame].copyTo(bm);
+ REPORTER_ASSERT(r, success);
+ }
+ }
+ SkCodec::Options opts;
+ SkCodec::MultiFrameOptions multiOpts;
+ multiOpts.fIndex = index;
+ multiOpts.fHasPriorFrame = cached;
+ opts.fFrameOptions = &multiOpts;
+ const SkCodec::Result result = codec->getPixels(info, bm->getPixels(), bm->rowBytes(),
+ &opts, nullptr, nullptr);
+ REPORTER_ASSERT(r, result == SkCodec::kSuccess);
+ };
+
+ for (size_t i = 0; i < frameCount; i++) {
+ SkBitmap& cachedFrame = cachedFrames[i];
+ decode(&cachedFrame, true, i);
+ SkBitmap uncachedFrame;
+ decode(&uncachedFrame, false, i);
+
+ // Now verify they're equal.
+ const size_t rowLen = info.bytesPerPixel() * info.width();
+ for (int y = 0; y < info.height(); y++) {
+ const void* cachedAddr = cachedFrame.getAddr(0, y);
+ SkASSERT(cachedAddr != nullptr);
+ const void* uncachedAddr = uncachedFrame.getAddr(0, y);
+ SkASSERT(uncachedAddr != nullptr);
+ const bool lineMatches = memcmp(cachedAddr, uncachedAddr, rowLen) == 0;
+ if (!lineMatches) {
+ ERRORF(r, "%s's frame %i is different depending on caching!", rec.fName, i);
+ break;
+ }
+ }
+ }
+
+ if (rec.fDurations.size() != expected) {
+ ERRORF(r, "'%s' has wrong number entries in fDurations; expected: %i\tactual: %i",
+ rec.fName, expected, rec.fDurations.size());
+ continue;
+ }
+
+ for (size_t i = 0; i < frameCount; i++) {
+ REPORTER_ASSERT(r, rec.fDurations[i] == codec->getFrameDuration(i));
+ }
+ }
+}
« src/codec/SkGifCodec.cpp ('K') | « src/codec/SkGifCodec.cpp ('k') | tests/CodecTest.cpp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698