aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/codec/SkWebpCodec.cpp
diff options
context:
space:
mode:
authorGravatar Leon Scroggins III <scroggo@google.com>2017-06-07 12:31:51 -0400
committerGravatar Skia Commit-Bot <skia-commit-bot@chromium.org>2017-06-07 20:15:17 +0000
commit33deb7ed4d583c88187ba240efb749e9a1fd6843 (patch)
treecf70e6f7dbd360853b84e16d586f5b8811b68c8f /src/codec/SkWebpCodec.cpp
parent9982c4eb76af58e18df2cd3dd81913439f1b6157 (diff)
Make SkCodec more flexible about its required frame
SkCodec sets fRequiredFrame to be the earliest possible frame that a given frame can depend on. e.g. - Frame A fills the screen, Keep - Frame B does not cover A, Keep - Frame C covers B but not A, and is opaque Frame C can depend on either A or B. SkCodec already reports that C depends on A. This CL allows a client of SkCodec to use either A or B to create C. Also expose the DisposalMethod. Since any frame between A and C can be used to create C except for DisposePrevious frames, the client needs to be able to know the disposal method so they do not try to use such a frame to create C. Further, the disposal method can be used to give the client a better idea whether they will continue to need a frame. (e.g. if frame i is DisposePrevious and depends on i-1, the client may not want to steal i-1 to create i, since i+1 may also depend on i-1.) TODO: Share code for decoding prior frames between GIF and WEBP Change-Id: I91a5ae22ba3d8dfbe0bde833fa67ae3da0d81ed6 Reviewed-on: https://skia-review.googlesource.com/13722 Reviewed-by: Mike Reed <reed@google.com> Reviewed-by: Chris Blume <cblume@chromium.org> Reviewed-by: Matt Sarett <msarett@google.com> Commit-Queue: Leon Scroggins <scroggo@google.com>
Diffstat (limited to 'src/codec/SkWebpCodec.cpp')
-rw-r--r--src/codec/SkWebpCodec.cpp39
1 files changed, 26 insertions, 13 deletions
diff --git a/src/codec/SkWebpCodec.cpp b/src/codec/SkWebpCodec.cpp
index 21d45da233..f702a3ae98 100644
--- a/src/codec/SkWebpCodec.cpp
+++ b/src/codec/SkWebpCodec.cpp
@@ -7,6 +7,8 @@
#include "SkBitmap.h"
#include "SkCanvas.h"
+#include "SkCodecAnimation.h"
+#include "SkCodecAnimationPriv.h"
#include "SkCodecPriv.h"
#include "SkColorSpaceXform.h"
#include "SkRasterPipeline.h"
@@ -253,8 +255,8 @@ int SkWebpCodec::onGetFrameCount() {
Frame* frame = fFrameHolder.appendNewFrame(iter.has_alpha);
frame->setXYWH(iter.x_offset, iter.y_offset, iter.width, iter.height);
frame->setDisposalMethod(iter.dispose_method == WEBP_MUX_DISPOSE_BACKGROUND ?
- SkCodecAnimation::RestoreBGColor_DisposalMethod :
- SkCodecAnimation::Keep_DisposalMethod);
+ SkCodecAnimation::DisposalMethod::kRestoreBGColor :
+ SkCodecAnimation::DisposalMethod::kKeep);
frame->setDuration(iter.duration);
if (WEBP_MUX_BLEND != iter.blend_method) {
frame->setBlend(SkCodecAnimation::Blend::kBG);
@@ -292,6 +294,7 @@ bool SkWebpCodec::onGetFrameInfo(int i, FrameInfo* frameInfo) const {
// animated image.
frameInfo->fFullyReceived = true;
frameInfo->fAlphaType = alpha_type(frame->hasAlpha());
+ frameInfo->fDisposalMethod = frame->getDisposalMethod();
}
return true;
@@ -437,9 +440,15 @@ SkCodec::Result SkWebpCodec::onGetPixels(const SkImageInfo& dstInfo, void* dst,
SkSampler::Fill(dstInfo, dst, rowBytes, 0, options.fZeroInitialized);
}
} else {
- if (!options.fHasPriorFrame) {
+ // FIXME: Share with GIF
+ if (options.fPriorFrame != kNone) {
+ if (options.fPriorFrame < requiredFrame || options.fPriorFrame >= index) {
+ return kInvalidParameters;
+ }
+ } else {
Options prevFrameOpts(options);
prevFrameOpts.fFrameIndex = requiredFrame;
+ prevFrameOpts.fPriorFrame = kNone;
const auto result = this->getPixels(dstInfo, dst, rowBytes, &prevFrameOpts,
nullptr, nullptr);
switch (result) {
@@ -452,16 +461,20 @@ SkCodec::Result SkWebpCodec::onGetPixels(const SkImageInfo& dstInfo, void* dst,
}
}
- // Dispose bg color
- const Frame* priorFrame = fFrameHolder.frame(requiredFrame);
- if (priorFrame->getDisposalMethod() == SkCodecAnimation::RestoreBGColor_DisposalMethod) {
- // FIXME: If we add support for scaling/subsets, this rectangle needs to be adjusted.
- const auto priorRect = priorFrame->frameRect();
- const auto info = dstInfo.makeWH(priorRect.width(), priorRect.height());
- const size_t bpp = SkColorTypeBytesPerPixel(dstInfo.colorType());
- const size_t offset = priorRect.x() * bpp + priorRect.y() * rowBytes;
- auto* eraseDst = SkTAddOffset<void>(dst, offset);
- SkSampler::Fill(info, eraseDst, rowBytes, 0, kNo_ZeroInitialized);
+ if (options.fPriorFrame == requiredFrame || options.fPriorFrame == kNone) {
+ // Dispose bg color
+ const Frame* priorFrame = fFrameHolder.frame(requiredFrame);
+ if (priorFrame->getDisposalMethod()
+ == SkCodecAnimation::DisposalMethod::kRestoreBGColor) {
+ // FIXME: If we add support for scaling/subsets, this rectangle needs to be
+ // adjusted.
+ const auto priorRect = priorFrame->frameRect();
+ const auto info = dstInfo.makeWH(priorRect.width(), priorRect.height());
+ const size_t bpp = SkColorTypeBytesPerPixel(dstInfo.colorType());
+ const size_t offset = priorRect.x() * bpp + priorRect.y() * rowBytes;
+ auto* eraseDst = SkTAddOffset<void>(dst, offset);
+ SkSampler::Fill(info, eraseDst, rowBytes, 0, kNo_ZeroInitialized);
+ }
}
}