diff options
author | Leon Scroggins III <scroggo@google.com> | 2018-01-16 15:26:35 -0500 |
---|---|---|
committer | Skia Commit-Bot <skia-commit-bot@chromium.org> | 2018-01-17 17:46:17 +0000 |
commit | b1b7f70103378aff5e9a315e7788866b648ab4b1 (patch) | |
tree | 5e9c63445bbd5c7ebb301273e929e942ad4642a0 /src/android/SkAnimatedImage.cpp | |
parent | 9d8abc5816d9e5533e7943c52fa6856177f482b2 (diff) |
Add Android ImageDecoder features to SkAnimatedImage
Bug: b/63909536
Bug: b/63908092
- Scale to an arbitrary size, using the decoding library if it supports
it, and Skia otherwise
- Crop to a subset
- Post-processing with an SkPicture, to facilitate circle masks etc
- isRunning, to implement Animatable2 interface in Java
Change-Id: I13dbabee8e4a22e5cc193856aa3e94ce23ae4cb5
Reviewed-on: https://skia-review.googlesource.com/94660
Reviewed-by: Derek Sollenberger <djsollen@google.com>
Commit-Queue: Leon Scroggins <scroggo@google.com>
Diffstat (limited to 'src/android/SkAnimatedImage.cpp')
-rw-r--r-- | src/android/SkAnimatedImage.cpp | 84 |
1 files changed, 75 insertions, 9 deletions
diff --git a/src/android/SkAnimatedImage.cpp b/src/android/SkAnimatedImage.cpp index 25c020fde8..4c87083957 100644 --- a/src/android/SkAnimatedImage.cpp +++ b/src/android/SkAnimatedImage.cpp @@ -10,46 +10,88 @@ #include "SkCanvas.h" #include "SkCodec.h" #include "SkCodecPriv.h" +#include "SkPicture.h" +#include "SkPictureRecorder.h" + +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->fActiveFrame.fBitmap.getPixels()) { + // tryAllocPixels failed. + return nullptr; + } + + return image; +} sk_sp<SkAnimatedImage> SkAnimatedImage::Make(std::unique_ptr<SkAndroidCodec> codec) { if (!codec) { return nullptr; } - auto image = sk_sp<SkAnimatedImage>(new SkAnimatedImage(std::move(codec))); + 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)); + if (!image->fActiveFrame.fBitmap.getPixels()) { // tryAllocPixels failed. return nullptr; } + SkASSERT(image->fSimple); return image; } // Sentinel value for starting at the beginning. static constexpr double kInit = -1.0; -SkAnimatedImage::SkAnimatedImage(std::unique_ptr<SkAndroidCodec> codec) +SkAnimatedImage::SkAnimatedImage(std::unique_ptr<SkAndroidCodec> codec, SkISize scaledSize, + SkImageInfo decodeInfo, SkIRect cropRect, sk_sp<SkPicture> postProcess) : fCodec(std::move(codec)) + , fScaledSize(scaledSize) + , fDecodeInfo(decodeInfo) + , fCropRect(cropRect) + , fPostProcess(std::move(postProcess)) + , fSimple(fScaledSize == fDecodeInfo.dimensions() && !fPostProcess + && fCropRect == fDecodeInfo.bounds()) , fFinished(false) , fRunning(false) , fNowMS(kInit) , fRemainingMS(kInit) { - if (!fActiveFrame.fBitmap.tryAllocPixels(fCodec->getInfo())) { + if (!fActiveFrame.fBitmap.tryAllocPixels(fDecodeInfo)) { return; } + if (!fSimple) { + fMatrix = SkMatrix::MakeTrans(-fCropRect.fLeft, -fCropRect.fTop); + float scaleX = (float) fScaledSize.width() / fDecodeInfo.width(); + float scaleY = (float) fScaledSize.height() / fDecodeInfo.height(); + fMatrix.preConcat(SkMatrix::MakeScale(scaleX, scaleY)); + } this->update(kInit); } SkAnimatedImage::~SkAnimatedImage() { } SkRect SkAnimatedImage::onGetBounds() { - return SkRect::Make(fCodec->getInfo().bounds()); -} - -void SkAnimatedImage::onDraw(SkCanvas* canvas) { - canvas->drawBitmap(fActiveFrame.fBitmap, 0, 0); + return SkRect::MakeIWH(fCropRect.width(), fCropRect.height()); } SkAnimatedImage::Frame::Frame() @@ -216,7 +258,7 @@ double SkAnimatedImage::update(double msecs) { if (dst->getPixels()) { SkAssertResult(dst->setAlphaType(alphaType)); } else { - auto info = fCodec->getInfo().makeAlphaType(alphaType); + auto info = fDecodeInfo.makeAlphaType(alphaType); if (!dst->tryAllocPixels(info)) { fFinished = true; return std::numeric_limits<double>::max(); @@ -236,3 +278,27 @@ double SkAnimatedImage::update(double msecs) { fActiveFrame.fDisposalMethod = frameInfo.fDisposalMethod; return fRemainingMS + fNowMS; } + +void SkAnimatedImage::onDraw(SkCanvas* canvas) { + if (fSimple) { + canvas->drawBitmap(fActiveFrame.fBitmap, 0, 0); + return; + } + + SkRect bounds = this->getBounds(); + if (fPostProcess) { + canvas->saveLayer(&bounds, nullptr); + } + { + SkAutoCanvasRestore acr(canvas, fPostProcess); + canvas->concat(fMatrix); + SkPaint paint; + paint.setBlendMode(SkBlendMode::kSrc); + paint.setFilterQuality(kLow_SkFilterQuality); + canvas->drawBitmap(fActiveFrame.fBitmap, 0, 0, &paint); + } + if (fPostProcess) { + canvas->drawPicture(fPostProcess); + canvas->restore(); + } +} |