• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2015 Google Inc.
3  *
4  * Use of this source code is governed by a BSD-style license that can be
5  * found in the LICENSE file.
6  */
7 #ifndef SkGifCodec_DEFINED
8 #define SkGifCodec_DEFINED
9 
10 #include "SkCodec.h"
11 #include "SkCodecAnimation.h"
12 #include "SkColorSpace.h"
13 #include "SkColorTable.h"
14 #include "SkImageInfo.h"
15 #include "SkSwizzler.h"
16 
17 #include "SkGifImageReader.h"
18 
19 /*
20  *
21  * This class implements the decoding for gif images
22  *
23  */
24 class SkGifCodec : public SkCodec {
25 public:
26     static bool IsGif(const void*, size_t);
27 
28     /*
29      * Assumes IsGif was called and returned true
30      * Reads enough of the stream to determine the image format
31      */
32     static std::unique_ptr<SkCodec> MakeFromStream(std::unique_ptr<SkStream>, Result*);
33 
34     // Callback for SkGifImageReader when a row is available.
35     void haveDecodedRow(int frameIndex, const unsigned char* rowBegin,
36                         int rowNumber, int repeatCount, bool writeTransparentPixels);
37 protected:
38     /*
39      * Performs the full gif decode
40      */
41     Result onGetPixels(const SkImageInfo&, void*, size_t, const Options&,
42             int*) override;
43 
onGetEncodedFormat()44     SkEncodedImageFormat onGetEncodedFormat() const override {
45         return SkEncodedImageFormat::kGIF;
46     }
47 
48     bool onRewind() override;
49 
50     int onGetFrameCount() override;
51     bool onGetFrameInfo(int, FrameInfo*) const override;
52     int onGetRepetitionCount() override;
53 
54     Result onStartIncrementalDecode(const SkImageInfo& /*dstInfo*/, void*, size_t,
55             const SkCodec::Options&) override;
56 
57     Result onIncrementalDecode(int*) override;
58 
getFrameHolder()59     const SkFrameHolder* getFrameHolder() const override {
60         return fReader.get();
61     }
62 
63 private:
64 
65     /*
66      * Initializes the color table that we will use for decoding.
67      *
68      * @param dstInfo         Contains the requested dst color type.
69      * @param frameIndex      Frame whose color table to use.
70      */
71     void initializeColorTable(const SkImageInfo& dstInfo, int frameIndex);
72 
73    /*
74     * Does necessary setup, including setting up the color table and swizzler.
75     */
76     Result prepareToDecode(const SkImageInfo& dstInfo, const Options& opts);
77 
78     /*
79      * Initializes the swizzler.
80      *
81      * @param dstInfo    Output image information.  Dimensions may have been
82      *                   adjusted if the image frame size does not match the size
83      *                   indicated in the header.
84      * @param frameIndex Which frame we are decoding. This determines the frameRect
85      *                   to use.
86      */
87     void initializeSwizzler(const SkImageInfo& dstInfo, int frameIndex);
88 
getSampler(bool createIfNecessary)89     SkSampler* getSampler(bool createIfNecessary) override {
90         SkASSERT(fSwizzler);
91         return fSwizzler.get();
92     }
93 
94     /*
95      * Recursive function to decode a frame.
96      *
97      * @param firstAttempt Whether this is the first call to decodeFrame since
98      *                     starting. e.g. true in onGetPixels, and true in the
99      *                     first call to onIncrementalDecode after calling
100      *                     onStartIncrementalDecode.
101      *                     When true, this method may have to initialize the
102      *                     frame, for example by filling or decoding the prior
103      *                     frame.
104      * @param opts         Options for decoding. May be different from
105      *                     this->options() for decoding prior frames. Specifies
106      *                     the frame to decode and whether the prior frame has
107      *                     already been decoded to fDst. If not, and the frame
108      *                     is not independent, this method will recursively
109      *                     decode the frame it depends on.
110      * @param rowsDecoded  Out-parameter to report the total number of rows
111      *                     that have been decoded (or at least written to, if
112      *                     it had to fill), including rows decoded by prior
113      *                     calls to onIncrementalDecode.
114      * @return             kSuccess if the frame is complete, kIncompleteInput
115      *                     otherwise.
116      */
117     Result decodeFrame(bool firstAttempt, const Options& opts, int* rowsDecoded);
118 
119     /*
120      *  Swizzles and color xforms (if necessary) into dst.
121      */
122     void applyXformRow(const SkImageInfo& dstInfo, void* dst, const uint8_t* src) const;
123 
124     /*
125      * Creates an instance of the decoder
126      * Called only by NewFromStream
127      * Takes ownership of the SkGifImageReader
128      */
129     SkGifCodec(SkEncodedInfo&&, SkGifImageReader*);
130 
131     std::unique_ptr<SkGifImageReader>   fReader;
132     std::unique_ptr<uint8_t[]>          fTmpBuffer;
133     std::unique_ptr<SkSwizzler>         fSwizzler;
134     sk_sp<SkColorTable>                 fCurrColorTable;
135     // We may create a dummy table if there is not a Map in the input data. In
136     // that case, we set this value to false, and we can skip a lot of decoding
137     // work (which would not be meaningful anyway). We create a "fake"/"dummy"
138     // one in that case, so the client and the swizzler have something to draw.
139     bool                                fCurrColorTableIsReal;
140     // Whether the background was filled.
141     bool                                fFilledBackground;
142     // True on the first call to onIncrementalDecode. This value is passed to
143     // decodeFrame.
144     bool                                fFirstCallToIncrementalDecode;
145 
146     void*                               fDst;
147     size_t                              fDstRowBytes;
148 
149     // Updated inside haveDecodedRow when rows are decoded, unless we filled
150     // the background, in which case it is set once and left alone.
151     int                                 fRowsDecoded;
152     std::unique_ptr<uint32_t[]>         fXformBuffer;
153 
154     typedef SkCodec INHERITED;
155 };
156 #endif  // SkGifCodec_DEFINED
157