aboutsummaryrefslogtreecommitdiffhomepage
path: root/third_party/gif/SkGifImageReader.h
diff options
context:
space:
mode:
authorGravatar Leon Scroggins III <scroggo@google.com>2017-05-23 09:37:21 -0400
committerGravatar Skia Commit-Bot <skia-commit-bot@chromium.org>2017-05-23 15:28:37 +0000
commit557fbbe05ba48bcc20be684d11fe0edfc24c87ba (patch)
treede83760e6e67a0866578056b4091091cef29cc53 /third_party/gif/SkGifImageReader.h
parente980174d0f3af8e497d9c38851114cc6a3c02e9a (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.h86
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;