// Verify that a webp image can be animated scaled down. This image has a // kRestoreBG frame, so it is an interesting image to test. After decoding that // frame, we have to erase its rectangle. The rectangle has to be adjusted // based on the scaled size. DEF_TEST(AndroidCodec_animated, r) { if (GetResourcePath().isEmpty()) { return; } const char* file = "images/required.webp"; sk_sp<SkData> data(GetResourceAsData(file)); if (!data) { ERRORF(r, "Missing %s", file); return; } auto codec = SkAndroidCodec::MakeFromCodec(SkCodec::MakeFromData(std::move(data))); if (!codec) { ERRORF(r, "Failed to decode %s", file); return; } auto info = codec->getInfo().makeAlphaType(kPremul_SkAlphaType); for (int sampleSize : { 8, 32, 100 }) { auto dimensions = codec->codec()->getScaledDimensions(1.0f / sampleSize); info = info.makeWH(dimensions.width(), dimensions.height()); SkBitmap bm; bm.allocPixels(info); SkCodec::Options options; for (int i = 0; i < codec->codec()->getFrameCount(); ++i) { SkCodec::FrameInfo frameInfo; REPORTER_ASSERT(r, codec->codec()->getFrameInfo(i, &frameInfo)); if (5 == i) { REPORTER_ASSERT(r, frameInfo.fDisposalMethod == SkCodecAnimation::DisposalMethod::kRestoreBGColor); } options.fFrameIndex = i; options.fPriorFrame = i - 1; info = info.makeAlphaType(frameInfo.fAlphaType); const auto result = codec->codec()->getPixels(info, bm.getPixels(), bm.rowBytes(), &options); REPORTER_ASSERT(r, result == SkCodec::kSuccess); } } }
sk_sp<SkAnimatedImage> SkAnimatedImage::Make(std::unique_ptr<SkAndroidCodec> codec, SkISize scaledSize, SkIRect cropRect, sk_sp<SkPicture> postProcess) { if (!codec) { return nullptr; } SkISize decodeSize = scaledSize; auto decodeInfo = codec->getInfo(); if (codec->getEncodedFormat() == SkEncodedImageFormat::kWEBP && scaledSize.width() < decodeInfo.width() && scaledSize.height() < decodeInfo.height()) { // libwebp can decode to arbitrary smaller sizes. decodeInfo = decodeInfo.makeWH(decodeSize.width(), decodeSize.height()); } auto image = sk_sp<SkAnimatedImage>(new SkAnimatedImage(std::move(codec), scaledSize, decodeInfo, cropRect, std::move(postProcess))); if (!image->fDisplayFrame.fBitmap.getPixels()) { // tryAllocPixels failed. return nullptr; } return image; }