Flutter Engine
The Flutter Engine
Loading...
Searching...
No Matches
Classes | Public Member Functions | Static Public Member Functions | Static Public Attributes | Protected Member Functions | List of all members
SkAnimatedImage Class Reference

#include <SkAnimatedImage.h>

Inheritance diagram for SkAnimatedImage:
SkDrawable SkFlattenable SkRefCnt SkRefCntBase

Public Member Functions

 ~SkAnimatedImage () override
 
void reset ()
 
bool isFinished () const
 
int decodeNextFrame ()
 
sk_sp< SkImagegetCurrentFrame ()
 
int currentFrameDuration ()
 
void setRepetitionCount (int count)
 
int getRepetitionCount () const
 
int getFrameCount () const
 
- Public Member Functions inherited from SkDrawable
void draw (SkCanvas *, const SkMatrix *=nullptr)
 
void draw (SkCanvas *, SkScalar x, SkScalar y)
 
std::unique_ptr< GpuDrawHandlersnapGpuDrawHandler (GrBackendApi backendApi, const SkMatrix &matrix, const SkIRect &clipBounds, const SkImageInfo &bufferInfo)
 
sk_sp< SkPicturemakePictureSnapshot ()
 
uint32_t getGenerationID ()
 
SkRect getBounds ()
 
size_t approximateBytesUsed ()
 
void notifyDrawingChanged ()
 
SkFlattenable::Type getFlattenableType () const override
 
Factory getFactory () const override
 
const char * getTypeName () const override
 
- Public Member Functions inherited from SkFlattenable
 SkFlattenable ()
 
virtual void flatten (SkWriteBuffer &) const
 
sk_sp< SkDataserialize (const SkSerialProcs *=nullptr) const
 
size_t serialize (void *memory, size_t memory_size, const SkSerialProcs *=nullptr) const
 
- Public Member Functions inherited from SkRefCntBase
 SkRefCntBase ()
 
virtual ~SkRefCntBase ()
 
bool unique () const
 
void ref () const
 
void unref () const
 

Static Public Member Functions

static sk_sp< SkAnimatedImageMake (std::unique_ptr< SkAndroidCodec >, const SkImageInfo &info, SkIRect cropRect, sk_sp< SkPicture > postProcess)
 
static sk_sp< SkAnimatedImageMake (std::unique_ptr< SkAndroidCodec >)
 
- Static Public Member Functions inherited from SkDrawable
static SkFlattenable::Type GetFlattenableType ()
 
static sk_sp< SkDrawableDeserialize (const void *data, size_t size, const SkDeserialProcs *procs=nullptr)
 
- Static Public Member Functions inherited from SkFlattenable
static Factory NameToFactory (const char name[])
 
static const char * FactoryToName (Factory)
 
static void Register (const char name[], Factory)
 
static sk_sp< SkFlattenableDeserialize (Type, const void *data, size_t length, const SkDeserialProcs *procs=nullptr)
 

Static Public Attributes

static constexpr int kFinished = -1
 

Protected Member Functions

SkRect onGetBounds () override
 
void onDraw (SkCanvas *) override
 
- Protected Member Functions inherited from SkDrawable
 SkDrawable ()
 
virtual size_t onApproximateBytesUsed ()
 
virtual std::unique_ptr< GpuDrawHandleronSnapGpuDrawHandler (GrBackendApi, const SkMatrix &, const SkIRect &, const SkImageInfo &)
 
virtual std::unique_ptr< GpuDrawHandleronSnapGpuDrawHandler (GrBackendApi, const SkMatrix &)
 
virtual sk_sp< SkPictureonMakePictureSnapshot ()
 

Additional Inherited Members

- Public Types inherited from SkFlattenable
enum  Type {
  kSkColorFilter_Type , kSkBlender_Type , kSkDrawable_Type , kSkDrawLooper_Type ,
  kSkImageFilter_Type , kSkMaskFilter_Type , kSkPathEffect_Type , kSkShader_Type
}
 
