diff options
author | Leon Scroggins III <scroggo@google.com> | 2017-05-23 09:37:21 -0400 |
---|---|---|
committer | Skia Commit-Bot <skia-commit-bot@chromium.org> | 2017-05-23 15:28:37 +0000 |
commit | 557fbbe05ba48bcc20be684d11fe0edfc24c87ba (patch) | |
tree | de83760e6e67a0866578056b4091091cef29cc53 /dm | |
parent | e980174d0f3af8e497d9c38851114cc6a3c02e9a (diff) |
Add animation support to SkWebpCodec
TBR=reed@google.com
(No change to the public API, but changed a header file)
SkWebpCodec:
- Implement onGetFrameCount, onGetFrameInfo, and onGetRepetitionCount
- Respect the alpha reported by libwebp. Although the spec states that
it is only a hint, the libwebp encoder uses it properly. Respecting
allows us to draw opaque images faster and decode them to 565. This
also matches other SkCodecs (and Chromium).
- onGetPixels:
- Decode the frame requested, recursively decoding required frame if
necessary
- When blending with a prior frame, use SkRasterPipeline
SkCodec:
- Move check for negative index to getFrameInfo
- Reset the colorXform if one is not needed
SkCodecAnimation:
- Add new blend enum, for WebP's (and APNG's) non-blending option
SkFrameHolder:
- New base classes for frames and the owner of the frames, allowing
code sharing between SkWebpCodec and SkGifCodec (particularly for
determining whether a frame has alpha and what frame it depends on)
- When moving items from SkGIFFrameContext, use Skia conventions (i.e.
int instead of unsigned)
- Rename "delay time" to "duration", to match e.g. SkFrameInfo::
fDuration
SkGifImageReader:
- Move pieces to SkFrameHolder, and adapt to changes made in the
process
- Make setAlphaAndRequiredFrame (now on the base class SkFrameHolder)
more general to support webp, and add support for frames that do not
blend
- Change SkGIFFrameContext from a struct to a class, to match how we
use the distinction elsewhere (i.e. struct is a small object with
public fields)
- Rework hasTransparentPixel (now hasTransparency, since it returns true
in some cases where there is not a transparent pixel) to better fit
with the modified setAlphaAndRequiredFrame. Also be more consistent
when there is no transparent pixel but no color map.
- Simplify an if condition that was previously simplified in 2d61e717
but accidentally got reverted in a4db9be6
CodecAnimTest:
- Test new animated webp files
- Rearrange the test to more cleanly print alpha type mismatches for
the first frame
resources:
- webp-animated.webp
- animated webp from Chromium
- blendBG.webp
- new webp file using bits of webp-animated-semitransparent4.webp
from Chromium
- tests required frame and alpha when using the non-blending mode
- frames have the following properties:
- Frame 0: no alpha, fills screen
- Frame 1: alpha, fills screen
- Frame 2: no alpha, fills screen
- Frame 3: alpha, fills screen, blendBG
- Frame 4: no alpha, fills screen, blendBG
- Frame 5: alpha, blendBG
- Frame 6: covers 4, has alpha, blendBG
- also used to test decoding to 565 if the new frame data has alpha
but blends onto an opaque frame
DM.cpp:
- Test animated images to non-native 8888 and unpremul
DMSrcSink.cpp:
- Do not test non-native 8888 decodes to f16 dst
- Test unpremul decodes to f16
- Copy a frame of an animated image prior to drawing, since in unpremul
mode, the DM code will premultiply first.
Bug: skia: 3315
Change-Id: I4e55ae2ee5bc095b37a743bdcfac644be603b980
Reviewed-on: https://skia-review.googlesource.com/16707
Commit-Queue: Mike Reed <reed@google.com>
Reviewed-by: Mike Reed <reed@google.com>
Reviewed-by: Leon Scroggins <scroggo@google.com>
Reviewed-by: Matt Sarett <msarett@google.com>
Diffstat (limited to 'dm')
-rw-r--r-- | dm/DM.cpp | 8 | ||||
-rw-r--r-- | dm/DMSrcSink.cpp | 28 |
2 files changed, 20 insertions, 16 deletions
@@ -603,8 +603,12 @@ static void push_codec_srcs(Path path) { { std::vector<SkCodec::FrameInfo> frameInfos = codec->getFrameInfo(); if (frameInfos.size() > 1) { - push_codec_src(path, CodecSrc::kAnimated_Mode, CodecSrc::kGetFromCanvas_DstColorType, - kPremul_SkAlphaType, 1.0f); + for (auto dstCT : { CodecSrc::kNonNative8888_Always_DstColorType, + CodecSrc::kGetFromCanvas_DstColorType }) { + for (auto at : { kUnpremul_SkAlphaType, kPremul_SkAlphaType }) { + push_codec_src(path, CodecSrc::kAnimated_Mode, dstCT, at, 1.0f); + } + } } } diff --git a/dm/DMSrcSink.cpp b/dm/DMSrcSink.cpp index 752ab2e4ae..8979d2d285 100644 --- a/dm/DMSrcSink.cpp +++ b/dm/DMSrcSink.cpp @@ -364,7 +364,8 @@ static bool get_decode_info(SkImageInfo* decodeInfo, SkColorType canvasColorType *decodeInfo = decodeInfo->makeColorType(kGray_8_SkColorType); break; case CodecSrc::kNonNative8888_Always_DstColorType: - if (kRGB_565_SkColorType == canvasColorType) { + if (kRGB_565_SkColorType == canvasColorType + || kRGBA_F16_SkColorType == canvasColorType) { return false; } #ifdef SK_PMCOLOR_IS_RGBA @@ -380,11 +381,6 @@ static bool get_decode_info(SkImageInfo* decodeInfo, SkColorType canvasColorType } if (kRGBA_F16_SkColorType == canvasColorType) { - if (kUnpremul_SkAlphaType == dstAlphaType) { - // Testing kPremul is enough for adequate coverage of F16 decoding. - return false; - } - sk_sp<SkColorSpace> linearSpace = as_CSB(decodeInfo->colorSpace())->makeLinearGamma(); *decodeInfo = decodeInfo->makeColorSpace(std::move(linearSpace)); @@ -499,6 +495,18 @@ Error CodecSrc::draw(SkCanvas* canvas) const { switch (result) { case SkCodec::kSuccess: case SkCodec::kIncompleteInput: { + // If the next frame depends on this one, store it in priorFrame. + // It is possible that we may discard a frame that future frames depend on, + // but the codec will simply redecode the discarded frame. + // Do this before calling draw_to_canvas, which premultiplies in place. If + // we're decoding to unpremul, we want to pass the unmodified frame to the + // codec for decoding the next frame. + if (static_cast<size_t>(i+1) < frameInfos.size() + && frameInfos[i+1].fRequiredFrame == i) { + memcpy(priorFramePixels.reset(safeSize), pixels.get(), safeSize); + cachedFrame = i; + } + SkAutoCanvasRestore acr(canvas, true); const int xTranslate = (i % factor) * decodeInfo.width(); const int yTranslate = (i / factor) * decodeInfo.height(); @@ -521,14 +529,6 @@ Error CodecSrc::draw(SkCanvas* canvas) const { return SkStringPrintf("Couldn't getPixels for frame %i in %s.", i, fPath.c_str()); } - - // If a future frame depends on this one, store it in priorFrame. - // (Note that if i+1 does *not* depend on i, then no future frame can.) - if (static_cast<size_t>(i+1) < frameInfos.size() - && frameInfos[i+1].fRequiredFrame == i) { - memcpy(priorFramePixels.reset(safeSize), pixels.get(), safeSize); - cachedFrame = i; - } } break; } |