blob: de25f309e4363e5f80a87e0e5e8c1d143fec2e68 [file] [log] [blame]
Leon Scroggins III7a10b332018-01-12 11:24:30 -05001/*
2 * Copyright 2018 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
Leon Scroggins III42ee2842018-01-14 14:46:51 -05008#include "SkAndroidCodec.h"
Leon Scroggins III7a10b332018-01-12 11:24:30 -05009#include "SkAnimatedImage.h"
10#include "SkCanvas.h"
11#include "SkCodec.h"
12#include "SkCodecPriv.h"
Leon Scroggins IIIb1b7f7012018-01-16 15:26:35 -050013#include "SkPicture.h"
14#include "SkPictureRecorder.h"
Leon Scroggins III7a10b332018-01-12 11:24:30 -050015
Leon Scroggins IIIb1b7f7012018-01-16 15:26:35 -050016sk_sp<SkAnimatedImage> SkAnimatedImage::Make(std::unique_ptr<SkAndroidCodec> codec,
17 SkISize scaledSize, SkIRect cropRect, sk_sp<SkPicture> postProcess) {
Leon Scroggins III7a10b332018-01-12 11:24:30 -050018 if (!codec) {
19 return nullptr;
20 }
21
Leon Scroggins IIIb1b7f7012018-01-16 15:26:35 -050022 SkISize decodeSize = scaledSize;
23 auto decodeInfo = codec->getInfo();
24 if (codec->getEncodedFormat() == SkEncodedImageFormat::kWEBP
25 && scaledSize.width() < decodeInfo.width()
26 && scaledSize.height() < decodeInfo.height()) {
27 // libwebp can decode to arbitrary smaller sizes.
28 decodeInfo = decodeInfo.makeWH(decodeSize.width(), decodeSize.height());
29 }
30
31 auto image = sk_sp<SkAnimatedImage>(new SkAnimatedImage(std::move(codec), scaledSize,
32 decodeInfo, cropRect, std::move(postProcess)));
Leon Scroggins III7a10b332018-01-12 11:24:30 -050033 if (!image->fActiveFrame.fBitmap.getPixels()) {
34 // tryAllocPixels failed.
35 return nullptr;
36 }
37
38 return image;
39}
40
Leon Scroggins IIIb1b7f7012018-01-16 15:26:35 -050041sk_sp<SkAnimatedImage> SkAnimatedImage::Make(std::unique_ptr<SkAndroidCodec> codec) {
42 if (!codec) {
43 return nullptr;
44 }
45
46 const auto decodeInfo = codec->getInfo();
47 const auto scaledSize = decodeInfo.dimensions();
48 const auto cropRect = SkIRect::MakeSize(scaledSize);
49 auto image = sk_sp<SkAnimatedImage>(new SkAnimatedImage(std::move(codec), scaledSize,
50 decodeInfo, cropRect, nullptr));
51
52 if (!image->fActiveFrame.fBitmap.getPixels()) {
53 // tryAllocPixels failed.
54 return nullptr;
55 }
56
57 SkASSERT(image->fSimple);
58 return image;
59}
60
Leon Scroggins IIIb1b7f7012018-01-16 15:26:35 -050061SkAnimatedImage::SkAnimatedImage(std::unique_ptr<SkAndroidCodec> codec, SkISize scaledSize,
62 SkImageInfo decodeInfo, SkIRect cropRect, sk_sp<SkPicture> postProcess)
Leon Scroggins III7a10b332018-01-12 11:24:30 -050063 : fCodec(std::move(codec))
Leon Scroggins IIIb1b7f7012018-01-16 15:26:35 -050064 , fScaledSize(scaledSize)
65 , fDecodeInfo(decodeInfo)
66 , fCropRect(cropRect)
67 , fPostProcess(std::move(postProcess))
Leon Scroggins III4c119452018-01-20 10:33:24 -050068 , fFrameCount(fCodec->codec()->getFrameCount())
Leon Scroggins IIIb1b7f7012018-01-16 15:26:35 -050069 , fSimple(fScaledSize == fDecodeInfo.dimensions() && !fPostProcess
70 && fCropRect == fDecodeInfo.bounds())
Leon Scroggins III7a10b332018-01-12 11:24:30 -050071 , fFinished(false)
Leon Scroggins III4c119452018-01-20 10:33:24 -050072 , fRepetitionCount(fCodec->codec()->getRepetitionCount())
73 , fRepetitionsCompleted(0)
Leon Scroggins III7a10b332018-01-12 11:24:30 -050074{
Leon Scroggins IIIb1b7f7012018-01-16 15:26:35 -050075 if (!fActiveFrame.fBitmap.tryAllocPixels(fDecodeInfo)) {
Leon Scroggins III7a10b332018-01-12 11:24:30 -050076 return;
77 }
78
Leon Scroggins IIIb1b7f7012018-01-16 15:26:35 -050079 if (!fSimple) {
80 fMatrix = SkMatrix::MakeTrans(-fCropRect.fLeft, -fCropRect.fTop);
81 float scaleX = (float) fScaledSize.width() / fDecodeInfo.width();
82 float scaleY = (float) fScaledSize.height() / fDecodeInfo.height();
83 fMatrix.preConcat(SkMatrix::MakeScale(scaleX, scaleY));
84 }
Leon Scroggins III495e0f02018-01-29 19:35:55 -050085 this->decodeNextFrame();
Leon Scroggins III7a10b332018-01-12 11:24:30 -050086}
87
88SkAnimatedImage::~SkAnimatedImage() { }
89
90SkRect SkAnimatedImage::onGetBounds() {
Leon Scroggins IIIb1b7f7012018-01-16 15:26:35 -050091 return SkRect::MakeIWH(fCropRect.width(), fCropRect.height());
Leon Scroggins III7a10b332018-01-12 11:24:30 -050092}
93
94SkAnimatedImage::Frame::Frame()
95 : fIndex(SkCodec::kNone)
96{}
97
98bool SkAnimatedImage::Frame::copyTo(Frame* dst) const {
99 if (dst->fBitmap.getPixels()) {
100 dst->fBitmap.setAlphaType(fBitmap.alphaType());
101 } else if (!dst->fBitmap.tryAllocPixels(fBitmap.info())) {
102 return false;
103 }
104
105 memcpy(dst->fBitmap.getPixels(), fBitmap.getPixels(), fBitmap.computeByteSize());
106 dst->fIndex = fIndex;
107 dst->fDisposalMethod = fDisposalMethod;
108 return true;
109}
110
Leon Scroggins III7a10b332018-01-12 11:24:30 -0500111void SkAnimatedImage::reset() {
Leon Scroggins III4c119452018-01-20 10:33:24 -0500112 fFinished = false;
113 fRepetitionsCompleted = 0;
Leon Scroggins III495e0f02018-01-29 19:35:55 -0500114 if (fActiveFrame.fIndex == 0) {
115 // Already showing the first frame.
116 return;
117 }
118
119 if (fRestoreFrame.fIndex == 0) {
120 SkTSwap(fActiveFrame, fRestoreFrame);
121 // Now we're showing the first frame.
122 return;
123 }
124
125 fActiveFrame.fIndex = SkCodec::kNone;
126 this->decodeNextFrame();
Leon Scroggins III7a10b332018-01-12 11:24:30 -0500127}
128
129static bool is_restore_previous(SkCodecAnimation::DisposalMethod dispose) {
130 return SkCodecAnimation::DisposalMethod::kRestorePrevious == dispose;
131}
132
Leon Scroggins III4c119452018-01-20 10:33:24 -0500133int SkAnimatedImage::computeNextFrame(int current, bool* animationEnded) {
134 SkASSERT(animationEnded != nullptr);
135 *animationEnded = false;
136
137 const int frameToDecode = current + 1;
138 if (frameToDecode == fFrameCount - 1) {
139 // Final frame. Check to determine whether to stop.
140 fRepetitionsCompleted++;
141 if (fRepetitionCount != SkCodec::kRepetitionCountInfinite
142 && fRepetitionsCompleted > fRepetitionCount) {
143 *animationEnded = true;
144 }
145 } else if (frameToDecode == fFrameCount) {
146 return 0;
147 }
148 return frameToDecode;
149}
150
151double SkAnimatedImage::finish() {
152 fFinished = true;
Leon Scroggins III495e0f02018-01-29 19:35:55 -0500153 fCurrentFrameDuration = kFinished;
154 return kFinished;
Leon Scroggins III4c119452018-01-20 10:33:24 -0500155}
156
Leon Scroggins III495e0f02018-01-29 19:35:55 -0500157int SkAnimatedImage::decodeNextFrame() {
Leon Scroggins III7a10b332018-01-12 11:24:30 -0500158 if (fFinished) {
Leon Scroggins III495e0f02018-01-29 19:35:55 -0500159 return kFinished;
Leon Scroggins III7a10b332018-01-12 11:24:30 -0500160 }
161
Leon Scroggins III4c119452018-01-20 10:33:24 -0500162 bool animationEnded = false;
Leon Scroggins III495e0f02018-01-29 19:35:55 -0500163 int frameToDecode = this->computeNextFrame(fActiveFrame.fIndex, &animationEnded);
Leon Scroggins III7a10b332018-01-12 11:24:30 -0500164
165 SkCodec::FrameInfo frameInfo;
Leon Scroggins III42ee2842018-01-14 14:46:51 -0500166 if (fCodec->codec()->getFrameInfo(frameToDecode, &frameInfo)) {
Leon Scroggins III7a10b332018-01-12 11:24:30 -0500167 if (!frameInfo.fFullyReceived) {
168 SkCodecPrintf("Frame %i not fully received\n", frameToDecode);
Leon Scroggins III4c119452018-01-20 10:33:24 -0500169 return this->finish();
Leon Scroggins III7a10b332018-01-12 11:24:30 -0500170 }
171
Leon Scroggins III495e0f02018-01-29 19:35:55 -0500172 fCurrentFrameDuration = frameInfo.fDuration;
Leon Scroggins III7a10b332018-01-12 11:24:30 -0500173 } else {
Leon Scroggins III4c119452018-01-20 10:33:24 -0500174 animationEnded = true;
Leon Scroggins III7a10b332018-01-12 11:24:30 -0500175 if (0 == frameToDecode) {
176 // Static image. This is okay.
177 frameInfo.fRequiredFrame = SkCodec::kNone;
178 frameInfo.fAlphaType = fCodec->getInfo().alphaType();
Kevin Lubick289d36f2018-02-13 10:25:00 -0500179 frameInfo.fDisposalMethod = SkCodecAnimation::DisposalMethod::kKeep;
Leon Scroggins III7a10b332018-01-12 11:24:30 -0500180 // These fields won't be read.
181 frameInfo.fDuration = INT_MAX;
182 frameInfo.fFullyReceived = true;
Leon Scroggins III495e0f02018-01-29 19:35:55 -0500183 fCurrentFrameDuration = kFinished;
Leon Scroggins III7a10b332018-01-12 11:24:30 -0500184 } else {
185 SkCodecPrintf("Error getting frameInfo for frame %i\n",
186 frameToDecode);
Leon Scroggins III4c119452018-01-20 10:33:24 -0500187 return this->finish();
Leon Scroggins III7a10b332018-01-12 11:24:30 -0500188 }
189 }
190
191 if (frameToDecode == fActiveFrame.fIndex) {
Leon Scroggins III4c119452018-01-20 10:33:24 -0500192 if (animationEnded) {
193 return this->finish();
194 }
Leon Scroggins III495e0f02018-01-29 19:35:55 -0500195 return fCurrentFrameDuration;
Leon Scroggins III7a10b332018-01-12 11:24:30 -0500196 }
197
198 if (frameToDecode == fRestoreFrame.fIndex) {
199 SkTSwap(fActiveFrame, fRestoreFrame);
Leon Scroggins III4c119452018-01-20 10:33:24 -0500200 if (animationEnded) {
201 return this->finish();
202 }
Leon Scroggins III495e0f02018-01-29 19:35:55 -0500203 return fCurrentFrameDuration;
Leon Scroggins III7a10b332018-01-12 11:24:30 -0500204 }
205
206 // The following code makes an effort to avoid overwriting a frame that will
207 // be used again. If frame |i| is_restore_previous, frame |i+1| will not
208 // depend on frame |i|, so do not overwrite frame |i-1|, which may be needed
209 // for frame |i+1|.
210 // We could be even smarter about which frames to save by looking at the
211 // entire dependency chain.
212 SkCodec::Options options;
213 options.fFrameIndex = frameToDecode;
214 if (frameInfo.fRequiredFrame == SkCodec::kNone) {
215 if (is_restore_previous(frameInfo.fDisposalMethod)) {
216 // frameToDecode will be discarded immediately after drawing, so
217 // do not overwrite a frame which could possibly be used in the
218 // future.
219 if (fActiveFrame.fIndex != SkCodec::kNone &&
220 !is_restore_previous(fActiveFrame.fDisposalMethod)) {
221 SkTSwap(fActiveFrame, fRestoreFrame);
222 }
223 }
224 } else {
225 auto validPriorFrame = [&frameInfo, &frameToDecode](const Frame& frame) {
226 if (SkCodec::kNone == frame.fIndex || is_restore_previous(frame.fDisposalMethod)) {
227 return false;
228 }
229
230 return frame.fIndex >= frameInfo.fRequiredFrame && frame.fIndex < frameToDecode;
231 };
232 if (validPriorFrame(fActiveFrame)) {
233 if (is_restore_previous(frameInfo.fDisposalMethod)) {
234 // fActiveFrame is a good frame to use for this one, but we
235 // don't want to overwrite it.
236 fActiveFrame.copyTo(&fRestoreFrame);
237 }
238 options.fPriorFrame = fActiveFrame.fIndex;
239 } else if (validPriorFrame(fRestoreFrame)) {
240 if (!is_restore_previous(frameInfo.fDisposalMethod)) {
241 SkTSwap(fActiveFrame, fRestoreFrame);
242 } else if (!fRestoreFrame.copyTo(&fActiveFrame)) {
243 SkCodecPrintf("Failed to restore frame\n");
Leon Scroggins III4c119452018-01-20 10:33:24 -0500244 return this->finish();
Leon Scroggins III7a10b332018-01-12 11:24:30 -0500245 }
246 options.fPriorFrame = fActiveFrame.fIndex;
247 }
248 }
249
250 auto alphaType = kOpaque_SkAlphaType == frameInfo.fAlphaType ?
251 kOpaque_SkAlphaType : kPremul_SkAlphaType;
252 SkBitmap* dst = &fActiveFrame.fBitmap;
253 if (dst->getPixels()) {
254 SkAssertResult(dst->setAlphaType(alphaType));
255 } else {
Leon Scroggins IIIb1b7f7012018-01-16 15:26:35 -0500256 auto info = fDecodeInfo.makeAlphaType(alphaType);
Leon Scroggins III7a10b332018-01-12 11:24:30 -0500257 if (!dst->tryAllocPixels(info)) {
Leon Scroggins III4c119452018-01-20 10:33:24 -0500258 return this->finish();
Leon Scroggins III7a10b332018-01-12 11:24:30 -0500259 }
260 }
261
Leon Scroggins III42ee2842018-01-14 14:46:51 -0500262 auto result = fCodec->codec()->getPixels(dst->info(), dst->getPixels(), dst->rowBytes(),
263 &options);
Leon Scroggins III7a10b332018-01-12 11:24:30 -0500264 if (result != SkCodec::kSuccess) {
Leon Scroggins III4c119452018-01-20 10:33:24 -0500265 SkCodecPrintf("error %i, frame %i of %i\n", result, frameToDecode, fFrameCount);
266 return this->finish();
Leon Scroggins III7a10b332018-01-12 11:24:30 -0500267 }
268
269 fActiveFrame.fIndex = frameToDecode;
270 fActiveFrame.fDisposalMethod = frameInfo.fDisposalMethod;
Leon Scroggins III4c119452018-01-20 10:33:24 -0500271
272 if (animationEnded) {
273 return this->finish();
274 }
Leon Scroggins III495e0f02018-01-29 19:35:55 -0500275 return fCurrentFrameDuration;
Leon Scroggins III7a10b332018-01-12 11:24:30 -0500276}
Leon Scroggins IIIb1b7f7012018-01-16 15:26:35 -0500277
278void SkAnimatedImage::onDraw(SkCanvas* canvas) {
279 if (fSimple) {
280 canvas->drawBitmap(fActiveFrame.fBitmap, 0, 0);
281 return;
282 }
283
284 SkRect bounds = this->getBounds();
285 if (fPostProcess) {
286 canvas->saveLayer(&bounds, nullptr);
287 }
288 {
289 SkAutoCanvasRestore acr(canvas, fPostProcess);
290 canvas->concat(fMatrix);
291 SkPaint paint;
Leon Scroggins IIIb1b7f7012018-01-16 15:26:35 -0500292 paint.setFilterQuality(kLow_SkFilterQuality);
293 canvas->drawBitmap(fActiveFrame.fBitmap, 0, 0, &paint);
294 }
295 if (fPostProcess) {
296 canvas->drawPicture(fPostProcess);
297 canvas->restore();
298 }
299}
Leon Scroggins III4c119452018-01-20 10:33:24 -0500300
301void SkAnimatedImage::setRepetitionCount(int newCount) {
302 fRepetitionCount = newCount;
303}