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 /third_party/gif/SkGifImageReader.h | |
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 'third_party/gif/SkGifImageReader.h')
-rw-r--r-- | third_party/gif/SkGifImageReader.h | 86 |
1 files changed, 25 insertions, 61 deletions
diff --git a/third_party/gif/SkGifImageReader.h b/third_party/gif/SkGifImageReader.h index 4667f7963f..6c313e923b 100644 --- a/third_party/gif/SkGifImageReader.h +++ b/third_party/gif/SkGifImageReader.h @@ -47,6 +47,7 @@ class SkGifCodec; #include "SkCodecAnimation.h" #include "SkColorTable.h" #include "SkData.h" +#include "SkFrameHolder.h" #include "SkImageInfo.h" #include "SkStreamBuffer.h" #include "../private/SkTArray.h" @@ -85,7 +86,7 @@ enum SkGIFState { SkGIFConsumeComment }; -struct SkGIFFrameContext; +class SkGIFFrameContext; class SkGIFColorMap; // LZW decoder state machine. @@ -191,19 +192,15 @@ private: mutable sk_sp<SkColorTable> m_table; }; +class SkGifImageReader; + // LocalFrame output state machine. -struct SkGIFFrameContext : SkNoncopyable { +class SkGIFFrameContext : public SkFrame { public: - SkGIFFrameContext(int id) - : m_frameId(id) - , m_xOffset(0) - , m_yOffset(0) - , m_width(0) - , m_height(0) + SkGIFFrameContext(SkGifImageReader* reader, int id) + : INHERITED(id) + , m_owner(reader) , m_transparentPixel(SkGIFColorMap::kNotFound) - , m_hasAlpha(false) - , m_disposalMethod(SkCodecAnimation::Keep_DisposalMethod) - , m_requiredFrame(kUninitialized) , m_dataSize(0) , m_progressiveDisplay(false) , m_interlaced(false) @@ -226,31 +223,8 @@ public: bool decode(SkStreamBuffer*, SkGifCodec* client, bool* frameDecoded); - int frameId() const { return m_frameId; } - void setRect(unsigned x, unsigned y, unsigned width, unsigned height) - { - m_xOffset = x; - m_yOffset = y; - m_width = width; - m_height = height; - } - SkIRect frameRect() const { return SkIRect::MakeXYWH(m_xOffset, m_yOffset, m_width, m_height); } - unsigned xOffset() const { return m_xOffset; } - unsigned yOffset() const { return m_yOffset; } - unsigned width() const { return m_width; } - unsigned height() const { return m_height; } int transparentPixel() const { return m_transparentPixel; } void setTransparentPixel(int pixel) { m_transparentPixel = pixel; } - bool hasAlpha() const { return m_hasAlpha; } - void setHasAlpha(bool alpha) { m_hasAlpha = alpha; } - SkCodecAnimation::DisposalMethod getDisposalMethod() const { return m_disposalMethod; } - void setDisposalMethod(SkCodecAnimation::DisposalMethod disposalMethod) { m_disposalMethod = disposalMethod; } - - int getRequiredFrame() const { - SkASSERT(this->reachedStartOfData()); - return m_requiredFrame; - } - void setRequiredFrame(int req) { m_requiredFrame = req; } unsigned delayTime() const { return m_delayTime; } void setDelayTime(unsigned delay) { m_delayTime = delay; } @@ -274,24 +248,14 @@ public: const SkGIFColorMap& localColorMap() const { return m_localColorMap; } SkGIFColorMap& localColorMap() { return m_localColorMap; } - bool reachedStartOfData() const { return m_requiredFrame != kUninitialized; } +protected: + bool onReportsAlpha() const override; private: - static constexpr int kUninitialized = -2; + // Unowned pointer to the object that owns this frame. + const SkGifImageReader* m_owner; - int m_frameId; - unsigned m_xOffset; - unsigned m_yOffset; // With respect to "screen" origin. - unsigned m_width; - unsigned m_height; int m_transparentPixel; // Index of transparent pixel. Value is kNotFound if there is no transparent pixel. - // Cached value, taking into account: - // - m_transparentPixel - // - frameRect - // - previous required frame - bool m_hasAlpha; - SkCodecAnimation::DisposalMethod m_disposalMethod; // Restore to background, leave in place, etc. - int m_requiredFrame; int m_dataSize; bool m_progressiveDisplay; // If true, do Haeberli interlace hack. @@ -309,9 +273,11 @@ private: bool m_isComplete; bool m_isHeaderDefined; bool m_isDataSizeDefined; + + typedef SkFrame INHERITED; }; -class SkGifImageReader final : public SkNoncopyable { +class SkGifImageReader final : public SkFrameHolder { public: // This takes ownership of stream. SkGifImageReader(SkStream* stream) @@ -319,8 +285,6 @@ public: , m_state(SkGIFType) , m_bytesToConsume(6) // Number of bytes for GIF type, either "GIF87a" or "GIF89a". , m_version(0) - , m_screenWidth(0) - , m_screenHeight(0) , m_loopCount(cLoopCountNotSeen) , m_streamBuffer(stream) , m_parseCompleted(false) @@ -335,9 +299,6 @@ public: void setClient(SkGifCodec* client) { m_client = client; } - unsigned screenWidth() const { return m_screenWidth; } - unsigned screenHeight() const { return m_screenHeight; } - // Option to pass to parse(). All enums are negative, because a non-negative value is used to // indicate that the Reader should parse up to and including the frame indicated. enum SkGIFParseQuery { @@ -408,6 +369,16 @@ public: bool firstFrameSupportsIndex8() const { return m_firstFrameSupportsIndex8; } + // Helper function that returns whether an SkGIFFrameContext has transparency. + // This method is sometimes called before creating one/parsing its color map, + // so it cannot rely on SkGIFFrameContext::transparentPixel or ::localColorMap(). + bool hasTransparency(int transPix, bool hasLocalColorMap, int localMapColors) const; + +protected: + const SkFrame* onGetFrame(int i) const override { + return static_cast<const SkFrame*>(this->frameContext(i)); + } + private: // Requires that one byte has been buffered into m_streamBuffer. unsigned char getOneByte() const { @@ -415,11 +386,6 @@ private: } void addFrameIfNecessary(); - // Must be called *after* the SkGIFFrameContext's color table (if any) has been parsed. - void setAlphaAndRequiredFrame(SkGIFFrameContext*); - // This method is sometimes called before creating a SkGIFFrameContext, so it cannot rely - // on SkGIFFrameContext::localColorMap(). - bool hasTransparentPixel(int frameIndex, bool hasLocalColorMap, int localMapColors); bool currentFrameIsFirstFrame() const { return m_frames.empty() || (m_frames.size() == 1u && !m_frames[0]->isComplete()); @@ -434,8 +400,6 @@ private: // Global (multi-image) state. int m_version; // Either 89 for GIF89 or 87 for GIF87. - unsigned m_screenWidth; // Logical screen width & height. - unsigned m_screenHeight; SkGIFColorMap m_globalColorMap; static constexpr int cLoopCountNotSeen = -2; |