typedef sk_sp< SkFlattenable >(* Factory) (SkReadBuffer &)
 

Detailed Description

Thread unsafe drawable for drawing animated images (e.g. GIF).

Definition at line 24 of file SkAnimatedImage.h.

Constructor & Destructor Documentation

◆ ~SkAnimatedImage()

SkAnimatedImage::~SkAnimatedImage ( )
override

Definition at line 106 of file SkAnimatedImage.cpp.

106{ }

Member Function Documentation

◆ currentFrameDuration()

int SkAnimatedImage::currentFrameDuration ( )
inline

How long to display the current frame.

Useful for the first frame, for which decodeNextFrame is called internally.

Definition at line 86 of file SkAnimatedImage.h.

86 {
87 return fCurrentFrameDuration;
88 }

◆ decodeNextFrame()

int SkAnimatedImage::decodeNextFrame ( )

Decode the next frame.

If the animation is on the last frame or has hit an error, returns kFinished.

Definition at line 190 of file SkAnimatedImage.cpp.

190 {
191 if (fFinished) {
192 return kFinished;
193 }
194
195 bool animationEnded = false;
196 const int frameToDecode = this->computeNextFrame(fDisplayFrame.fIndex, &animationEnded);
197
198 SkCodec::FrameInfo frameInfo;
199 if (fCodec->codec()->getFrameInfo(frameToDecode, &frameInfo)) {
200 if (!frameInfo.fFullyReceived) {
201 SkCodecPrintf("Frame %i not fully received\n", frameToDecode);
202 return this->finish();
203 }
204
205 fCurrentFrameDuration = frameInfo.fDuration;
206 } else {
207 animationEnded = true;
208 if (0 == frameToDecode) {
209 // Static image. This is okay.
211 frameInfo.fAlphaType = fCodec->getInfo().alphaType();
213 // These fields won't be read.
214 frameInfo.fDuration = INT_MAX;
215 frameInfo.fFullyReceived = true;
216 fCurrentFrameDuration = kFinished;
217 } else {
218 SkCodecPrintf("Error getting frameInfo for frame %i\n",
219 frameToDecode);
220 return this->finish();
221 }
222 }
223
224 if (frameToDecode == fDisplayFrame.fIndex) {
225 if (animationEnded) {
226 return this->finish();
227 }
228 return fCurrentFrameDuration;
229 }
230
231 for (Frame* frame : { &fRestoreFrame, &fDecodingFrame }) {
232 if (frameToDecode == frame->fIndex) {
233 using std::swap;
234 swap(fDisplayFrame, *frame);
235 if (animationEnded) {
236 return this->finish();
237 }
238 return fCurrentFrameDuration;
239 }
240 }
241
242 // The following code makes an effort to avoid overwriting a frame that will
243 // be used again. If frame |i| is_restore_previous, frame |i+1| will not
244 // depend on frame |i|, so do not overwrite frame |i-1|, which may be needed
245 // for frame |i+1|.
246 // We could be even smarter about which frames to save by looking at the
247 // entire dependency chain.
249 options.fSampleSize = fSampleSize;
250 options.fFrameIndex = frameToDecode;
251 if (frameInfo.fRequiredFrame == SkCodec::kNoFrame) {
252 if (is_restore_previous(frameInfo.fDisposalMethod)) {
253 // frameToDecode will be discarded immediately after drawing, so
254 // do not overwrite a frame which could possibly be used in the
255 // future.
256 if (fDecodingFrame.fIndex != SkCodec::kNoFrame &&
257 !is_restore_previous(fDecodingFrame.fDisposalMethod)) {
258 using std::swap;
259 swap(fDecodingFrame, fRestoreFrame);
260 }
261 }
262 } else {
263 auto validPriorFrame = [&frameInfo, &frameToDecode](const Frame& frame) {
264 if (SkCodec::kNoFrame == frame.fIndex ||
265 is_restore_previous(frame.fDisposalMethod)) {
266 return false;
267 }
268
269 return frame.fIndex >= frameInfo.fRequiredFrame && frame.fIndex < frameToDecode;
270 };
271 if (validPriorFrame(fDecodingFrame)) {
272 if (is_restore_previous(frameInfo.fDisposalMethod)) {
273 // fDecodingFrame is a good frame to use for this one, but we
274 // don't want to overwrite it.
275 fDecodingFrame.copyTo(&fRestoreFrame);
276 }
277 options.fPriorFrame = fDecodingFrame.fIndex;
278 } else if (validPriorFrame(fDisplayFrame)) {
279 if (!fDisplayFrame.copyTo(&fDecodingFrame)) {
280 SkCodecPrintf("Failed to allocate pixels for frame\n");
281 return this->finish();
282 }
283 options.fPriorFrame = fDecodingFrame.fIndex;
284 } else if (validPriorFrame(fRestoreFrame)) {
285 if (!is_restore_previous(frameInfo.fDisposalMethod)) {
286 using std::swap;
287 swap(fDecodingFrame, fRestoreFrame);
288 } else if (!fRestoreFrame.copyTo(&fDecodingFrame)) {
289 SkCodecPrintf("Failed to restore frame\n");
290 return this->finish();
291 }
292 options.fPriorFrame = fDecodingFrame.fIndex;
293 }
294 }
295
296 auto alphaType = kOpaque_SkAlphaType == frameInfo.fAlphaType ?
298 auto info = fDecodeInfo.makeAlphaType(alphaType);
299 SkBitmap* dst = &fDecodingFrame.fBitmap;
300 if (!fDecodingFrame.init(info, Frame::OnInit::kRestoreIfNecessary)) {
301 return this->finish();
302 }
303
304 auto result = fCodec->getAndroidPixels(dst->info(), dst->getPixels(), dst->rowBytes(),
305 &options);
306 if (result != SkCodec::kSuccess) {
307 SkCodecPrintf("%s, frame %i of %i\n", SkCodec::ResultToString(result),
308 frameToDecode, fFrameCount);
309 return this->finish();
310 }
311
312 fDecodingFrame.fIndex = frameToDecode;
313 fDecodingFrame.fDisposalMethod = frameInfo.fDisposalMethod;
314
315 using std::swap;
316 swap(fDecodingFrame, fDisplayFrame);
317 fDisplayFrame.fBitmap.notifyPixelsChanged();
318
319 if (animationEnded) {
320 return this->finish();
321 } else if (fCodec->getEncodedFormat() == SkEncodedImageFormat::kHEIF) {
322 // HEIF doesn't know the frame duration until after decoding. Update to
323 // the correct value. Note that earlier returns in this method either
324 // return kFinished, or fCurrentFrameDuration. If they return the
325 // latter, it is a frame that was previously decoded, so it has the
326 // updated value.
327 if (fCodec->codec()->getFrameInfo(frameToDecode, &frameInfo)) {
328 fCurrentFrameDuration = frameInfo.fDuration;
329 } else {
330 SkCodecPrintf("Failed to getFrameInfo on second attempt (HEIF)");
331 }
332 }
333 return fCurrentFrameDuration;
334}
const char * options
static void info(const char *fmt,...) SK_PRINTF_LIKE(1
Definition DM.cpp:213
@ kOpaque_SkAlphaType
pixel is opaque
Definition SkAlphaType.h:28
@ kPremul_SkAlphaType
pixel components are premultiplied by alpha
Definition SkAlphaType.h:29
static bool is_restore_previous(SkCodecAnimation::DisposalMethod dispose)
#define SkCodecPrintf(...)
Definition SkCodecPriv.h:23
void swap(sk_sp< T > &a, sk_sp< T > &b)
Definition SkRefCnt.h:341
static constexpr int kFinished
static const char * ResultToString(Result)
Definition SkCodec.cpp:880
@ kSuccess
Definition SkCodec.h:80
static constexpr int kNoFrame
Definition SkCodec.h:650
double frame
Definition examples.cpp:31
GAsyncResult * result
dst
Definition cp.py:12
SkCodecAnimation::DisposalMethod fDisposalMethod
Definition SkCodec.h:704
SkAlphaType fAlphaType
Definition SkCodec.h:689
SkImageInfo makeAlphaType(SkAlphaType newAlphaType) const

◆ getCurrentFrame()

sk_sp< SkImage > SkAnimatedImage::getCurrentFrame ( )

Returns the current frame as an SkImage. The SkImage will not change after it has been returned. If there is no current frame, nullptr will be returned.

Definition at line 372 of file SkAnimatedImage.cpp.

372 {
373 if (this->simple()) return this->getCurrentFrameSimple();
374
375 auto imageInfo = fDisplayFrame.fBitmap.info().makeDimensions(fCropRect.size());
376 if (fPostProcess) {
377 // Defensively use premul in case the post process adds alpha.
378 imageInfo = imageInfo.makeAlphaType(kPremul_SkAlphaType);
379 }
380
382 if (!dst.tryAllocPixels(imageInfo)) {
383 return nullptr;
384 }
385
386 SkCanvas canvas(dst);
387 this->draw(&canvas);
389}
SK_SPI sk_sp< SkImage > SkMakeImageFromRasterBitmap(const SkBitmap &, SkCopyPixelsMode)
@ kNever_SkCopyPixelsMode
never copy src pixels (even if they are marked mutable)
Definition SkImagePriv.h:20
void draw(SkCanvas *, const SkMatrix *=nullptr)
constexpr SkISize size() const
Definition SkRect.h:172

◆ getFrameCount()

int SkAnimatedImage::getFrameCount ( ) const
inline

Return the total number of frames in the animation.

Definition at line 111 of file SkAnimatedImage.h.

111{ return fFrameCount; }

◆ getRepetitionCount()

int SkAnimatedImage::getRepetitionCount ( ) const
inline

Return the currently set repetition count.

Definition at line 104 of file SkAnimatedImage.h.

104 {
105 return fRepetitionCount;
106 }

◆ isFinished()

bool SkAnimatedImage::isFinished ( ) const
inline

Whether the animation completed.

Returns true after all repetitions are complete, or an error stops the animation. Gets reset to false if the animation is restarted.

Definition at line 57 of file SkAnimatedImage.h.

57{ return fFinished; }

◆ Make() [1/2]

sk_sp< SkAnimatedImage > SkAnimatedImage::Make ( std::unique_ptr< SkAndroidCodec codec)
static

Simpler version that uses the default size, no cropping, and no postProcess.

Definition at line 43 of file SkAnimatedImage.cpp.

43 {
44 if (!codec) {
45 return nullptr;
46 }
47
48 auto decodeInfo = codec->getInfo();
49 const auto origin = codec->codec()->getOrigin();
51 decodeInfo = decodeInfo.makeWH(decodeInfo.height(), decodeInfo.width());
52 }
53 const auto cropRect = SkIRect::MakeSize(decodeInfo.dimensions());
54 return Make(std::move(codec), decodeInfo, cropRect, nullptr);
55}
static bool SkEncodedOriginSwapsWidthHeight(SkEncodedOrigin origin)
static sk_sp< SkAnimatedImage > Make(std::unique_ptr< SkAndroidCodec >, const SkImageInfo &info, SkIRect cropRect, sk_sp< SkPicture > postProcess)
static constexpr SkIRect MakeSize(const SkISize &size)
Definition SkRect.h:66

