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
|
/*
* 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 "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;
SkEncodedFormat onGetEncodedFormat() const override {
return kGIF_SkEncodedFormat;
}
bool onRewind() override;
uint64_t onGetFillValue(const SkImageInfo&) const override;
std::vector<FrameInfo> onGetFrameInfo() 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.
* @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, this will be set
* to the number of colors in the array that
* inputColorPtr now points to. This will typically
* be 256. Since gifs may have up to 8-bit indices,
* using a 256-entry table means a pixel will never
* be out of range. This will be set to 1 if there
* is no color table, since that will be a
* transparent frame.
*/
void initializeColorTable(const SkImageInfo& dstInfo, size_t frameIndex,
SkPMColor* colorPtr, int* inputColorCount);
/*
* 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);
/*
* 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;
typedef SkCodec INHERITED;
};
|