aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/codec/SkGifCodec.h
blob: 11714eb39edc0decc420b327d20f18d8d3f5ce23 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
/*
 * Copyright 2015 Google Inc.
 *
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */
#ifndef SkGifCodec_DEFINED
#define SkGifCodec_DEFINED

#include "SkCodec.h"
#include "SkCodecAnimation.h"
#include "SkColorSpace.h"
#include "SkColorTable.h"
#include "SkImageInfo.h"
#include "SkSwizzler.h"

#include "SkGifImageReader.h"

/*
 *
 * This class implements the decoding for gif images
 *
 */
class SkGifCodec : public SkCodec {
public:
    static bool IsGif(const void*, size_t);

    /*
     * Assumes IsGif was called and returned true
     * Creates a gif decoder
     * Reads enough of the stream to determine the image format
     */
    static SkCodec* NewFromStream(SkStream*);

    // Callback for SkGifImageReader when a row is available.
    bool haveDecodedRow(size_t frameIndex, const unsigned char* rowBegin,
                        size_t rowNumber, unsigned repeatCount, bool writeTransparentPixels);
protected:
    /*
     * Performs the full gif decode
     */
    Result onGetPixels(const SkImageInfo&, void*, size_t, const Options&,
            SkPMColor*, int*, int*) override;

    SkEncodedImageFormat onGetEncodedFormat() const override {
        return SkEncodedImageFormat::kGIF;
    }

    bool onRewind() override;

    uint64_t onGetFillValue(const SkImageInfo&) const override;

    size_t onGetFrameCount() override;
    bool onGetFrameInfo(size_t, FrameInfo*) const override;
    int onGetRepetitionCount() override;

    Result onStartIncrementalDecode(const SkImageInfo& /*dstInfo*/, void*, size_t,
            const SkCodec::Options&, SkPMColor*, int*) override;

    Result onIncrementalDecode(int*) override;

private:

    /*
     * Initializes the color table that we will use for decoding.
     *
     * @param dstInfo         Contains the requested dst color type.
     * @param frameIndex      Frame whose color table to use.
     */
    void initializeColorTable(const SkImageInfo& dstInfo, size_t frameIndex);

   /*
    * Does necessary setup, including setting up the color table and swizzler,
    * and reports color info to the client.
    */
    Result prepareToDecode(const SkImageInfo& dstInfo, SkPMColor* inputColorPtr,
            int* inputColorCount, const Options& opts);

    /*
     * Initializes the swizzler.
     *
     * @param dstInfo    Output image information.  Dimensions may have been
     *                   adjusted if the image frame size does not match the size
     *                   indicated in the header.
     * @param frameIndex Which frame we are decoding. This determines the frameRect
     *                   to use.
     */
    void initializeSwizzler(const SkImageInfo& dstInfo, size_t frameIndex);

    SkSampler* getSampler(bool createIfNecessary) override {
        SkASSERT(fSwizzler);
        return fSwizzler.get();
    }

    /*
     * Recursive function to decode a frame.
     *
     * @param firstAttempt Whether this is the first call to decodeFrame since
     *                     starting. e.g. true in onGetPixels, and true in the
     *                     first call to onIncrementalDecode after calling
     *                     onStartIncrementalDecode.
     *                     When true, this method may have to initialize the
     *                     frame, for example by filling or decoding the prior
     *                     frame.
     * @param opts         Options for decoding. May be different from
     *                     this->options() for decoding prior frames. Specifies
     *                     the frame to decode and whether the prior frame has
     *                     already been decoded to fDst. If not, and the frame
     *                     is not independent, this method will recursively
     *                     decode the frame it depends on.
     * @param rowsDecoded  Out-parameter to report the total number of rows
     *                     that have been decoded (or at least written to, if
     *                     it had to fill), including rows decoded by prior
     *                     calls to onIncrementalDecode.
     * @return             kSuccess if the frame is complete, kIncompleteInput
     *                     otherwise.
     */
    Result decodeFrame(bool firstAttempt, const Options& opts, int* rowsDecoded);

    /*
     *  Swizzles and color xforms (if necessary) into dst.
     */
    void applyXformRow(const SkImageInfo& dstInfo, void* dst, const uint8_t* src) const;

    /*
     * Creates an instance of the decoder
     * Called only by NewFromStream
     * Takes ownership of the SkGifImageReader
     */
    SkGifCodec(const SkEncodedInfo&, const SkImageInfo&, SkGifImageReader*);

    std::unique_ptr<SkGifImageReader>   fReader;
    std::unique_ptr<uint8_t[]>          fTmpBuffer;
    std::unique_ptr<SkSwizzler>         fSwizzler;
    sk_sp<SkColorTable>                 fCurrColorTable;
    // We may create a dummy table if there is not a Map in the input data. In
    // that case, we set this value to false, and we can skip a lot of decoding
    // work (which would not be meaningful anyway). We create a "fake"/"dummy"
    // one in that case, so the client and the swizzler have something to draw.
    bool                                fCurrColorTableIsReal;
    // Whether the background was filled.
    bool                                fFilledBackground;
    // True on the first call to onIncrementalDecode. This value is passed to
    // decodeFrame.
    bool                                fFirstCallToIncrementalDecode;

    void*                               fDst;
    size_t                              fDstRowBytes;

    // Updated inside haveDecodedRow when rows are decoded, unless we filled
    // the background, in which case it is set once and left alone.
    int                                 fRowsDecoded;
    std::unique_ptr<uint32_t[]>         fXformBuffer;
    bool                                fXformOnDecode;

    typedef SkCodec INHERITED;
};
#endif  // SkGifCodec_DEFINED