◆ Make() [2/2]

sk_sp< SkAnimatedImage > SkAnimatedImage::Make ( std::unique_ptr< SkAndroidCodec codec,
const SkImageInfo info,
SkIRect  cropRect,
sk_sp< SkPicture postProcess 
)
static

Create an SkAnimatedImage from the SkAndroidCodec.

Returns null on failure to allocate pixels. On success, this will decode the first frame.

Parameters
infoWidth and height may require scaling.
cropRectRectangle to crop to after scaling.
postProcessPicture to apply after scaling and cropping.

Definition at line 23 of file SkAnimatedImage.cpp.

24 {
25 if (!codec) {
26 return nullptr;
27 }
28
29 if (!requestedInfo.bounds().contains(cropRect)) {
30 return nullptr;
31 }
32
33 auto image = sk_sp<SkAnimatedImage>(new SkAnimatedImage(std::move(codec), requestedInfo,
34 cropRect, std::move(postProcess)));
35 if (!image->fDisplayFrame.fBitmap.getPixels()) {
36 // tryAllocPixels failed.
37 return nullptr;
38 }
39
40 return image;
41}
sk_sp< SkImage > image
Definition examples.cpp:29

◆ onDraw()

void SkAnimatedImage::onDraw ( SkCanvas canvas)
overrideprotectedvirtual

