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
* Reads enough of the stream to determine the image format
*/
static std::unique_ptr<SkCodec> MakeFromStream(std::unique_ptr<SkStream>, Result*);
// Callback for SkGifImageReader when a row is available.
void haveDecodedRow(int frameIndex, const unsigned char* rowBegin,
int rowNumber, int repeatCount, bool writeTransparentPixels);
protected:
/*
* Performs the full gif decode
*/
Result onGetPixels(const SkImageInfo&, void*, size_t, const Options&,
int*) override;
SkEncodedImageFormat onGetEncodedFormat() const override {
return SkEncodedImageFormat::kGIF;
}
bool onRewind() override;
uint64_t onGetFillValue(const SkImageInfo&) const override;
int onGetFrameCount() override;
bool onGetFrameInfo(int, FrameInfo*) const override;
int onGetRepetitionCount() override;
Result onStartIncrementalDecode(const SkImageInfo& /*dstInfo*/, void*, size_t,
const SkCodec::Options&) override;
Result onIncrementalDecode(int*) override;
const SkFrameHolder* getFrameHolder() const override {
return fReader.get();
}
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, int frameIndex);
/*
* Does necessary setup, including setting up the color table and swizzler.
*/
Result prepareToDecode(const SkImageInfo& dstInfo, 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, int 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;
typedef SkCodec INHERITED;
};
#endif // SkGifCodec_DEFINED
|