aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/codec/SkCodec_libgif.h
blob: c29cbdb9d588acf27ee614bda1acd30fdd6693b2 (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
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
/*
 * Copyright 2015 Google Inc.
 *
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */

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

#include "gif_lib.h"

/*
 *
 * This class implements the decoding for gif images
 *
 */
class SkGifCodec : public SkCodec {
public:

    /*
     * Checks the start of the stream to see if the image is a gif
     */
    static bool IsGif(SkStream*);

    /*
     * 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*);

protected:

    /*
     * Read enough of the stream to initialize the SkGifCodec.
     * Returns a bool representing success or failure.
     *
     * @param codecOut
     * If it returned true, and codecOut was not nullptr,
     * codecOut will be set to a new SkGifCodec.
     *
     * @param gifOut
     * If it returned true, and codecOut was nullptr,
     * gifOut must be non-nullptr and gifOut will be set to a new
     * GifFileType pointer.
     *
     * @param stream
     * Deleted on failure.
     * codecOut will take ownership of it in the case where we created a codec.
     * Ownership is unchanged when we returned a gifOut.
     *
     */
    static bool ReadHeader(SkStream* stream, SkCodec** codecOut,
            GifFileType** gifOut);

    /*
     * Performs the full gif decode
     */
    Result onGetPixels(const SkImageInfo&, void*, size_t, const Options&,
            SkPMColor*, int32_t*) override;

    SkEncodedFormat onGetEncodedFormat() const override {
        return kGIF_SkEncodedFormat;
    }

    bool onRewind() override;

private:

    /*
     * A gif can contain multiple image frames.  We will only decode the first
     * frame.  This function reads up to the first image frame, processing
     * transparency and/or animation information that comes before the image
     * data.
     *
     * @param gif        Pointer to the library type that manages the gif decode
     * @param transIndex This call will set the transparent index based on the
     *                   extension data.
     */
     static Result ReadUpToFirstImage(GifFileType* gif, uint32_t* transIndex);

     /*
      * A gif may contain many image frames, all of different sizes.
      * This function checks if the frame dimensions are valid and corrects
      * them if necessary.  It then sets fFrameDims to the corrected
      * dimensions.
      *
      * @param desc The image frame descriptor
      */
     bool setFrameDimensions(const GifImageDesc& desc);

    /*
     * Initializes the color table that we will use for decoding.
     *
     * @param dstInfo         Contains the requested dst color type.
     * @param inputColorPtr   Copies the encoded color table to the client's
     *                        input color table if the client requests kIndex8.
     * @param inputColorCount If the client requests kIndex8, sets
     *                        inputColorCount to 256.  Since gifs always
     *                        contain 8-bit indices, we need a 256 entry color
     *                        table to ensure that indexing is always in
     *                        bounds.
     */
    void initializeColorTable(const SkImageInfo& dstInfo, SkPMColor* colorPtr,
            int* inputColorCount);

   /*
    * Checks for invalid inputs and calls setFrameDimensions(), and
    * initializeColorTable() in the proper sequence.
    */
    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 zeroInit Indicates if destination memory is zero initialized.
     */
    Result initializeSwizzler(const SkImageInfo& dstInfo, ZeroInitialized zeroInit);

    SkSampler* getSampler() override { return fSwizzler; }

    /*
     * @return kSuccess if the read is successful and kIncompleteInput if the
     *         read fails.
     */
    Result readRow();

    Result onStartScanlineDecode(const SkImageInfo& dstInfo, const Options& opts,
                   SkPMColor inputColorPtr[], int* inputColorCount) override;

    Result onGetScanlines(void* dst, int count, size_t rowBytes) override;

    SkScanlineOrder onGetScanlineOrder() const override;

    int onNextScanline() const override;

    /*
     * This function cleans up the gif object after the decode completes
     * It is used in a SkAutoTCallIProc template
     */
    static void CloseGif(GifFileType* gif);

    /*
     * Frees any extension data used in the decode
     * Used in a SkAutoTCallVProc
     */
    static void FreeExtension(SavedImage* image);

    /*
     * Creates an instance of the decoder
     * Called only by NewFromStream
     *
     * @param srcInfo contains the source width and height
     * @param stream the stream of image data
     * @param gif pointer to library type that manages gif decode
     *            takes ownership
     * @param transIndex  The transparent index.  An invalid value
     *            indicates that there is no transparent index.
     */
    SkGifCodec(const SkImageInfo& srcInfo, SkStream* stream, GifFileType* gif, uint32_t transIndex);

    SkAutoTCallVProc<GifFileType, CloseGif> fGif; // owned
    SkAutoTDeleteArray<uint8_t>             fSrcBuffer;
    SkIRect                                 fFrameDims;
    const uint32_t                          fTransIndex;
    uint32_t                                fFillIndex;
    bool                                    fFrameIsSubset;
    SkAutoTDelete<SkSwizzler>               fSwizzler;
    SkAutoTUnref<SkColorTable>              fColorTable;

    typedef SkCodec INHERITED;
};