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 onGetEncodedFormat()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 getFrameHolder()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 getSampler(bool createIfNecessary)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