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     uint64_t onGetFillValue(const SkImageInfo&) const override;
51 
52     int onGetFrameCount() override;
53     bool onGetFrameInfo(int, FrameInfo*) const override;
54     int onGetRepetitionCount() override;
55 
56     Result onStartIncrementalDecode(const SkImageInfo& /*dstInfo*/, void*, size_t,
57             const SkCodec::Options&) override;
58 
59     Result onIncrementalDecode(int*) override;
60 
getFrameHolder()61     const SkFrameHolder* getFrameHolder() const override {
62         return fReader.get();
63     }
64 
65 private:
66 
67     /*
68      * Initializes the color table that we will use for decoding.
69      *
70      * @param dstInfo         Contains the requested dst color type.
71      * @param frameIndex      Frame whose color table to use.
72      */
73     void initializeColorTable(const SkImageInfo& dstInfo, int frameIndex);
74 
75    /*
76     * Does necessary setup, including setting up the color table and swizzler.
77     */
78     Result prepareToDecode(const SkImageInfo& dstInfo, const Options& opts);
79 
80     /*
81      * Initializes the swizzler.
82      *
83      * @param dstInfo    Output image information.  Dimensions may have been
84      *                   adjusted if the image frame size does not match the size
85      *                   indicated in the header.
86      * @param frameIndex Which frame we are decoding. This determines the frameRect
87      *                   to use.
88      */
89     void initializeSwizzler(const SkImageInfo& dstInfo, int frameIndex);
90 
getSampler(bool createIfNecessary)91     SkSampler* getSampler(bool createIfNecessary) override {
92         SkASSERT(fSwizzler);
93         return fSwizzler.get();
94     }
95 
96     /*
97      * Recursive function to decode a frame.
98      *
99      * @param firstAttempt Whether this is the first call to decodeFrame since
100      *                     starting. e.g. true in onGetPixels, and true in the
101      *                     first call to onIncrementalDecode after calling
102      *                     onStartIncrementalDecode.
103      *                     When true, this method may have to initialize the
104      *                     frame, for example by filling or decoding the prior
105      *                     frame.
106      * @param opts         Options for decoding. May be different from
107      *                     this->options() for decoding prior frames. Specifies
108      *                     the frame to decode and whether the prior frame has
109      *                     already been decoded to fDst. If not, and the frame
110      *                     is not independent, this method will recursively
111      *                     decode the frame it depends on.
112      * @param rowsDecoded  Out-parameter to report the total number of rows
113      *                     that have been decoded (or at least written to, if
114      *                     it had to fill), including rows decoded by prior
115      *                     calls to onIncrementalDecode.
116      * @return             kSuccess if the frame is complete, kIncompleteInput
117      *                     otherwise.
118      */
119     Result decodeFrame(bool firstAttempt, const Options& opts, int* rowsDecoded);
120 
121     /*
122      *  Swizzles and color xforms (if necessary) into dst.
123      */
124     void applyXformRow(const SkImageInfo& dstInfo, void* dst, const uint8_t* src) const;
125 
126     /*
127      * Creates an instance of the decoder
128      * Called only by NewFromStream
129      * Takes ownership of the SkGifImageReader
130      */
131     SkGifCodec(const SkEncodedInfo&, const SkImageInfo&, SkGifImageReader*);
132 
133     std::unique_ptr<SkGifImageReader>   fReader;
134     std::unique_ptr<uint8_t[]>          fTmpBuffer;
135     std::unique_ptr<SkSwizzler>         fSwizzler;
136     sk_sp<SkColorTable>                 fCurrColorTable;
137     // We may create a dummy table if there is not a Map in the input data. In
138     // that case, we set this value to false, and we can skip a lot of decoding
139     // work (which would not be meaningful anyway). We create a "fake"/"dummy"
140     // one in that case, so the client and the swizzler have something to draw.
141     bool                                fCurrColorTableIsReal;
142     // Whether the background was filled.
143     bool                                fFilledBackground;
144     // True on the first call to onIncrementalDecode. This value is passed to
145     // decodeFrame.
146     bool                                fFirstCallToIncrementalDecode;
147 
148     void*                               fDst;
149     size_t                              fDstRowBytes;
150 
151     // Updated inside haveDecodedRow when rows are decoded, unless we filled
152     // the background, in which case it is set once and left alone.
153     int                                 fRowsDecoded;
154     std::unique_ptr<uint32_t[]>         fXformBuffer;
155 
156     typedef SkCodec INHERITED;
157 };
158 #endif  // SkGifCodec_DEFINED
159