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