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