Implements SkDrawable.

Definition at line 336 of file SkAnimatedImage.cpp.

336 {
337 auto image = this->getCurrentFrameSimple();
338
339 if (this->simple()) {
340 canvas->drawImage(image, 0, 0);
341 return;
342 }
343
344 SkRect bounds = this->getBounds();
345 if (fPostProcess) {
346 canvas->saveLayer(&bounds, nullptr);
347 }
348 canvas->clipRect(bounds);
349 {
350 SkAutoCanvasRestore acr(canvas, fPostProcess != nullptr);
351 canvas->concat(fMatrix);
352 canvas->drawImage(image, 0, 0, SkSamplingOptions(SkFilterMode::kLinear), nullptr);
353 }
354 if (fPostProcess) {
355 canvas->drawPicture(fPostProcess);
356 canvas->restore();
357 }
358}
int saveLayer(const SkRect *bounds, const SkPaint *paint)
Definition SkCanvas.cpp:500
void clipRect(const SkRect &rect, SkClipOp op, bool doAntiAlias)
void restore()
Definition SkCanvas.cpp:465
void concat(const SkMatrix &matrix)
void drawPicture(const SkPicture *picture)
Definition SkCanvas.h:1961
void drawImage(const SkImage *image, SkScalar left, SkScalar top)
Definition SkCanvas.h:1528
SkRect getBounds()
Optional< SkRect > bounds
Definition SkRecords.h:189

