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

Side by Side 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 unified diff | Download patch
OLDNEW
(Empty)
1 /*
2 * Copyright 2016 Google Inc.
3 *
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
6 */
7
8 #include "SkCodec.h"
9 #include "SkStream.h"
10
11 #include "Resources.h"
12 #include "Test.h"
13
14 #include <initializer_list>
15 #include <vector>
16
17 DEF_TEST(Codec_frames, r) {
18 static const struct {
19 const char* fName;
20 size_t fFrameCount;
21 // One less than fFramecount, since the first frame is always
22 // independent.
23 std::vector<size_t> fRequiredFrames;
24 std::vector<size_t> fDurations;
25 } gRecs[] = {
26 { "box.gif", 1, {}, {} },
27 { "color_wheel.gif", 1, {}, {} },
28 { "test640x479.gif", 4, { 0, 1, 2 }, { 20, 20, 20, 20 } },
29
30 { "arrow.png", 1, {}, {} },
31 { "google_chrome.ico", 1, {}, {} },
32 { "brickwork-texture.jpg", 1, {}, {} },
33 { "dng_with_preview.dng", 1, {}, {} },
34 { "mandrill.wbmp", 1, {}, {} },
35 { "randPixels.bmp", 1, {}, {} },
36 { "yellow_rose.webp", 1, {}, {} },
37 };
38
39 for (auto rec : gRecs) {
40 std::unique_ptr<SkStream> stream(GetResourceAsStream(rec.fName));
41 if (!stream) {
42 // Useful error statement, but sometimes people run tests without
43 // resources, and they do not want to see these messages.
44 //ERRORF(r, "Missing resources? Could not find '%s'", rec.fName);
45 continue;
46 }
47
48 std::unique_ptr<SkCodec> codec(SkCodec::NewFromStream(stream.release())) ;
49 if (!codec) {
50 ERRORF(r, "Failed to create an SkCodec from '%s'", rec.fName);
51 continue;
52 }
53
54 const size_t expected = rec.fFrameCount;
55 const size_t frameCount = codec->getFrameCount();
56 if (frameCount != expected) {
57 ERRORF(r, "'%s' expected frame count: %i\tactual: %i", rec.fName, ex pected, frameCount);
58 continue;
59 }
60
61 REPORTER_ASSERT(r, codec->getRequiredFrame(0) == SkCodec::kIndependentFr ame);
62
63 if (rec.fRequiredFrames.size() + 1 != expected) {
64 ERRORF(r, "'%s' has wrong number entries in fRequiredFrames; expecte d: %i\tactual: %i",
65 rec.fName, expected, rec.fRequiredFrames.size());
66 continue;
67 }
68
69 if (1 == frameCount) {
70 continue;
71 }
72
73 // From here on, we are only concerned with animated images.
74 for (size_t i = 1; i < frameCount; i++) {
75 REPORTER_ASSERT(r, rec.fRequiredFrames[i-1] == codec->getRequiredFra me(i));
76 }
77
78 // Compare decoding in two ways:
79 // 1. Provide the frame that a frame depends on, so the codec just has t o blend.
80 // (in the array cachedFrames)
81 // 2. Do not provide the frame that a frame depends on, so the codec has to decode all the
82 // way back to a key-frame. (in a local variable uncachedFrame)
83 // The two should look the same.
84 std::vector<SkBitmap> cachedFrames(frameCount);
85 const auto& info = codec->getInfo().makeColorType(kN32_SkColorType);
86
87 auto decode = [&](SkBitmap* bm, bool cached, size_t index) {
88 bm->allocPixels(info);
89 if (cached) {
90 // First copy the pixels from the cached frame
91 const size_t requiredFrame = codec->getRequiredFrame(index);
92 if (requiredFrame != SkCodec::kIndependentFrame) {
93 const bool success = cachedFrames[requiredFrame].copyTo(bm);
94 REPORTER_ASSERT(r, success);
95 }
96 }
97 SkCodec::Options opts;
98 SkCodec::MultiFrameOptions multiOpts;
99 multiOpts.fIndex = index;
100 multiOpts.fHasPriorFrame = cached;
101 opts.fFrameOptions = &multiOpts;
102 const SkCodec::Result result = codec->getPixels(info, bm->getPixels( ), bm->rowBytes(),
103 &opts, nullptr, null ptr);
104 REPORTER_ASSERT(r, result == SkCodec::kSuccess);
105 };
106
107 for (size_t i = 0; i < frameCount; i++) {
108 SkBitmap& cachedFrame = cachedFrames[i];
109 decode(&cachedFrame, true, i);
110 SkBitmap uncachedFrame;
111 decode(&uncachedFrame, false, i);
112
113 // Now verify they're equal.
114 const size_t rowLen = info.bytesPerPixel() * info.width();
115 for (int y = 0; y < info.height(); y++) {
116 const void* cachedAddr = cachedFrame.getAddr(0, y);
117 SkASSERT(cachedAddr != nullptr);
118 const void* uncachedAddr = uncachedFrame.getAddr(0, y);
119 SkASSERT(uncachedAddr != nullptr);
120 const bool lineMatches = memcmp(cachedAddr, uncachedAddr, rowLen ) == 0;
121 if (!lineMatches) {
122 ERRORF(r, "%s's frame %i is different depending on caching!" , rec.fName, i);
123 break;
124 }
125 }
126 }
127
128 if (rec.fDurations.size() != expected) {
129 ERRORF(r, "'%s' has wrong number entries in fDurations; expected: %i \tactual: %i",
130 rec.fName, expected, rec.fDurations.size());
131 continue;
132 }
133
134 for (size_t i = 0; i < frameCount; i++) {
135 REPORTER_ASSERT(r, rec.fDurations[i] == codec->getFrameDuration(i));
136 }
137 }
138 }
OLDNEW
« 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