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

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: Fix a test - we now draw transparent background for missing color table Created 4 years, 2 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
« no previous file with comments | « src/codec/SkSwizzler.h ('k') | tests/CodecPartialTest.cpp » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: tests/CodecAnimTest.cpp
diff --git a/tests/CodecAnimTest.cpp b/tests/CodecAnimTest.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..e0a446f227cfd2e2442686627164e1b1aa161a06
--- /dev/null
+++ b/tests/CodecAnimTest.cpp
@@ -0,0 +1,141 @@
+/*
+ * 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;
+ // The size of this one should match fFrameCount for animated, empty
+ // otherwise.
+ std::vector<size_t> fDurations;
+ } gRecs[] = {
+ { "box.gif", 1, {}, {} },
+ { "color_wheel.gif", 1, {}, {} },
+ { "test640x479.gif", 4, { 0, 1, 2 }, { 200, 200, 200, 200 } },
+
+ { "arrow.png", 1, {}, {} },
+ { "google_chrome.ico", 1, {}, {} },
+ { "brickwork-texture.jpg", 1, {}, {} },
+#if defined(SK_CODEC_DECODES_RAW) && (!defined(_WIN32))
+ { "dng_with_preview.dng", 1, {}, {} },
+#endif
+ { "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 auto frameInfos = codec->getFrameInfo();
+ // getFrameInfo returns empty set for non-animated.
+ const size_t frameCount = frameInfos.size() == 0 ? 1 : frameInfos.size();
+ if (frameCount != expected) {
+ ERRORF(r, "'%s' expected frame count: %i\tactual: %i", rec.fName, expected, frameCount);
+ continue;
+ }
+
+ 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.
+ REPORTER_ASSERT(r, frameInfos[0].fRequiredFrame == SkCodec::kNone);
+ for (size_t i = 1; i < frameCount; i++) {
+ REPORTER_ASSERT(r, rec.fRequiredFrames[i-1] == frameInfos[i].fRequiredFrame);
+ }
+
+ // 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 = frameInfos[index].fRequiredFrame;
+ if (requiredFrame != SkCodec::kNone) {
+ const bool success = cachedFrames[requiredFrame].copyTo(bm);
+ REPORTER_ASSERT(r, success);
+ }
+ }
+ SkCodec::Options opts;
+ opts.fFrameIndex = index;
+ opts.fHasPriorFrame = cached;
+ 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] == frameInfos[i].fDuration);
+ }
+ }
+}
« no previous file with comments | « src/codec/SkSwizzler.h ('k') | tests/CodecPartialTest.cpp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698