◆ onGetBounds()

SkRect SkAnimatedImage::onGetBounds ( )
overrideprotectedvirtual

Implements SkDrawable.

Definition at line 108 of file SkAnimatedImage.cpp.

108 {
109 return SkRect::MakeIWH(fCropRect.width(), fCropRect.height());
110}
constexpr int32_t height() const
Definition SkRect.h:165
constexpr int32_t width() const
Definition SkRect.h:158
static SkRect MakeIWH(int w, int h)
Definition SkRect.h:623

◆ reset()

void SkAnimatedImage::reset ( )

Reset the animation to the beginning.

Definition at line 153 of file SkAnimatedImage.cpp.

153 {
154 fFinished = false;
155 fRepetitionsCompleted = 0;
156 if (fDisplayFrame.fIndex != 0) {
157 fDisplayFrame.fIndex = SkCodec::kNoFrame;
158 this->decodeNextFrame();
159 }
160}

◆ setRepetitionCount()

void SkAnimatedImage::setRepetitionCount ( int  count)

Change the repetition count.

By default, the image will repeat the number of times indicated in the encoded data.

Use SkCodec::kRepetitionCountInfinite for infinite, and 0 to show all frames once and then stop.

Definition at line 360 of file SkAnimatedImage.cpp.

360 {
361 fRepetitionCount = newCount;
362}

Member Data Documentation

◆ kFinished

constexpr int SkAnimatedImage::kFinished = -1
staticconstexpr

Returned by decodeNextFrame and currentFrameDuration if the animation is not running.

Definition at line 63 of file SkAnimatedImage.h.


The documentation for this class was generated from the following files: