Reland "SkAnimatedImage: Use fSampleSize"

This is a reland of 4fdf9f9ce5

No change from the original, which was just reverted to be able to
cleanly revert its parent, which has now been relanded with a fix.

Original change's description:
> SkAnimatedImage: Use fSampleSize
>
> Bug: b/163595585
>
> This will allow using less memory when decoding an animated GIF by
> sampling at decode time. This is tested by the animated_image GMs.
>
> Change-Id: I748b2180827623e4ca1fc0fd4d6dd02733b3b5f2
> Reviewed-on: https://skia-review.googlesource.com/c/skia/+/333226
> Commit-Queue: Leon Scroggins <scroggo@google.com>
> Reviewed-by: Derek Sollenberger <djsollen@google.com>

Bug: b/163595585
Change-Id: I3249bd04b64750a50a4c5c787db3e80ac4d85e67
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/335279
Reviewed-by: Derek Sollenberger <djsollen@google.com>
Commit-Queue: Leon Scroggins <scroggo@google.com>
This commit is contained in:
Leon Scroggins 2020-11-09 16:00:53 -05:00 committed by Skia Commit-Bot
parent abd73e2507
commit da3d8c2471
2 changed files with 24 additions and 32 deletions

View File

@ -143,6 +143,7 @@ private:
const sk_sp<SkPicture> fPostProcess;
const int fFrameCount;
SkMatrix fMatrix;
int fSampleSize;
bool fFinished;
int fCurrentFrameDuration;
@ -152,9 +153,8 @@ private:
int fRepetitionCount;
int fRepetitionsCompleted;
SkAnimatedImage(std::unique_ptr<SkAndroidCodec>, SkISize scaledSize,
SkImageInfo decodeInfo, SkIRect cropRect, sk_sp<SkPicture> postProcess);
SkAnimatedImage(std::unique_ptr<SkAndroidCodec>);
SkAnimatedImage(std::unique_ptr<SkAndroidCodec>, const SkImageInfo& requestedInfo,
SkIRect cropRect, sk_sp<SkPicture> postProcess);
int computeNextFrame(int current, bool* animationEnded);
double finish();

View File

@ -29,18 +29,8 @@ sk_sp<SkAnimatedImage> SkAnimatedImage::Make(std::unique_ptr<SkAndroidCodec> cod
return nullptr;
}
auto scaledSize = requestedInfo.dimensions();
auto decodeInfo = requestedInfo;
if (codec->getEncodedFormat() != SkEncodedImageFormat::kWEBP
|| scaledSize.width() >= decodeInfo.width()
|| scaledSize.height() >= decodeInfo.height()) {
// Only libwebp can decode to arbitrary smaller sizes.
auto dims = codec->getInfo().dimensions();
decodeInfo = decodeInfo.makeDimensions(dims);
}
auto image = sk_sp<SkAnimatedImage>(new SkAnimatedImage(std::move(codec), scaledSize,
decodeInfo, cropRect, std::move(postProcess)));
auto image = sk_sp<SkAnimatedImage>(new SkAnimatedImage(std::move(codec), requestedInfo,
cropRect, std::move(postProcess)));
if (!image->fDisplayFrame.fBitmap.getPixels()) {
// tryAllocPixels failed.
return nullptr;
@ -54,32 +44,28 @@ sk_sp<SkAnimatedImage> SkAnimatedImage::Make(std::unique_ptr<SkAndroidCodec> cod
return nullptr;
}
const auto decodeInfo = codec->getInfo();
const auto scaledSize = decodeInfo.dimensions();
const auto cropRect = SkIRect::MakeSize(scaledSize);
auto image = sk_sp<SkAnimatedImage>(new SkAnimatedImage(std::move(codec), scaledSize,
decodeInfo, cropRect, nullptr));
const auto& decodeInfo = codec->getInfo();
const auto cropRect = SkIRect::MakeSize(decodeInfo.dimensions());
auto image = Make(std::move(codec), decodeInfo, cropRect, nullptr);
if (!image->fDisplayFrame.fBitmap.getPixels()) {
// tryAllocPixels failed.
return nullptr;
}
SkASSERT(image->simple());
SkASSERT(!image || image->simple());
return image;
}
SkAnimatedImage::SkAnimatedImage(std::unique_ptr<SkAndroidCodec> codec, SkISize scaledSize,
SkImageInfo decodeInfo, SkIRect cropRect, sk_sp<SkPicture> postProcess)
SkAnimatedImage::SkAnimatedImage(std::unique_ptr<SkAndroidCodec> codec,
const SkImageInfo& requestedInfo, SkIRect cropRect, sk_sp<SkPicture> postProcess)
: fCodec(std::move(codec))
, fDecodeInfo(decodeInfo)
, fDecodeInfo(requestedInfo)
, fCropRect(cropRect)
, fPostProcess(std::move(postProcess))
, fFrameCount(fCodec->codec()->getFrameCount())
, fSampleSize(1)
, fFinished(false)
, fRepetitionCount(fCodec->codec()->getRepetitionCount())
, fRepetitionsCompleted(0)
{
auto scaledSize = requestedInfo.dimensions();
// For simplicity in decoding and compositing frames, decode directly to a size and
// orientation that fCodec can do directly, and then use fMatrix to handle crop (along with a
// clip), orientation, and scaling outside of fCodec. The matrices are computed individually
@ -100,6 +86,11 @@ SkAnimatedImage::SkAnimatedImage(std::unique_ptr<SkAndroidCodec> codec, SkISize
scaledSize = { scaledSize.height(), scaledSize.width() };
}
}
auto decodeSize = scaledSize;
fSampleSize = fCodec->computeSampleSize(&decodeSize);
fDecodeInfo = fDecodeInfo.makeDimensions(decodeSize);
if (!fDecodingFrame.fBitmap.tryAllocPixels(fDecodeInfo)) {
return;
}
@ -255,7 +246,8 @@ int SkAnimatedImage::decodeNextFrame() {
// for frame |i+1|.
// We could be even smarter about which frames to save by looking at the
// entire dependency chain.
SkCodec::Options options;
SkAndroidCodec::AndroidOptions options;
options.fSampleSize = fSampleSize;
options.fFrameIndex = frameToDecode;
if (frameInfo.fRequiredFrame == SkCodec::kNoFrame) {
if (is_restore_previous(frameInfo.fDisposalMethod)) {
@ -310,8 +302,8 @@ int SkAnimatedImage::decodeNextFrame() {
return this->finish();
}
auto result = fCodec->codec()->getPixels(dst->info(), dst->getPixels(), dst->rowBytes(),
&options);
auto result = fCodec->getAndroidPixels(dst->info(), dst->getPixels(), dst->rowBytes(),
&options);
if (result != SkCodec::kSuccess) {
SkCodecPrintf("error %i, frame %i of %i\n", result, frameToDecode, fFrameCount);
return this->finish();