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 uint64_t onGetFillValue(const SkImageInfo&) const override; 51 52 int onGetFrameCount() override; 53 bool onGetFrameInfo(int, FrameInfo*) const override; 54 int onGetRepetitionCount() override; 55 56 Result onStartIncrementalDecode(const SkImageInfo& /*dstInfo*/, void*, size_t, 57 const SkCodec::Options&) override; 58 59 Result onIncrementalDecode(int*) override; 60 61 const SkFrameHolder* getFrameHolder() const override { 62 return fReader.get(); 63 } 64 65 private: 66 67 /* 68 * Initializes the color table that we will use for decoding. 69 * 70 * @param dstInfo Contains the requested dst color type. 71 * @param frameIndex Frame whose color table to use. 72 */ 73 void initializeColorTable(const SkImageInfo& dstInfo, int frameIndex); 74 75 /* 76 * Does necessary setup, including setting up the color table and swizzler. 77 */ 78 Result prepareToDecode(const SkImageInfo& dstInfo, const Options& opts); 79 80 /* 81 * Initializes the swizzler. 82 * 83 * @param dstInfo Output image information. Dimensions may have been 84 * adjusted if the image frame size does not match the size 85 * indicated in the header. 86 * @param frameIndex Which frame we are decoding. This determines the frameRect 87 * to use. 88 */ 89 void initializeSwizzler(const SkImageInfo& dstInfo, int frameIndex); 90 91 SkSampler* getSampler(bool createIfNecessary) override { 92 SkASSERT(fSwizzler); 93 return fSwizzler.get(); 94 } 95 96 /* 97 * Recursive function to decode a frame. 98 * 99 * @param firstAttempt Whether this is the first call to decodeFrame since 100 * starting. e.g. true in onGetPixels, and true in the 101 * first call to onIncrementalDecode after calling 102 * onStartIncrementalDecode. 103 * When true, this method may have to initialize the 104 * frame, for example by filling or decoding the prior 105 * frame. 106 * @param opts Options for decoding. May be different from 107 * this->options() for decoding prior frames. Specifies 108 * the frame to decode and whether the prior frame has 109 * already been decoded to fDst. If not, and the frame 110 * is not independent, this method will recursively 111 * decode the frame it depends on. 112 * @param rowsDecoded Out-parameter to report the total number of rows 113 * that have been decoded (or at least written to, if 114 * it had to fill), including rows decoded by prior 115 * calls to onIncrementalDecode. 116 * @return kSuccess if the frame is complete, kIncompleteInput 117 * otherwise. 118 */ 119 Result decodeFrame(bool firstAttempt, const Options& opts, int* rowsDecoded); 120 121 /* 122 * Swizzles and color xforms (if necessary) into dst. 123 */ 124 void applyXformRow(const SkImageInfo& dstInfo, void* dst, const uint8_t* src) const; 125 126 /* 127 * Creates an instance of the decoder 128 * Called only by NewFromStream 129 * Takes ownership of the SkGifImageReader 130 */ 131 SkGifCodec(const SkEncodedInfo&, const SkImageInfo&, SkGifImageReader*); 132 133 std::unique_ptr<SkGifImageReader> fReader; 134 std::unique_ptr<uint8_t[]> fTmpBuffer; 135 std::unique_ptr<SkSwizzler> fSwizzler; 136 sk_sp<SkColorTable> fCurrColorTable; 137 // We may create a dummy table if there is not a Map in the input data. In 138 // that case, we set this value to false, and we can skip a lot of decoding 139 // work (which would not be meaningful anyway). We create a "fake"/"dummy" 140 // one in that case, so the client and the swizzler have something to draw. 141 bool fCurrColorTableIsReal; 142 // Whether the background was filled. 143 bool fFilledBackground; 144 // True on the first call to onIncrementalDecode. This value is passed to 145 // decodeFrame. 146 bool fFirstCallToIncrementalDecode; 147 148 void* fDst; 149 size_t fDstRowBytes; 150 151 // Updated inside haveDecodedRow when rows are decoded, unless we filled 152 // the background, in which case it is set once and left alone. 153 int fRowsDecoded; 154 std::unique_ptr<uint32_t[]> fXformBuffer; 155 156 typedef SkCodec INHERITED; 157 }; 158 #endif // SkGifCodec_DEFINED 159