34 cropRect, std::move(postProcess)));
35 if (!
image->fDisplayFrame.fBitmap.getPixels()) {
48 auto decodeInfo = codec->getInfo();
49 const auto origin = codec->codec()->getOrigin();
51 decodeInfo = decodeInfo.makeWH(decodeInfo.height(), decodeInfo.width());
54 return Make(std::move(codec), decodeInfo, cropRect,
nullptr);
57SkAnimatedImage::SkAnimatedImage(std::unique_ptr<SkAndroidCodec> codec,
59 : fCodec(
std::move(codec))
60 , fDecodeInfo(requestedInfo)
62 , fPostProcess(
std::move(postProcess))
63 , fFrameCount(fCodec->codec()->getFrameCount())
66 , fRepetitionCount(fCodec->codec()->getRepetitionCount())
67 , fRepetitionsCompleted(0)
76 const auto origin = fCodec->codec()->getOrigin();
85 scaledSize = { scaledSize.height(), scaledSize.width() };
89 auto decodeSize = scaledSize;
90 fSampleSize = fCodec->computeSampleSize(&decodeSize);
93 if (!fDecodingFrame.fBitmap.tryAllocPixels(fDecodeInfo)) {
99 float scaleY = (
float) scaledSize.height() / fDecodeInfo.
height();
112SkAnimatedImage::Frame::Frame()
117 if (fBitmap.getPixels()) {
118 if (fBitmap.pixelRef()->unique()) {
126 if (OnInit::kRestoreIfNecessary == onInit) {
132 memcpy(tmp.
getPixels(), fBitmap.getPixels(), fBitmap.computeByteSize());
139 return fBitmap.tryAllocPixels(
info);
142bool SkAnimatedImage::Frame::copyTo(Frame*
dst)
const {
143 if (!
dst->init(fBitmap.info(), OnInit::kNoRestore)) {
147 memcpy(
dst->fBitmap.getPixels(), fBitmap.getPixels(), fBitmap.computeByteSize());
148 dst->fIndex = fIndex;
149 dst->fDisposalMethod = fDisposalMethod;
155 fRepetitionsCompleted = 0;
156 if (fDisplayFrame.fIndex != 0) {
166int SkAnimatedImage::computeNextFrame(
int current,
bool* animationEnded) {
167 SkASSERT(animationEnded !=
nullptr);
168 *animationEnded =
false;
170 const int frameToDecode = current + 1;
171 if (frameToDecode == fFrameCount - 1) {
173 fRepetitionsCompleted++;
175 && fRepetitionsCompleted > fRepetitionCount) {
176 *animationEnded =
true;
178 }
else if (frameToDecode == fFrameCount) {
181 return frameToDecode;
184double SkAnimatedImage::finish() {
195 bool animationEnded =
false;
196 const int frameToDecode = this->computeNextFrame(fDisplayFrame.fIndex, &animationEnded);
199 if (fCodec->codec()->getFrameInfo(frameToDecode, &frameInfo)) {
201 SkCodecPrintf(
"Frame %i not fully received\n", frameToDecode);
202 return this->finish();
205 fCurrentFrameDuration = frameInfo.
fDuration;
207 animationEnded =
true;
208 if (0 == frameToDecode) {
211 frameInfo.
fAlphaType = fCodec->getInfo().alphaType();
220 return this->finish();
224 if (frameToDecode == fDisplayFrame.fIndex) {
225 if (animationEnded) {
226 return this->finish();
228 return fCurrentFrameDuration;
231 for (Frame*
frame : { &fRestoreFrame, &fDecodingFrame }) {
232 if (frameToDecode ==
frame->fIndex) {
235 if (animationEnded) {
236 return this->finish();
238 return fCurrentFrameDuration;
249 options.fSampleSize = fSampleSize;
250 options.fFrameIndex = frameToDecode;
259 swap(fDecodingFrame, fRestoreFrame);
263 auto validPriorFrame = [&frameInfo, &frameToDecode](
const Frame&
frame) {
271 if (validPriorFrame(fDecodingFrame)) {
275 fDecodingFrame.copyTo(&fRestoreFrame);
277 options.fPriorFrame = fDecodingFrame.fIndex;
278 }
else if (validPriorFrame(fDisplayFrame)) {
279 if (!fDisplayFrame.copyTo(&fDecodingFrame)) {
281 return this->finish();
283 options.fPriorFrame = fDecodingFrame.fIndex;
284 }
else if (validPriorFrame(fRestoreFrame)) {
287 swap(fDecodingFrame, fRestoreFrame);
288 }
else if (!fRestoreFrame.copyTo(&fDecodingFrame)) {
290 return this->finish();
292 options.fPriorFrame = fDecodingFrame.fIndex;
300 if (!fDecodingFrame.init(
info, Frame::OnInit::kRestoreIfNecessary)) {
301 return this->finish();
304 auto result = fCodec->getAndroidPixels(
dst->info(),
dst->getPixels(),
dst->rowBytes(),
308 frameToDecode, fFrameCount);
309 return this->finish();
312 fDecodingFrame.fIndex = frameToDecode;
316 swap(fDecodingFrame, fDisplayFrame);
317 fDisplayFrame.fBitmap.notifyPixelsChanged();
319 if (animationEnded) {
320 return this->finish();
327 if (fCodec->codec()->getFrameInfo(frameToDecode, &frameInfo)) {
328 fCurrentFrameDuration = frameInfo.
fDuration;
330 SkCodecPrintf(
"Failed to getFrameInfo on second attempt (HEIF)");
333 return fCurrentFrameDuration;
337 auto image = this->getCurrentFrameSimple();
339 if (this->simple()) {
361 fRepetitionCount = newCount;
373 if (this->simple())
return this->getCurrentFrameSimple();
375 auto imageInfo = fDisplayFrame.fBitmap.info().makeDimensions(fCropRect.
size());
382 if (!
dst.tryAllocPixels(imageInfo)) {
static void info(const char *fmt,...) SK_PRINTF_LIKE(1
SkAssertResult(font.textToGlyphs("Hello", 5, SkTextEncoding::kUTF8, glyphs, std::size(glyphs))==count)
@ kOpaque_SkAlphaType
pixel is opaque
@ kPremul_SkAlphaType
pixel components are premultiplied by alpha
static bool is_restore_previous(SkCodecAnimation::DisposalMethod dispose)
#define SkCodecPrintf(...)
@ kDefault_SkEncodedOrigin
static bool SkEncodedOriginSwapsWidthHeight(SkEncodedOrigin origin)
static SkMatrix SkEncodedOriginToMatrix(SkEncodedOrigin origin, int w, int h)
SK_SPI sk_sp< SkImage > SkMakeImageFromRasterBitmap(const SkBitmap &, SkCopyPixelsMode)
@ kNever_SkCopyPixelsMode
never copy src pixels (even if they are marked mutable)
void swap(sk_sp< T > &a, sk_sp< T > &b)
static sk_sp< SkAnimatedImage > Make(std::unique_ptr< SkAndroidCodec >, const SkImageInfo &info, SkIRect cropRect, sk_sp< SkPicture > postProcess)
void onDraw(SkCanvas *) override
static constexpr int kFinished
~SkAnimatedImage() override
SkRect onGetBounds() override
void setRepetitionCount(int count)
sk_sp< SkImage > getCurrentFrame()
bool tryAllocPixels(const SkImageInfo &info, size_t rowBytes)
int saveLayer(const SkRect *bounds, const SkPaint *paint)
void clipRect(const SkRect &rect, SkClipOp op, bool doAntiAlias)
void concat(const SkMatrix &matrix)
void drawPicture(const SkPicture *picture)
void drawImage(const SkImage *image, SkScalar left, SkScalar top)
static const char * ResultToString(Result)
static constexpr int kRepetitionCountInfinite
static constexpr int kNoFrame
void draw(SkCanvas *, const SkMatrix *=nullptr)
static SkMatrix Scale(SkScalar sx, SkScalar sy)
SkMatrix & postConcat(const SkMatrix &other)
static SkMatrix Translate(SkScalar dx, SkScalar dy)
SkMatrix & preConcat(const SkMatrix &other)
SK_API SkImageInfo SwapWidthHeight(const SkImageInfo &info)
Optional< SkRect > bounds
sk_sp< const SkImage > image
SkSamplingOptions(SkFilterMode::kLinear))
SkCodecAnimation::DisposalMethod fDisposalMethod
constexpr SkISize size() const
constexpr int32_t height() const
int32_t fTop
smaller y-axis bounds
static constexpr SkIRect MakeSize(const SkISize &size)
constexpr int32_t width() const
int32_t fLeft
smaller x-axis bounds
bool contains(int32_t x, int32_t y) const
SkImageInfo makeAlphaType(SkAlphaType newAlphaType) const
SkImageInfo makeDimensions(SkISize newSize) const
SkISize dimensions() const
static SkRect MakeIWH(int w, int h)