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